|
|
1.1.1.3 root 1: /*
1.1 root 2: * UAE - The Un*x Amiga Emulator
1.1.1.3 root 3: *
1.1 root 4: * Debugger
1.1.1.3 root 5: *
1.1 root 6: * (c) 1995 Bernd Schmidt
1.1.1.3 root 7: *
1.1 root 8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include <ctype.h>
14: #include <signal.h>
15:
16: #include "config.h"
17: #include "options.h"
1.1.1.3 root 18: #include "threaddep/penguin.h"
19: #include "uae.h"
1.1 root 20: #include "memory.h"
21: #include "custom.h"
1.1.1.2 root 22: #include "readcpu.h"
1.1 root 23: #include "newcpu.h"
24: #include "debug.h"
25: #include "cia.h"
26: #include "xwin.h"
27: #include "gui.h"
28:
29: static int debugger_active = 0;
1.1.1.3 root 30: static uaecptr skipaddr;
1.1 root 31: static int do_skip;
32: int debugging = 0;
33:
1.1.1.4 ! root 34: void activate_debugger (void)
1.1 root 35: {
36: do_skip = 0;
37: if (debugger_active)
38: return;
39: debugger_active = 1;
40: regs.spcflags |= SPCFLAG_BRK;
41: debugging = 1;
42: use_debugger = 1;
43: }
44:
45: int firsthist = 0;
46: int lasthist = 0;
47: #ifdef NEED_TO_DEBUG_BADLY
48: struct regstruct history[MAX_HIST];
49: union flagu historyf[MAX_HIST];
50: #else
1.1.1.3 root 51: uaecptr history[MAX_HIST];
1.1 root 52: #endif
53:
1.1.1.4 ! root 54: static void ignore_ws (char **c)
1.1 root 55: {
56: while (**c && isspace(**c)) (*c)++;
57: }
58:
1.1.1.4 ! root 59: static uae_u32 readhex (char **c)
1.1 root 60: {
1.1.1.3 root 61: uae_u32 val = 0;
1.1 root 62: char nc;
63:
1.1.1.4 ! root 64: ignore_ws (c);
1.1.1.3 root 65:
1.1.1.4 ! root 66: while (isxdigit(nc = **c)) {
1.1 root 67: (*c)++;
68: val *= 16;
69: nc = toupper(nc);
70: if (isdigit(nc)) {
71: val += nc - '0';
72: } else {
73: val += nc - 'A' + 10;
74: }
75: }
76: return val;
77: }
78:
1.1.1.4 ! root 79: static char next_char( char **c)
1.1 root 80: {
1.1.1.4 ! root 81: ignore_ws (c);
1.1 root 82: return *(*c)++;
83: }
84:
1.1.1.4 ! root 85: static int more_params (char **c)
1.1 root 86: {
1.1.1.4 ! root 87: ignore_ws (c);
1.1 root 88: return (**c) != 0;
89: }
90:
1.1.1.4 ! root 91: static void dumpmem (uaecptr addr, uaecptr *nxmem, int lines)
1.1 root 92: {
93: broken_in = 0;
1.1.1.4 ! root 94: for (;lines-- && !broken_in;) {
1.1 root 95: int i;
1.1.1.4 ! root 96: printf ("%08lx ", addr);
! 97: for (i = 0; i < 16; i++) {
! 98: printf ("%04x ", get_word(addr)); addr += 2;
1.1 root 99: }
1.1.1.4 ! root 100: printf ("\n");
1.1 root 101: }
102: *nxmem = addr;
103: }
104:
1.1.1.3 root 105: static void foundmod (uae_u32 ptr, char *type)
1.1.1.2 root 106: {
1.1.1.3 root 107: char name[21];
108: uae_u8 *ptr2 = chipmemory + ptr;
109: int i,length;
110:
111: printf ("Found possible %s module at 0x%lx.\n", type, ptr);
112: memcpy (name, ptr2, 20);
113: name[20] = '\0';
114:
115: /* Browse playlist */
116: length = 0;
117: for (i = 0x3b8; i < 0x438; i++)
118: if (ptr2[i] > length)
119: length = ptr2[i];
120:
121: length = (length+1)*1024 + 0x43c;
122:
123: /* Add sample lengths */
124: ptr2 += 0x2A;
1.1.1.4 ! root 125: for (i = 0; i < 31; i++, ptr2 += 30)
1.1.1.3 root 126: length += 2*((ptr2[0]<<8)+ptr2[1]);
1.1.1.2 root 127:
1.1.1.4 ! root 128: printf ("Name \"%s\", Length 0x%lx bytes.\n", name, length);
1.1.1.3 root 129: }
130:
1.1.1.4 ! root 131: static void modulesearch (void)
1.1.1.3 root 132: {
133: uae_u8 *p = get_real_address (0);
134: uae_u32 ptr;
135:
1.1.1.4 ! root 136: for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
1.1.1.2 root 137: /* Check for Mahoney & Kaktus */
138: /* Anyone got the format of old 15 Sample (SoundTracker)modules? */
1.1.1.3 root 139: if (ptr >= 0x438 && p[0] == 'M' && p[1] == '.' && p[2] == 'K' && p[3] == '.')
140: foundmod (ptr - 0x438, "ProTracker (31 samples)");
141:
142: if (ptr >= 0x438 && p[0] == 'F' && p[1] == 'L' && p[2] == 'T' && p[3] == '4')
143: foundmod (ptr - 0x438, "Startrekker");
144:
145: if (strncmp ((char *)p, "SMOD", 4) == 0) {
146: printf ("Found possible FutureComposer 1.3 module at 0x%lx, length unknown.\n", ptr);
147: }
148: if (strncmp ((char *)p, "FC14", 4) == 0) {
149: printf ("Found possible FutureComposer 1.4 module at 0x%lx, length unknown.\n", ptr);
150: }
151: if (p[0] == 0x48 && p[1] == 0xe7 && p[4] == 0x61 && p[5] == 0
152: && p[8] == 0x4c && p[9] == 0xdf && p[12] == 0x4e && p[13] == 0x75
153: && p[14] == 0x48 && p[15] == 0xe7 && p[18] == 0x61 && p[19] == 0
154: && p[22] == 0x4c && p[23] == 0xdf && p[26] == 0x4e && p[27] == 0x75) {
155: printf ("Found possible Whittaker module at 0x%lx, length unknown.\n", ptr);
156: }
157: if (p[4] == 0x41 && p[5] == 0xFA) {
158: int i;
159:
160: for (i = 0; i < 0x240; i += 2)
161: if (p[i] == 0xE7 && p[i + 1] == 0x42 && p[i + 2] == 0x41 && p[i + 3] == 0xFA)
162: break;
163: if (i < 0x240) {
164: uae_u8 *p2 = p + i + 4;
165: for (i = 0; i < 0x30; i += 2)
166: if (p2[i] == 0xD1 && p2[i + 1] == 0xFA) {
167: printf ("Found possible MarkII module at %lx, length unknown.\n", ptr);
168: }
169: }
170:
1.1.1.2 root 171: }
172: }
173: }
174:
1.1.1.4 ! root 175: /* cheat-search by Holger Jakob */
! 176: static void cheatsearch (char **c)
! 177: {
! 178: uae_u8 *p = get_real_address (0);
! 179: static uae_u32 *vlist = NULL;
! 180: uae_u32 ptr;
! 181: uae_u32 val = 0;
! 182: uae_u32 type = 0; /* not yet */
! 183: uae_u32 count = 0;
! 184: uae_u32 fcount = 0;
! 185: uae_u32 full = 0;
! 186: char nc;
! 187:
! 188: ignore_ws (c);
! 189:
! 190: while (isxdigit (nc = **c)) {
! 191: (*c)++;
! 192: val *= 10;
! 193: nc = toupper (nc);
! 194: if (isdigit (nc)) {
! 195: val += nc - '0';
! 196: }
! 197: }
! 198: if (vlist == NULL) {
! 199: vlist = malloc (256*4);
! 200: if (vlist != 0) {
! 201: for (count = 0; count<255; count++)
! 202: vlist[count] = 0;
! 203: count = 0;
! 204: for (ptr = 0; ptr < allocated_chipmem - 40; ptr += 2, p += 2) {
! 205: if (ptr >= 0x438 && p[3] == (val & 0xff)
! 206: && p[2] == (val >> 8 & 0xff)
! 207: && p[1] == (val >> 16 & 0xff)
! 208: && p[0] == (val >> 24 & 0xff))
! 209: {
! 210: if (count < 255) {
! 211: vlist[count++]=ptr;
! 212: printf ("%08x: %x%x%x%x\n",ptr,p[0],p[1],p[2],p[3]);
! 213: } else
! 214: full = 1;
! 215: }
! 216: }
! 217: printf ("Found %d possible addresses with %d\n",count,val);
! 218: printf ("Now continue with 'g' and use 'C' with a different value\n");
! 219: }
! 220: } else {
! 221: for (count = 0; count<255; count++) {
! 222: if (p[vlist[count]+3] == (val & 0xff)
! 223: && p[vlist[count]+2] == (val>>8 & 0xff)
! 224: && p[vlist[count]+1] == (val>>16 & 0xff)
! 225: && p[vlist[count]] == (val>>24 & 0xff))
! 226: {
! 227: fcount++;
! 228: printf ("%08x: %x%x%x%x\n", vlist[count], p[vlist[count]],
! 229: p[vlist[count]+1], p[vlist[count]+2], p[vlist[count]+3]);
! 230: }
! 231: }
! 232: printf ("%d hits of %d found\n",fcount,val);
! 233: free (vlist);
! 234: vlist = NULL;
! 235: }
! 236: }
! 237:
! 238: static void writeintomem (char **c)
! 239: {
! 240: uae_u8 *p = get_real_address (0);
! 241: uae_u32 addr = 0;
! 242: uae_u32 val = 0;
! 243: char nc;
! 244:
! 245: ignore_ws(c);
! 246: while (isxdigit(nc = **c)) {
! 247: (*c)++;
! 248: addr *= 16;
! 249: nc = toupper(nc);
! 250: if (isdigit(nc)) {
! 251: addr += nc - '0';
! 252: } else {
! 253: addr += nc - 'A' + 10;
! 254: }
! 255: }
! 256: ignore_ws(c);
! 257: while (isxdigit(nc = **c)) {
! 258: (*c)++;
! 259: val *= 10;
! 260: nc = toupper(nc);
! 261: if (isdigit(nc)) {
! 262: val += nc - '0';
! 263: }
! 264: }
! 265:
! 266: if (addr < allocated_chipmem) {
! 267: p[addr] = val>>24 & 0xff;
! 268: p[addr+1] = val>>16 & 0xff;
! 269: p[addr+2] = val>>8 & 0xff;
! 270: p[addr+3] = val & 0xff;
! 271: printf("Wrote %d at %08x\n",val,addr);
! 272: } else
! 273: printf("Invalid address %08x\n",addr);
! 274: }
! 275:
! 276: void debug (void)
1.1 root 277: {
1.1.1.4 ! root 278: char input[80];
1.1.1.3 root 279: uaecptr nextpc,nxdis,nxmem;
1.1 root 280:
281: bogusframe = 1;
1.1.1.3 root 282:
1.1 root 283: if (do_skip && (m68k_getpc() != skipaddr/* || regs.a[0] != 0x1e558*/)) {
284: regs.spcflags |= SPCFLAG_BRK;
285: return;
286: }
287: do_skip = 0;
288:
289: #ifdef NEED_TO_DEBUG_BADLY
290: history[lasthist] = regs;
291: historyf[lasthist] = regflags;
292: #else
293: history[lasthist] = m68k_getpc();
294: #endif
295: if (++lasthist == MAX_HIST) lasthist = 0;
296: if (lasthist == firsthist) {
297: if (++firsthist == MAX_HIST) firsthist = 0;
298: }
299:
1.1.1.4 ! root 300: m68k_dumpstate (&nextpc);
1.1 root 301: nxdis = nextpc; nxmem = 0;
302:
1.1.1.4 ! root 303: for (;;) {
! 304: char cmd, *inptr;
1.1.1.3 root 305:
1.1.1.4 ! root 306: printf (">");
1.1.1.2 root 307: fflush (stdout);
1.1.1.4 ! root 308: if (fgets (input, 80, stdin) == 0)
1.1.1.2 root 309: return;
1.1 root 310: inptr = input;
1.1.1.4 ! root 311: cmd = next_char (&inptr);
! 312: switch (cmd) {
! 313: case 'c': dumpcia (); dumpcustom (); break;
! 314: case 'r': m68k_dumpstate (&nextpc); break;
! 315: case 'M': modulesearch (); break;
! 316: case 'C': cheatsearch (&inptr); break;
! 317: case 'W': writeintomem (&inptr); break;
1.1.1.3 root 318: case 'S':
319: {
320: uae_u8 *memp;
321: uae_u32 src, len;
322: char *name;
323: FILE *fp;
324:
325: if (!more_params (&inptr))
326: goto S_argh;
327:
328: name = inptr;
329: while (*inptr != '\0' && !isspace (*inptr))
330: inptr++;
331: if (!isspace (*inptr))
332: goto S_argh;
333:
334: *inptr = '\0';
335: inptr++;
336: if (!more_params (&inptr))
337: goto S_argh;
338: src = readhex (&inptr);
339: if (!more_params (&inptr))
340: goto S_argh;
341: len = readhex (&inptr);
342: if (! valid_address (src, len)) {
343: printf ("Invalid memory block\n");
344: break;
345: }
346: memp = get_real_address (src);
347: fp = fopen (name, "w");
348: if (fp == NULL) {
349: printf ("Couldn't open file\n");
350: break;
351: }
352: if (fwrite (memp, 1, len, fp) != len) {
353: printf ("Error writing file\n");
354: }
355: fclose (fp);
356: break;
357:
358: S_argh:
359: printf ("S command needs more arguments!\n");
360: break;
361: }
362: case 'd':
1.1 root 363: {
1.1.1.3 root 364: uae_u32 daddr;
1.1 root 365: int count;
1.1.1.3 root 366:
1.1 root 367: if (more_params(&inptr))
368: daddr = readhex(&inptr);
1.1.1.3 root 369: else
1.1 root 370: daddr = nxdis;
371: if (more_params(&inptr))
1.1.1.3 root 372: count = readhex(&inptr);
1.1 root 373: else
374: count = 10;
375: m68k_disasm(daddr, &nxdis, count);
376: }
377: break;
378: case 't': regs.spcflags |= SPCFLAG_BRK; return;
379: case 'z':
380: skipaddr = nextpc;
381: do_skip = 1;
382: regs.spcflags |= SPCFLAG_BRK;
383: return;
384:
1.1.1.3 root 385: case 'f':
1.1 root 386: skipaddr = readhex(&inptr);
387: do_skip = 1;
388: regs.spcflags |= SPCFLAG_BRK;
389: return;
390:
1.1.1.3 root 391: case 'q': uae_quit();
392: debugger_active = 0;
393: debugging = 0;
394: return;
395:
1.1 root 396: case 'g':
397: if (more_params (&inptr))
398: m68k_setpc (readhex (&inptr));
1.1.1.3 root 399: fill_prefetch_0 ();
1.1 root 400: debugger_active = 0;
401: debugging = 0;
402: return;
403:
404: case 'H':
405: {
406: int count;
407: int temp;
408: #ifdef NEED_TO_DEBUG_BADLY
409: struct regstruct save_regs = regs;
410: union flagu save_flags = regflags;
411: #endif
412:
1.1.1.3 root 413: if (more_params(&inptr))
414: count = readhex(&inptr);
415: else
1.1 root 416: count = 10;
1.1.1.3 root 417: if (count < 0)
1.1 root 418: break;
1.1.1.3 root 419: temp = lasthist;
420: while (count-- > 0 && temp != firsthist) {
1.1 root 421: if (temp == 0) temp = MAX_HIST-1; else temp--;
1.1.1.3 root 422: }
423: while (temp != lasthist) {
1.1 root 424: #ifdef NEED_TO_DEBUG_BADLY
425: regs = history[temp];
426: regflags = historyf[temp];
427: m68k_dumpstate(NULL);
428: #else
429: m68k_disasm(history[temp], NULL, 1);
430: #endif
431: if (++temp == MAX_HIST) temp = 0;
1.1.1.3 root 432: }
1.1 root 433: #ifdef NEED_TO_DEBUG_BADLY
434: regs = save_regs;
435: regflags = save_flags;
436: #endif
437: }
438: break;
439: case 'm':
440: {
1.1.1.3 root 441: uae_u32 maddr; int lines;
1.1 root 442: if (more_params(&inptr))
1.1.1.3 root 443: maddr = readhex(&inptr);
444: else
1.1 root 445: maddr = nxmem;
446: if (more_params(&inptr))
1.1.1.3 root 447: lines = readhex(&inptr);
448: else
1.1 root 449: lines = 16;
450: dumpmem(maddr, &nxmem, lines);
451: }
452: break;
1.1.1.3 root 453: case 'h':
454: case '?':
1.1 root 455: {
1.1.1.3 root 456: printf (" HELP for UAE Debugger\n");
457: printf (" -----------------------\n\n");
458: printf (" g: <address> Start execution at the current address or <address>\n");
459: printf (" c: Dump state of the CIA and custom chips\n");
460: printf (" r: Dump state of the CPU\n");
461: printf (" m <address> <lines>: Memory dump starting at <address>\n");
462: printf (" d <address> <lines>: Disassembly starting at <address>\n");
463: printf (" t: Step one instruction\n");
464: printf (" z: Step through one instruction - useful for JSR, DBRA etc\n");
465: printf (" f <address>: Step forward until PC == <address>\n");
466: printf (" H <count>: Show PC history <count> instructions\n");
467: printf (" M: Search for *Tracker sound modules\n");
1.1.1.4 ! root 468: printf (" C <value>: Search for values like energy or lifes in games\n");
! 469: printf (" W <address> <value>: Write into Amiga memory\n");
1.1.1.3 root 470: printf (" S <file> <addr> <n>: Save a block of Amiga memory\n");
471: printf (" h,?: Show this help page\n");
472: printf (" q: Quit the emulator. You don't want to use this command.\n\n");
473: }
474: break;
475:
1.1 root 476: }
477: }
478: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.