123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- /** M6502: portable 6502 emulator ****************************/
- /** **/
- /** Debug.c **/
- /** **/
- /** This file contains the built-in debugging routine for **/
- /** the 6502 emulator which is called on each 6502 step **/
- /** when Trap!=0. **/
- /** **/
- /** Copyright (C) Marat Fayzullin 1996-1997 **/
- /** Alex Krasivsky 1996 **/
- /** You are not allowed to distribute this software **/
- /** commercially. Please, notify me, if you make any **/
- /** changes to this file. **/
- /*************************************************************/
- /*
- * $LastChangedDate$
- * $Author$
- * $HeadURL$
- * $Revision$
- */
- #include "M6502.h"
- #ifdef DEBUG
- #include <allegro.h>
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <ppu/ppu.h>
- #include <mappers/manager.h>
- #include <memory/manager.h>
- #include <Sound.h>
- #define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
- extern unsigned char *Memory;
- void showlastop();
- enum Addressing_Modes
- {
- Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
- };
- static char *mn[] =
- {
- "adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
- "bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
- "clv", "cmp ", "cpx ", "cpy ", "dec ", "dex", "dey", "inx",
- "iny", "eor ", "inc ", "jmp ", "jsr ", "lda ", "nop ", "ldx ",
- "ldy ", "lsr ", "ora ", "pha", "php", "pla", "plp", "rol ",
- "ror ", "rti", "rts", "sbc ", "sta ", "stx ", "sty ", "sec ",
- "sed", "sei", "tax", "tay", "txa", "tya", "tsx", "txs"
- };
- static byte ad[512] =
- {
- 10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
- 36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
- 9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
- 13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
- 28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
- 38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
- 7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
- 47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
- 41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
- 35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
- 11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
- 15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
- 42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
- 37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
- 12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
- 49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
- No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
- 22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
- 3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
- 53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
- 32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
- 51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
- 4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
- 16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
- 19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
- 24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
- 8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
- 14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
- 18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
- 23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
- 5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
- 48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
- };
- /** DAsm() ****************************************************/
- /** This function will disassemble a single command and **/
- /** return the number of bytes disassembled. **/
- /**************************************************************/
- int DAsm(char *S, word A)
- {
-
- byte J;
-
- word B, OP, TO;
-
-
- B = A;
- OP = Rd6502(B++) * 2;
-
-
- switch (ad[OP + 1])
-
- {
-
- case Ac:
- sprintf(S, "%s a", mn[ad[OP]]);
- break;
-
- case Il:
- sprintf(S, "%s", mn[ad[OP]]);
- break;
-
-
- case Rl:
- J = Rd6502(B++);
- TO = A + 2 + ((J < 0x80) ? J : (J - 256));
-
- sprintf(S, "%s $%04X", mn[ad[OP]], TO);
- break;
-
-
- case Im:
- sprintf(S, "%s #$%02X", mn[ad[OP]], Rd6502(B++));
- break;
-
- case Zp:
- sprintf(S, "%s $%02X", mn[ad[OP]], Rd6502(B++));
- break;
-
- case Zx:
- sprintf(S, "%s $%02X,x", mn[ad[OP]], Rd6502(B++));
- break;
-
- case Zy:
- sprintf(S, "%s $%02X,y", mn[ad[OP]], Rd6502(B++));
- break;
-
- case Ix:
- sprintf(S, "%s ($%02X,x)", mn[ad[OP]], Rd6502(B++));
- break;
-
- case Iy:
- sprintf(S, "%s ($%02X),y", mn[ad[OP]], Rd6502(B++));
- break;
-
-
- case Ab:
- sprintf(S, "%s $%04X", mn[ad[OP]], RDWORD(B));
- B += 2;
- break;
-
- case Ax:
- sprintf(S, "%s $%04X,x", mn[ad[OP]], RDWORD(B));
- B += 2;
- break;
-
- case Ay:
- sprintf(S, "%s $%04X,y", mn[ad[OP]], RDWORD(B));
- B += 2;
- break;
-
- case In:
- sprintf(S, "%s ($%04X)", mn[ad[OP]], RDWORD(B));
- B += 2;
- break;
-
-
- default:
- sprintf(S, ".db $%02X; <Invalid OPcode>", OP / 2);
-
- }
- return (B - A);
-
- }
- /** Debug6502() **********************************************/
- /** This function should exist if DEBUG is #defined. When **/
- /** Trace!=0, it is called after each command executed by **/
- /** the CPU, and given the 6502 registers. Emulation exits **/
- /** if Debug6502() returns 0. **/
- /*************************************************************/
- byte Debug6502(M6502 * R)
- {
- static char FA[8] = "NVRBDIZC";
- char S[128];
- byte F;
- int J, I;
-
- DAsm(S, R->PC.W);
-
- printf
- (
- "A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
- R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
- );
-
-
- for (J = 0, F = R->P; J < 8; J++, F <<= 1)
-
- printf("%c", F & 0x80 ? FA[J] : '.');
-
- puts("]");
-
-
- printf
- (
- "AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
- Rd6502(R->PC.W), S,
- Rd6502(0x0100 + (byte) (R->S + 1)),
- Rd6502(0x0100 + (byte) (R->S + 2)),
- Rd6502(0x0100 + (byte) (R->S + 3))
- );
- S[0] = 0;
- remove_keyboard();
- #ifdef USE_SOUND
- StopSound();
- #endif
-
- while (1)
- {
- printf("\n[Command,'?']-> ");
-
- fflush(stdout);
- fflush(stdin);
- fgets(S, 50, stdin);
-
- for (J = 0; S[J] >= ' '; J++)
- S[J] = toupper(S[J]);
-
- S[J] = '\0';
-
-
- switch (S[0])
- {
- case 'H':
- case '?':
- puts("\n***** Built-in 6502 Debugger Commands *****");
- puts("<CR> : Break at the next instruction");
- puts("= <addr> : Break at addr");
- puts("+ <offset> : Break at PC + offset");
- puts("t <addr> : Set PC to addr");
- puts("c : Continue without break");
- puts("j <addr> : Continue from addr");
- puts("m <addr> : Memory dump at addr");
- puts("d <addr> : Disassembly at addr");
- puts("v : Show ;interrupt vectors");
- puts("?,h : Show this help text");
- puts("r : Show Register Status");
- puts("q : Exit 6502 emulation");
-
- puts("----- TI-NES Specific -----");
- puts("w : Dump Memory State");
- puts("o : Show PPU registers");
- puts("p <addr> : Dump PPU memory at addr");
- puts("a : Dump all memory to memory.log");
- puts("s : Dump sprite table to sprite.log");
- puts("n <nb> : Dump name table <nb> to nt.log");
- puts("z : Dump mapper status");
- puts("i : SpriteTable Dump");
- puts("g <nb> : Get sprite <nb> info");
- break;
-
- case '\0':
- return (1);
-
- case 'Z':
- mapper_dump(stdout);
- break;
- case 'W':
- DumpMemoryState(stdout);
- break;
-
-
- case 'A':
- {
-
- FILE * fpDmpMem;
-
- if ((fpDmpMem = fopen("memory.log", "wb")) != NULL)
-
- {
-
- // fwrite(Memory, 1, 0x8000, fpDmpMem);
- //fwrite(mLBank, 1, 0x4000, fpDmpMem);
- //fwrite(mUBank, 1, 0x4000, fpDmpMem);
-
- fclose(fpDmpMem);
-
- }
- }
- break;
-
-
-
-
-
- case '=':
- if (strlen(S) >= 2)
-
- {
- sscanf(S + 1, "%hX", &(R->Trap));
- R->Trace = 0;
- return (1);
- }
- break;
-
- case '+':
- if (strlen(S) >= 2)
-
- {
-
- sscanf(S + 1, "%hX", &(R->Trap));
-
- R->Trap += R->PC.W;
- R->Trace = 0;
-
- return (1);
-
- }
- break;
-
- case 'J':
- if (strlen(S) >= 2)
-
- {
- sscanf(S + 1, "%hX", &(R->PC.W));
- R->Trace = 0;
- return (1);
- }
- break;
-
- case 'T':
- if (strlen(S) >= 2)
-
- {
- sscanf(S + 1, "%hX", &(R->PC.W));
- R->Trace = 1;
- }
- break;
- case 'C':
- R->Trap = 0xFFFF;
- R->Trace = 0;
- install_keyboard();
-
- //ResumeSound();
-
- SetSound(0, SND_RECTANGLE);
- SetSound(1, SND_RECTANGLE);
- SetSound(2, SND_TRIANGLE);
- SetSound(3, SND_NOISE);
-
- return (1);
-
- case 'Q':
- return (0);
-
-
- case 'V':
- puts("\n6502 Interrupt Vectors:");
- printf("[$FFFC] INIT: $%04X\n", Rd6502(0xFFFC) + 256 * Rd6502(0xFFFD));
- printf("[$FFFE] IRQ: $%04X\n", Rd6502(0xFFFE) + 256 * Rd6502(0xFFFF));
- printf("[$FFFA] NMI: $%04X\n", Rd6502(0xFFFA) + 256 * Rd6502(0xFFFB));
- break;
-
- case 'M':
- {
- word Addr;
-
- if (strlen(S) > 1)
- sscanf(S + 1, "%hX", &Addr);
- else
- Addr = R->PC.W;
- puts("");
- for (J = 0; J < 16; J++)
- {
- printf("%04X: ", Addr);
- for (I = 0; I < 16; I++, Addr++)
-
- printf("%02X ", Rd6502(Addr));
-
- printf(" | ");
- Addr -= 16;
-
- for (I = 0; I < 16; I++, Addr++)
-
- putchar(isprint(Rd6502(Addr)) ? Rd6502(Addr) : '.');
-
- puts("");
-
- }
- }
- break;
-
- case 'R':
-
- printf
- (
- "A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
- R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
- );
-
-
- for (J = 0, F = R->P; J < 8; J++, F <<= 1)
-
- printf("%c", F & 0x80 ? FA[J] : '.');
-
- puts("]");
-
-
- printf
- (
- "AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
- Rd6502(R->PC.W), S,
- Rd6502(0x0100 + (byte) (R->S + 1)),
- Rd6502(0x0100 + (byte) (R->S + 2)),
- Rd6502(0x0100 + (byte) (R->S + 3))
- );
-
- break;
-
-
- case 'D':
-
- {
-
- word Addr;
-
-
- if (strlen(S) > 1)
- sscanf(S + 1, "%hX", &Addr);
- else
- Addr = R->PC.W;
-
- puts("");
-
- for (J = 0; J < 16; J++)
-
- {
-
- printf("%04X: ", Addr);
-
- Addr += DAsm(S, Addr);
-
- puts(S);
-
- }
- }
- break;
-
- }
- }
-
- /* Continue with emulation */
- return (1);
-
- }
- #endif /* DEBUG */
|