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