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