Dave Van Wagner / Mbed OS c-simple-emu6502-cbm
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers emu6502.cpp Source File

emu6502.cpp

00001 // emu6502.c - Emu6502 - MOS6502 Emulator
00002 //
00003 ////////////////////////////////////////////////////////////////////////////////
00004 //
00005 // c-simple-emu-cbm (C Portable Version)
00006 // C64/6502 Emulator for Terminal Console
00007 //
00008 // MIT License
00009 //
00010 // Copyright(c) 2020 by David R. Van Wagner
00011 // davevw.com
00012 //
00013 // Permission is hereby granted, free of charge, to any person obtaining a copy
00014 // of this software and associated documentation files (the "Software"), to deal
00015 // in the Software without restriction, including without limitation the rights
00016 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00017 // copies of the Software, and to permit persons to whom the Software is
00018 // furnished to do so, subject to the following conditions:
00019 //
00020 // The above copyright notice and this permission notice shall be included in all
00021 // copies or substantial portions of the Software.
00022 //
00023 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00024 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00025 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
00026 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00027 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00028 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00029 // SOFTWARE.
00030 //
00031 ////////////////////////////////////////////////////////////////////////////////
00032 
00033 //#define snprintf sprintf_s
00034 
00035 #include <mbed.h>
00036 #include "emu6502.h"
00037 
00038 // global references
00039 extern Serial pc;
00040 
00041 // globals
00042 byte A = 0;
00043 byte X = 0;
00044 byte Y = 0;
00045 byte S = 0xFF;
00046 bool N = false;
00047 bool V = false;
00048 bool B = false;
00049 bool D = false;
00050 bool I = false;
00051 bool Z = false;
00052 bool C = false;
00053 ushort PC = 0;
00054 bool trace = false;
00055 bool step = false;
00056 
00057 #define USE_IRQ 0
00058 
00059 extern void ResetRun(bool (*ExecutePatch)(void))
00060 {
00061     ushort addr = (ushort)((GetMemory(0xFFFC) | (GetMemory(0xFFFD) << 8))); // JMP(RESET)
00062     Execute(addr, ExecutePatch);
00063 }
00064 
00065 #ifndef WIN32
00066 static void strcpy_s(char* dest, size_t size, const char* src)
00067 {
00068     strncpy(dest, src, size);
00069 }
00070 
00071 static void strcat_s(char* dest, size_t size, const char* src)
00072 {
00073     strncat(dest, src, size);
00074 }
00075 #endif
00076 
00077 static void PHP()
00078 {
00079     int flags = (N ? 0x80 : 0)
00080         | (V ? 0x40 : 0)
00081         | (B ? 0x10 : 0)
00082         | (D ? 0x08 : 0)
00083         | (I ? 0x04 : 0)
00084         | (Z ? 0x02 : 0)
00085         | (C ? 0x01 : 0);
00086     Push(flags);
00087 }
00088 
00089 extern byte LO(ushort value)
00090 {
00091     return (byte)value;
00092 }
00093 
00094 extern byte HI(ushort value)
00095 {
00096     return (byte)(value >> 8);
00097 }
00098 
00099 static byte Subtract(byte reg, byte value, bool *p_overflow)
00100 {
00101     bool old_reg_neg = (reg & 0x80) != 0;
00102     bool value_neg = (value & 0x80) != 0;
00103     int result = reg - value - (C ? 0 : 1);
00104     N = (result & 0x80) != 0;
00105     C = (result >= 0);
00106     Z = (result == 0);
00107     bool result_neg = (result & 0x80) != 0;
00108     *p_overflow = (old_reg_neg && !value_neg && !result_neg) // neg - pos = pos
00109         || (!old_reg_neg && value_neg && result_neg); // pos - neg = neg
00110     return (byte)result;
00111 }
00112 
00113 static byte SubtractWithoutOverflow(byte reg, byte value)
00114 {
00115     C = true; // init for CMP, etc.
00116     bool unused;
00117     return Subtract(reg, value, &unused);
00118 }
00119 
00120 static void CMP(byte value)
00121 {
00122     SubtractWithoutOverflow(A, value);
00123 }
00124 
00125 static void CPX(byte value)
00126 {
00127     SubtractWithoutOverflow(X, value);
00128 }
00129 
00130 static void CPY(byte value)
00131 {
00132     SubtractWithoutOverflow(Y, value);
00133 }
00134 
00135 static void SetReg(byte *p_reg, int value)
00136 {
00137     *p_reg = (byte)value;
00138     Z = (*p_reg == 0);
00139     N = ((*p_reg & 0x80) != 0);
00140 }
00141 
00142 static void SetA(int value)
00143 {
00144     SetReg(&A, value);
00145 }
00146 
00147 static void SetX(int value)
00148 {
00149     SetReg(&X, value);
00150 }
00151 
00152 static void SetY(int value)
00153 {
00154     SetReg(&Y, value);
00155 }
00156 
00157 static void SBC(byte value)
00158 {
00159     if (D)
00160     {
00161         int A_dec = (A & 0xF) + ((A >> 4) * 10);
00162         int value_dec = (value & 0xF) + ((value >> 4) * 10);
00163         int result_dec = A_dec - value_dec - (C ? 0 : 1);
00164         C = (result_dec >= 0);
00165         if (!C)
00166             result_dec = -result_dec; // absolute value
00167         int result = (result_dec % 10) | (((result_dec / 10) % 10) << 4);
00168         SetA(result);
00169         N = false; // undefined?
00170         V = false; // undefined?
00171     }
00172     else
00173     {
00174         byte result = Subtract(A, value, &V);
00175         SetA(result);
00176     }
00177 }
00178 
00179 static void ADC_OP(byte value)
00180 {
00181     int result;
00182     if (D)
00183     {
00184         int A_dec = (A & 0xF) + ((A >> 4) * 10);
00185         int value_dec = (value & 0xF) + ((value >> 4) * 10);
00186         int result_dec = A_dec + value_dec + (C ? 1 : 0);
00187         C = (result_dec > 99);
00188         result = (result_dec % 10) | (((result_dec / 10) % 10) << 4);
00189         SetA(result);
00190         Z = (result_dec == 0); // BCD quirk -- 100 doesn't set Z
00191         V = false;
00192     }
00193     else
00194     {
00195         bool A_old_neg = (A & 0x80) != 0;
00196         bool value_neg = (value & 0x80) != 0;
00197         result = A + value + (C ? 1 : 0);
00198         C = (result & 0x100) != 0;
00199         SetA(result);
00200         bool result_neg = (result & 0x80) != 0;
00201         V = (!A_old_neg && !value_neg && result_neg) // pos + pos = neg: overflow
00202             || (A_old_neg && value_neg && !result_neg); // neg + neg = pos: overflow
00203     }
00204 }
00205 
00206 static void ORA(int value)
00207 {
00208     SetA(A | value);
00209 }
00210 
00211 static void EOR(int value)
00212 {
00213     SetA(A ^ value);
00214 }
00215 
00216 static void AND(int value)
00217 {
00218     SetA(A & value);
00219 }
00220 
00221 static void BIT_OP(byte value)
00222 {
00223     Z = (A & value) == 0;
00224     N = (value & 0x80) != 0;
00225     V = (value & 0x40) != 0;
00226 }
00227 
00228 static byte ASL(int value)
00229 {
00230     C = (value & 0x80) != 0;
00231     value = (byte)(value << 1);
00232     Z = (value == 0);
00233     N = (value & 0x80) != 0;
00234     return (byte)value;
00235 }
00236 
00237 static byte LSR(int value)
00238 {
00239     C = (value & 0x01) != 0;
00240     value = (byte)(value >> 1);
00241     Z = (value == 0);
00242     N = false;
00243     return (byte)value;
00244 }
00245 
00246 static byte ROL(int value)
00247 {
00248     bool newC = (value & 0x80) != 0;
00249     value = (byte)((value << 1) | (C ? 1 : 0));
00250     C = newC;
00251     Z = (value == 0);
00252     N = (value & 0x80) != 0;
00253     return (byte)value;
00254 }
00255 
00256 static byte ROR(int value)
00257 {
00258     bool newC = (value & 0x01) != 0;
00259     N = C;
00260     value = (byte)((value >> 1) | (C ? 0x80 : 0));
00261     C = newC;
00262     Z = (value == 0);
00263     return (byte)value;
00264 }
00265 
00266 extern void Push(int value)
00267 {
00268     SetMemory((ushort)(0x100 + (S--)), (byte)value);
00269 }
00270 
00271 extern byte Pop(void)
00272 {
00273     return GetMemory((ushort)(0x100 + (++S)));
00274 }
00275 
00276 static void PLP()
00277 {
00278     int flags = Pop();
00279     N = (flags & 0x80) != 0;
00280     V = (flags & 0x40) != 0;
00281     B = (flags & 0x10) != 0;
00282     D = (flags & 0x08) != 0;
00283     I = (flags & 0x04) != 0;
00284     Z = (flags & 0x02) != 0;
00285     C = (flags & 0x01) != 0;
00286 }
00287 
00288 static void PHA()
00289 {
00290     Push(A);
00291 }
00292 
00293 static void PLA()
00294 {
00295     SetA(Pop());
00296 }
00297 
00298 static void CLC()
00299 {
00300     C = false;
00301 }
00302 
00303 static void CLD()
00304 {
00305     D = false;
00306 }
00307 
00308 static void CLI()
00309 {
00310     I = false;
00311 }
00312 
00313 static void CLV()
00314 {
00315     V = false;
00316 }
00317 
00318 static void SEC()
00319 {
00320     C = true;
00321 }
00322 
00323 static void SED()
00324 {
00325     D = true;
00326 }
00327 
00328 static void SEI()
00329 {
00330     I = true;
00331 }
00332 
00333 static byte INC(byte value)
00334 {
00335     ++value;
00336     Z = (value == 0);
00337     N = (value & 0x80) != 0;
00338     return (byte)value;
00339 }
00340 
00341 static void INX()
00342 {
00343     X = INC(X);
00344 }
00345 
00346 static void INY()
00347 {
00348     Y = INC(Y);
00349 }
00350 
00351 static byte DEC(byte value)
00352 {
00353     --value;
00354     Z = (value == 0);
00355     N = (value & 0x80) != 0;
00356     return (byte)value;
00357 }
00358 
00359 static void DEX()
00360 {
00361     X = DEC(X);
00362 }
00363 
00364 static void DEY()
00365 {
00366     Y = DEC(Y);
00367 }
00368 
00369 static void NOP()
00370 {
00371 }
00372 
00373 static void TXA()
00374 {
00375     SetReg(&A, X);
00376 }
00377 
00378 static void TAX()
00379 {
00380     SetReg(&X, A);
00381 }
00382 
00383 static void TYA()
00384 {
00385     SetReg(&A, Y);
00386 }
00387 
00388 static void TAY()
00389 {
00390     SetReg(&Y, A);
00391 }
00392 
00393 static void TXS()
00394 {
00395     S = X;
00396 }
00397 
00398 static void TSX()
00399 {
00400     SetReg(&X, S);
00401 }
00402 
00403 static ushort GetBR(ushort addr, bool *p_conditional, byte *p_bytes)
00404 {
00405     *p_conditional = true;
00406     *p_bytes = 2;
00407     sbyte offset = (sbyte)GetMemory((ushort)(addr + 1));
00408     ushort addr2 = (ushort)(addr + 2 + offset);
00409     return addr2;
00410 }
00411 
00412 static void BR(bool branch, ushort *p_addr, bool *p_conditional, byte *p_bytes)
00413 {
00414     ushort addr2 = GetBR(*p_addr, p_conditional, p_bytes);
00415     if (branch)
00416     {
00417         *p_addr = addr2;
00418         *p_bytes = 0; // don't advance addr
00419     }
00420 }
00421 
00422 static void BPL(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00423 {
00424     BR(!N, p_addr, p_conditional, p_bytes);
00425 }
00426 
00427 static void BMI(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00428 {
00429     BR(N, p_addr, p_conditional, p_bytes);
00430 }
00431 
00432 static void BCC(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00433 {
00434     BR(!C, p_addr, p_conditional, p_bytes);
00435 }
00436 
00437 static void BCS(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00438 {
00439     BR(C, p_addr, p_conditional, p_bytes);
00440 }
00441 
00442 static void BVC(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00443 {
00444     BR(!V, p_addr, p_conditional, p_bytes);
00445 }
00446 
00447 static void BVS(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00448 {
00449     BR(V, p_addr, p_conditional, p_bytes);
00450 }
00451 
00452 static void BNE(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00453 {
00454     BR(!Z, p_addr, p_conditional, p_bytes);
00455 }
00456 
00457 static void BEQ(ushort *p_addr, bool *p_conditional, byte *p_bytes)
00458 {
00459     BR(Z, p_addr, p_conditional, p_bytes);
00460 }
00461 
00462 static void JSR(ushort *p_addr, byte *p_bytes)
00463 {
00464     *p_bytes = 3; // for next calculation
00465     ushort addr2 = (ushort)(*p_addr + *p_bytes - 1);
00466     ushort addr3 = (ushort)(GetMemory((ushort)(*p_addr + 1)) | (GetMemory((ushort)(*p_addr + 2)) << 8));
00467     Push(HI(addr2));
00468     Push(LO(addr2));
00469     *p_addr = addr3;
00470     *p_bytes = 0; // addr already changed
00471 }
00472 
00473 static void RTS(ushort *p_addr, byte *p_bytes)
00474 {
00475     byte lo = Pop();
00476     byte hi = Pop();
00477     *p_bytes = 1; // make sure caller increases addr by one
00478     *p_addr = (ushort)((hi << 8) | lo);
00479 }
00480 
00481 static void RTI(ushort *p_addr, byte *p_bytes)
00482 {
00483     PLP();
00484     byte lo = Pop();
00485     byte hi = Pop();
00486     *p_bytes = 0; // make sure caller does not increase addr by one
00487     *p_addr = (ushort)((hi << 8) | lo);
00488 }
00489 
00490 static void BRK(byte *p_bytes)
00491 {
00492     ++PC;
00493     Push(HI(PC));
00494     Push(LO(PC));
00495     PHP();
00496     B = true;
00497     PC = (ushort)(GetMemory(0xFFFE) + (GetMemory(0xFFFF) << 8)); // JMP(IRQ)
00498     *p_bytes = 0;
00499 }
00500 
00501 static void JMP(ushort *p_addr, byte *p_bytes)
00502 {
00503     *p_bytes = 0; // caller should not advance address
00504     ushort addr2 = (ushort)(GetMemory((ushort)(*p_addr + 1)) | (GetMemory((ushort)(*p_addr + 2)) << 8));
00505     *p_addr = addr2;
00506 }
00507 
00508 static void JMPIND(ushort *p_addr, byte *p_bytes)
00509 {
00510     *p_bytes = 0; // caller should not advance address
00511     ushort addr2 = (ushort)(GetMemory((ushort)(*p_addr + 1)) | (GetMemory((ushort)(*p_addr + 2)) << 8));
00512     ushort addr3;
00513     if ((addr2 & 0xFF) == 0xFF) // JMP($XXFF) won't go over page boundary
00514         addr3 = (ushort)(GetMemory(addr2) | (GetMemory((ushort)(addr2 - 0xFF)) << 8)); // 6502 "bug" - will use XXFF and XX00 as source of address
00515     else
00516         addr3 = (ushort)(GetMemory(addr2) | (GetMemory((ushort)(addr2 + 1)) << 8));
00517     *p_addr = addr3;
00518 }
00519 
00520 // "A:FF X:FF Y:FF S:FF P:XX-XXXXX"
00521 static void GetDisplayState(char *state, int state_size)
00522 {
00523     snprintf(state, state_size, "A:%02X X:%02X Y:%02X S:%02X P:%c%c-%c%c%c%c%c",
00524         A,
00525         X,
00526         Y,
00527         S,
00528         N ? 'N' : ' ',
00529         V ? 'V' : ' ',
00530         B ? 'B' : ' ',
00531         D ? 'D' : ' ',
00532         I ? 'I' : ' ',
00533         Z ? 'Z' : ' ',
00534         C ? 'C' : ' '
00535     );
00536 }
00537 
00538 static byte GetIndX(ushort addr, byte *p_bytes)
00539 {
00540     *p_bytes = 2;
00541     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)) + X);
00542     return GetMemory((ushort)(GetMemory(addr2) | (GetMemory((ushort)(addr2 + 1)) << 8)));
00543 }
00544 
00545 static void SetIndX(byte value, ushort addr, byte *p_bytes)
00546 {
00547     *p_bytes = 2;
00548     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)) + X);
00549     ushort addr3 = (ushort)(GetMemory(addr2) | (GetMemory((ushort)(addr2 + 1)) << 8));
00550     SetMemory(addr3, value);
00551 }
00552 
00553 static byte GetIndY(ushort addr, byte *p_bytes)
00554 {
00555     *p_bytes = 2;
00556     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)));
00557     ushort addr3 = (ushort)((GetMemory(addr2) | (GetMemory((ushort)(addr2 + 1)) << 8)) + Y);
00558     return GetMemory(addr3);
00559 }
00560 
00561 static void SetIndY(byte value, ushort addr, byte *p_bytes)
00562 {
00563     *p_bytes = 2;
00564     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)));
00565     ushort addr3 = (ushort)((GetMemory(addr2) | (GetMemory((ushort)(addr2 + 1)) << 8)) + Y);
00566     SetMemory(addr3, value);
00567 }
00568 
00569 static byte GetZP(ushort addr, byte *p_bytes)
00570 {
00571     *p_bytes = 2;
00572     ushort addr2 = GetMemory((ushort)(addr + 1));
00573     return GetMemory(addr2);
00574 }
00575 
00576 static void SetZP(byte value, ushort addr, byte *p_bytes)
00577 {
00578     *p_bytes = 2;
00579     ushort addr2 = GetMemory((ushort)(addr + 1));
00580     SetMemory(addr2, value);
00581 }
00582 
00583 static byte GetZPX(ushort addr, byte *p_bytes)
00584 {
00585     *p_bytes = 2;
00586     ushort addr2 = GetMemory((ushort)(addr + 1));
00587     return GetMemory((byte)(addr2 + X));
00588 }
00589 
00590 static void SetZPX(byte value, ushort addr, byte *p_bytes)
00591 {
00592     *p_bytes = 2;
00593     ushort addr2 = GetMemory((ushort)(addr + 1));
00594     SetMemory((byte)(addr2 + X), value);
00595 }
00596 
00597 static byte GetZPY(ushort addr, byte *p_bytes)
00598 {
00599     *p_bytes = 2;
00600     ushort addr2 = GetMemory((ushort)(addr + 1));
00601     return GetMemory((byte)(addr2 + Y));
00602 }
00603 
00604 static void SetZPY(byte value, ushort addr, byte *p_bytes)
00605 {
00606     *p_bytes = 2;
00607     ushort addr2 = GetMemory((ushort)(addr + 1));
00608     SetMemory((byte)(addr2 + Y), value);
00609 }
00610 
00611 static byte GetABS(ushort addr, byte *p_bytes)
00612 {
00613     *p_bytes = 3;
00614     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00615     return GetMemory(addr2);
00616 }
00617 
00618 static void SetABS(byte value, ushort addr, byte *p_bytes)
00619 {
00620     *p_bytes = 3;
00621     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00622     SetMemory(addr2, value);
00623 }
00624 
00625 static byte GetABSX(ushort addr, byte *p_bytes)
00626 {
00627     *p_bytes = 3;
00628     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00629     return GetMemory((ushort)(addr2 + X));
00630 }
00631 
00632 static void SetABSX(byte value, ushort addr, byte *p_bytes)
00633 {
00634     *p_bytes = 3;
00635     ushort addr2 = (ushort)((GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8)) + X);
00636     SetMemory(addr2, value);
00637 }
00638 
00639 static byte GetABSY(ushort addr, byte *p_bytes)
00640 {
00641     *p_bytes = 3;
00642     ushort addr2 = (ushort)(GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00643     return GetMemory((ushort)(addr2 + Y));
00644 }
00645 
00646 static void SetABSY(byte value, ushort addr, byte *p_bytes)
00647 {
00648     *p_bytes = 3;
00649     ushort addr2 = (ushort)((GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8)) + Y);
00650     SetMemory(addr2, value);
00651 }
00652 
00653 static byte GetIM(ushort addr, byte *p_bytes)
00654 {
00655     *p_bytes = 2;
00656     return GetMemory((ushort)(addr + 1));
00657 }
00658 
00659 extern void Execute(ushort addr, bool (*ExecutePatch)(void))
00660 {
00661     bool conditional;
00662     byte bytes;
00663 
00664 #if (USE_IRQ == 1)
00665     // IRQ support
00666     Timer timer;
00667     const double interrupt_time = 1.0 / 60.0 ; // 60 times per second
00668     timer.start();
00669     double timer_then = timer.read();   
00670 #endif
00671 
00672     PC = addr;
00673 
00674     while (true)
00675     {
00676         while (true)
00677         {
00678 #if (USE_IRQ == 1)
00679             if (!I && (timer.read()-timer_then) >= interrupt_time) // IRQ
00680             {
00681                 timer_then = timer.read(); // reset timer
00682                 Push(HI(PC));
00683                 Push(LO(PC));
00684                 PHP();
00685                 I = true;
00686                 PC = (GetMemory(0xfffe) | (GetMemory(0xffff) << 8));
00687             }
00688             else
00689 #endif          
00690             {
00691                 bytes = 1;
00692                 bool breakpoint = false;
00693                 //if (Breakpoints.Contains(PC))
00694                 //  breakpoint = true;
00695                 if (trace || breakpoint || step)
00696                 {
00697                     ushort addr2;
00698                     char line[27];
00699                     char dis[13];
00700                     DisassembleLong(PC, &conditional, &bytes, &addr2, dis, sizeof(dis), line, sizeof(line));
00701                     char state[33];
00702                     GetDisplayState(state, sizeof(state));
00703                     char full_line[80];
00704                     snprintf(full_line, sizeof(full_line), "%-30s%s\n", line, state);
00705     #ifdef WIN32
00706                     OutputDebugStringA(full_line);
00707     #else               
00708                     pc.printf("%s", full_line);
00709     #endif              
00710                     if (step)
00711                         step = step; // user can put debug breakpoint here to allow stepping
00712                     if (breakpoint)
00713                         breakpoint = breakpoint; // user can put debug breakpoint here to allow break
00714                 }
00715                 if (ExecutePatch != 0 && !ExecutePatch()) // allow execute to be overriden at a specific address
00716                     break;
00717             }
00718         }
00719 
00720         switch (GetMemory(PC))
00721         {
00722         case 0x00: BRK(&bytes); break;
00723         case 0x01: ORA(GetIndX(PC, &bytes)); break;
00724         case 0x05: ORA(GetZP(PC, &bytes)); break;
00725         case 0x06: SetZP(ASL(GetZP(PC, &bytes)), PC, &bytes); break;
00726         case 0x08: PHP(); break;
00727         case 0x09: ORA(GetIM(PC, &bytes)); break;
00728         case 0x0A: SetA(ASL(A)); break;
00729         case 0x0D: ORA(GetABS(PC, &bytes)); break;
00730         case 0x0E: SetABS(ASL(GetABS(PC, &bytes)), PC, &bytes); break;
00731 
00732         case 0x10: BPL(&PC, &conditional, &bytes); break;
00733         case 0x11: ORA(GetIndY(PC, &bytes)); break;
00734         case 0x15: ORA(GetZPX(PC, &bytes)); break;
00735         case 0x16: SetZPX(ASL(GetZPX(PC, &bytes)), PC, &bytes); break;
00736         case 0x18: CLC(); break;
00737         case 0x19: ORA(GetABSY(PC, &bytes)); break;
00738         case 0x1D: ORA(GetABSX(PC, &bytes)); break;
00739         case 0x1E: SetABSX(ASL(GetABSX(PC, &bytes)), PC, &bytes); break;
00740 
00741         case 0x20: JSR(&PC, &bytes); break;
00742         case 0x21: AND(GetIndX(PC, &bytes)); break;
00743         case 0x24: BIT_OP(GetZP(PC, &bytes)); break;
00744         case 0x25: AND(GetZP(PC, &bytes)); break;
00745         case 0x26: SetZP(ROL(GetZP(PC, &bytes)), PC, &bytes); break;
00746         case 0x28: PLP(); break;
00747         case 0x29: AND(GetIM(PC, &bytes)); break;
00748         case 0x2A: SetA(ROL(A)); break;
00749         case 0x2C: BIT_OP(GetABS(PC, &bytes)); break;
00750         case 0x2D: AND(GetABS(PC, &bytes)); break;
00751         case 0x2E: ROL(GetABS(PC, &bytes)); break;
00752 
00753         case 0x30: BMI(&PC, &conditional, &bytes); break;
00754         case 0x31: AND(GetIndY(PC, &bytes)); break;
00755         case 0x35: AND(GetZPX(PC, &bytes)); break;
00756         case 0x36: SetZPX(ROL(GetZPX(PC, &bytes)), PC, &bytes); break;
00757         case 0x38: SEC(); break;
00758         case 0x39: AND(GetABSY(PC, &bytes)); break;
00759         case 0x3D: AND(GetABSX(PC, &bytes)); break;
00760         case 0x3E: SetABSX(ROL(GetABSX(PC, &bytes)), PC, &bytes); break;
00761 
00762         case 0x40: RTI(&PC, &bytes); break;
00763         case 0x41: EOR(GetIndX(PC, &bytes)); break;
00764         case 0x45: EOR(GetZP(PC, &bytes)); break;
00765         case 0x46: SetZP(LSR(GetZP(PC, &bytes)), PC, &bytes); break;
00766         case 0x48: PHA(); break;
00767         case 0x49: EOR(GetIM(PC, &bytes)); break;
00768         case 0x4A: SetA(LSR(A)); break;
00769         case 0x4C: JMP(&PC, &bytes); break;
00770         case 0x4D: EOR(GetABS(PC, &bytes)); break;
00771         case 0x4E: LSR(GetABS(PC, &bytes)); break;
00772 
00773         case 0x50: BVC(&PC, &conditional, &bytes); break;
00774         case 0x51: EOR(GetIndY(PC, &bytes)); break;
00775         case 0x55: EOR(GetZPX(PC, &bytes)); break;
00776         case 0x56: SetZPX(LSR(GetZPX(PC, &bytes)), PC, &bytes); break;
00777         case 0x58: CLI(); break;
00778         case 0x59: EOR(GetABSY(PC, &bytes)); break;
00779         case 0x5D: EOR(GetABSX(PC, &bytes)); break;
00780         case 0x5E: SetABSX(LSR(GetABSX(PC, &bytes)), PC, &bytes); break;
00781 
00782         case 0x60: RTS(&PC, &bytes); break;
00783         case 0x61: ADC_OP(GetIndX(PC, &bytes)); break;
00784         case 0x65: ADC_OP(GetZP(PC, &bytes)); break;
00785         case 0x66: SetZP(ROR(GetZP(PC, &bytes)), PC, &bytes); break;
00786         case 0x68: PLA(); break;
00787         case 0x69: ADC_OP(GetIM(PC, &bytes)); break;
00788         case 0x6A: SetA(ROR(A)); break;
00789         case 0x6C: JMPIND(&PC, &bytes); break;
00790         case 0x6D: ADC_OP(GetABS(PC, &bytes)); break;
00791         case 0x6E: SetABS(ROR(GetABS(PC, &bytes)), PC, &bytes); break;
00792 
00793         case 0x70: BVS(&PC, &conditional, &bytes); break;
00794         case 0x71: ADC_OP(GetIndY(PC, &bytes)); break;
00795         case 0x75: ADC_OP(GetZPX(PC, &bytes)); break;
00796         case 0x76: SetZPX(ROR(GetZPX(PC, &bytes)), PC, &bytes); break;
00797         case 0x78: SEI(); break;
00798         case 0x79: ADC_OP(GetABSY(PC, &bytes)); break;
00799         case 0x7D: ADC_OP(GetABSX(PC, &bytes)); break;
00800         case 0x7E: SetABSX(ROR(GetABSX(PC, &bytes)), PC, &bytes); break;
00801 
00802         case 0x81: SetIndX(A, PC, &bytes); break;
00803         case 0x84: SetZP(Y, PC, &bytes); break;
00804         case 0x85: SetZP(A, PC, &bytes); break;
00805         case 0x86: SetZP(X, PC, &bytes); break;
00806         case 0x88: DEY(); break;
00807         case 0x8A: TXA(); break;
00808         case 0x8C: SetABS(Y, PC, &bytes); break;
00809         case 0x8D: SetABS(A, PC, &bytes); break;
00810         case 0x8E: SetABS(X, PC, &bytes); break;
00811 
00812         case 0x90: BCC(&PC, &conditional, &bytes); break;
00813         case 0x91: SetIndY(A, PC, &bytes); break;
00814         case 0x94: SetZPX(Y, PC, &bytes); break;
00815         case 0x95: SetZPX(A, PC, &bytes); break;
00816         case 0x96: SetZPY(X, PC, &bytes); break;
00817         case 0x98: TYA(); break;
00818         case 0x99: SetABSY(A, PC, &bytes); break;
00819         case 0x9A: TXS(); break;
00820         case 0x9D: SetABSX(A, PC, &bytes); break;
00821 
00822         case 0xA0: SetY(GetIM(PC, &bytes)); break;
00823         case 0xA1: SetA(GetIndX(PC, &bytes)); break;
00824         case 0xA2: SetX(GetIM(PC, &bytes)); break;
00825         case 0xA4: SetY(GetZP(PC, &bytes)); break;
00826         case 0xA5: SetA(GetZP(PC, &bytes)); break;
00827         case 0xA6: SetX(GetZP(PC, &bytes)); break;
00828         case 0xA8: TAY(); break;
00829         case 0xA9: SetA(GetIM(PC, &bytes)); break;
00830         case 0xAA: TAX(); break;
00831         case 0xAC: SetY(GetABS(PC, &bytes)); break;
00832         case 0xAD: SetA(GetABS(PC, &bytes)); break;
00833         case 0xAE: SetX(GetABS(PC, &bytes)); break;
00834 
00835         case 0xB0: BCS(&PC, &conditional, &bytes); break;
00836         case 0xB1: SetA(GetIndY(PC, &bytes)); break;
00837         case 0xB4: SetY(GetZPX(PC, &bytes)); break;
00838         case 0xB5: SetA(GetZPX(PC, &bytes)); break;
00839         case 0xB6: SetX(GetZPY(PC, &bytes)); break;
00840         case 0xB8: CLV(); break;
00841         case 0xB9: SetA(GetABSY(PC, &bytes)); break;
00842         case 0xBA: TSX(); break;
00843         case 0xBC: SetY(GetABSX(PC, &bytes)); break;
00844         case 0xBD: SetA(GetABSX(PC, &bytes)); break;
00845         case 0xBE: SetX(GetABSY(PC, &bytes)); break;
00846 
00847         case 0xC0: CPY(GetIM(PC, &bytes)); break;
00848         case 0xC1: CMP(GetIndX(PC, &bytes)); break;
00849         case 0xC4: CPY(GetZP(PC, &bytes)); break;
00850         case 0xC5: CMP(GetZP(PC, &bytes)); break;
00851         case 0xC6: SetZP(DEC(GetZP(PC, &bytes)), PC, &bytes); break;
00852         case 0xC8: INY(); break;
00853         case 0xC9: CMP(GetIM(PC, &bytes)); break;
00854         case 0xCA: DEX(); break;
00855         case 0xCC: CPY(GetABS(PC, &bytes)); break;
00856         case 0xCD: CMP(GetABS(PC, &bytes)); break;
00857         case 0xCE: SetABS(DEC(GetABS(PC, &bytes)), PC, &bytes); break;
00858 
00859         case 0xD0: BNE(&PC, &conditional, &bytes); break;
00860         case 0xD1: CMP(GetIndY(PC, &bytes)); break;
00861         case 0xD5: CMP(GetZPX(PC, &bytes)); break;
00862         case 0xD6: SetZPX(DEC(GetZPX(PC, &bytes)), PC, &bytes); break;
00863         case 0xD8: CLD(); break;
00864         case 0xD9: CMP(GetABSY(PC, &bytes)); break;
00865         case 0xDD: CMP(GetABSX(PC, &bytes)); break;
00866         case 0xDE: SetABSX(DEC(GetABSX(PC, &bytes)), PC, &bytes); break;
00867 
00868         case 0xE0: CPX(GetIM(PC, &bytes)); break;
00869         case 0xE1: SBC(GetIndX(PC, &bytes)); break;
00870         case 0xE4: CPX(GetZP(PC, &bytes)); break;
00871         case 0xE5: SBC(GetZP(PC, &bytes)); break;
00872         case 0xE6: SetZP(INC(GetZP(PC, &bytes)), PC, &bytes); break;
00873         case 0xE8: INX(); break;
00874         case 0xE9: SBC(GetIM(PC, &bytes)); break;
00875         case 0xEA: NOP(); break;
00876         case 0xEC: CPX(GetABS(PC, &bytes)); break;
00877         case 0xED: SBC(GetABS(PC, &bytes)); break;
00878         case 0xEE: SetABS(INC(GetABS(PC, &bytes)), PC, &bytes); break;
00879 
00880         case 0xF0: BEQ(&PC, &conditional, &bytes); break;
00881         case 0xF1: SBC(GetIndY(PC, &bytes)); break;
00882         case 0xF5: SBC(GetZPX(PC, &bytes)); break;
00883         case 0xF6: SetZPX(INC(GetZPX(PC, &bytes)), PC, &bytes); break;
00884         case 0xF8: SED(); break;
00885         case 0xF9: SBC(GetABSY(PC, &bytes)); break;
00886         case 0xFD: SBC(GetABSX(PC, &bytes)); break;
00887         case 0xFE: SetABSX(INC(GetABSX(PC, &bytes)), PC, &bytes); break;
00888 
00889         default:
00890             {
00891                 printf("Invalid opcode %02X at %04X", GetMemory(PC), PC);
00892                 exit(1);
00893             }
00894         }
00895 
00896         PC += bytes;
00897     }
00898 }
00899 
00900 // Examples:
00901 // FFFF FF FF FF JMP ($FFFF)
00902 // FFFF FF FF FF LDA $FFFF,X
00903 extern void DisassembleLong(ushort addr, bool *p_conditional, byte *p_bytes, ushort *p_addr2, char *dis, int dis_size, char *line, int line_size)
00904 {
00905     DisassembleShort(addr, p_conditional, p_bytes, p_addr2, dis, dis_size);
00906     snprintf(line, line_size, "%04X ", addr);
00907     for (int i = 0; i < 3; ++i)
00908     {
00909         if (i < *p_bytes)
00910             snprintf(line+strlen(line), line_size-strlen(line), "%02X ", GetMemory((ushort)(addr + i)));
00911         else
00912             strcat_s(line, line_size, "   ");
00913     }
00914     strcat_s(line, line_size, dis);
00915 }
00916 
00917 static void Ind(char *dis, int dis_size, char* opcode, ushort addr, ushort *p_addr2, byte *p_bytes)
00918 {
00919     *p_bytes = 3;
00920     ushort addr1 = (ushort)(GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00921     *p_addr2 = (ushort)(GetMemory(addr1) | (GetMemory((ushort)(addr1 + 1)) << 8));
00922     snprintf(dis, dis_size, "%s ($%0X4)", opcode, addr1);
00923 }
00924 
00925 static void IndX(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00926 {
00927     *p_bytes = 2;
00928     snprintf(dis, dis_size, "%s ($%02X,X)", opcode, GetMemory((ushort)(addr + 1)));
00929 }
00930 
00931 static void IndY(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00932 {
00933     *p_bytes = 2;
00934     snprintf(dis, dis_size, "%s ($%02X),Y", opcode, GetMemory((ushort)(addr + 1)));
00935 }
00936 
00937 static void ZP(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00938 {
00939     *p_bytes = 2;
00940     snprintf(dis, dis_size, "%s $%02X", opcode, GetMemory((ushort)(addr + 1)));
00941 }
00942 
00943 static void ZPX(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00944 {
00945     *p_bytes = 2;
00946     snprintf(dis, dis_size, "%s $%02X,X", opcode, GetMemory((ushort)(addr + 1)));
00947 }
00948 
00949 static void ZPY(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00950 {
00951     *p_bytes = 2;
00952     snprintf(dis, dis_size, "%s $%02X,Y", opcode, GetMemory((ushort)(addr + 1)));
00953 }
00954 
00955 static void ABS(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00956 {
00957     *p_bytes = 3;
00958     snprintf(dis, dis_size, "%s $%04X", opcode, GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00959 }
00960 
00961 static void ABSAddr(char *dis, int dis_size, char* opcode, ushort addr, ushort *p_addr2, byte *p_bytes)
00962 {
00963     *p_bytes = 3;
00964     *p_addr2 = (ushort)(GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00965     snprintf(dis, dis_size, "%s $%04X", opcode, *p_addr2);
00966 }
00967 
00968 static void ABSX(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00969 {
00970     *p_bytes = 3;
00971     snprintf(dis, dis_size, "%s $%04X,X", opcode, GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00972 }
00973 
00974 static void ABSY(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00975 {
00976     *p_bytes = 3;
00977     snprintf(dis, dis_size, "%s $%04X,Y", opcode, GetMemory((ushort)(addr + 1)) | (GetMemory((ushort)(addr + 2)) << 8));
00978 }
00979 
00980 static void IM(char *dis, int dis_size, char* opcode, ushort addr, byte *p_bytes)
00981 {
00982     *p_bytes = 2;
00983     snprintf(dis, dis_size, "%s #$%02X", opcode, GetMemory((ushort)(addr + 1)));
00984 }
00985 
00986 static void BRX(char *dis, int dis_size, char* opcode, ushort addr, bool *p_conditional, ushort *p_addr2, byte *p_bytes)
00987 {
00988     *p_bytes = 2;
00989     *p_conditional = true;
00990     sbyte offset = (sbyte)GetMemory((ushort)(addr + 1));
00991     *p_addr2 = (ushort)(addr + 2 + offset);
00992     snprintf(dis, dis_size, "%s $%04X", opcode, *p_addr2);
00993 }
00994 
00995 // JMP ($FFFF)
00996 // LDA $FFFF,X
00997 extern void DisassembleShort(ushort addr, bool *p_conditional, byte *p_bytes, ushort *p_addr2, char *dis, int dis_size)
00998 {
00999     *p_conditional = false;
01000     *p_addr2 = 0;
01001     *p_bytes = 1;
01002 
01003     switch (GetMemory(addr))
01004     {
01005     case 0x00: strcpy_s(dis, dis_size, "BRK"); return;
01006     case 0x01: IndX(dis, dis_size, "ORA", addr, p_bytes); return;
01007     case 0x05: ZP(dis, dis_size, "ORA", addr, p_bytes); return;
01008     case 0x06: ZP(dis, dis_size, "ASL", addr, p_bytes); return;
01009     case 0x08: strcpy_s(dis, dis_size, "PHP"); return;
01010     case 0x09: IM(dis, dis_size, "ORA", addr, p_bytes); return;
01011     case 0x0A: strcpy_s(dis, dis_size, "ASL A"); return;
01012     case 0x0D: ABS(dis, dis_size, "ORA", addr, p_bytes); return;
01013     case 0x0E: ABS(dis, dis_size, "ASL", addr, p_bytes); return;
01014 
01015     case 0x10: BRX(dis, dis_size, "BPL", addr, p_conditional, p_addr2, p_bytes); return;
01016     case 0x11: IndY(dis, dis_size, "ORA", addr, p_bytes); return;
01017     case 0x15: ZPX(dis, dis_size, "ORA", addr, p_bytes); return;
01018     case 0x16: ZPX(dis, dis_size, "ASL", addr, p_bytes); return;
01019     case 0x18: strcpy_s(dis, dis_size, "CLC"); return;
01020     case 0x19: ABSY(dis, dis_size, "ORA", addr, p_bytes); return;
01021     case 0x1D: ABSX(dis, dis_size, "ORA", addr, p_bytes); return;
01022     case 0x1E: ABSX(dis, dis_size, "ASL", addr, p_bytes); return;
01023 
01024     case 0x20: ABSAddr(dis, dis_size, "JSR", addr, p_addr2, p_bytes); return;
01025     case 0x21: IndX(dis, dis_size, "AND", addr, p_bytes); return;
01026     case 0x24: ZP(dis, dis_size, "BIT", addr, p_bytes); return;
01027     case 0x25: ZP(dis, dis_size, "AND", addr, p_bytes); return;
01028     case 0x26: ZP(dis, dis_size, "ROL", addr, p_bytes); return;
01029     case 0x28: strcpy_s(dis, dis_size, "PLP"); return;
01030     case 0x29: IM(dis, dis_size, "AND", addr, p_bytes); return;
01031     case 0x2A: strcpy_s(dis, dis_size, "ROL A"); return;
01032     case 0x2C: ABS(dis, dis_size, "BIT", addr, p_bytes); return;
01033     case 0x2D: ABS(dis, dis_size, "AND", addr, p_bytes); return;
01034     case 0x2E: ABS(dis, dis_size, "ROL", addr, p_bytes); return;
01035 
01036     case 0x30: BRX(dis, dis_size, "BMI", addr, p_conditional, p_addr2, p_bytes); return;
01037     case 0x31: IndY(dis, dis_size, "AND", addr, p_bytes); return;
01038     case 0x35: ZPX(dis, dis_size, "AND", addr, p_bytes); return;
01039     case 0x36: ZPX(dis, dis_size, "ROL", addr, p_bytes); return;
01040     case 0x38: strcpy_s(dis, dis_size, "SEC"); return;
01041     case 0x39: ABSY(dis, dis_size, "AND", addr, p_bytes); return;
01042     case 0x3D: ABSX(dis, dis_size, "AND", addr, p_bytes); return;
01043     case 0x3E: ABSX(dis, dis_size, "ROL", addr, p_bytes); return;
01044 
01045     case 0x40: strcpy_s(dis, dis_size, "RTI"); return;
01046     case 0x41: IndX(dis, dis_size, "EOR", addr, p_bytes); return;
01047     case 0x45: ZP(dis, dis_size, "EOR", addr, p_bytes); return;
01048     case 0x46: ZP(dis, dis_size, "LSR", addr, p_bytes); return;
01049     case 0x48: strcpy_s(dis, dis_size, "PHA"); return;
01050     case 0x49: IM(dis, dis_size, "EOR", addr, p_bytes); return;
01051     case 0x4A: strcpy_s(dis, dis_size, "LSR A"); return;
01052     case 0x4C: ABSAddr(dis, dis_size, "JMP", addr, p_addr2, p_bytes); return;
01053     case 0x4D: ABS(dis, dis_size, "EOR", addr, p_bytes); return;
01054     case 0x4E: ABS(dis, dis_size, "LSR", addr, p_bytes); return;
01055 
01056     case 0x50: BRX(dis, dis_size, "BVC", addr, p_conditional, p_addr2, p_bytes); return;
01057     case 0x51: IndY(dis, dis_size, "EOR", addr, p_bytes); return;
01058     case 0x55: ZPX(dis, dis_size, "EOR", addr, p_bytes); return;
01059     case 0x56: ZPX(dis, dis_size, "LSR", addr, p_bytes); return;
01060     case 0x58: strcpy_s(dis, dis_size, "CLI"); return;
01061     case 0x59: ABSY(dis, dis_size, "EOR", addr, p_bytes); return;
01062     case 0x5D: ABSX(dis, dis_size, "EOR", addr, p_bytes); return;
01063     case 0x5E: ABSX(dis, dis_size, "LSR", addr, p_bytes); return;
01064 
01065     case 0x60: strcpy_s(dis, dis_size, "RTS"); return;
01066     case 0x61: IndX(dis, dis_size, "ADC", addr, p_bytes); return;
01067     case 0x65: ZP(dis, dis_size, "ADC", addr, p_bytes); return;
01068     case 0x66: ZP(dis, dis_size, "ROR", addr, p_bytes); return;
01069     case 0x68: strcpy_s(dis, dis_size, "PLA"); return;
01070     case 0x69: IM(dis, dis_size, "ADC", addr, p_bytes); return;
01071     case 0x6A: strcpy_s(dis, dis_size, "ROR A"); return;
01072     case 0x6C: Ind(dis, dis_size, "JMP", addr, p_addr2, p_bytes); return;
01073     case 0x6D: ABS(dis, dis_size, "ADC", addr, p_bytes); return;
01074     case 0x6E: ABS(dis, dis_size, "ROR", addr, p_bytes); return;
01075 
01076     case 0x70: BRX(dis, dis_size, "BVS", addr, p_conditional, p_addr2, p_bytes); return;
01077     case 0x71: IndY(dis, dis_size, "ADC", addr, p_bytes); return;
01078     case 0x75: ZPX(dis, dis_size, "ADC", addr, p_bytes); return;
01079     case 0x76: ZPX(dis, dis_size, "ROR", addr, p_bytes); return;
01080     case 0x78: strcpy_s(dis, dis_size, "SEI"); return;
01081     case 0x79: ABSY(dis, dis_size, "ADC", addr, p_bytes); return;
01082     case 0x7D: ABSX(dis, dis_size, "ADC", addr, p_bytes); return;
01083     case 0x7E: ABSX(dis, dis_size, "ROR", addr, p_bytes); return;
01084 
01085     case 0x81: IndX(dis, dis_size, "STA", addr, p_bytes); return;
01086     case 0x84: ZP(dis, dis_size, "STY", addr, p_bytes); return;
01087     case 0x85: ZP(dis, dis_size, "STA", addr, p_bytes); return;
01088     case 0x86: ZP(dis, dis_size, "STX", addr, p_bytes); return;
01089     case 0x88: strcpy_s(dis, dis_size, "DEY"); return;
01090     case 0x8A: strcpy_s(dis, dis_size, "TXA"); return;
01091     case 0x8C: ABS(dis, dis_size, "STY", addr, p_bytes); return;
01092     case 0x8D: ABS(dis, dis_size, "STA", addr, p_bytes); return;
01093     case 0x8E: ABS(dis, dis_size, "STX", addr, p_bytes); return;
01094 
01095     case 0x90: BRX(dis, dis_size, "BCC", addr, p_conditional, p_addr2, p_bytes); return;
01096     case 0x91: IndY(dis, dis_size, "STA", addr, p_bytes); return;
01097     case 0x94: ZPX(dis, dis_size, "STY", addr, p_bytes); return;
01098     case 0x95: ZPX(dis, dis_size, "STA", addr, p_bytes); return;
01099     case 0x96: ZPY(dis, dis_size, "STX", addr, p_bytes); return;
01100     case 0x98: strcpy_s(dis, dis_size, "TYA"); return;
01101     case 0x99: ABSY(dis, dis_size, "STA", addr, p_bytes); return;
01102     case 0x9A: strcpy_s(dis, dis_size, "TXS"); return;
01103     case 0x9D: ABSX(dis, dis_size, "STA", addr, p_bytes); return;
01104 
01105     case 0xA0: IM(dis, dis_size, "LDY", addr, p_bytes); return;
01106     case 0xA1: IndX(dis, dis_size, "LDA", addr, p_bytes); return;
01107     case 0xA2: IM(dis, dis_size, "LDX", addr, p_bytes); return;
01108     case 0xA4: ZP(dis, dis_size, "LDY", addr, p_bytes); return;
01109     case 0xA5: ZP(dis, dis_size, "LDA", addr, p_bytes); return;
01110     case 0xA6: ZP(dis, dis_size, "LDX", addr, p_bytes); return;
01111     case 0xA8: strcpy_s(dis, dis_size, "TAY"); return;
01112     case 0xA9: IM(dis, dis_size, "LDA", addr, p_bytes); return;
01113     case 0xAA: strcpy_s(dis, dis_size, "TAX"); return;
01114     case 0xAC: ABS(dis, dis_size, "LDY", addr, p_bytes); return;
01115     case 0xAD: ABS(dis, dis_size, "LDA", addr, p_bytes); return;
01116     case 0xAE: ABS(dis, dis_size, "LDX", addr, p_bytes); return;
01117 
01118     case 0xB0: BRX(dis, dis_size, "BCS", addr, p_conditional, p_addr2, p_bytes); return;
01119     case 0xB1: IndY(dis, dis_size, "LDA", addr, p_bytes); return;
01120     case 0xB4: ZPX(dis, dis_size, "LDY", addr, p_bytes); return;
01121     case 0xB5: ZPX(dis, dis_size, "LDA", addr, p_bytes); return;
01122     case 0xB6: ZPY(dis, dis_size, "LDX", addr, p_bytes); return;
01123     case 0xB8: strcpy_s(dis, dis_size, "CLV"); return;
01124     case 0xB9: ABSY(dis, dis_size, "LDA", addr, p_bytes); return;
01125     case 0xBA: strcpy_s(dis, dis_size, "TSX"); return;
01126     case 0xBC: ABSX(dis, dis_size, "LDY", addr, p_bytes); return;
01127     case 0xBD: ABSX(dis, dis_size, "LDA", addr, p_bytes); return;
01128     case 0xBE: ABSY(dis, dis_size, "LDX", addr, p_bytes); return;
01129 
01130     case 0xC0: IM(dis, dis_size, "CPY", addr, p_bytes); return;
01131     case 0xC1: IndX(dis, dis_size, "CMP", addr, p_bytes); return;
01132     case 0xC4: ZP(dis, dis_size, "CPY", addr, p_bytes); return;
01133     case 0xC5: ZP(dis, dis_size, "CMP", addr, p_bytes); return;
01134     case 0xC6: ZP(dis, dis_size, "DEC", addr, p_bytes); return;
01135     case 0xC8: strcpy_s(dis, dis_size, "INY"); return;
01136     case 0xC9: IM(dis, dis_size, "CMP", addr, p_bytes); return;
01137     case 0xCA: strcpy_s(dis, dis_size, "DEX"); return;
01138     case 0xCC: ABS(dis, dis_size, "CPY", addr, p_bytes); return;
01139     case 0xCD: ABS(dis, dis_size, "CMP", addr, p_bytes); return;
01140     case 0xCE: ABS(dis, dis_size, "DEC", addr, p_bytes); return;
01141 
01142     case 0xD0: BRX(dis, dis_size, "BNE", addr, p_conditional, p_addr2, p_bytes); return;
01143     case 0xD1: IndY(dis, dis_size, "CMP", addr, p_bytes); return;
01144     case 0xD5: ZPX(dis, dis_size, "CMP", addr, p_bytes); return;
01145     case 0xD6: ZPX(dis, dis_size, "DEC", addr, p_bytes); return;
01146     case 0xD8: strcpy_s(dis, dis_size, "CLD"); return;
01147     case 0xD9: ABSY(dis, dis_size, "CMP", addr, p_bytes); return;
01148     case 0xDD: ABSX(dis, dis_size, "CMP", addr, p_bytes); return;
01149     case 0xDE: ABSX(dis, dis_size, "DEC", addr, p_bytes); return;
01150 
01151     case 0xE0: IM(dis, dis_size, "CPX", addr, p_bytes); return;
01152     case 0xE1: IndX(dis, dis_size, "SBC", addr, p_bytes); return;
01153     case 0xE4: ZP(dis, dis_size, "CPX", addr, p_bytes); return;
01154     case 0xE5: ZP(dis, dis_size, "SBC", addr, p_bytes); return;
01155     case 0xE6: ZP(dis, dis_size, "INC", addr, p_bytes); return;
01156     case 0xE8: strcpy_s(dis, dis_size, "INX"); return;
01157     case 0xE9: IM(dis, dis_size, "SBC", addr, p_bytes); return;
01158     case 0xEA: strcpy_s(dis, dis_size, "NOP"); return;
01159     case 0xEC: ABS(dis, dis_size, "CPX", addr, p_bytes); return;
01160     case 0xED: ABS(dis, dis_size, "SBC", addr, p_bytes); return;
01161     case 0xEE: ABS(dis, dis_size, "INC", addr, p_bytes); return;
01162 
01163     case 0xF0: BRX(dis, dis_size, "BEQ", addr, p_conditional, p_addr2, p_bytes); return;
01164     case 0xF1: IndY(dis, dis_size, "SBC", addr, p_bytes); return;
01165     case 0xF5: ZPX(dis, dis_size, "SBC", addr, p_bytes); return;
01166     case 0xF6: ZPX(dis, dis_size, "INC", addr, p_bytes); return;
01167     case 0xF8: strcpy_s(dis, dis_size, "SED"); return;
01168     case 0xF9: ABSY(dis, dis_size, "SBC", addr, p_bytes); return;
01169     case 0xFD: ABSX(dis, dis_size, "SBC", addr, p_bytes); return;
01170     case 0xFE: ABSX(dis, dis_size, "INC", addr, p_bytes); return;
01171 
01172     default:
01173         strcpy_s(dis, dis_size, "???");
01174         return;
01175         //throw new Exception(string.Format("Invalid opcode {0:X2}", memory[addr]));
01176     }
01177 }