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