ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CPU1541.h
Revision: 1.4
Committed: 2005-06-27T19:55:48Z (19 years, 4 months ago) by cebix
Content type: text/plain
Branch: MAIN
CVS Tags: VERSION_4_2
Changes since 1.3: +1 -1 lines
Log Message:
updated copyright dates

File Contents

# Content
1 /*
2 * CPU1541.h - 6502 (1541) emulation (line based)
3 *
4 * Frodo (C) 1994-1997,2002-2005 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifndef _CPU_1541_H
22 #define _CPU_1541_H
23
24 #include "CIA.h"
25 #include "C64.h"
26
27
28 // Set this to 1 if the 6502 PC should be represented by a real pointer
29 #ifndef FRODO_SC
30 #ifndef PC_IS_POINTER
31 #define PC_IS_POINTER 1
32 #endif
33 #endif
34
35 // Set this to 1 for more precise CPU cycle calculation
36 #ifndef PRECISE_CPU_CYCLES
37 #define PRECISE_CPU_CYCLES 0
38 #endif
39
40
41 // Interrupt types
42 enum {
43 INT_VIA1IRQ,
44 INT_VIA2IRQ,
45 INT_IECIRQ
46 // INT_RESET (private)
47 };
48
49
50 class C64;
51 class Job1541;
52 class C64Display;
53 struct MOS6502State;
54
55
56 // 6502 emulation (1541)
57 class MOS6502_1541 {
58 public:
59 MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom);
60
61 #ifdef FRODO_SC
62 void EmulateCycle(void); // Emulate one clock cycle
63 #else
64 int EmulateLine(int cycles_left); // Emulate until cycles_left underflows
65 #endif
66 void Reset(void);
67 void AsyncReset(void); // Reset the CPU asynchronously
68 void GetState(MOS6502State *s);
69 void SetState(MOS6502State *s);
70 uint8 ExtReadByte(uint16 adr);
71 void ExtWriteByte(uint16 adr, uint8 byte);
72 void CountVIATimers(int cycles);
73 void NewATNState(void);
74 void IECInterrupt(void);
75 void TriggerJobIRQ(void);
76 bool InterruptEnabled(void);
77
78 MOS6526_2 *TheCIA2; // Pointer to C64 CIA 2
79
80 uint8 IECLines; // State of IEC lines (bit 7 - DATA, bit 6 - CLK)
81 bool Idle; // true: 1541 is idle
82
83 private:
84 uint8 read_byte(uint16 adr);
85 uint8 read_byte_io(uint16 adr);
86 uint16 read_word(uint16 adr);
87 void write_byte(uint16 adr, uint8 byte);
88 void write_byte_io(uint16 adr, uint8 byte);
89
90 uint8 read_zp(uint16 adr);
91 uint16 read_zp_word(uint16 adr);
92 void write_zp(uint16 adr, uint8 byte);
93
94 void jump(uint16 adr);
95 void illegal_op(uint8 op, uint16 at);
96 void illegal_jump(uint16 at, uint16 to);
97
98 void do_adc(uint8 byte);
99 void do_sbc(uint8 byte);
100
101 uint8 *ram; // Pointer to main RAM
102 uint8 *rom; // Pointer to ROM
103 C64 *the_c64; // Pointer to C64 object
104 C64Display *the_display; // Pointer to C64 display object
105 Job1541 *the_job; // Pointer to 1541 job object
106
107 union { // Pending interrupts
108 uint8 intr[4]; // Index: See definitions above
109 unsigned long intr_any;
110 } interrupt;
111
112 uint8 n_flag, z_flag;
113 bool v_flag, d_flag, i_flag, c_flag;
114 uint8 a, x, y, sp;
115 #if PC_IS_POINTER
116 uint8 *pc, *pc_base;
117 #else
118 uint16 pc;
119 #endif
120
121 #ifdef FRODO_SC
122 uint32 first_irq_cycle;
123
124 uint8 state, op; // Current state and opcode
125 uint16 ar, ar2; // Address registers
126 uint8 rdbuf; // Data buffer for RMW instructions
127 uint8 ddr, pr; // Processor port
128 #else
129 int borrowed_cycles; // Borrowed cycles from next line
130 #endif
131
132 uint8 via1_pra; // PRA of VIA 1
133 uint8 via1_ddra; // DDRA of VIA 1
134 uint8 via1_prb; // PRB of VIA 1
135 uint8 via1_ddrb; // DDRB of VIA 1
136 uint16 via1_t1c; // T1 Counter of VIA 1
137 uint16 via1_t1l; // T1 Latch of VIA 1
138 uint16 via1_t2c; // T2 Counter of VIA 1
139 uint16 via1_t2l; // T2 Latch of VIA 1
140 uint8 via1_sr; // SR of VIA 1
141 uint8 via1_acr; // ACR of VIA 1
142 uint8 via1_pcr; // PCR of VIA 1
143 uint8 via1_ifr; // IFR of VIA 1
144 uint8 via1_ier; // IER of VIA 1
145
146 uint8 via2_pra; // PRA of VIA 2
147 uint8 via2_ddra; // DDRA of VIA 2
148 uint8 via2_prb; // PRB of VIA 2
149 uint8 via2_ddrb; // DDRB of VIA 2
150 uint16 via2_t1c; // T1 Counter of VIA 2
151 uint16 via2_t1l; // T1 Latch of VIA 2
152 uint16 via2_t2c; // T2 Counter of VIA 2
153 uint16 via2_t2l; // T2 Latch of VIA 2
154 uint8 via2_sr; // SR of VIA 2
155 uint8 via2_acr; // ACR of VIA 2
156 uint8 via2_pcr; // PCR of VIA 2
157 uint8 via2_ifr; // IFR of VIA 2
158 uint8 via2_ier; // IER of VIA 2
159 };
160
161 // 6502 state
162 struct MOS6502State {
163 uint8 a, x, y;
164 uint8 p; // Processor flags
165 uint16 pc, sp;
166
167 uint8 intr[4]; // Interrupt state
168 bool instruction_complete;
169 bool idle;
170
171 uint8 via1_pra; // VIA 1
172 uint8 via1_ddra;
173 uint8 via1_prb;
174 uint8 via1_ddrb;
175 uint16 via1_t1c;
176 uint16 via1_t1l;
177 uint16 via1_t2c;
178 uint16 via1_t2l;
179 uint8 via1_sr;
180 uint8 via1_acr;
181 uint8 via1_pcr;
182 uint8 via1_ifr;
183 uint8 via1_ier;
184
185 uint8 via2_pra; // VIA 2
186 uint8 via2_ddra;
187 uint8 via2_prb;
188 uint8 via2_ddrb;
189 uint16 via2_t1c;
190 uint16 via2_t1l;
191 uint16 via2_t2c;
192 uint16 via2_t2l;
193 uint8 via2_sr;
194 uint8 via2_acr;
195 uint8 via2_pcr;
196 uint8 via2_ifr;
197 uint8 via2_ier;
198 };
199
200
201
202 /*
203 * Trigger job loop IRQ
204 */
205
206 #ifdef FRODO_SC
207 inline void MOS6502_1541::TriggerJobIRQ(void)
208 {
209 if (!(interrupt.intr[INT_VIA2IRQ]))
210 first_irq_cycle = the_c64->CycleCounter;
211 interrupt.intr[INT_VIA2IRQ] = true;
212 Idle = false;
213 }
214 #else
215 inline void MOS6502_1541::TriggerJobIRQ(void)
216 {
217 interrupt.intr[INT_VIA2IRQ] = true;
218 Idle = false;
219 }
220 #endif
221
222
223 /*
224 * Count VIA timers
225 */
226
227 inline void MOS6502_1541::CountVIATimers(int cycles)
228 {
229 unsigned long tmp;
230
231 via1_t1c = tmp = via1_t1c - cycles;
232 if (tmp > 0xffff) {
233 if (via1_acr & 0x40) // Reload from latch in free-run mode
234 via1_t1c = via1_t1l;
235 via1_ifr |= 0x40;
236 }
237
238 if (!(via1_acr & 0x20)) { // Only count in one-shot mode
239 via1_t2c = tmp = via1_t2c - cycles;
240 if (tmp > 0xffff)
241 via1_ifr |= 0x20;
242 }
243
244 via2_t1c = tmp = via2_t1c - cycles;
245 if (tmp > 0xffff) {
246 if (via2_acr & 0x40) // Reload from latch in free-run mode
247 via2_t1c = via2_t1l;
248 via2_ifr |= 0x40;
249 if (via2_ier & 0x40)
250 TriggerJobIRQ();
251 }
252
253 if (!(via2_acr & 0x20)) { // Only count in one-shot mode
254 via2_t2c = tmp = via2_t2c - cycles;
255 if (tmp > 0xffff)
256 via2_ifr |= 0x20;
257 }
258 }
259
260
261 /*
262 * ATN line probably changed state, recalc IECLines
263 */
264
265 inline void MOS6502_1541::NewATNState(void)
266 {
267 uint8 byte = ~via1_prb & via1_ddrb;
268 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80 // DATA (incl. ATN acknowledge)
269 | (byte << 3) & 0x40; // CLK
270 }
271
272
273 /*
274 * Interrupt by negative edge of ATN on IEC bus
275 */
276
277 inline void MOS6502_1541::IECInterrupt(void)
278 {
279 ram[0x7c] = 1;
280
281 // Wake up 1541
282 Idle = false;
283 }
284
285
286 /*
287 * Test if interrupts are enabled (for job loop)
288 */
289
290 inline bool MOS6502_1541::InterruptEnabled(void)
291 {
292 return !i_flag;
293 }
294
295 #endif