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