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