]> Shamusworld >> Repos - apple2/blob - apple2/src/v65c02.cpp
1538f5321195ce145837247205f744d10d618731
[apple2] / apple2 / src / v65c02.cpp
1 //\r
2 // Virtual 65C02 Emulator v1.0\r
3 //\r
4 // by James L. Hammons\r
5 // (c) 2005 Underground Software\r
6 //\r
7 // JLH = James L. Hammons <jlhamm@acm.org>\r
8 //\r
9 // WHO  WHEN        WHAT\r
10 // ---  ----------  ------------------------------------------------------------\r
11 // JLH  01/04/2006  Added changelog ;-)\r
12 //\r
13 \r
14 //OK, the wraparound bug exists in both the Apple and Atari versions of Ultima II.\r
15 //However, the Atari version *does* occassionally pick strength while the Apple\r
16 //versions do not--which would seem to indicate a bug either in the RNG algorithm,\r
17 //the 65C02 core, or the Apple hardware. Need to investigate all three!\r
18 \r
19 #define __DEBUG__\r
20 //#define __DEBUGMON__\r
21 \r
22 #include "v65c02.h"\r
23 \r
24 #ifdef __DEBUG__\r
25 #include "dis65c02.h"\r
26 #include "log.h"\r
27 #endif\r
28 \r
29 // Various macros\r
30 \r
31 #define CLR_Z                           (regs.cc &= ~FLAG_Z)\r
32 #define CLR_ZN                          (regs.cc &= ~(FLAG_Z | FLAG_N))\r
33 #define CLR_ZNC                         (regs.cc &= ~(FLAG_Z | FLAG_N | FLAG_C))\r
34 #define CLR_V                           (regs.cc &= ~FLAG_V)\r
35 #define CLR_N                           (regs.cc &= ~FLAG_N)\r
36 #define SET_Z(r)                        (regs.cc = ((r) == 0 ? regs.cc | FLAG_Z : regs.cc & ~FLAG_Z))\r
37 #define SET_N(r)                        (regs.cc = ((r) & 0x80 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N))\r
38 \r
39 //Not sure that this code is computing the carry correctly... Investigate! [Seems to be]\r
40 #define SET_C_ADD(a,b)          (regs.cc = ((uint8)(b) > (uint8)(~(a)) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))\r
41 //#define SET_C_SUB(a,b)                (regs.cc = ((uint8)(b) >= (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))\r
42 #define SET_C_CMP(a,b)          (regs.cc = ((uint8)(b) >= (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))\r
43 #define SET_ZN(r)                       SET_N(r); SET_Z(r)\r
44 #define SET_ZNC_ADD(a,b,r)      SET_N(r); SET_Z(r); SET_C_ADD(a,b)\r
45 //#define SET_ZNC_SUB(a,b,r)    SET_N(r); SET_Z(r); SET_C_SUB(a,b)\r
46 #define SET_ZNC_CMP(a,b,r)      SET_N(r); SET_Z(r); SET_C_CMP(a,b)\r
47 \r
48 //Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!!\r
49 #define EA_IMM                          regs.pc++\r
50 #define EA_ZP                           regs.RdMem(regs.pc++)\r
51 #define EA_ZP_X                         (regs.RdMem(regs.pc++) + regs.x) & 0xFF\r
52 #define EA_ZP_Y                         (regs.RdMem(regs.pc++) + regs.y) & 0xFF\r
53 #define EA_ABS                          RdMemW(regs.pc)\r
54 #define EA_ABS_X                        RdMemW(regs.pc) + regs.x\r
55 #define EA_ABS_Y                        RdMemW(regs.pc) + regs.y\r
56 #define EA_IND_ZP_X                     RdMemW((regs.RdMem(regs.pc++) + regs.x) & 0xFF)\r
57 #define EA_IND_ZP_Y                     RdMemW(regs.RdMem(regs.pc++)) + regs.y\r
58 #define EA_IND_ZP                       RdMemW(regs.RdMem(regs.pc++))\r
59 \r
60 #define READ_IMM                        regs.RdMem(EA_IMM)\r
61 #define READ_ZP                         regs.RdMem(EA_ZP)\r
62 #define READ_ZP_X                       regs.RdMem(EA_ZP_X)\r
63 #define READ_ZP_Y                       regs.RdMem(EA_ZP_Y)\r
64 #define READ_ABS                        regs.RdMem(EA_ABS);     regs.pc += 2\r
65 #define READ_ABS_X                      regs.RdMem(EA_ABS_X);   regs.pc += 2\r
66 #define READ_ABS_Y                      regs.RdMem(EA_ABS_Y);   regs.pc += 2\r
67 #define READ_IND_ZP_X           regs.RdMem(EA_IND_ZP_X)\r
68 #define READ_IND_ZP_Y           regs.RdMem(EA_IND_ZP_Y)\r
69 #define READ_IND_ZP                     regs.RdMem(EA_IND_ZP)\r
70 \r
71 #define READ_IMM_WB(v)          uint16 addr = EA_IMM;      v = regs.RdMem(addr)\r
72 #define READ_ZP_WB(v)           uint16 addr = EA_ZP;       v = regs.RdMem(addr)\r
73 #define READ_ZP_X_WB(v)         uint16 addr = EA_ZP_X;     v = regs.RdMem(addr)\r
74 #define READ_ABS_WB(v)          uint16 addr = EA_ABS;      v = regs.RdMem(addr); regs.pc += 2\r
75 #define READ_ABS_X_WB(v)        uint16 addr = EA_ABS_X;    v = regs.RdMem(addr); regs.pc += 2\r
76 #define READ_ABS_Y_WB(v)        uint16 addr = EA_ABS_Y;    v = regs.RdMem(addr); regs.pc += 2\r
77 #define READ_IND_ZP_X_WB(v)     uint16 addr = EA_IND_ZP_X; v = regs.RdMem(addr)\r
78 #define READ_IND_ZP_Y_WB(v)     uint16 addr = EA_IND_ZP_Y; v = regs.RdMem(addr)\r
79 #define READ_IND_ZP_WB(v)       uint16 addr = EA_IND_ZP;   v = regs.RdMem(addr)\r
80 \r
81 #define WRITE_BACK(d)           regs.WrMem(addr, (d))\r
82 \r
83 // Private global variables\r
84 \r
85 static V65C02REGS regs;\r
86 \r
87 //This is probably incorrect, at least WRT to the $x7 and $xF opcodes... !!! FIX !!!\r
88 //Also this doesn't take into account the extra cycle it takes when an indirect fetch\r
89 //(ABS, ABS X/Y, ZP) crosses a page boundary, or extra cycle for BCD add/subtract...\r
90 #warning Cycle counts are not accurate--!!! FIX !!!\r
91 static uint8 CPUCycles[256] = {\r
92         7, 6, 1, 1, 5, 3, 5, 1, 3, 2, 2, 1, 6, 4, 6, 1,\r
93         2, 5, 5, 1, 5, 4, 6, 1, 2, 4, 2, 1, 6, 4, 6, 1,\r
94         6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 4, 4, 6, 1,\r
95         2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 2, 1, 4, 4, 6, 1,\r
96         6, 6, 1, 1, 1, 3, 5, 1, 3, 2, 2, 1, 3, 4, 6, 1,\r
97         2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,\r
98         6, 6, 1, 1, 3, 3, 5, 1, 4, 2, 2, 1, 6, 4, 6, 1,\r
99         2, 5, 5, 1, 4, 4, 6, 1, 2, 4, 4, 1, 6, 4, 6, 1,\r
100         2, 6, 1, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,\r
101         2, 6, 5, 1, 4, 4, 4, 1, 2, 5, 2, 1, 4, 5, 5, 1,\r
102         2, 6, 2, 1, 3, 3, 3, 1, 2, 2, 2, 1, 4, 4, 4, 1,\r
103         2, 5, 5, 1, 4, 4, 4, 1, 2, 4, 2, 1, 4, 4, 4, 1,\r
104         2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,\r
105         2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 3, 1, 1, 4, 6, 1,\r
106         2, 6, 1, 1, 3, 3, 5, 1, 2, 2, 2, 1, 4, 4, 6, 1,\r
107         2, 5, 5, 1, 1, 4, 6, 1, 2, 4, 4, 1, 1, 4, 6, 1 };\r
108 \r
109 // Private function prototypes\r
110 \r
111 static uint16 RdMemW(uint16);\r
112 \r
113 //\r
114 // Read a uint16 out of 65C02 memory (big endian format)\r
115 //\r
116 static uint16 RdMemW(uint16 address)\r
117 {\r
118         return (uint16)(regs.RdMem(address + 1) << 8) | regs.RdMem(address + 0);\r
119 }\r
120 \r
121 \r
122 //\r
123 // 65C02 OPCODE IMPLEMENTATION\r
124 //\r
125 // NOTE: Lots of macros are used here to save a LOT of typing. Also\r
126 //       helps speed the debugging process. :-) Because of this, combining\r
127 //       certain lines may look like a good idea but would end in disaster.\r
128 //       You have been warned! ;-)\r
129 //\r
130 \r
131 /*\r
132 Mnemonic        Addressing mode Form            Opcode  Size    Timing\r
133 \r
134 ADC                     Immediate               ADC #Oper       69              2               2\r
135                         Zero Page               ADC Zpg         65              2               3\r
136                         Zero Page,X             ADC Zpg,X       75              2               4\r
137                         Absolute                ADC Abs         6D              3               4\r
138                         Absolute,X              ADC Abs,X       7D              3               4\r
139                         Absolute,Y              ADC Abs,Y       79              3               4\r
140                         (Zero Page,X)   ADC (Zpg,X)     61              2               6\r
141                         (Zero Page),Y   ADC (Zpg),Y     71              2               5\r
142                         (Zero Page)             ADC (Zpg)       72              2               5\r
143 */\r
144 \r
145 // ADC opcodes\r
146 \r
147 //This is non-optimal, but it works--optimize later. :-)\r
148 #define OP_ADC_HANDLER(m) \\r
149         uint16 sum = (uint16)regs.a + (m) + (uint16)(regs.cc & FLAG_C); \\r
150 \\r
151         if (regs.cc & FLAG_D) \\r
152         { \\r
153                 if ((sum & 0x0F) > 0x09) \\r
154                         sum += 0x06; \\r
155 \\r
156                 if ((sum & 0xF0) > 0x90) \\r
157                         sum += 0x60; \\r
158         } \\r
159 \\r
160         regs.cc = (regs.cc & ~FLAG_C) | (sum >> 8); \\r
161         regs.cc = (~(regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \\r
162         regs.a = sum & 0xFF; \\r
163         SET_ZN(regs.a)\r
164 \r
165 //OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V);\r
166 \r
167 static void Op69(void)                                                  // ADC #\r
168 {\r
169         uint16 m = READ_IMM;\r
170         OP_ADC_HANDLER(m);\r
171 }\r
172 \r
173 static void Op65(void)                                                  // ADC ZP\r
174 {\r
175         uint16 m = READ_ZP;\r
176         OP_ADC_HANDLER(m);\r
177 }\r
178 \r
179 static void Op75(void)                                                  // ADC ZP, X\r
180 {\r
181         uint16 m = READ_ZP_X;\r
182         OP_ADC_HANDLER(m);\r
183 }\r
184 \r
185 static void Op6D(void)                                                  // ADC ABS\r
186 {\r
187         uint16 m = READ_ABS;\r
188         OP_ADC_HANDLER(m);\r
189 }\r
190 \r
191 static void Op7D(void)                                                  // ADC ABS, X\r
192 {\r
193         uint16 m = READ_ABS_X;\r
194         OP_ADC_HANDLER(m);\r
195 }\r
196 \r
197 static void Op79(void)                                                  // ADC ABS, Y\r
198 {\r
199         uint16 m = READ_ABS_Y;\r
200         OP_ADC_HANDLER(m);\r
201 }\r
202 \r
203 static void Op61(void)                                                  // ADC (ZP, X)\r
204 {\r
205         uint16 m = READ_IND_ZP_X;\r
206         OP_ADC_HANDLER(m);\r
207 }\r
208 \r
209 static void Op71(void)                                                  // ADC (ZP), Y\r
210 {\r
211         uint16 m = READ_IND_ZP_Y;\r
212         OP_ADC_HANDLER(m);\r
213 }\r
214 \r
215 static void Op72(void)                                                  // ADC (ZP)\r
216 {\r
217         uint16 m = READ_IND_ZP;\r
218         OP_ADC_HANDLER(m);\r
219 }\r
220 \r
221 /*\r
222 AND     Immediate       AND #Oper       29      2       2\r
223 Zero Page               AND Zpg         25      2       3\r
224 Zero Page,X             AND Zpg,X       35      2       4\r
225 Absolute                AND Abs         2D      3       4\r
226 Absolute,X              AND Abs,X       3D      3       4\r
227 Absolute,Y              AND Abs,Y       39      3       4\r
228 (Zero Page,X)   AND (Zpg,X)     21      2       6\r
229 (Zero Page),Y   AND (Zpg),Y     31      2       5\r
230 (Zero Page)             AND (Zpg)       32      2       5\r
231 */\r
232 \r
233 // AND opcodes\r
234 \r
235 #define OP_AND_HANDLER(m) \\r
236         regs.a &= m; \\r
237         SET_ZN(regs.a)\r
238 \r
239 static void Op29(void)                                                  // AND #\r
240 {\r
241         uint8 m = READ_IMM;\r
242         OP_AND_HANDLER(m);\r
243 }\r
244 \r
245 static void Op25(void)                                                  // AND ZP\r
246 {\r
247         uint8 m = READ_ZP;\r
248         OP_AND_HANDLER(m);\r
249 }\r
250 \r
251 static void Op35(void)                                                  // AND ZP, X\r
252 {\r
253         uint8 m = READ_ZP_X;\r
254         OP_AND_HANDLER(m);\r
255 }\r
256 \r
257 static void Op2D(void)                                                  // AND ABS\r
258 {\r
259         uint8 m = READ_ABS;\r
260         OP_AND_HANDLER(m);\r
261 }\r
262 \r
263 static void Op3D(void)                                                  // AND ABS, X\r
264 {\r
265         uint8 m = READ_ABS_X;\r
266         OP_AND_HANDLER(m);\r
267 }\r
268 \r
269 static void Op39(void)                                                  // AND ABS, Y\r
270 {\r
271         uint8 m = READ_ABS_Y;\r
272         OP_AND_HANDLER(m);\r
273 }\r
274 \r
275 static void Op21(void)                                                  // AND (ZP, X)\r
276 {\r
277         uint8 m = READ_IND_ZP_X;\r
278         OP_AND_HANDLER(m);\r
279 }\r
280 \r
281 static void Op31(void)                                                  // AND (ZP), Y\r
282 {\r
283         uint8 m = READ_IND_ZP_Y;\r
284         OP_AND_HANDLER(m);\r
285 }\r
286 \r
287 static void Op32(void)                                                  // AND (ZP)\r
288 {\r
289         uint8 m = READ_IND_ZP;\r
290         OP_AND_HANDLER(m);\r
291 }\r
292 \r
293 /*\r
294 ASL     Accumulator     ASL A           0A      1       2\r
295 Zero Page               ASL Zpg         06      2       5\r
296 Zero Page,X             ASL Zpg,X       16      2       6\r
297 Absolute                ASL Abs         0E      3       6\r
298 Absolute,X              ASL Abs,X       1E      3       7\r
299 */\r
300 \r
301 /*static void Op78(void)  // LSL ABS\r
302 {\r
303         uint8 tmp;  uint16 addr;\r
304         addr = FetchW();\r
305         tmp = regs.RdMem(addr);\r
306         (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry\r
307         tmp <<= 1;\r
308         regs.WrMem(addr, tmp);\r
309         (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag\r
310         (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag\r
311 }*/\r
312 \r
313 // ASL opcodes\r
314 \r
315 #define OP_ASL_HANDLER(m) \\r
316         regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \\r
317         (m) <<= 1; \\r
318         SET_ZN((m))\r
319 \r
320 static void Op0A(void)                                                  // ASL A\r
321 {\r
322         OP_ASL_HANDLER(regs.a);\r
323 }\r
324 \r
325 static void Op06(void)                                                  // ASL ZP\r
326 {\r
327         uint8 m;\r
328         READ_ZP_WB(m);\r
329         OP_ASL_HANDLER(m);\r
330         WRITE_BACK(m);\r
331 }\r
332 \r
333 static void Op16(void)                                                  // ASL ZP, X\r
334 {\r
335         uint8 m;\r
336         READ_ZP_X_WB(m);\r
337         OP_ASL_HANDLER(m);\r
338         WRITE_BACK(m);\r
339 }\r
340 \r
341 static void Op0E(void)                                                  // ASL ABS\r
342 {\r
343         uint8 m;\r
344         READ_ABS_WB(m);\r
345         OP_ASL_HANDLER(m);\r
346         WRITE_BACK(m);\r
347 }\r
348 \r
349 static void Op1E(void)                                                  // ASL ABS, X\r
350 {\r
351         uint8 m;\r
352         READ_ABS_X_WB(m);\r
353         OP_ASL_HANDLER(m);\r
354         WRITE_BACK(m);\r
355 }\r
356 \r
357 /*\r
358 BBR0    Relative        BBR0 Oper       0F      2       2\r
359 BBR1    Relative        BBR1 Oper       1F      2       2\r
360 BBR2    Relative        BBR2 Oper       2F      2       2\r
361 BBR3    Relative        BBR3 Oper       3F      2       2\r
362 BBR4    Relative        BBR4 Oper       4F      2       2\r
363 BBR5    Relative        BBR5 Oper       5F      2       2\r
364 BBR6    Relative        BBR6 Oper       6F      2       2\r
365 BBR7    Relative        BBR7 Oper       7F      2       2\r
366 BBS0    Relative        BBS0 Oper       8F      2       2\r
367 BBS1    Relative        BBS1 Oper       9F      2       2\r
368 BBS2    Relative        BBS2 Oper       AF      2       2\r
369 BBS3    Relative        BBS3 Oper       BF      2       2\r
370 BBS4    Relative        BBS4 Oper       CF      2       2\r
371 BBS5    Relative        BBS5 Oper       DF      2       2\r
372 BBS6    Relative        BBS6 Oper       EF      2       2\r
373 BBS7    Relative        BBS7 Oper       FF      2       2\r
374 */\r
375 \r
376 // BBR/Sn opcodes\r
377 \r
378 static void Op0F(void)                                                  // BBR0\r
379 {\r
380         int16 m = (int16)(int8)READ_IMM;\r
381 \r
382         if (!(regs.a & 0x01))\r
383                 regs.pc += m;\r
384 }\r
385 \r
386 static void Op1F(void)                                                  // BBR1\r
387 {\r
388         int16 m = (int16)(int8)READ_IMM;\r
389 \r
390         if (!(regs.a & 0x02))\r
391                 regs.pc += m;\r
392 }\r
393 \r
394 static void Op2F(void)                                                  // BBR2\r
395 {\r
396         int16 m = (int16)(int8)READ_IMM;\r
397 \r
398         if (!(regs.a & 0x04))\r
399                 regs.pc += m;\r
400 }\r
401 \r
402 static void Op3F(void)                                                  // BBR3\r
403 {\r
404         int16 m = (int16)(int8)READ_IMM;\r
405 \r
406         if (!(regs.a & 0x08))\r
407                 regs.pc += m;\r
408 }\r
409 \r
410 static void Op4F(void)                                                  // BBR4\r
411 {\r
412         int16 m = (int16)(int8)READ_IMM;\r
413 \r
414         if (!(regs.a & 0x10))\r
415                 regs.pc += m;\r
416 }\r
417 \r
418 static void Op5F(void)                                                  // BBR5\r
419 {\r
420         int16 m = (int16)(int8)READ_IMM;\r
421 \r
422         if (!(regs.a & 0x20))\r
423                 regs.pc += m;\r
424 }\r
425 \r
426 static void Op6F(void)                                                  // BBR6\r
427 {\r
428         int16 m = (int16)(int8)READ_IMM;\r
429 \r
430         if (!(regs.a & 0x40))\r
431                 regs.pc += m;\r
432 }\r
433 \r
434 static void Op7F(void)                                                  // BBR7\r
435 {\r
436         int16 m = (int16)(int8)READ_IMM;\r
437 \r
438         if (!(regs.a & 0x80))\r
439                 regs.pc += m;\r
440 }\r
441 \r
442 static void Op8F(void)                                                  // BBS0\r
443 {\r
444         int16 m = (int16)(int8)READ_IMM;\r
445 \r
446         if (regs.a & 0x01)\r
447                 regs.pc += m;\r
448 }\r
449 \r
450 static void Op9F(void)                                                  // BBS1\r
451 {\r
452         int16 m = (int16)(int8)READ_IMM;\r
453 \r
454         if (regs.a & 0x02)\r
455                 regs.pc += m;\r
456 }\r
457 \r
458 static void OpAF(void)                                                  // BBS2\r
459 {\r
460         int16 m = (int16)(int8)READ_IMM;\r
461 \r
462         if (regs.a & 0x04)\r
463                 regs.pc += m;\r
464 }\r
465 \r
466 static void OpBF(void)                                                  // BBS3\r
467 {\r
468         int16 m = (int16)(int8)READ_IMM;\r
469 \r
470         if (regs.a & 0x08)\r
471                 regs.pc += m;\r
472 }\r
473 \r
474 static void OpCF(void)                                                  // BBS4\r
475 {\r
476         int16 m = (int16)(int8)READ_IMM;\r
477 \r
478         if (regs.a & 0x10)\r
479                 regs.pc += m;\r
480 }\r
481 \r
482 static void OpDF(void)                                                  // BBS5\r
483 {\r
484         int16 m = (int16)(int8)READ_IMM;\r
485 \r
486         if (regs.a & 0x20)\r
487                 regs.pc += m;\r
488 }\r
489 \r
490 static void OpEF(void)                                                  // BBS6\r
491 {\r
492         int16 m = (int16)(int8)READ_IMM;\r
493 \r
494         if (regs.a & 0x40)\r
495                 regs.pc += m;\r
496 }\r
497 \r
498 static void OpFF(void)                                                  // BBS7\r
499 {\r
500         int16 m = (int16)(int8)READ_IMM;\r
501 \r
502         if (regs.a & 0x80)\r
503                 regs.pc += m;\r
504 }\r
505 \r
506 /*\r
507 BCC     Relative        BCC Oper        90      2       2\r
508 BCS     Relative        BCS Oper        B0      2       2\r
509 BEQ     Relative        BEQ Oper        F0      2       2\r
510 */\r
511 \r
512 // Branch opcodes\r
513 \r
514 static void Op90(void)                                                  // BCC\r
515 {\r
516         int16 m = (int16)(int8)READ_IMM;\r
517 \r
518         if (!(regs.cc & FLAG_C))\r
519                 regs.pc += m;\r
520 }\r
521 \r
522 static void OpB0(void)                                                  // BCS\r
523 {\r
524         int16 m = (int16)(int8)READ_IMM;\r
525 \r
526         if (regs.cc & FLAG_C)\r
527                 regs.pc += m;\r
528 }\r
529 \r
530 static void OpF0(void)                                                  // BEQ\r
531 {\r
532         int16 m = (int16)(int8)READ_IMM;\r
533 \r
534         if (regs.cc & FLAG_Z)\r
535                 regs.pc += m;\r
536 }\r
537 \r
538 /*\r
539 BIT     Immediate       BIT #Oper       89      2       2\r
540 Zero Page               BIT Zpg         24      2       3\r
541 Zero Page,X             BIT Zpg,X       34      2       4\r
542 Absolute                BIT Abs         2C      3       4\r
543 Absolute,X              BIT Abs,X       3C      3       4\r
544 */\r
545 \r
546 // BIT opcodes\r
547 \r
548 /* 1. The BIT instruction copies bit 6 to the V flag, and bit 7 to the N flag (except in immediate\r
549       addressing mode where V & N are untouched.) The accumulator and the operand are ANDed and the\r
550       Z flag is set appropriately. */\r
551 \r
552 #define OP_BIT_HANDLER(m) \\r
553         int8 result = regs.a & (m); \\r
554         regs.cc &= ~(FLAG_N | FLAG_V); \\r
555         regs.cc |= ((m) & 0xC0); \\r
556         SET_Z(result)\r
557 \r
558 static void Op89(void)                                                  // BIT #\r
559 {\r
560         int8 m = READ_IMM;\r
561         int8 result = regs.a & m;\r
562         SET_Z(result);\r
563 }\r
564 \r
565 static void Op24(void)                                                  // BIT ZP\r
566 {\r
567         int8 m = READ_ZP;\r
568         OP_BIT_HANDLER(m);\r
569 }\r
570 \r
571 static void Op34(void)                                                  // BIT ZP, X\r
572 {\r
573         uint8 m = READ_ZP_X;\r
574         OP_BIT_HANDLER(m);\r
575 }\r
576 \r
577 static void Op2C(void)                                                  // BIT ABS\r
578 {\r
579         uint8 m = READ_ABS;\r
580         OP_BIT_HANDLER(m);\r
581 }\r
582 \r
583 static void Op3C(void)                                                  // BIT ABS, X\r
584 {\r
585         uint8 m = READ_ABS_X;\r
586         OP_BIT_HANDLER(m);\r
587 }\r
588 \r
589 /*\r
590 BMI     Relative        BMI Oper        30      2       2\r
591 BNE     Relative        BNE Oper        D0      2       2\r
592 BPL     Relative        BPL Oper        10      2       2\r
593 BRA     Relative        BRA Oper        80      2       3\r
594 */\r
595 \r
596 // More branch opcodes\r
597 \r
598 static void Op30(void)                                                  // BMI\r
599 {\r
600         int16 m = (int16)(int8)READ_IMM;\r
601 \r
602         if (regs.cc & FLAG_N)\r
603                 regs.pc += m;\r
604 }\r
605 \r
606 static void OpD0(void)                                                  // BNE\r
607 {\r
608         int16 m = (int16)(int8)READ_IMM;\r
609 \r
610         if (!(regs.cc & FLAG_Z))\r
611                 regs.pc += m;\r
612 }\r
613 \r
614 static void Op10(void)                                                  // BPL\r
615 {\r
616         int16 m = (int16)(int8)READ_IMM;\r
617 \r
618         if (!(regs.cc & FLAG_N))\r
619                 regs.pc += m;\r
620 }\r
621 \r
622 static void Op80(void)                                                  // BRA\r
623 {\r
624         int16 m = (int16)(int8)READ_IMM;\r
625         regs.pc += m;\r
626 }\r
627 \r
628 /*\r
629 BRK     Implied         BRK                     00      1       7\r
630 */\r
631 \r
632 static void Op00(void)                                                  // BRK\r
633 {\r
634         regs.cc |= FLAG_B;                                                      // Set B\r
635         regs.pc++;                                                                      // RTI comes back to the instruction one byte after the BRK\r
636         regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);   // Save PC and CC\r
637         regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);\r
638         regs.WrMem(0x0100 + regs.sp--, regs.cc);\r
639         regs.cc |= FLAG_I;                                                      // Set I\r
640         regs.cc &= ~FLAG_D;                                                     // & clear D\r
641         regs.pc = RdMemW(0xFFFE);                                       // Grab the IRQ vector & go...\r
642 }\r
643 \r
644 /*\r
645 BVC     Relative        BVC Oper        50      2       2\r
646 BVS     Relative        BVS Oper        70      2       2\r
647 */\r
648 \r
649 // Even more branch opcodes\r
650 \r
651 static void Op50(void)                                                  // BVC\r
652 {\r
653         int16 m = (int16)(int8)READ_IMM;\r
654 \r
655         if (!(regs.cc & FLAG_V))\r
656                 regs.pc += m;\r
657 }\r
658 \r
659 static void Op70(void)                                                  // BVS\r
660 {\r
661         int16 m = (int16)(int8)READ_IMM;\r
662 \r
663         if (regs.cc & FLAG_V)\r
664                 regs.pc += m;\r
665 }\r
666 \r
667 /*\r
668 CLC     Implied         CLC                     18      1       2\r
669 */\r
670 \r
671 static void Op18(void)                                                  // CLC\r
672 {\r
673         regs.cc &= ~FLAG_C;\r
674 }\r
675 \r
676 /*\r
677 CLD     Implied         CLD                     D8      1       2\r
678 */\r
679 \r
680 static void OpD8(void)                                                  // CLD\r
681 {\r
682         regs.cc &= ~FLAG_D;\r
683 }\r
684 \r
685 /*\r
686 CLI     Implied         CLI                     58      1       2\r
687 */\r
688 \r
689 static void Op58(void)                                                  // CLI\r
690 {\r
691         regs.cc &= ~FLAG_I;\r
692 }\r
693 \r
694 /*\r
695 CLV     Implied         CLV                     B8      1       2\r
696 */\r
697 \r
698 static void OpB8(void)                                                  // CLV\r
699 {\r
700         regs.cc &= ~FLAG_V;\r
701 }\r
702 \r
703 /*\r
704 CMP     Immediate       CMP #Oper       C9      2       2\r
705 Zero Page               CMP Zpg         C5      2       3\r
706 Zero Page,X             CMP Zpg         D5      2       4\r
707 Absolute                CMP Abs         CD      3       4\r
708 Absolute,X              CMP Abs,X       DD      3       4\r
709 Absolute,Y              CMP Abs,Y       D9      3       4\r
710 (Zero Page,X)   CMP (Zpg,X)     C1      2       6\r
711 (Zero Page),Y   CMP (Zpg),Y     D1      2       5\r
712 (Zero Page)             CMP (Zpg)       D2      2       5\r
713 */\r
714 \r
715 // CMP opcodes\r
716 \r
717 /*\r
718 Here's the latest: The CMP is NOT generating the Z flag when A=$C0!\r
719 \r
720 FABA: A0 07          LDY   #$07                 [PC=FABC, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07]\r
721 FABC: C6 01          DEC   $01          [PC=FABE, SP=01FF, CC=N--B-I--, A=00, X=00, Y=07]\r
722 FABE: A5 01          LDA   $01          [PC=FAC0, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]\r
723 FAC0: C9 C0          CMP   #$C0                 [PC=FAC2, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]\r
724 FAC2: F0 D7          BEQ   $FA9B                [PC=FAC4, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]\r
725 FAC4: 8D F8 07       STA   $07F8                [PC=FAC7, SP=01FF, CC=N--B-I--, A=C0, X=00, Y=07]\r
726 FAC7: B1 00          LDA   ($00),Y\r
727 *** Read at I/O address C007\r
728                 [PC=FAC9, SP=01FF, CC=---B-IZ-, A=00, X=00, Y=07]\r
729 FAC9: D9 01 FB       CMP   $FB01,Y              [PC=FACC, SP=01FF, CC=---B-I--, A=00, X=00, Y=07]\r
730 FACC: D0 EC          BNE   $FABA                [PC=FABA, SP=01FF, CC=---B-I--, A=00, X=00, Y=07]\r
731 \r
732 Should be fixed now... (was adding instead of subtracting!)\r
733 \r
734 Small problem here... First two should set the carry while the last one should clear it. !!! FIX !!! [DONE]\r
735 \r
736 FDF0: C9 A0          CMP   #$A0                 [PC=FDF2, SP=01F1, CC=---B-IZ-, A=A0, X=02, Y=03]\r
737 FD7E: C9 E0          CMP   #$E0                 [PC=FD80, SP=01F4, CC=N--B-I--, A=A0, X=02, Y=03]\r
738 FD38: C9 9B          CMP   #$9B                 [PC=FD3A, SP=01F2, CC=---B-I-C, A=A0, X=02, Y=03]\r
739 \r
740 Compare sets flags as if a subtraction had been carried out. If the value in the accumulator is equal or greater than the compared value, the Carry will be set. The equal (Z) and sign (S) flags will be set based on equality or lack thereof and the sign (i.e. A>=$80) of the accumulator.\r
741 */\r
742 \r
743 #define OP_CMP_HANDLER(m) \\r
744         uint8 result = regs.a - (m); \\r
745         SET_ZNC_CMP(m, regs.a, result)\r
746 \r
747 static void OpC9(void)                                                  // CMP #\r
748 {\r
749         uint8 m = READ_IMM;\r
750         OP_CMP_HANDLER(m);\r
751 }\r
752 \r
753 static void OpC5(void)                                                  // CMP ZP\r
754 {\r
755         uint8 m = READ_ZP;\r
756         OP_CMP_HANDLER(m);\r
757 }\r
758 \r
759 static void OpD5(void)                                                  // CMP ZP, X\r
760 {\r
761         uint8 m = READ_ZP_X;\r
762         OP_CMP_HANDLER(m);\r
763 }\r
764 \r
765 static void OpCD(void)                                                  // CMP ABS\r
766 {\r
767         uint8 m = READ_ABS;\r
768         OP_CMP_HANDLER(m);\r
769 }\r
770 \r
771 static void OpDD(void)                                                  // CMP ABS, X\r
772 {\r
773         uint8 m = READ_ABS_X;\r
774         OP_CMP_HANDLER(m);\r
775 }\r
776 \r
777 static void OpD9(void)                                                  // CMP ABS, Y\r
778 {\r
779         uint8 m = READ_ABS_Y;\r
780         OP_CMP_HANDLER(m);\r
781 }\r
782 \r
783 static void OpC1(void)                                                  // CMP (ZP, X)\r
784 {\r
785         uint8 m = READ_IND_ZP_X;\r
786         OP_CMP_HANDLER(m);\r
787 }\r
788 \r
789 static void OpD1(void)                                                  // CMP (ZP), Y\r
790 {\r
791         uint8 m = READ_IND_ZP_Y;\r
792         OP_CMP_HANDLER(m);\r
793 }\r
794 \r
795 static void OpD2(void)                                                  // CMP (ZP)\r
796 {\r
797         uint8 m = READ_IND_ZP;\r
798         OP_CMP_HANDLER(m);\r
799 }\r
800 \r
801 /*\r
802 CPX     Immediate       CPX #Oper       E0      2       2\r
803 Zero Page               CPX Zpg         E4      2       3\r
804 Absolute                CPX Abs         EC      3       4\r
805 */\r
806 \r
807 // CPX opcodes\r
808 \r
809 #define OP_CPX_HANDLER(m) \\r
810         uint8 result = regs.x - (m); \\r
811         SET_ZNC_CMP(m, regs.x, result)\r
812 \r
813 static void OpE0(void)                                                  // CPX #\r
814 {\r
815         uint8 m = READ_IMM;\r
816         OP_CPX_HANDLER(m);\r
817 }\r
818 \r
819 static void OpE4(void)                                                  // CPX ZP\r
820 {\r
821         uint8 m = READ_ZP;\r
822         OP_CPX_HANDLER(m);\r
823 }\r
824 \r
825 static void OpEC(void)                                                  // CPX ABS\r
826 {\r
827         uint8 m = READ_ABS;\r
828         OP_CPX_HANDLER(m);\r
829 }\r
830 \r
831 /*\r
832 CPY     Immediate       CPY #Oper       C0      2       2\r
833 Zero Page               CPY Zpg         C4      2       3\r
834 Absolute                CPY Abs         CC      3       4\r
835 */\r
836 \r
837 // CPY opcodes\r
838 \r
839 #define OP_CPY_HANDLER(m) \\r
840         uint8 result = regs.y - (m); \\r
841         SET_ZNC_CMP(m, regs.y, result)\r
842 \r
843 static void OpC0(void)                                                  // CPY #\r
844 {\r
845         uint8 m = READ_IMM;\r
846         OP_CPY_HANDLER(m);\r
847 }\r
848 \r
849 static void OpC4(void)                                                  // CPY ZP\r
850 {\r
851         uint8 m = READ_ZP;\r
852         OP_CPY_HANDLER(m);\r
853 }\r
854 \r
855 static void OpCC(void)                                                  // CPY ABS\r
856 {\r
857         uint8 m = READ_ABS;\r
858         OP_CPY_HANDLER(m);\r
859 }\r
860 \r
861 /*\r
862 DEA     Accumulator     DEA                     3A      1       2\r
863 */\r
864 \r
865 static void Op3A(void)                                                  // DEA\r
866 {\r
867         regs.a--;\r
868         SET_ZN(regs.a);\r
869 }\r
870 \r
871 /*\r
872 DEC     Zero Page       DEC Zpg         C6      2       5\r
873 Zero Page,X             DEC Zpg,X       D6      2       6\r
874 Absolute                DEC Abs         CE      3       6\r
875 Absolute,X              DEC Abs,X       DE      3       7\r
876 */\r
877 \r
878 // DEC opcodes\r
879 \r
880 #define OP_DEC_HANDLER(m) \\r
881         m--; \\r
882         SET_ZN(m)\r
883 \r
884 static void OpC6(void)                                                  // DEC ZP\r
885 {\r
886         uint8 m;\r
887         READ_ZP_WB(m);\r
888         OP_DEC_HANDLER(m);\r
889         WRITE_BACK(m);\r
890 }\r
891 \r
892 static void OpD6(void)                                                  // DEC ZP, X\r
893 {\r
894         uint8 m;\r
895         READ_ZP_X_WB(m);\r
896         OP_DEC_HANDLER(m);\r
897         WRITE_BACK(m);\r
898 }\r
899 \r
900 static void OpCE(void)                                                  // DEC ABS\r
901 {\r
902         uint8 m;\r
903         READ_ABS_WB(m);\r
904         OP_DEC_HANDLER(m);\r
905         WRITE_BACK(m);\r
906 }\r
907 \r
908 static void OpDE(void)                                                  // DEC ABS, X\r
909 {\r
910         uint8 m;\r
911         READ_ABS_X_WB(m);\r
912         OP_DEC_HANDLER(m);\r
913         WRITE_BACK(m);\r
914 }\r
915 \r
916 /*\r
917 Here's one problem: DEX is setting the N flag!\r
918 \r
919 D3EE: A2 09          LDX   #$09                 [PC=D3F0, SP=01F7, CC=---B-I-C, A=01, X=09, Y=08]\r
920 D3F0: 98             TYA                [PC=D3F1, SP=01F7, CC=N--B-I-C, A=08, X=09, Y=08]\r
921 D3F1: 48             PHA                [PC=D3F2, SP=01F6, CC=N--B-I-C, A=08, X=09, Y=08]\r
922 D3F2: B5 93          LDA   $93,X                [PC=D3F4, SP=01F6, CC=---B-IZC, A=00, X=09, Y=08]\r
923 D3F4: CA             DEX                [PC=D3F5, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]\r
924 D3F5: 10 FA          BPL   $D3F1                [PC=D3F7, SP=01F6, CC=N--B-I-C, A=00, X=08, Y=08]\r
925 D3F7: 20 84 E4       JSR   $E484                [PC=E484, SP=01F4, CC=N--B-I-C, A=00, X=08, Y=08]\r
926 \r
927 should be fixed now...\r
928 */\r
929 \r
930 /*\r
931 DEX     Implied         DEX                     CA      1       2\r
932 */\r
933 \r
934 static void OpCA(void)                                                  // DEX\r
935 {\r
936         regs.x--;\r
937         SET_ZN(regs.x);\r
938 }\r
939 \r
940 /*\r
941 DEY     Implied         DEY                     88      1       2\r
942 */\r
943 \r
944 static void Op88(void)                                                  // DEY\r
945 {\r
946         regs.y--;\r
947         SET_ZN(regs.y);\r
948 }\r
949 \r
950 /*\r
951 EOR     Immediate       EOR #Oper       49      2       2\r
952 Zero Page               EOR Zpg         45      2       3\r
953 Zero Page,X             EOR Zpg,X       55      2       4\r
954 Absolute                EOR Abs         4D      3       4\r
955 Absolute,X              EOR Abs,X       5D      3       4\r
956 Absolute,Y              EOR Abs,Y       59      3       4\r
957 (Zero Page,X)   EOR (Zpg,X)     41      2       6\r
958 (Zero Page),Y   EOR (Zpg),Y     51      2       5\r
959 (Zero Page)             EOR (Zpg)       52      2       5\r
960 */\r
961 \r
962 // EOR opcodes\r
963 \r
964 #define OP_EOR_HANDLER(m) \\r
965         regs.a ^= m; \\r
966         SET_ZN(regs.a)\r
967 \r
968 static void Op49(void)                                                  // EOR #\r
969 {\r
970         uint8 m = READ_IMM;\r
971         OP_EOR_HANDLER(m);\r
972 }\r
973 \r
974 static void Op45(void)                                                  // EOR ZP\r
975 {\r
976         uint8 m = READ_ZP;\r
977         OP_EOR_HANDLER(m);\r
978 }\r
979 \r
980 static void Op55(void)                                                  // EOR ZP, X\r
981 {\r
982         uint8 m = READ_ZP_X;\r
983         OP_EOR_HANDLER(m);\r
984 }\r
985 \r
986 static void Op4D(void)                                                  // EOR ABS\r
987 {\r
988         uint8 m = READ_ABS;\r
989         OP_EOR_HANDLER(m);\r
990 }\r
991 \r
992 static void Op5D(void)                                                  // EOR ABS, X\r
993 {\r
994         uint8 m = READ_ABS_X;\r
995         OP_EOR_HANDLER(m);\r
996 }\r
997 \r
998 static void Op59(void)                                                  // EOR ABS, Y\r
999 {\r
1000         uint8 m = READ_ABS_Y;\r
1001         OP_EOR_HANDLER(m);\r
1002 }\r
1003 \r
1004 static void Op41(void)                                                  // EOR (ZP, X)\r
1005 {\r
1006         uint8 m = READ_IND_ZP_X;\r
1007         OP_EOR_HANDLER(m);\r
1008 }\r
1009 \r
1010 static void Op51(void)                                                  // EOR (ZP), Y\r
1011 {\r
1012         uint8 m = READ_IND_ZP_Y;\r
1013         OP_EOR_HANDLER(m);\r
1014 }\r
1015 \r
1016 static void Op52(void)                                                  // EOR (ZP)\r
1017 {\r
1018         uint8 m = READ_IND_ZP;\r
1019         OP_EOR_HANDLER(m);\r
1020 }\r
1021 \r
1022 /*\r
1023 INA     Accumulator     INA                     1A      1       2\r
1024 */\r
1025 \r
1026 static void Op1A(void)                                                  // INA\r
1027 {\r
1028         regs.a++;\r
1029         SET_ZN(regs.a);\r
1030 }\r
1031 \r
1032 /*\r
1033 INC     Zero Page       INC Zpg         E6      2       5\r
1034 Zero Page,X             INC Zpg,X       F6      2       6\r
1035 Absolute                INC Abs         EE      3       6\r
1036 Absolute,X              INC Abs,X       FE      3       7\r
1037 */\r
1038 \r
1039 // INC opcodes\r
1040 \r
1041 #define OP_INC_HANDLER(m) \\r
1042         m++; \\r
1043         SET_ZN(m)\r
1044 \r
1045 static void OpE6(void)                                                  // INC ZP\r
1046 {\r
1047         uint8 m;\r
1048         READ_ZP_WB(m);\r
1049         OP_INC_HANDLER(m);\r
1050         WRITE_BACK(m);\r
1051 }\r
1052 \r
1053 static void OpF6(void)                                                  // INC ZP, X\r
1054 {\r
1055         uint8 m;\r
1056         READ_ZP_X_WB(m);\r
1057         OP_INC_HANDLER(m);\r
1058         WRITE_BACK(m);\r
1059 }\r
1060 \r
1061 static void OpEE(void)                                                  // INC ABS\r
1062 {\r
1063         uint8 m;\r
1064         READ_ABS_WB(m);\r
1065         OP_INC_HANDLER(m);\r
1066         WRITE_BACK(m);\r
1067 }\r
1068 \r
1069 static void OpFE(void)                                                  // INC ABS, X\r
1070 {\r
1071         uint8 m;\r
1072         READ_ABS_X_WB(m);\r
1073         OP_INC_HANDLER(m);\r
1074         WRITE_BACK(m);\r
1075 }\r
1076 \r
1077 /*\r
1078 INX     Implied         INX                     E8      1       2\r
1079 */\r
1080 \r
1081 static void OpE8(void)                                                  // INX\r
1082 {\r
1083         regs.x++;\r
1084         SET_ZN(regs.x);\r
1085 }\r
1086 \r
1087 /*\r
1088 INY     Implied         INY                     C8      1       2\r
1089 */\r
1090 \r
1091 static void OpC8(void)                                                  // INY\r
1092 {\r
1093         regs.y++;\r
1094         SET_ZN(regs.y);\r
1095 }\r
1096 \r
1097 /*\r
1098 JMP     Absolute        JMP Abs         4C      3       3\r
1099 (Absolute)              JMP (Abs)       6C      3       5\r
1100 (Absolute,X)    JMP (Abs,X)     7C      3       6\r
1101 */\r
1102 \r
1103 // JMP opcodes\r
1104 \r
1105 static void Op4C(void)                                                  // JMP ABS\r
1106 {\r
1107         regs.pc = RdMemW(regs.pc);\r
1108 }\r
1109 \r
1110 static void Op6C(void)                                                  // JMP (ABS)\r
1111 {\r
1112 //      uint16 addr = RdMemW(regs.pc);\r
1113 //#ifdef __DEBUG__\r
1114 //WriteLog("\n[JMP ABS]: addr fetched = %04X, bytes at %04X = %02X %02X (RdMemw=%04X)\n",\r
1115 //      addr, addr, regs.RdMem(addr), regs.RdMem(addr+1), RdMemW(addr));\r
1116 //#endif\r
1117 //      addr = RdMemW(addr);\r
1118         regs.pc = RdMemW(RdMemW(regs.pc));\r
1119 }\r
1120 \r
1121 static void Op7C(void)                                                  // JMP (ABS, X)\r
1122 {\r
1123         regs.pc = RdMemW(RdMemW(regs.pc) + regs.x);\r
1124 }\r
1125 \r
1126 /*\r
1127 JSR     Absolute        JSR Abs         20      3       6\r
1128 */\r
1129 \r
1130 //This is not jumping to the correct address... !!! FIX !!! [DONE]\r
1131 static void Op20(void)                                                  // JSR\r
1132 {\r
1133         uint16 addr = RdMemW(regs.pc);\r
1134         regs.pc++;                                                                      // Since it pushes return address - 1...\r
1135         regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);\r
1136         regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);\r
1137         regs.pc = addr;\r
1138 }\r
1139 \r
1140 /*\r
1141 LDA     Immediate       LDA #Oper       A9      2       2\r
1142 Zero Page               LDA Zpg         A5      2       3\r
1143 Zero Page,X             LDA Zpg,X       B5      2       4\r
1144 Absolute                LDA Abs         AD      3       4\r
1145 Absolute,X              LDA Abs,X       BD      3       4\r
1146 Absolute,Y              LDA Abs,Y       B9      3       4\r
1147 (Zero Page,X)   LDA (Zpg,X)     A1      2       6\r
1148 (Zero Page),Y   LDA (Zpg),Y     B1      2       5\r
1149 (Zero Page)             LDA (Zpg)       B2      2       5\r
1150 */\r
1151 \r
1152 // LDA opcodes\r
1153 \r
1154 #define OP_LDA_HANDLER(m) \\r
1155         regs.a = m; \\r
1156         SET_ZN(regs.a)\r
1157 \r
1158 static void OpA9(void)                                                  // LDA #\r
1159 {\r
1160         uint8 m = READ_IMM;\r
1161         OP_LDA_HANDLER(m);\r
1162 }\r
1163 \r
1164 static void OpA5(void)                                                  // LDA ZP\r
1165 {\r
1166         uint8 m = READ_ZP;\r
1167         OP_LDA_HANDLER(m);\r
1168 }\r
1169 \r
1170 static void OpB5(void)                                                  // LDA ZP, X\r
1171 {\r
1172         uint8 m = READ_ZP_X;\r
1173         OP_LDA_HANDLER(m);\r
1174 }\r
1175 \r
1176 static void OpAD(void)                                                  // LDA ABS\r
1177 {\r
1178         uint8 m = READ_ABS;\r
1179         OP_LDA_HANDLER(m);\r
1180 }\r
1181 \r
1182 static void OpBD(void)                                                  // LDA ABS, X\r
1183 {\r
1184         uint8 m = READ_ABS_X;\r
1185         OP_LDA_HANDLER(m);\r
1186 }\r
1187 \r
1188 static void OpB9(void)                                                  // LDA ABS, Y\r
1189 {\r
1190         uint8 m = READ_ABS_Y;\r
1191         OP_LDA_HANDLER(m);\r
1192 }\r
1193 \r
1194 static void OpA1(void)                                                  // LDA (ZP, X)\r
1195 {\r
1196         uint8 m = READ_IND_ZP_X;\r
1197         OP_LDA_HANDLER(m);\r
1198 }\r
1199 \r
1200 static void OpB1(void)                                                  // LDA (ZP), Y\r
1201 {\r
1202         uint8 m = READ_IND_ZP_Y;\r
1203         OP_LDA_HANDLER(m);\r
1204 }\r
1205 \r
1206 static void OpB2(void)                                                  // LDA (ZP)\r
1207 {\r
1208         uint8 m = READ_IND_ZP;\r
1209         OP_LDA_HANDLER(m);\r
1210 }\r
1211 \r
1212 /*\r
1213 LDX     Immediate       LDX #Oper       A2      2       2\r
1214 Zero Page               LDX Zpg         A6      2       3\r
1215 Zero Page,Y             LDX Zpg,Y       B6      2       4\r
1216 Absolute                LDX Abs         AE      3       4\r
1217 Absolute,Y              LDX Abs,Y       BE      3       4\r
1218 */\r
1219 \r
1220 // LDX opcodes\r
1221 \r
1222 #define OP_LDX_HANDLER(m) \\r
1223         regs.x = m; \\r
1224         SET_ZN(regs.x)\r
1225 \r
1226 static void OpA2(void)                                                  // LDX #\r
1227 {\r
1228         uint8 m = READ_IMM;\r
1229         OP_LDX_HANDLER(m);\r
1230 }\r
1231 \r
1232 static void OpA6(void)                                                  // LDX ZP\r
1233 {\r
1234         uint8 m = READ_ZP;\r
1235         OP_LDX_HANDLER(m);\r
1236 }\r
1237 \r
1238 static void OpB6(void)                                                  // LDX ZP, Y\r
1239 {\r
1240         uint8 m = READ_ZP_Y;\r
1241         OP_LDX_HANDLER(m);\r
1242 }\r
1243 \r
1244 static void OpAE(void)                                                  // LDX ABS\r
1245 {\r
1246         uint8 m = READ_ABS;\r
1247         OP_LDX_HANDLER(m);\r
1248 }\r
1249 \r
1250 static void OpBE(void)                                                  // LDX ABS, Y\r
1251 {\r
1252         uint8 m = READ_ABS_Y;\r
1253         OP_LDX_HANDLER(m);\r
1254 }\r
1255 \r
1256 /*\r
1257 LDY     Immediate       LDY #Oper       A0      2       2\r
1258 Zero Page               LDY Zpg         A4      2       3\r
1259 Zero Page,Y             LDY Zpg,X       B4      2       4\r
1260 Absolute                LDY Abs         AC      3       4\r
1261 Absolute,Y              LDY Abs,X       BC      3       4\r
1262 */\r
1263 \r
1264 // LDY opcodes\r
1265 \r
1266 #define OP_LDY_HANDLER(m) \\r
1267         regs.y = m; \\r
1268         SET_ZN(regs.y)\r
1269 \r
1270 static void OpA0(void)                                                  // LDY #\r
1271 {\r
1272         uint8 m = READ_IMM;\r
1273         OP_LDY_HANDLER(m);\r
1274 }\r
1275 \r
1276 static void OpA4(void)                                                  // LDY ZP\r
1277 {\r
1278         uint8 m = READ_ZP;\r
1279         OP_LDY_HANDLER(m);\r
1280 }\r
1281 \r
1282 static void OpB4(void)                                                  // LDY ZP, X\r
1283 {\r
1284         uint8 m = READ_ZP_X;\r
1285         OP_LDY_HANDLER(m);\r
1286 }\r
1287 \r
1288 static void OpAC(void)                                                  // LDY ABS\r
1289 {\r
1290         uint8 m = READ_ABS;\r
1291         OP_LDY_HANDLER(m);\r
1292 }\r
1293 \r
1294 static void OpBC(void)                                                  // LDY ABS, X\r
1295 {\r
1296         uint8 m = READ_ABS_X;\r
1297         OP_LDY_HANDLER(m);\r
1298 }\r
1299 \r
1300 /*\r
1301 LSR     Accumulator     LSR A           4A      1       2\r
1302 Zero Page               LSR Zpg         46      2       5\r
1303 Zero Page,X             LSR Zpg,X       56      2       6\r
1304 Absolute                LSR Abs         4E      3       6\r
1305 Absolute,X              LSR Abs,X       5E      3       7\r
1306 */\r
1307 \r
1308 // LSR opcodes\r
1309 \r
1310 #define OP_LSR_HANDLER(m) \\r
1311         regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \\r
1312         (m) >>= 1; \\r
1313         CLR_N; SET_Z((m))\r
1314 \r
1315 static void Op4A(void)                                                  // LSR A\r
1316 {\r
1317         OP_LSR_HANDLER(regs.a);\r
1318 }\r
1319 \r
1320 static void Op46(void)                                                  // LSR ZP\r
1321 {\r
1322         uint8 m;\r
1323         READ_ZP_WB(m);\r
1324         OP_LSR_HANDLER(m);\r
1325         WRITE_BACK(m);\r
1326 }\r
1327 \r
1328 static void Op56(void)                                                  // LSR ZP, X\r
1329 {\r
1330         uint8 m;\r
1331         READ_ZP_X_WB(m);\r
1332         OP_LSR_HANDLER(m);\r
1333         WRITE_BACK(m);\r
1334 }\r
1335 \r
1336 static void Op4E(void)                                                  // LSR ABS\r
1337 {\r
1338         uint8 m;\r
1339         READ_ABS_WB(m);\r
1340         OP_LSR_HANDLER(m);\r
1341         WRITE_BACK(m);\r
1342 }\r
1343 \r
1344 static void Op5E(void)                                                  // LSR ABS, X\r
1345 {\r
1346         uint8 m;\r
1347         READ_ABS_X_WB(m);\r
1348         OP_LSR_HANDLER(m);\r
1349         WRITE_BACK(m);\r
1350 }\r
1351 \r
1352 /*\r
1353 NOP     Implied         NOP                     EA      1       2\r
1354 */\r
1355 \r
1356 static void OpEA(void)                                                  // NOP\r
1357 {\r
1358 }\r
1359 \r
1360 /*\r
1361 ORA     Immediate       ORA #Oper       09      2       2\r
1362 Zero Page               ORA Zpg         05      2       3\r
1363 Zero Page,X             ORA Zpg,X       15      2       4\r
1364 Absolute                ORA Abs         0D      3       4\r
1365 Absolute,X              ORA Abs,X       1D      3       4\r
1366 Absolute,Y              ORA Abs,Y       19      3       4\r
1367 (Zero Page,X)   ORA (Zpg,X)     01      2       6\r
1368 (Zero Page),Y   ORA (Zpg),Y     11      2       5\r
1369 (Zero Page)             ORA (Zpg)       12      2       5\r
1370 */\r
1371 \r
1372 // ORA opcodes\r
1373 \r
1374 #define OP_ORA_HANDLER(m) \\r
1375         regs.a |= m; \\r
1376         SET_ZN(regs.a)\r
1377 \r
1378 static void Op09(void)                                                  // ORA #\r
1379 {\r
1380         uint8 m = READ_IMM;\r
1381         OP_ORA_HANDLER(m);\r
1382 }\r
1383 \r
1384 static void Op05(void)                                                  // ORA ZP\r
1385 {\r
1386         uint8 m = READ_ZP;\r
1387         OP_ORA_HANDLER(m);\r
1388 }\r
1389 \r
1390 static void Op15(void)                                                  // ORA ZP, X\r
1391 {\r
1392         uint8 m = READ_ZP_X;\r
1393         OP_ORA_HANDLER(m);\r
1394 }\r
1395 \r
1396 static void Op0D(void)                                                  // ORA ABS\r
1397 {\r
1398         uint8 m = READ_ABS;\r
1399         OP_ORA_HANDLER(m);\r
1400 }\r
1401 \r
1402 static void Op1D(void)                                                  // ORA ABS, X\r
1403 {\r
1404         uint8 m = READ_ABS_X;\r
1405         OP_ORA_HANDLER(m);\r
1406 }\r
1407 \r
1408 static void Op19(void)                                                  // ORA ABS, Y\r
1409 {\r
1410         uint8 m = READ_ABS_Y;\r
1411         OP_ORA_HANDLER(m);\r
1412 }\r
1413 \r
1414 static void Op01(void)                                                  // ORA (ZP, X)\r
1415 {\r
1416         uint8 m = READ_IND_ZP_X;\r
1417         OP_ORA_HANDLER(m);\r
1418 }\r
1419 \r
1420 static void Op11(void)                                                  // ORA (ZP), Y\r
1421 {\r
1422         uint8 m = READ_IND_ZP_Y;\r
1423         OP_ORA_HANDLER(m);\r
1424 }\r
1425 \r
1426 static void Op12(void)                                                  // ORA (ZP)\r
1427 {\r
1428         uint8 m = READ_IND_ZP;\r
1429         OP_ORA_HANDLER(m);\r
1430 }\r
1431 \r
1432 /*\r
1433 PHA     Implied         PHA                     48      1       3\r
1434 */\r
1435 \r
1436 static void Op48(void)                                                  // PHA\r
1437 {\r
1438         regs.WrMem(0x0100 + regs.sp--, regs.a);\r
1439 }\r
1440 \r
1441 static void Op08(void)                                                  // PHP\r
1442 {\r
1443         regs.cc |= FLAG_UNK;                                            // Make sure that the unused bit is always set\r
1444         regs.WrMem(0x0100 + regs.sp--, regs.cc);\r
1445 }\r
1446 \r
1447 /*\r
1448 PHX     Implied         PHX                     DA      1       3\r
1449 */\r
1450 \r
1451 static void OpDA(void)                                                  // PHX\r
1452 {\r
1453         regs.WrMem(0x0100 + regs.sp--, regs.x);\r
1454 }\r
1455 \r
1456 /*\r
1457 PHY     Implied         PHY                     5A      1       3\r
1458 */\r
1459 \r
1460 static void Op5A(void)                                                  // PHY\r
1461 {\r
1462         regs.WrMem(0x0100 + regs.sp--, regs.y);\r
1463 }\r
1464 \r
1465 /*\r
1466 PLA     Implied         PLA                     68      1       4\r
1467 */\r
1468 \r
1469 static void Op68(void)                                                  // PLA\r
1470 {\r
1471         regs.a = regs.RdMem(0x0100 + ++regs.sp);\r
1472         SET_ZN(regs.a);\r
1473 }\r
1474 \r
1475 static void Op28(void)                                                  // PLP\r
1476 {\r
1477         regs.cc = regs.RdMem(0x0100 + ++regs.sp);\r
1478 }\r
1479 \r
1480 /*\r
1481 PLX     Implied         PLX                     FA      1       4\r
1482 */\r
1483 \r
1484 static void OpFA(void)                                                  // PLX\r
1485 {\r
1486         regs.x = regs.RdMem(0x0100 + ++regs.sp);\r
1487         SET_ZN(regs.x);\r
1488 }\r
1489 \r
1490 /*\r
1491 PLY     Implied         PLY                     7A      1       4\r
1492 */\r
1493 \r
1494 static void Op7A(void)                                                  // PLY\r
1495 {\r
1496         regs.y = regs.RdMem(0x0100 + ++regs.sp);\r
1497         SET_ZN(regs.y);\r
1498 }\r
1499 \r
1500 /*\r
1501 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear. \r
1502    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7\r
1503   zp  07  17  27  37  47  57  67  77\r
1504      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7\r
1505   zp  87  97  A7  B7  C7  D7  E7  F7\r
1506 */\r
1507 \r
1508 // RMB opcodes\r
1509 \r
1510 static void Op07(void)                                                  // RMB0 ZP\r
1511 {\r
1512         uint8 m;\r
1513         READ_ZP_WB(m);\r
1514         m &= 0xFE;\r
1515         WRITE_BACK(m);\r
1516 }\r
1517 \r
1518 static void Op17(void)                                                  // RMB1 ZP\r
1519 {\r
1520         uint8 m;\r
1521         READ_ZP_WB(m);\r
1522         m &= 0xFD;\r
1523         WRITE_BACK(m);\r
1524 }\r
1525 \r
1526 static void Op27(void)                                                  // RMB2 ZP\r
1527 {\r
1528         uint8 m;\r
1529         READ_ZP_WB(m);\r
1530         m &= 0xFB;\r
1531         WRITE_BACK(m);\r
1532 }\r
1533 \r
1534 static void Op37(void)                                                  // RMB3 ZP\r
1535 {\r
1536         uint8 m;\r
1537         READ_ZP_WB(m);\r
1538         m &= 0xF7;\r
1539         WRITE_BACK(m);\r
1540 }\r
1541 \r
1542 static void Op47(void)                                                  // RMB4 ZP\r
1543 {\r
1544         uint8 m;\r
1545         READ_ZP_WB(m);\r
1546         m &= 0xEF;\r
1547         WRITE_BACK(m);\r
1548 }\r
1549 \r
1550 static void Op57(void)                                                  // RMB5 ZP\r
1551 {\r
1552         uint8 m;\r
1553         READ_ZP_WB(m);\r
1554         m &= 0xDF;\r
1555         WRITE_BACK(m);\r
1556 }\r
1557 \r
1558 static void Op67(void)                                                  // RMB6 ZP\r
1559 {\r
1560         uint8 m;\r
1561         READ_ZP_WB(m);\r
1562         m &= 0xBF;\r
1563         WRITE_BACK(m);\r
1564 }\r
1565 \r
1566 static void Op77(void)                                                  // RMB7 ZP\r
1567 {\r
1568         uint8 m;\r
1569         READ_ZP_WB(m);\r
1570         m &= 0x7F;\r
1571         WRITE_BACK(m);\r
1572 }\r
1573 \r
1574 /*\r
1575 ROL     Accumulator     ROL A           2A      1       2\r
1576 Zero Page               ROL Zpg         26      2       5\r
1577 Zero Page,X             ROL Zpg,X       36      2       6\r
1578 Absolute                ROL Abs         2E      3       6\r
1579 Absolute,X              ROL Abs,X       3E      3       7\r
1580 */\r
1581 \r
1582 // ROL opcodes\r
1583 \r
1584 #define OP_ROL_HANDLER(m) \\r
1585         uint8 tmp = regs.cc & 0x01; \\r
1586         regs.cc = ((m) & 0x80 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \\r
1587         (m) = ((m) << 1) | tmp; \\r
1588         SET_ZN((m))\r
1589 \r
1590 static void Op2A(void)                                                  // ROL A\r
1591 {\r
1592         OP_ROL_HANDLER(regs.a);\r
1593 }\r
1594 \r
1595 static void Op26(void)                                                  // ROL ZP\r
1596 {\r
1597         uint8 m;\r
1598         READ_ZP_WB(m);\r
1599         OP_ROL_HANDLER(m);\r
1600         WRITE_BACK(m);\r
1601 }\r
1602 \r
1603 static void Op36(void)                                                  // ROL ZP, X\r
1604 {\r
1605         uint8 m;\r
1606         READ_ZP_X_WB(m);\r
1607         OP_ROL_HANDLER(m);\r
1608         WRITE_BACK(m);\r
1609 }\r
1610 \r
1611 static void Op2E(void)                                                  // ROL ABS\r
1612 {\r
1613         uint8 m;\r
1614         READ_ABS_WB(m);\r
1615         OP_ROL_HANDLER(m);\r
1616         WRITE_BACK(m);\r
1617 }\r
1618 \r
1619 static void Op3E(void)                                                  // ROL ABS, X\r
1620 {\r
1621         uint8 m;\r
1622         READ_ABS_X_WB(m);\r
1623         OP_ROL_HANDLER(m);\r
1624         WRITE_BACK(m);\r
1625 }\r
1626 \r
1627 /*\r
1628 ROR     Accumulator     ROR A           6A      1       2\r
1629 Zero Page               ROR Zpg         66      2       5\r
1630 Zero Page,X             ROR Zpg,X       76      2       6\r
1631 Absolute                ROR Abs         6E      3       6\r
1632 Absolute,X              ROR Abs,X       7E      3       7\r
1633 */\r
1634 \r
1635 // ROR opcodes\r
1636 \r
1637 #define OP_ROR_HANDLER(m) \\r
1638         uint8 tmp = (regs.cc & 0x01) << 7; \\r
1639         regs.cc = ((m) & 0x01 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C); \\r
1640         (m) = ((m) >> 1) | tmp; \\r
1641         SET_ZN((m))\r
1642 \r
1643 static void Op6A(void)                                                  // ROR A\r
1644 {\r
1645         OP_ROR_HANDLER(regs.a);\r
1646 }\r
1647 \r
1648 static void Op66(void)                                                  // ROR ZP\r
1649 {\r
1650         uint8 m;\r
1651         READ_ZP_WB(m);\r
1652         OP_ROR_HANDLER(m);\r
1653         WRITE_BACK(m);\r
1654 }\r
1655 \r
1656 static void Op76(void)                                                  // ROR ZP, X\r
1657 {\r
1658         uint8 m;\r
1659         READ_ZP_X_WB(m);\r
1660         OP_ROR_HANDLER(m);\r
1661         WRITE_BACK(m);\r
1662 }\r
1663 \r
1664 static void Op6E(void)                                                  // ROR ABS\r
1665 {\r
1666         uint8 m;\r
1667         READ_ABS_WB(m);\r
1668         OP_ROR_HANDLER(m);\r
1669         WRITE_BACK(m);\r
1670 }\r
1671 \r
1672 static void Op7E(void)                                                  // ROR ABS, X\r
1673 {\r
1674         uint8 m;\r
1675         READ_ABS_X_WB(m);\r
1676         OP_ROR_HANDLER(m);\r
1677         WRITE_BACK(m);\r
1678 }\r
1679 \r
1680 /*\r
1681 RTI     Implied         RTI                     40      1       6\r
1682 */\r
1683 \r
1684 static void Op40(void)                                                  // RTI\r
1685 {\r
1686         regs.cc = regs.RdMem(0x0100 + ++regs.sp);\r
1687         regs.pc = regs.RdMem(0x0100 + ++regs.sp);\r
1688         regs.pc |= (uint16)(regs.RdMem(0x0100 + ++regs.sp)) << 8;\r
1689 }\r
1690 \r
1691 /*\r
1692 RTS     Implied         RTS                     60      1       6\r
1693 */\r
1694 \r
1695 static void Op60(void)                                                  // RTS\r
1696 {\r
1697         regs.pc = regs.RdMem(0x0100 + ++regs.sp);\r
1698         regs.pc |= (uint16)(regs.RdMem(0x0100 + ++regs.sp)) << 8;\r
1699         regs.pc++;                                                                      // Since it pushes return address - 1...\r
1700 //printf("*** RTS: PC = $%04X, SP= $1%02X\n", regs.pc, regs.sp);\r
1701 //fflush(stdout);\r
1702 }\r
1703 \r
1704 /*\r
1705 SBC     Immediate       SBC #Oper       E9      2       2\r
1706 Zero Page               SBC Zpg         E5      2       3\r
1707 Zero Page,X             SBC Zpg,X       F5      2       4\r
1708 Absolute                SBC Abs         ED      3       4\r
1709 Absolute,X              SBC Abs,X       FD      3       4\r
1710 Absolute,Y              SBC Abs,Y       F9      3       4\r
1711 (Zero Page,X)   SBC (Zpg,X)     E1      2       6\r
1712 (Zero Page),Y   SBC (Zpg),Y     F1      2       5\r
1713 (Zero Page)             SBC (Zpg)       F2      2       5\r
1714 */\r
1715 \r
1716 // SBC opcodes\r
1717 \r
1718 //This is non-optimal, but it works--optimize later. :-)\r
1719 //This is correct except for the BCD handling... !!! FIX !!! [Possibly DONE]\r
1720 #define OP_SBC_HANDLER(m) \\r
1721         uint16 sum = (uint16)regs.a - (m) - (uint16)((regs.cc & FLAG_C) ^ 0x01); \\r
1722 \\r
1723         if (regs.cc & FLAG_D) \\r
1724         { \\r
1725                 if ((sum & 0x0F) > 0x09) \\r
1726                         sum -= 0x06; \\r
1727 \\r
1728                 if ((sum & 0xF0) > 0x90) \\r
1729                         sum -= 0x60; \\r
1730         } \\r
1731 \\r
1732         regs.cc = (regs.cc & ~FLAG_C) | (((sum >> 8) ^ 0x01) & FLAG_C); \\r
1733         regs.cc = ((regs.a ^ (m)) & (regs.a ^ sum) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \\r
1734         regs.a = sum & 0xFF; \\r
1735         SET_ZN(regs.a)\r
1736 \r
1737 /*\r
1738 D5AF: 38             SEC                [PC=D5B0, SP=01F6, CC=---B-I-C, A=4C, X=00, Y=06]\r
1739 \r
1740 *** HERE'S where it sets the D flag on a subtract... Arg!\r
1741 \r
1742 D5B0: F1 9D          SBC   ($9D),Y      [PC=D5B2, SP=01F6, CC=N--BDI--, A=FE, X=00, Y=06]\r
1743 \r
1744 Fixed. :-)\r
1745 */\r
1746 \r
1747 //OLD V detection: regs.cc = ((regs.a ^ (m) ^ sum ^ (regs.cc << 7)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V);\r
1748 \r
1749 static void OpE9(void)                                                  // SBC #\r
1750 {\r
1751         uint16 m = READ_IMM;\r
1752         OP_SBC_HANDLER(m);\r
1753 }\r
1754 \r
1755 static void OpE5(void)                                                  // SBC ZP\r
1756 {\r
1757         uint16 m = READ_ZP;\r
1758         OP_SBC_HANDLER(m);\r
1759 }\r
1760 \r
1761 static void OpF5(void)                                                  // SBC ZP, X\r
1762 {\r
1763         uint16 m = READ_ZP_X;\r
1764         OP_SBC_HANDLER(m);\r
1765 }\r
1766 \r
1767 static void OpED(void)                                                  // SBC ABS\r
1768 {\r
1769         uint16 m = READ_ABS;\r
1770         OP_SBC_HANDLER(m);\r
1771 }\r
1772 \r
1773 static void OpFD(void)                                                  // SBC ABS, X\r
1774 {\r
1775         uint16 m = READ_ABS_X;\r
1776         OP_SBC_HANDLER(m);\r
1777 }\r
1778 \r
1779 static void OpF9(void)                                                  // SBC ABS, Y\r
1780 {\r
1781         uint16 m = READ_ABS_Y;\r
1782         OP_SBC_HANDLER(m);\r
1783 }\r
1784 \r
1785 static void OpE1(void)                                                  // SBC (ZP, X)\r
1786 {\r
1787         uint16 m = READ_IND_ZP_X;\r
1788         OP_SBC_HANDLER(m);\r
1789 }\r
1790 \r
1791 static void OpF1(void)                                                  // SBC (ZP), Y\r
1792 {\r
1793         uint16 m = READ_IND_ZP_Y;\r
1794         OP_SBC_HANDLER(m);\r
1795 }\r
1796 \r
1797 static void OpF2(void)                                                  // SBC (ZP)\r
1798 {\r
1799         uint16 m = READ_IND_ZP;\r
1800         OP_SBC_HANDLER(m);\r
1801 }\r
1802 \r
1803 /*\r
1804 SEC     Implied         SEC                     38      1       2\r
1805 */\r
1806 \r
1807 static void Op38(void)                                                  // SEC\r
1808 {\r
1809         regs.cc |= FLAG_C;\r
1810 }\r
1811 \r
1812 /*\r
1813 SED     Implied         SED                     F8      1       2\r
1814 */\r
1815 \r
1816 static void OpF8(void)                                                  // SED\r
1817 {\r
1818         regs.cc |= FLAG_D;\r
1819 }\r
1820 \r
1821 /*\r
1822 SEI     Implied         SEI                     78      1       2\r
1823 */\r
1824 \r
1825 static void Op78(void)                                                  // SEI\r
1826 {\r
1827         regs.cc |= FLAG_I;\r
1828 }\r
1829 \r
1830 /*\r
1831 The bit set and clear instructions have the form xyyy0111, where x is 0 to clear a bit or 1 to set it, and yyy is which bit at the memory location to set or clear. \r
1832    RMB0  RMB1  RMB2  RMB3  RMB4  RMB5  RMB6  RMB7\r
1833   zp  07  17  27  37  47  57  67  77\r
1834      SMB0  SMB1  SMB2  SMB3  SMB4  SMB5  SMB6  SMB7\r
1835   zp  87  97  A7  B7  C7  D7  E7  F7\r
1836 */\r
1837 \r
1838 // SMB opcodes\r
1839 \r
1840 static void Op87(void)                                                  // SMB0 ZP\r
1841 {\r
1842         uint8 m;\r
1843         READ_ZP_WB(m);\r
1844         m |= 0x01;\r
1845         WRITE_BACK(m);\r
1846 }\r
1847 \r
1848 static void Op97(void)                                                  // SMB1 ZP\r
1849 {\r
1850         uint8 m;\r
1851         READ_ZP_WB(m);\r
1852         m |= 0x02;\r
1853         WRITE_BACK(m);\r
1854 }\r
1855 \r
1856 static void OpA7(void)                                                  // SMB2 ZP\r
1857 {\r
1858         uint8 m;\r
1859         READ_ZP_WB(m);\r
1860         m |= 0x04;\r
1861         WRITE_BACK(m);\r
1862 }\r
1863 \r
1864 static void OpB7(void)                                                  // SMB3 ZP\r
1865 {\r
1866         uint8 m;\r
1867         READ_ZP_WB(m);\r
1868         m |= 0x08;\r
1869         WRITE_BACK(m);\r
1870 }\r
1871 \r
1872 static void OpC7(void)                                                  // SMB4 ZP\r
1873 {\r
1874         uint8 m;\r
1875         READ_ZP_WB(m);\r
1876         m |= 0x10;\r
1877         WRITE_BACK(m);\r
1878 }\r
1879 \r
1880 static void OpD7(void)                                                  // SMB5 ZP\r
1881 {\r
1882         uint8 m;\r
1883         READ_ZP_WB(m);\r
1884         m |= 0x20;\r
1885         WRITE_BACK(m);\r
1886 }\r
1887 \r
1888 static void OpE7(void)                                                  // SMB6 ZP\r
1889 {\r
1890         uint8 m;\r
1891         READ_ZP_WB(m);\r
1892         m |= 0x40;\r
1893         WRITE_BACK(m);\r
1894 }\r
1895 \r
1896 static void OpF7(void)                                                  // SMB7 ZP\r
1897 {\r
1898         uint8 m;\r
1899         READ_ZP_WB(m);\r
1900         m |= 0x80;\r
1901         WRITE_BACK(m);\r
1902 }\r
1903 \r
1904 /*\r
1905 STA     Zero Page       STA Zpg         85      2       3\r
1906 Zero Page,X             STA Zpg,X       95      2       4\r
1907 Absolute                STA Abs         8D      3       4\r
1908 Absolute,X              STA Abs,X       9D      3       5\r
1909 Absolute,Y              STA Abs,Y       99      3       5\r
1910 (Zero Page,X)   STA (Zpg,X)     81      2       6\r
1911 (Zero Page),Y   STA (Zpg),Y     91      2       6\r
1912 (Zero Page)             STA (Zpg)       92      2       5\r
1913 */\r
1914 \r
1915 // STA opcodes\r
1916 \r
1917 static void Op85(void)\r
1918 {\r
1919         regs.WrMem(EA_ZP, regs.a);\r
1920 }\r
1921 \r
1922 static void Op95(void)\r
1923 {\r
1924         regs.WrMem(EA_ZP_X, regs.a);\r
1925 }\r
1926 \r
1927 static void Op8D(void)\r
1928 {\r
1929         regs.WrMem(EA_ABS, regs.a);\r
1930         regs.pc += 2;\r
1931 }\r
1932 \r
1933 static void Op9D(void)\r
1934 {\r
1935         regs.WrMem(EA_ABS_X, regs.a);\r
1936         regs.pc += 2;\r
1937 }\r
1938 \r
1939 static void Op99(void)\r
1940 {\r
1941         regs.WrMem(EA_ABS_Y, regs.a);\r
1942         regs.pc += 2;\r
1943 }\r
1944 \r
1945 static void Op81(void)\r
1946 {\r
1947         regs.WrMem(EA_IND_ZP_X, regs.a);\r
1948 }\r
1949 \r
1950 static void Op91(void)\r
1951 {\r
1952         regs.WrMem(EA_IND_ZP_Y, regs.a);\r
1953 }\r
1954 \r
1955 static void Op92(void)\r
1956 {\r
1957         regs.WrMem(EA_IND_ZP, regs.a);\r
1958 }\r
1959 \r
1960 /*\r
1961 STX     Zero Page       STX Zpg         86      2       3\r
1962 Zero Page,Y             STX Zpg,Y       96      2       4\r
1963 Absolute                STX Abs         8E      3       4\r
1964 */\r
1965 \r
1966 // STX opcodes\r
1967 \r
1968 static void Op86(void)\r
1969 {\r
1970         regs.WrMem(EA_ZP, regs.x);\r
1971 }\r
1972 \r
1973 static void Op96(void)\r
1974 {\r
1975         regs.WrMem(EA_ZP_X, regs.x);\r
1976 }\r
1977 \r
1978 static void Op8E(void)\r
1979 {\r
1980         regs.WrMem(EA_ABS, regs.x);\r
1981         regs.pc += 2;\r
1982 }\r
1983 \r
1984 /*\r
1985 STY     Zero Page       STY Zpg         84      2       3\r
1986 Zero Page,X             STY Zpg,X       94      2       4\r
1987 Absolute                STY Abs         8C      3       4\r
1988 */\r
1989 \r
1990 // STY opcodes\r
1991 \r
1992 static void Op84(void)\r
1993 {\r
1994         regs.WrMem(EA_ZP, regs.y);\r
1995 }\r
1996 \r
1997 static void Op94(void)\r
1998 {\r
1999         regs.WrMem(EA_ZP_X, regs.y);\r
2000 }\r
2001 \r
2002 static void Op8C(void)\r
2003 {\r
2004         regs.WrMem(EA_ABS, regs.y);\r
2005         regs.pc += 2;\r
2006 }\r
2007 \r
2008 /*\r
2009 STZ     Zero Page       STZ Zpg         64      2       3\r
2010 Zero Page,X             STZ Zpg,X       74      2       4\r
2011 Absolute                STZ Abs         9C      3       4\r
2012 Absolute,X              STZ Abs,X       9E      3       5\r
2013 */\r
2014 \r
2015 // STZ opcodes\r
2016 \r
2017 static void Op64(void)\r
2018 {\r
2019         regs.WrMem(EA_ZP, 0x00);\r
2020 }\r
2021 \r
2022 static void Op74(void)\r
2023 {\r
2024         regs.WrMem(EA_ZP_X, 0x00);\r
2025 }\r
2026 \r
2027 static void Op9C(void)\r
2028 {\r
2029         regs.WrMem(EA_ABS, 0x00);\r
2030         regs.pc += 2;\r
2031 }\r
2032 \r
2033 static void Op9E(void)\r
2034 {\r
2035         regs.WrMem(EA_ABS_X, 0x00);\r
2036         regs.pc += 2;\r
2037 }\r
2038 \r
2039 /*\r
2040 TAX     Implied         TAX                     AA      1       2\r
2041 */\r
2042 \r
2043 static void OpAA(void)                                                  // TAX\r
2044 {\r
2045         regs.x = regs.a;\r
2046         SET_ZN(regs.x);\r
2047 }\r
2048 \r
2049 /*\r
2050 TAY     Implied         TAY                     A8      1       2\r
2051 */\r
2052 \r
2053 static void OpA8(void)                                                  // TAY\r
2054 {\r
2055         regs.y = regs.a;\r
2056         SET_ZN(regs.y);\r
2057 }\r
2058 \r
2059 /*\r
2060 TRB     Zero Page       TRB Zpg         14      2       5\r
2061 Absolute                TRB Abs         1C      3       6\r
2062 */\r
2063 \r
2064 // TRB opcodes\r
2065 \r
2066 #define OP_TRB_HANDLER(m) \\r
2067         SET_Z(m & regs.a); \\r
2068         m &= ~regs.a\r
2069 \r
2070 static void Op14(void)                                                  // TRB ZP\r
2071 {\r
2072         uint8 m;\r
2073         READ_ZP_WB(m);\r
2074         OP_TRB_HANDLER(m);\r
2075         WRITE_BACK(m);\r
2076 }\r
2077 \r
2078 static void Op1C(void)                                                  // TRB ABS\r
2079 {\r
2080         uint8 m;\r
2081         READ_ABS_WB(m);\r
2082         OP_TRB_HANDLER(m);\r
2083         WRITE_BACK(m);\r
2084 }\r
2085 \r
2086 /*\r
2087 TSB     Zero Page       TSB Zpg         04      2       5\r
2088 Absolute                TSB Abs         0C      3       6\r
2089 */\r
2090 \r
2091 // TSB opcodes\r
2092 \r
2093 #define OP_TSB_HANDLER(m) \\r
2094         SET_Z(m & regs.a); \\r
2095         m |= regs.a\r
2096 \r
2097 static void Op04(void)                                                  // TSB ZP\r
2098 {\r
2099         uint8 m;\r
2100         READ_ZP_WB(m);\r
2101         OP_TSB_HANDLER(m);\r
2102         WRITE_BACK(m);\r
2103 }\r
2104 \r
2105 static void Op0C(void)                                                  // TSB ABS\r
2106 {\r
2107         uint8 m;\r
2108         READ_ABS_WB(m);\r
2109         OP_TSB_HANDLER(m);\r
2110         WRITE_BACK(m);\r
2111 }\r
2112 \r
2113 /*\r
2114 TSX     Implied         TSX                     BA      1       2\r
2115 */\r
2116 \r
2117 static void OpBA(void)                                                  // TSX\r
2118 {\r
2119         regs.x = regs.sp;\r
2120         SET_ZN(regs.x);\r
2121 }\r
2122 \r
2123 /*\r
2124 TXA     Implied         TXA                     8A      1       2\r
2125 */\r
2126 \r
2127 static void Op8A(void)                                                  // TXA\r
2128 {\r
2129         regs.a = regs.x;\r
2130         SET_ZN(regs.a);\r
2131 }\r
2132 \r
2133 /*\r
2134 TXS     Implied         TXS                     9A      1       2\r
2135 */\r
2136 \r
2137 static void Op9A(void)                                                  // TXS\r
2138 {\r
2139         regs.sp = regs.x;\r
2140 }\r
2141 \r
2142 /*\r
2143 TYA     Implied         TYA                     98      1       2\r
2144 */\r
2145 static void Op98(void)                                                  // TYA\r
2146 {\r
2147         regs.a = regs.y;\r
2148         SET_ZN(regs.a);\r
2149 }\r
2150 \r
2151 static void Op__(void)\r
2152 {\r
2153         regs.cpuFlags |= V65C02_STATE_ILLEGAL_INST;\r
2154 }\r
2155 \r
2156 \r
2157 //\r
2158 // Ok, the exec_op[] array is globally defined here basically to save\r
2159 // a LOT of unnecessary typing.  Sure it's ugly, but hey, it works!\r
2160 //\r
2161 void (* exec_op[256])() = {\r
2162         Op00, Op01, Op__, Op__, Op04, Op05, Op06, Op07, Op08, Op09, Op0A, Op__, Op0C, Op0D, Op0E, Op0F,\r
2163         Op10, Op11, Op12, Op__, Op14, Op15, Op16, Op17, Op18, Op19, Op1A, Op__, Op1C, Op1D, Op1E, Op1F,\r
2164         Op20, Op21, Op__, Op__, Op24, Op25, Op26, Op27, Op28, Op29, Op2A, Op__, Op2C, Op2D, Op2E, Op2F,\r
2165         Op30, Op31, Op32, Op__, Op34, Op35, Op36, Op37, Op38, Op39, Op3A, Op__, Op3C, Op3D, Op3E, Op3F,\r
2166         Op40, Op41, Op__, Op__, Op__, Op45, Op46, Op47, Op48, Op49, Op4A, Op__, Op4C, Op4D, Op4E, Op4F,\r
2167         Op50, Op51, Op52, Op__, Op__, Op55, Op56, Op57, Op58, Op59, Op5A, Op__, Op__, Op5D, Op5E, Op5F,\r
2168         Op60, Op61, Op__, Op__, Op64, Op65, Op66, Op67, Op68, Op69, Op6A, Op__, Op6C, Op6D, Op6E, Op6F,\r
2169         Op70, Op71, Op72, Op__, Op74, Op75, Op76, Op77, Op78, Op79, Op7A, Op__, Op7C, Op7D, Op7E, Op7F,\r
2170         Op80, Op81, Op__, Op__, Op84, Op85, Op86, Op87, Op88, Op89, Op8A, Op__, Op8C, Op8D, Op8E, Op8F,\r
2171         Op90, Op91, Op92, Op__, Op94, Op95, Op96, Op97, Op98, Op99, Op9A, Op__, Op9C, Op9D, Op9E, Op9F,\r
2172         OpA0, OpA1, OpA2, Op__, OpA4, OpA5, OpA6, OpA7, OpA8, OpA9, OpAA, Op__, OpAC, OpAD, OpAE, OpAF,\r
2173         OpB0, OpB1, OpB2, Op__, OpB4, OpB5, OpB6, OpB7, OpB8, OpB9, OpBA, Op__, OpBC, OpBD, OpBE, OpBF,\r
2174         OpC0, OpC1, Op__, Op__, OpC4, OpC5, OpC6, OpC7, OpC8, OpC9, OpCA, Op__, OpCC, OpCD, OpCE, OpCF,\r
2175         OpD0, OpD1, OpD2, Op__, Op__, OpD5, OpD6, OpD7, OpD8, OpD9, OpDA, Op__, Op__, OpDD, OpDE, OpDF,\r
2176         OpE0, OpE1, Op__, Op__, OpE4, OpE5, OpE6, OpE7, OpE8, OpE9, OpEA, Op__, OpEC, OpED, OpEE, OpEF,\r
2177         OpF0, OpF1, OpF2, Op__, Op__, OpF5, OpF6, OpF7, OpF8, OpF9, OpFA, Op__, Op__, OpFD, OpFE, OpFF\r
2178 };\r
2179 \r
2180 //\r
2181 // Internal "memcpy" (so we don't have to link with any external libraries!)\r
2182 //\r
2183 static void myMemcpy(void * dst, void * src, uint32 size)\r
2184 {\r
2185         uint8 * d = (uint8 *)dst, * s = (uint8 *)src;\r
2186 \r
2187         for(uint32 i=0; i<size; i++)\r
2188                 d[i] = s[i];\r
2189 }\r
2190 \r
2191 /*\r
2192 FCA8: 38        698  WAIT     SEC\r
2193 FCA9: 48        699  WAIT2    PHA\r
2194 FCAA: E9 01     700  WAIT3    SBC   #$01\r
2195 FCAC: D0 FC     701           BNE   WAIT3      ;1.0204 USEC\r
2196 FCAE: 68        702           PLA              ;(13+27/2*A+5/2*A*A)\r
2197 FCAF: E9 01     703           SBC   #$01\r
2198 FCB1: D0 F6     704           BNE   WAIT2\r
2199 FCB3: 60        705           RTS\r
2200 \r
2201 FBD9: C9 87     592  BELL1    CMP   #$87       ;BELL CHAR? (CNTRL-G)\r
2202 FBDB: D0 12     593           BNE   RTS2B      ;  NO, RETURN\r
2203 FBDD: A9 40     594           LDA   #$40       ;DELAY .01 SECONDS\r
2204 FBDF: 20 A8 FC  595           JSR   WAIT\r
2205 FBE2: A0 C0     596           LDY   #$C0\r
2206 FBE4: A9 0C     597  BELL2    LDA   #$0C       ;TOGGLE SPEAKER AT\r
2207 FBE6: 20 A8 FC  598           JSR   WAIT       ;  1 KHZ FOR .1 SEC.\r
2208 FBE9: AD 30 C0  599           LDA   SPKR\r
2209 FBEC: 88        600           DEY\r
2210 FBED: D0 F5     601           BNE   BELL2\r
2211 FBEF: 60        602  RTS2B    RTS\r
2212 */\r
2213 //int instCount[256];\r
2214 #ifdef __DEBUG__\r
2215 bool dumpDis = false;\r
2216 #endif\r
2217 //\r
2218 // Function to execute 6808 for "cycles" cycles\r
2219 //\r
2220 void Execute65C02(V65C02REGS * context, uint32 cycles)\r
2221 {\r
2222         myMemcpy(&regs, context, sizeof(V65C02REGS));\r
2223 \r
2224         // Execute here...\r
2225         while (regs.clock < cycles)\r
2226         {\r
2227 #if 0\r
2228 /*if (regs.pc == 0x4007)\r
2229 {\r
2230         dumpDis = true;\r
2231 }//*/\r
2232 if (regs.pc == 0x444B)\r
2233 {\r
2234         WriteLog("\n*** End of wait...\n\n");\r
2235         dumpDis = true;\r
2236 }//*/\r
2237 if (regs.pc == 0x444E)\r
2238 {\r
2239         WriteLog("\n*** Start of wait...\n\n");\r
2240         dumpDis = false;\r
2241 }//*/\r
2242 #endif\r
2243 \r
2244 #ifdef __DEBUGMON__\r
2245 //WAIT is commented out here because it's called by BELL1...\r
2246 if (regs.pc == 0xFCA8)\r
2247 {\r
2248         WriteLog("\n*** WAIT subroutine...\n\n");\r
2249         dumpDis = false;\r
2250 }//*/\r
2251 if (regs.pc == 0xFBD9)\r
2252 {\r
2253         WriteLog("\n*** BELL1 subroutine...\n\n");\r
2254 //      dumpDis = false;\r
2255 }//*/\r
2256 if (regs.pc == 0xFC58)\r
2257 {\r
2258         WriteLog("\n*** HOME subroutine...\n\n");\r
2259 //      dumpDis = false;\r
2260 }//*/\r
2261 if (regs.pc == 0xFDED)\r
2262 {\r
2263         WriteLog("\n*** COUT subroutine...\n\n");\r
2264         dumpDis = false;\r
2265 }\r
2266 #endif\r
2267 \r
2268 #ifdef __DEBUG__\r
2269 if (dumpDis)\r
2270         Decode65C02(regs.pc);\r
2271 #endif\r
2272                 uint8 opcode = regs.RdMem(regs.pc++);\r
2273 \r
2274 //if (!(regs.cpuFlags & V65C02_STATE_ILLEGAL_INST))\r
2275 //instCount[opcode]++;\r
2276 \r
2277                 exec_op[opcode]();                                                              // Execute that opcode...\r
2278                 regs.clock += CPUCycles[opcode];\r
2279 #ifdef __DEBUG__\r
2280 if (dumpDis)\r
2281         WriteLog(" [PC=%04X, SP=%04X, CC=%s%s-%s%s%s%s%s, A=%02X, X=%02X, Y=%02X]\n",\r
2282                 regs.pc, 0x0100 + regs.sp,\r
2283                 (regs.cc & FLAG_N ? "N" : "-"), (regs.cc & FLAG_V ? "V" : "-"),\r
2284                 (regs.cc & FLAG_B ? "B" : "-"), (regs.cc & FLAG_D ? "D" : "-"),\r
2285                 (regs.cc & FLAG_I ? "I" : "-"), (regs.cc & FLAG_Z ? "Z" : "-"),\r
2286                 (regs.cc & FLAG_C ? "C" : "-"), regs.a, regs.x, regs.y);\r
2287 #endif\r
2288 \r
2289 #ifdef __DEBUGMON__\r
2290 if (regs.pc == 0xFCB3)  // WAIT exit point\r
2291 {\r
2292         dumpDis = true;\r
2293 }//*/\r
2294 /*if (regs.pc == 0xFBEF)        // BELL1 exit point\r
2295 {\r
2296         dumpDis = true;\r
2297 }//*/\r
2298 /*if (regs.pc == 0xFC22)        // HOME exit point\r
2299 {\r
2300         dumpDis = true;\r
2301 }//*/\r
2302 if (regs.pc == 0xFDFF)  // COUT exit point\r
2303 {\r
2304         dumpDis = true;\r
2305 }\r
2306 if (regs.pc == 0xFBD8)\r
2307 {\r
2308         WriteLog("\n*** BASCALC set BASL/H = $%04X\n\n", RdMemW(0x0028));\r
2309 }//*/\r
2310 #endif\r
2311 \r
2312 //These should be correct now...\r
2313                 if (regs.cpuFlags & V65C02_ASSERT_LINE_RESET)\r
2314                 {\r
2315 #ifdef __DEBUG__\r
2316 WriteLog("\n*** RESET ***\n\n");\r
2317 #endif\r
2318                         // Not sure about this...\r
2319                         regs.sp = 0xFF;\r
2320                         regs.cc = FLAG_B | FLAG_I;                                      // Reset the CC register\r
2321                         regs.pc = RdMemW(0xFFFC);                                       // And load PC with the RESET vector\r
2322 \r
2323                         context->cpuFlags &= ~V65C02_ASSERT_LINE_RESET;\r
2324                         regs.cpuFlags &= ~V65C02_ASSERT_LINE_RESET;\r
2325                 }\r
2326                 else if (regs.cpuFlags & V65C02_ASSERT_LINE_NMI)\r
2327                 {\r
2328 #ifdef __DEBUG__\r
2329 WriteLog("\n*** NMI ***\n\n");\r
2330 #endif\r
2331                         regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);   // Save PC and CC\r
2332                         regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);\r
2333                         regs.WrMem(0x0100 + regs.sp--, regs.cc);\r
2334                         regs.cc |= FLAG_I;                                                      // Set I\r
2335                         regs.cc &= ~FLAG_D;                                                     // & clear D\r
2336                         regs.pc = RdMemW(0xFFFA);                                       // And do it!\r
2337 \r
2338                         regs.clock += 7;\r
2339                         context->cpuFlags &= ~V65C02_ASSERT_LINE_NMI;// Reset the asserted line (NMI)...\r
2340                         regs.cpuFlags &= ~V65C02_ASSERT_LINE_NMI;       // Reset the asserted line (NMI)...\r
2341                 }\r
2342                 else if (regs.cpuFlags & V65C02_ASSERT_LINE_IRQ)\r
2343                 {\r
2344                         if (!(regs.cc & FLAG_I))                                        // Process an interrupt (I=0)?\r
2345                         {\r
2346 #ifdef __DEBUG__\r
2347 WriteLog("\n*** IRQ ***\n\n");\r
2348 #endif\r
2349                                 regs.WrMem(0x0100 + regs.sp--, regs.pc >> 8);   // Save PC and CC\r
2350                                 regs.WrMem(0x0100 + regs.sp--, regs.pc & 0xFF);\r
2351                                 regs.WrMem(0x0100 + regs.sp--, regs.cc);\r
2352                                 regs.cc |= FLAG_I;                                              // Set I\r
2353                                 regs.cc &= ~FLAG_D;                                             // & clear D\r
2354                                 regs.pc = RdMemW(0xFFFE);                               // And do it!\r
2355 \r
2356                                 regs.clock += 7;\r
2357                                 context->cpuFlags &= ~V65C02_ASSERT_LINE_IRQ;   // Reset the asserted line (IRQ)...\r
2358                                 regs.cpuFlags &= ~V65C02_ASSERT_LINE_IRQ;       // Reset the asserted line (IRQ)...\r
2359                         }\r
2360                 }\r
2361         }\r
2362 \r
2363         myMemcpy(context, &regs, sizeof(V65C02REGS));\r
2364 }\r
2365 \r
2366 //\r
2367 // Get the clock of the currently executing CPU\r
2368 //\r
2369 uint32 GetCurrentV65C02Clock(void)\r
2370 {\r
2371         return regs.clock;\r
2372 }\r