Debug.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /** M6502: portable 6502 emulator ****************************/
  2. /** **/
  3. /** Debug.c **/
  4. /** **/
  5. /** This file contains the built-in debugging routine for **/
  6. /** the 6502 emulator which is called on each 6502 step **/
  7. /** when Trap!=0. **/
  8. /** **/
  9. /** Copyright (C) Marat Fayzullin 1996-1997 **/
  10. /** Alex Krasivsky 1996 **/
  11. /** You are not allowed to distribute this software **/
  12. /** commercially. Please, notify me, if you make any **/
  13. /** changes to this file. **/
  14. /*************************************************************/
  15. /*
  16. * $LastChangedDate$
  17. * $Author$
  18. * $HeadURL$
  19. * $Revision$
  20. */
  21. #include "M6502.h"
  22. #ifdef DEBUG
  23. #include <allegro.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <ctype.h>
  27. #include <ppu/ppu.h>
  28. #include <mappers/manager.h>
  29. #include <memory/manager.h>
  30. #include <Sound.h>
  31. #define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
  32. extern unsigned char *Memory;
  33. void showlastop();
  34. enum Addressing_Modes
  35. {
  36. Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
  37. };
  38. static char *mn[] =
  39. {
  40. "adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
  41. "bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
  42. "clv", "cmp ", "cpx ", "cpy ", "dec ", "dex", "dey", "inx",
  43. "iny", "eor ", "inc ", "jmp ", "jsr ", "lda ", "nop ", "ldx ",
  44. "ldy ", "lsr ", "ora ", "pha", "php", "pla", "plp", "rol ",
  45. "ror ", "rti", "rts", "sbc ", "sta ", "stx ", "sty ", "sec ",
  46. "sed", "sei", "tax", "tay", "txa", "tya", "tsx", "txs"
  47. };
  48. static byte ad[512] =
  49. {
  50. 10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
  51. 36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
  52. 9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
  53. 13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
  54. 28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
  55. 38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
  56. 7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
  57. 47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
  58. 41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
  59. 35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
  60. 11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
  61. 15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
  62. 42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
  63. 37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
  64. 12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
  65. 49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
  66. No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
  67. 22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
  68. 3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
  69. 53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
  70. 32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
  71. 51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
  72. 4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
  73. 16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
  74. 19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
  75. 24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
  76. 8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
  77. 14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
  78. 18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
  79. 23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
  80. 5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
  81. 48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
  82. };
  83. /** DAsm() ****************************************************/
  84. /** This function will disassemble a single command and **/
  85. /** return the number of bytes disassembled. **/
  86. /**************************************************************/
  87. int DAsm(char *S, word A)
  88. {
  89. byte J;
  90. word B, OP, TO;
  91. B = A;
  92. OP = Rd6502(B++) * 2;
  93. switch (ad[OP + 1])
  94. {
  95. case Ac:
  96. sprintf(S, "%s a", mn[ad[OP]]);
  97. break;
  98. case Il:
  99. sprintf(S, "%s", mn[ad[OP]]);
  100. break;
  101. case Rl:
  102. J = Rd6502(B++);
  103. TO = A + 2 + ((J < 0x80) ? J : (J - 256));
  104. sprintf(S, "%s $%04X", mn[ad[OP]], TO);
  105. break;
  106. case Im:
  107. sprintf(S, "%s #$%02X", mn[ad[OP]], Rd6502(B++));
  108. break;
  109. case Zp:
  110. sprintf(S, "%s $%02X", mn[ad[OP]], Rd6502(B++));
  111. break;
  112. case Zx:
  113. sprintf(S, "%s $%02X,x", mn[ad[OP]], Rd6502(B++));
  114. break;
  115. case Zy:
  116. sprintf(S, "%s $%02X,y", mn[ad[OP]], Rd6502(B++));
  117. break;
  118. case Ix:
  119. sprintf(S, "%s ($%02X,x)", mn[ad[OP]], Rd6502(B++));
  120. break;
  121. case Iy:
  122. sprintf(S, "%s ($%02X),y", mn[ad[OP]], Rd6502(B++));
  123. break;
  124. case Ab:
  125. sprintf(S, "%s $%04X", mn[ad[OP]], RDWORD(B));
  126. B += 2;
  127. break;
  128. case Ax:
  129. sprintf(S, "%s $%04X,x", mn[ad[OP]], RDWORD(B));
  130. B += 2;
  131. break;
  132. case Ay:
  133. sprintf(S, "%s $%04X,y", mn[ad[OP]], RDWORD(B));
  134. B += 2;
  135. break;
  136. case In:
  137. sprintf(S, "%s ($%04X)", mn[ad[OP]], RDWORD(B));
  138. B += 2;
  139. break;
  140. default:
  141. sprintf(S, ".db $%02X; <Invalid OPcode>", OP / 2);
  142. }
  143. return (B - A);
  144. }
  145. /** Debug6502() **********************************************/
  146. /** This function should exist if DEBUG is #defined. When **/
  147. /** Trace!=0, it is called after each command executed by **/
  148. /** the CPU, and given the 6502 registers. Emulation exits **/
  149. /** if Debug6502() returns 0. **/
  150. /*************************************************************/
  151. byte Debug6502(M6502 * R)
  152. {
  153. static char FA[8] = "NVRBDIZC";
  154. char S[128];
  155. byte F;
  156. int J, I;
  157. DAsm(S, R->PC.W);
  158. printf
  159. (
  160. "A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
  161. R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
  162. );
  163. for (J = 0, F = R->P; J < 8; J++, F <<= 1)
  164. printf("%c", F & 0x80 ? FA[J] : '.');
  165. puts("]");
  166. printf
  167. (
  168. "AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
  169. Rd6502(R->PC.W), S,
  170. Rd6502(0x0100 + (byte) (R->S + 1)),
  171. Rd6502(0x0100 + (byte) (R->S + 2)),
  172. Rd6502(0x0100 + (byte) (R->S + 3))
  173. );
  174. S[0] = 0;
  175. remove_keyboard();
  176. #ifdef USE_SOUND
  177. StopSound();
  178. #endif
  179. while (1)
  180. {
  181. printf("\n[Command,'?']-> ");
  182. fflush(stdout);
  183. fflush(stdin);
  184. fgets(S, 50, stdin);
  185. for (J = 0; S[J] >= ' '; J++)
  186. S[J] = toupper(S[J]);
  187. S[J] = '\0';
  188. switch (S[0])
  189. {
  190. case 'H':
  191. case '?':
  192. puts("\n***** Built-in 6502 Debugger Commands *****");
  193. puts("<CR> : Break at the next instruction");
  194. puts("= <addr> : Break at addr");
  195. puts("+ <offset> : Break at PC + offset");
  196. puts("t <addr> : Set PC to addr");
  197. puts("c : Continue without break");
  198. puts("j <addr> : Continue from addr");
  199. puts("m <addr> : Memory dump at addr");
  200. puts("d <addr> : Disassembly at addr");
  201. puts("v : Show ;interrupt vectors");
  202. puts("?,h : Show this help text");
  203. puts("r : Show Register Status");
  204. puts("q : Exit 6502 emulation");
  205. puts("----- TI-NES Specific -----");
  206. puts("w : Dump Memory State");
  207. puts("o : Show PPU registers");
  208. puts("p <addr> : Dump PPU memory at addr");
  209. puts("a : Dump all memory to memory.log");
  210. puts("s : Dump sprite table to sprite.log");
  211. puts("n <nb> : Dump name table <nb> to nt.log");
  212. puts("z : Dump mapper status");
  213. puts("i : SpriteTable Dump");
  214. puts("g <nb> : Get sprite <nb> info");
  215. break;
  216. case '\0':
  217. return (1);
  218. case 'Z':
  219. mapper_dump(stdout);
  220. break;
  221. case 'W':
  222. DumpMemoryState(stdout);
  223. break;
  224. case 'A':
  225. {
  226. FILE * fpDmpMem;
  227. if ((fpDmpMem = fopen("memory.log", "wb")) != NULL)
  228. {
  229. // fwrite(Memory, 1, 0x8000, fpDmpMem);
  230. //fwrite(mLBank, 1, 0x4000, fpDmpMem);
  231. //fwrite(mUBank, 1, 0x4000, fpDmpMem);
  232. fclose(fpDmpMem);
  233. }
  234. }
  235. break;
  236. case '=':
  237. if (strlen(S) >= 2)
  238. {
  239. sscanf(S + 1, "%hX", &(R->Trap));
  240. R->Trace = 0;
  241. return (1);
  242. }
  243. break;
  244. case '+':
  245. if (strlen(S) >= 2)
  246. {
  247. sscanf(S + 1, "%hX", &(R->Trap));
  248. R->Trap += R->PC.W;
  249. R->Trace = 0;
  250. return (1);
  251. }
  252. break;
  253. case 'J':
  254. if (strlen(S) >= 2)
  255. {
  256. sscanf(S + 1, "%hX", &(R->PC.W));
  257. R->Trace = 0;
  258. return (1);
  259. }
  260. break;
  261. case 'T':
  262. if (strlen(S) >= 2)
  263. {
  264. sscanf(S + 1, "%hX", &(R->PC.W));
  265. R->Trace = 1;
  266. }
  267. break;
  268. case 'C':
  269. R->Trap = 0xFFFF;
  270. R->Trace = 0;
  271. install_keyboard();
  272. //ResumeSound();
  273. SetSound(0, SND_RECTANGLE);
  274. SetSound(1, SND_RECTANGLE);
  275. SetSound(2, SND_TRIANGLE);
  276. SetSound(3, SND_NOISE);
  277. return (1);
  278. case 'Q':
  279. return (0);
  280. case 'V':
  281. puts("\n6502 Interrupt Vectors:");
  282. printf("[$FFFC] INIT: $%04X\n", Rd6502(0xFFFC) + 256 * Rd6502(0xFFFD));
  283. printf("[$FFFE] IRQ: $%04X\n", Rd6502(0xFFFE) + 256 * Rd6502(0xFFFF));
  284. printf("[$FFFA] NMI: $%04X\n", Rd6502(0xFFFA) + 256 * Rd6502(0xFFFB));
  285. break;
  286. case 'M':
  287. {
  288. word Addr;
  289. if (strlen(S) > 1)
  290. sscanf(S + 1, "%hX", &Addr);
  291. else
  292. Addr = R->PC.W;
  293. puts("");
  294. for (J = 0; J < 16; J++)
  295. {
  296. printf("%04X: ", Addr);
  297. for (I = 0; I < 16; I++, Addr++)
  298. printf("%02X ", Rd6502(Addr));
  299. printf(" | ");
  300. Addr -= 16;
  301. for (I = 0; I < 16; I++, Addr++)
  302. putchar(isprint(Rd6502(Addr)) ? Rd6502(Addr) : '.');
  303. puts("");
  304. }
  305. }
  306. break;
  307. case 'R':
  308. printf
  309. (
  310. "A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
  311. R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
  312. );
  313. for (J = 0, F = R->P; J < 8; J++, F <<= 1)
  314. printf("%c", F & 0x80 ? FA[J] : '.');
  315. puts("]");
  316. printf
  317. (
  318. "AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
  319. Rd6502(R->PC.W), S,
  320. Rd6502(0x0100 + (byte) (R->S + 1)),
  321. Rd6502(0x0100 + (byte) (R->S + 2)),
  322. Rd6502(0x0100 + (byte) (R->S + 3))
  323. );
  324. break;
  325. case 'D':
  326. {
  327. word Addr;
  328. if (strlen(S) > 1)
  329. sscanf(S + 1, "%hX", &Addr);
  330. else
  331. Addr = R->PC.W;
  332. puts("");
  333. for (J = 0; J < 16; J++)
  334. {
  335. printf("%04X: ", Addr);
  336. Addr += DAsm(S, Addr);
  337. puts(S);
  338. }
  339. }
  340. break;
  341. }
  342. }
  343. /* Continue with emulation */
  344. return (1);
  345. }
  346. #endif /* DEBUG */