1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "GBA.h"
24 #include "Port.h"
25 #include "armdis.h"
26 #include "elf.h"
27 #include "exprNode.h"
28
29 extern bool debugger;
30 extern int emulating;
31
32 extern struct EmulatedSystem emulator;
33
34 #define debuggerReadMemory(addr) \
35 READ32LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
36
37 #define debuggerReadHalfWord(addr) \
38 READ16LE((&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
39
40 #define debuggerReadByte(addr) \
41 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
42
43 #define debuggerWriteMemory(addr, value) \
44 WRITE32LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
45
46 #define debuggerWriteHalfWord(addr, value) \
47 WRITE16LE(&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask], value)
48
49 #define debuggerWriteByte(addr, value) \
50 map[(addr)>>24].address[(addr) & map[(addr)>>24].mask] = (value)
51
52 struct breakpointInfo {
53 u32 address;
54 u32 value;
55 int size;
56 };
57
58 struct DebuggerCommand {
59 char *name;
60 void (*function)(int,char **);
61 char *help;
62 char *syntax;
63 };
64
65 void debuggerContinueAfterBreakpoint();
66
67 void debuggerHelp(int,char **);
68 void debuggerNext(int,char **);
69 void debuggerContinue(int, char **);
70 void debuggerRegisters(int, char **);
71 void debuggerBreak(int, char **);
72 void debuggerBreakDelete(int, char **);
73 void debuggerBreakList(int, char **);
74 void debuggerBreakArm(int, char **);
75 void debuggerBreakWriteClear(int, char **);
76 void debuggerBreakThumb(int, char **);
77 void debuggerBreakWrite(int, char **);
78 void debuggerDebug(int, char **);
79 void debuggerDisassemble(int, char **);
80 void debuggerDisassembleArm(int, char **);
81 void debuggerDisassembleThumb(int, char **);
82 void debuggerEditByte(int, char **);
83 void debuggerEditHalfWord(int, char **);
84 void debuggerEdit(int, char **);
85 void debuggerIo(int, char **);
86 void debuggerLocals(int, char **);
87 void debuggerMemoryByte(int, char **);
88 void debuggerMemoryHalfWord(int, char **);
89 void debuggerMemory(int, char **);
90 void debuggerPrint(int, char **);
91 void debuggerQuit(int, char **);
92 void debuggerSetRadix(int, char **);
93 void debuggerSymbols(int, char **);
94 void debuggerVerbose(int, char **);
95 void debuggerWhere(int, char **);
96
97 DebuggerCommand debuggerCommands[] = {
98 { "?", debuggerHelp, "Shows this help information. Type ? <command> for command help", "[<command>]" },
99 { "ba", debuggerBreakArm, "Adds an ARM breakpoint", "<address>" },
100 { "bd", debuggerBreakDelete,"Deletes a breakpoint", "<number>" },
101 { "bl", debuggerBreakList, "Lists breakpoints" },
102 { "bpw", debuggerBreakWrite, "Break on write", "<address> <size>" },
103 { "bpwc", debuggerBreakWriteClear, "Clear break on write", NULL },
104 { "break", debuggerBreak, "Adds a breakpoint on the given function", "<function>|<line>|<file:line>" },
105 { "bt", debuggerBreakThumb, "Adds a THUMB breakpoint", "<address>" },
106 { "c", debuggerContinue, "Continues execution" , NULL },
107 { "d", debuggerDisassemble, "Disassembles instructions", "[<address> [<number>]]" },
108 { "da", debuggerDisassembleArm, "Disassembles ARM instructions", "[<address> [<number>]]" },
109 { "dt", debuggerDisassembleThumb, "Disassembles THUMB instructions", "[<address> [<number>]]" },
110 { "eb", debuggerEditByte, "Modify memory location (byte)", "<address> <hex value>" },
111 { "eh", debuggerEditHalfWord,"Modify memory location (half-word)","<address> <hex value>" },
112 { "ew", debuggerEdit, "Modify memory location (word)", "<address> <hex value" },
113 { "h", debuggerHelp, "Shows this help information. Type h <command> for command help", "[<command>]" },
114 { "io", debuggerIo, "Show I/O registers status", "[video|video2|dma|timer|misc]" },
115 { "locals", debuggerLocals, "Shows local variables", NULL },
116 { "mb", debuggerMemoryByte, "Shows memory contents (bytes)", "<address>" },
117 { "mh", debuggerMemoryHalfWord, "Shows memory contents (half-words)", "<address>"},
118 { "mw", debuggerMemory, "Shows memory contents (words)", "<address>" },
119 { "n", debuggerNext, "Executes the next instruction", "[<count>]" },
120 { "print", debuggerPrint, "Print the value of a expression (if known)", "[/x|/o|/d] <expression>" },
121 { "q", debuggerQuit, "Quits the emulator", NULL },
122 { "r", debuggerRegisters, "Shows ARM registers", NULL },
123 { "radix", debuggerSetRadix, "Sets the print radix", "<radix>" },
124 { "symbols", debuggerSymbols, "List symbols", "[<symbol>]" },
125 #ifndef FINAL_VERSION
126 { "trace", debuggerDebug, "Sets the trace level", "<value>" },
127 #endif
128 #ifdef DEV_VERSION
129 { "verbose", debuggerVerbose, "Change verbose setting", "<value>" },
130 #endif
131 { "where", debuggerWhere, "Shows call chain", NULL },
132 { NULL, NULL, NULL, NULL} // end marker
133 };
134
135 breakpointInfo debuggerBreakpointList[100];
136
137 int debuggerNumOfBreakpoints = 0;
138 bool debuggerAtBreakpoint = false;
139 int debuggerBreakpointNumber = 0;
140 int debuggerRadix = 0;
141
debuggerApplyBreakpoint(u32 address,int num,int size)142 void debuggerApplyBreakpoint(u32 address, int num, int size)
143 {
144 if(size)
145 debuggerWriteMemory(address, (u32)(0xe1200070 |
146 (num & 0xf) |
147 ((num<<4)&0xf0)));
148 else
149 debuggerWriteHalfWord(address,
150 (u16)(0xbe00 | num));
151 }
152
debuggerDisableBreakpoints()153 void debuggerDisableBreakpoints()
154 {
155 for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
156 if(debuggerBreakpointList[i].size)
157 debuggerWriteMemory(debuggerBreakpointList[i].address,
158 debuggerBreakpointList[i].value);
159 else
160 debuggerWriteHalfWord(debuggerBreakpointList[i].address,
161 debuggerBreakpointList[i].value);
162 }
163 }
164
debuggerEnableBreakpoints(bool skipPC)165 void debuggerEnableBreakpoints(bool skipPC)
166 {
167 for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
168 if(debuggerBreakpointList[i].address == armNextPC && skipPC)
169 continue;
170
171 debuggerApplyBreakpoint(debuggerBreakpointList[i].address,
172 i,
173 debuggerBreakpointList[i].size);
174 }
175 }
176
debuggerUsage(char * cmd)177 void debuggerUsage(char *cmd)
178 {
179 for(int i = 0; ; i++) {
180 if(debuggerCommands[i].name) {
181 if(!strcmp(debuggerCommands[i].name, cmd)) {
182 printf("%s %s\t%s\n",
183 debuggerCommands[i].name,
184 debuggerCommands[i].syntax ? debuggerCommands[i].syntax : "",
185 debuggerCommands[i].help);
186 break;
187 }
188 } else {
189 printf("Unrecognized command '%s'.", cmd);
190 break;
191 }
192 }
193 }
194
debuggerPrintBaseType(Type * t,u32 value,u32 location,LocationType type,int bitSize,int bitOffset)195 void debuggerPrintBaseType(Type *t, u32 value, u32 location,
196 LocationType type,
197 int bitSize, int bitOffset)
198 {
199 if(bitSize) {
200 if(bitOffset)
201 value >>= ((t->size*8)-bitOffset-bitSize);
202 value &= (1 << bitSize)-1;
203 } else {
204 if(t->size == 2)
205 value &= 0xFFFF;
206 else if(t->size == 1)
207 value &= 0xFF;
208 }
209
210 if(t->size == 8) {
211 u64 value = 0;
212 if(type == LOCATION_memory) {
213 value = debuggerReadMemory(location) |
214 ((u64)debuggerReadMemory(location+4)<<32);
215 } else if(type == LOCATION_register) {
216 value = reg[location].I | ((u64)reg[location+1].I << 32);
217 }
218 switch(t->encoding) {
219 case DW_ATE_signed:
220 switch(debuggerRadix) {
221 case 0:
222 printf("%lld", value);
223 break;
224 case 1:
225 printf("0x%llx", value);
226 break;
227 case 2:
228 printf("0%llo", value);
229 break;
230 }
231 break;
232 case DW_ATE_unsigned:
233 switch(debuggerRadix) {
234 case 0:
235 printf("%llu", value);
236 break;
237 case 1:
238 printf("0x%llx", value);
239 break;
240 case 2:
241 printf("0%llo", value);
242 break;
243 }
244 break;
245 default:
246 printf("Unknowing 64-bit encoding\n");
247 }
248 return;
249 }
250
251 switch(t->encoding) {
252 case DW_ATE_boolean:
253 if(value)
254 printf("true");
255 else
256 printf("false");
257 break;
258 case DW_ATE_signed:
259 switch(debuggerRadix) {
260 case 0:
261 printf("%d", value);
262 break;
263 case 1:
264 printf("0x%x", value);
265 break;
266 case 2:
267 printf("0%o", value);
268 break;
269 }
270 break;
271 case DW_ATE_unsigned:
272 case DW_ATE_unsigned_char:
273 switch(debuggerRadix) {
274 case 0:
275 printf("%u", value);
276 break;
277 case 1:
278 printf("0x%x", value);
279 break;
280 case 2:
281 printf("0%o", value);
282 break;
283 }
284 break;
285 default:
286 printf("UNKNOWN BASE %d %08x", t->encoding, value);
287 }
288 }
289
debuggerPrintType(Type * t)290 char *debuggerPrintType(Type *t)
291 {
292 char buffer[1024];
293 static char buffer2[1024];
294
295 if(t->type == TYPE_pointer) {
296 if(t->pointer)
297 strcpy(buffer, debuggerPrintType(t->pointer));
298 else
299 strcpy(buffer, "void");
300 sprintf(buffer2, "%s *", buffer);
301 return buffer2;
302 } else if(t->type == TYPE_reference) {
303 strcpy(buffer, debuggerPrintType(t->pointer));
304 sprintf(buffer2, "%s &", buffer);
305 return buffer2;
306 }
307 return t->name;
308 }
309
310 void debuggerPrintValueInternal(Function *, Type *, ELFBlock *, int, int, u32);
311 void debuggerPrintValueInternal(Function *f, Type *t,
312 int bitSize, int bitOffset,
313 u32 objLocation, LocationType type);
314
debuggerGetValue(u32 location,LocationType type)315 u32 debuggerGetValue(u32 location, LocationType type)
316 {
317 switch(type) {
318 case LOCATION_memory:
319 return debuggerReadMemory(location);
320 case LOCATION_register:
321 return reg[location].I;
322 case LOCATION_value:
323 return location;
324 }
325 return 0;
326 }
327
debuggerPrintPointer(Type * t,u32 value)328 void debuggerPrintPointer(Type *t, u32 value)
329 {
330 printf("(%s)0x%08x", debuggerPrintType(t), value);
331 }
332
debuggerPrintReference(Type * t,u32 value)333 void debuggerPrintReference(Type *t, u32 value)
334 {
335 printf("(%s)0x%08x", debuggerPrintType(t), value);
336 }
337
debuggerPrintFunction(Type * t,u32 value)338 void debuggerPrintFunction(Type *t, u32 value)
339 {
340 printf("(%s)0x%08x", debuggerPrintType(t), value);
341 }
342
debuggerPrintArray(Type * t,u32 value)343 void debuggerPrintArray(Type *t, u32 value)
344 {
345 // todo
346 printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value);
347 }
348
debuggerPrintMember(Function * f,Member * m,u32 objLocation,u32 location)349 void debuggerPrintMember(Function *f,
350 Member *m,
351 u32 objLocation,
352 u32 location)
353 {
354 int bitSize = m->bitSize;
355 if(bitSize) {
356 u32 value = 0;
357 int off = m->bitOffset;
358 int size = m->byteSize;
359 u32 v = 0;
360 if(size == 1)
361 v = debuggerReadByte(location);
362 else if(size == 2)
363 v = debuggerReadHalfWord(location);
364 else if(size == 4)
365 v = debuggerReadMemory(location);
366
367 while(bitSize) {
368 int top = size*8 - off;
369 int bot = top - bitSize;
370 top--;
371 if(bot >= 0) {
372 value = (v >> (size*8 - bitSize - off)) & ((1 << bitSize)-1);
373 bitSize = 0;
374 } else {
375 value |= (v & ((1 << top)-1)) << (bitSize - top);
376 bitSize -= (top+1);
377 location -= size;
378 off = 0;
379 if(size == 1)
380 v = debuggerReadByte(location);
381 else if(size == 2)
382 v = debuggerReadHalfWord(location);
383 else
384 v = debuggerReadMemory(location);
385 }
386 }
387 debuggerPrintBaseType(m->type, value, location, LOCATION_memory,
388 bitSize, 0);
389 } else {
390 debuggerPrintValueInternal(f, m->type, m->location, m->bitSize,
391 m->bitOffset, objLocation);
392 }
393 }
394
debuggerPrintStructure(Function * f,Type * t,u32 objLocation)395 void debuggerPrintStructure(Function *f, Type *t, u32 objLocation)
396 {
397 printf("{");
398 int count = t->structure->memberCount;
399 int i = 0;
400 while(i < count) {
401 Member *m = &t->structure->members[i];
402 printf("%s=", m->name);
403 LocationType type;
404 u32 location = elfDecodeLocation(f, m->location, &type, objLocation);
405 debuggerPrintMember(f, m, objLocation, location);
406 i++;
407 if(i < count)
408 printf(",");
409 }
410 printf("}");
411 }
412
debuggerPrintUnion(Function * f,Type * t,u32 objLocation)413 void debuggerPrintUnion(Function *f, Type *t, u32 objLocation)
414 {
415 // todo
416 printf("{");
417 int count = t->structure->memberCount;
418 int i = 0;
419 while(i < count) {
420 Member *m = &t->structure->members[i];
421 printf("%s=", m->name);
422 debuggerPrintMember(f, m, objLocation, 0);
423 i++;
424 if(i < count)
425 printf(",");
426 }
427 printf("}");
428 }
429
debuggerPrintEnum(Type * t,u32 value)430 void debuggerPrintEnum(Type *t, u32 value)
431 {
432 int i;
433 for(i = 0; i < t->enumeration->count; i++) {
434 EnumMember *m = (EnumMember *)&t->enumeration->members[i];
435 if(value == m->value) {
436 printf(m->name);
437 return;
438 }
439 }
440 printf("(UNKNOWN VALUE) %d", value);
441 }
442
debuggerPrintValueInternal(Function * f,Type * t,int bitSize,int bitOffset,u32 objLocation,LocationType type)443 void debuggerPrintValueInternal(Function *f, Type *t,
444 int bitSize, int bitOffset,
445 u32 objLocation, LocationType type)
446 {
447 u32 value = debuggerGetValue(objLocation, type);
448 if(!t) {
449 printf("void");
450 return;
451 }
452 switch(t->type) {
453 case TYPE_base:
454 debuggerPrintBaseType(t, value, objLocation, type, bitSize, bitOffset);
455 break;
456 case TYPE_pointer:
457 debuggerPrintPointer(t, value);
458 break;
459 case TYPE_reference:
460 debuggerPrintReference(t, value);
461 break;
462 case TYPE_function:
463 debuggerPrintFunction(t, value);
464 break;
465 case TYPE_array:
466 debuggerPrintArray(t, objLocation);
467 break;
468 case TYPE_struct:
469 debuggerPrintStructure(f, t, objLocation);
470 break;
471 case TYPE_union:
472 debuggerPrintUnion(f, t, objLocation);
473 break;
474 case TYPE_enum:
475 debuggerPrintEnum(t, value);
476 break;
477 default:
478 printf("%08x", value);
479 break;
480 }
481 }
482
debuggerPrintValueInternal(Function * f,Type * t,ELFBlock * loc,int bitSize,int bitOffset,u32 objLocation)483 void debuggerPrintValueInternal(Function *f, Type *t, ELFBlock *loc,
484 int bitSize, int bitOffset, u32 objLocation)
485 {
486 LocationType type;
487 u32 location;
488 if(loc) {
489 if(objLocation)
490 location = elfDecodeLocation(f, loc, &type, objLocation);
491 else
492 location = elfDecodeLocation(f, loc,&type);
493 } else {
494 location = objLocation;
495 type = LOCATION_memory;
496 }
497
498 debuggerPrintValueInternal(f, t, bitSize, bitOffset, location, type);
499 }
500
debuggerPrintValue(Function * f,Object * o)501 void debuggerPrintValue(Function *f, Object *o)
502 {
503 debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0);
504
505 printf("\n");
506 }
507
debuggerSymbols(int argc,char ** argv)508 void debuggerSymbols(int argc, char **argv)
509 {
510 int i = 0;
511 u32 value;
512 u32 size;
513 int type;
514 bool match = false;
515 int matchSize = 0;
516 char *matchStr = NULL;
517
518 if(argc == 2) {
519 match = true;
520 matchSize = strlen(argv[1]);
521 matchStr = argv[1];
522 }
523 printf("Symbol Value Size Type \n");
524 printf("-------------------- ------- -------- -------\n");
525 char *s = NULL;
526 while((s = elfGetSymbol(i, &value, &size, &type))) {
527 if(*s) {
528 if(match) {
529 if(strncmp(s, matchStr, matchSize) != 0) {
530 i++;
531 continue;
532 }
533 }
534 char *ts = "?";
535 switch(type) {
536 case 2:
537 ts = "ARM";
538 break;
539 case 0x0d:
540 ts = "THUMB";
541 break;
542 case 1:
543 ts = "DATA";
544 break;
545 }
546 printf("%-20s %08x %08x %-7s\n",
547 s, value, size, ts);
548 }
549 i++;
550 }
551 }
552
debuggerSetRadix(int argc,char ** argv)553 void debuggerSetRadix(int argc, char **argv)
554 {
555 if(argc != 2)
556 debuggerUsage(argv[0]);
557 else {
558 int r = atoi(argv[1]);
559
560 bool error = false;
561 switch(r) {
562 case 10:
563 debuggerRadix = 0;
564 break;
565 case 8:
566 debuggerRadix = 2;
567 break;
568 case 16:
569 debuggerRadix = 1;
570 break;
571 default:
572 error = true;
573 printf("Unknown radix %d. Valid values are 8, 10 and 16.\n", r);
574 break;
575 }
576 if(!error)
577 printf("Radix set to %d\n", r);
578 }
579 }
580
debuggerPrint(int argc,char ** argv)581 void debuggerPrint(int argc, char **argv)
582 {
583 if(argc != 2 && argc != 3) {
584 debuggerUsage(argv[0]);
585 } else {
586 u32 pc = armNextPC;
587 Function *f = NULL;
588 CompileUnit *u = NULL;
589
590 elfGetCurrentFunction(pc,
591 &f, &u);
592
593 int oldRadix = debuggerRadix;
594 if(argc == 3) {
595 if(argv[1][0] == '/') {
596 if(argv[1][1] == 'x')
597 debuggerRadix = 1;
598 else if(argv[1][1] == 'o')
599 debuggerRadix = 2;
600 else if(argv[1][1] == 'd')
601 debuggerRadix = 0;
602 else {
603 printf("Unknown format %c\n", argv[1][1]);
604 return;
605 }
606 } else {
607 printf("Unknown option %s\n", argv[1]);
608 return;
609 }
610 }
611
612 char *s = argc == 2 ? argv[1] : argv[2];
613
614 extern char *exprString;
615 extern int exprCol;
616 extern int yyparse();
617 exprString = s;
618 exprCol = 0;
619 if(!yyparse()) {
620 extern Node *result;
621 if(result->resolve(result, f, u)) {
622 if(result->member)
623 debuggerPrintMember(f,
624 result->member,
625 result->objLocation,
626 result->location);
627 else
628 debuggerPrintValueInternal(f, result->type, 0, 0,
629 result->location,
630 result->locType);
631 printf("\n");
632 } else {
633 printf("Error resolving expression\n");
634 }
635 } else {
636 printf("Error parsing expression:\n");
637 printf("%s\n", s);
638 exprCol--;
639 for(int i = 0; i < exprCol; i++)
640 printf(" ");
641 printf("^\n");
642 }
643 extern void exprCleanBuffer();
644 exprCleanBuffer();
645 exprNodeCleanUp();
646 debuggerRadix = oldRadix;
647 }
648 }
649
debuggerHelp(int n,char ** args)650 void debuggerHelp(int n, char **args)
651 {
652 if(n == 2) {
653 debuggerUsage(args[1]);
654 } else {
655 for(int i = 0; ; i++) {
656 if(debuggerCommands[i].name) {
657 printf("%s\t%s\n", debuggerCommands[i].name, debuggerCommands[i].help);
658 } else
659 break;
660 }
661 }
662 }
663
debuggerDebug(int n,char ** args)664 void debuggerDebug(int n, char **args)
665 {
666 if(n == 2) {
667 int v = 0;
668 sscanf(args[1], "%d", &v);
669 systemDebug = v;
670 printf("Debug level set to %d\n", systemDebug);
671 } else
672 debuggerUsage("trace");
673 }
674
debuggerVerbose(int n,char ** args)675 void debuggerVerbose(int n, char **args)
676 {
677 if(n == 2) {
678 int v = 0;
679 sscanf(args[1], "%d", &v);
680 systemVerbose = v;
681 printf("Verbose level set to %d\n", systemVerbose);
682 } else
683 debuggerUsage("verbose");
684 }
685
debuggerWhere(int n,char ** args)686 void debuggerWhere(int n, char **args)
687 {
688 void elfPrintCallChain(u32);
689 elfPrintCallChain(armNextPC);
690 }
691
debuggerLocals(int n,char ** args)692 void debuggerLocals(int n, char **args)
693 {
694 Function *f = NULL;
695 CompileUnit *u = NULL;
696 u32 pc = armNextPC;
697 if(elfGetCurrentFunction(pc,
698 &f, &u)) {
699 Object *o = f->parameters;
700 while(o) {
701 printf("%s=", o->name);
702 debuggerPrintValue(f, o);
703 o = o->next;
704 }
705
706 o = f->variables;
707 while(o) {
708 bool visible = o->startScope ? pc>=o->startScope : true;
709 if(visible)
710 visible = o->endScope ? pc < o->endScope : true;
711 if(visible) {
712 printf("%s=", o->name);
713 debuggerPrintValue(f, o);
714 }
715 o = o->next;
716 }
717 } else {
718 printf("No information for current address\n");
719 }
720 }
721
debuggerNext(int n,char ** args)722 void debuggerNext(int n, char **args)
723 {
724 int count = 1;
725 if(n == 2) {
726 sscanf(args[1], "%d", &count);
727 }
728 for(int i = 0; i < count; i++) {
729 if(debuggerAtBreakpoint) {
730 debuggerContinueAfterBreakpoint();
731 debuggerEnableBreakpoints(false);
732 } else
733 emulator.emuMain(1);
734 }
735 debuggerDisableBreakpoints();
736 Function *f = NULL;
737 CompileUnit *u = NULL;
738 u32 a = armNextPC;
739 if(elfGetCurrentFunction(a, &f, &u)) {
740 char *file;
741 int line = elfFindLine(u, f, a, &file);
742
743 printf("File %s, function %s, line %d\n", file, f->name,
744 line);
745 }
746 debuggerRegisters(0, NULL);
747 }
748
debuggerContinue(int n,char ** args)749 void debuggerContinue(int n, char **args)
750 {
751 if(debuggerAtBreakpoint)
752 debuggerContinueAfterBreakpoint();
753 debuggerEnableBreakpoints(false);
754 debugger = false;
755 }
756
debuggerSignal(int sig,int number)757 void debuggerSignal(int sig,int number)
758 {
759 switch(sig) {
760 case 4:
761 {
762 printf("Illegal instruction at %08x\n", armNextPC);
763 debugger = true;
764 }
765 break;
766 case 5:
767 {
768 printf("Breakpoint %d reached\n", number);
769 debugger = true;
770 debuggerAtBreakpoint = true;
771 debuggerBreakpointNumber = number;
772 debuggerDisableBreakpoints();
773
774 Function *f = NULL;
775 CompileUnit *u = NULL;
776
777 if(elfGetCurrentFunction(armNextPC, &f, &u)) {
778 char *file;
779 int line = elfFindLine(u,f,armNextPC,&file);
780 printf("File %s, function %s, line %d\n", file, f->name,
781 line);
782 }
783 }
784 break;
785 default:
786 printf("Unknown signal %d\n", sig);
787 break;
788 }
789 }
790
debuggerBreakList(int,char **)791 void debuggerBreakList(int, char **)
792 {
793 printf("Num Address Type Symbol\n");
794 printf("--- -------- ----- ------\n");
795 for(int i = 0; i < debuggerNumOfBreakpoints; i++) {
796 printf("%3d %08x %s %s\n",i, debuggerBreakpointList[i].address,
797 debuggerBreakpointList[i].size ? "ARM" : "THUMB",
798 elfGetAddressSymbol(debuggerBreakpointList[i].address));
799 }
800 }
801
debuggerBreakDelete(int n,char ** args)802 void debuggerBreakDelete(int n, char **args)
803 {
804 if(n == 2) {
805 int n = 0;
806 sscanf(args[1], "%d", &n);
807 printf("Deleting breakpoint %d (%d)\n", n, debuggerNumOfBreakpoints);
808 if(n >= 0 && n < debuggerNumOfBreakpoints) {
809 n++;
810 if(n < debuggerNumOfBreakpoints) {
811 for(int i = n; i < debuggerNumOfBreakpoints; i++) {
812 debuggerBreakpointList[i-1].address =
813 debuggerBreakpointList[i].address;
814 debuggerBreakpointList[i-1].value =
815 debuggerBreakpointList[i].value;
816 debuggerBreakpointList[i-1].size =
817 debuggerBreakpointList[i].size;
818 }
819 }
820 debuggerNumOfBreakpoints--;
821 }
822 } else
823 debuggerUsage("bd");
824 }
825
debuggerBreak(int n,char ** args)826 void debuggerBreak(int n, char **args)
827 {
828 if(n == 2) {
829 u32 address = 0;
830 u32 value = 0;
831 int type = 0;
832 char *s = args[1];
833 char c = *s;
834 if(strchr(s, ':')) {
835 char *name = s;
836 char *l = strchr(s, ':');
837 *l++ = 0;
838 int line = atoi(l);
839
840 u32 addr;
841 Function *f;
842 CompileUnit *u;
843
844 if(elfFindLineInModule(&addr, name, line)) {
845 if(elfGetCurrentFunction(addr, &f, &u)) {
846 u32 addr2;
847 if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) {
848 address = addr;
849 } else {
850 printf("Unable to get function symbol data\n");
851 return;
852 }
853 } else {
854 printf("Unable to find function for address\n");
855 return;
856 }
857 } else {
858 printf("Unable to find module or line\n");
859 return;
860 }
861 } else if(c >= '0' && c <= '9') {
862 int line = atoi(s);
863 Function *f;
864 CompileUnit *u;
865 u32 addr;
866
867 if(elfGetCurrentFunction(armNextPC, &f, &u)) {
868 if(elfFindLineInUnit(&addr, u, line)) {
869 if(elfGetCurrentFunction(addr, &f, &u)) {
870 u32 addr2;
871 if(elfGetSymbolAddress(f->name, &addr2, &value, &type)) {
872 address = addr;
873 } else {
874 printf("Unable to get function symbol data\n");
875 return;
876 }
877 } else {
878 printf("Unable to find function for address\n");
879 return;
880 }
881 } else {
882 printf("Unable to find line\n");
883 return;
884 }
885 } else {
886 printf("Cannot find current function\n");
887 return;
888 }
889 } else {
890 if(!elfGetSymbolAddress(s, &address, &value, &type)) {
891 printf("Function %s not found\n", args[1]);
892 return;
893 }
894 }
895 if(type == 0x02 || type == 0x0d) {
896 int i = debuggerNumOfBreakpoints;
897 int size = 0;
898 if(type == 2)
899 size = 1;
900 debuggerBreakpointList[i].address = address;
901 debuggerBreakpointList[i].value = type == 0x02 ?
902 debuggerReadMemory(address) : debuggerReadHalfWord(address);
903 debuggerBreakpointList[i].size = size;
904 // debuggerApplyBreakpoint(address, i, size);
905 debuggerNumOfBreakpoints++;
906 if(size)
907 printf("Added ARM breakpoint at %08x\n", address);
908 else
909 printf("Added THUMB breakpoint at %08x\n", address);
910 } else {
911 printf("%s is not a function symbol\n", args[1]);
912 }
913 } else
914 debuggerUsage("break");
915 }
916
debuggerBreakThumb(int n,char ** args)917 void debuggerBreakThumb(int n, char **args)
918 {
919 if(n == 2) {
920 u32 address = 0;
921 sscanf(args[1],"%x", &address);
922 int i = debuggerNumOfBreakpoints;
923 debuggerBreakpointList[i].address = address;
924 debuggerBreakpointList[i].value = debuggerReadHalfWord(address);
925 debuggerBreakpointList[i].size = 0;
926 // debuggerApplyBreakpoint(address, i, 0);
927 debuggerNumOfBreakpoints++;
928 printf("Added THUMB breakpoint at %08x\n", address);
929 } else
930 debuggerUsage("bt");
931 }
932
debuggerBreakArm(int n,char ** args)933 void debuggerBreakArm(int n, char **args)
934 {
935 if(n == 2) {
936 u32 address = 0;
937 sscanf(args[1],"%x", &address);
938 int i = debuggerNumOfBreakpoints;
939 debuggerBreakpointList[i].address = address;
940 debuggerBreakpointList[i].value = debuggerReadMemory(address);
941 debuggerBreakpointList[i].size = 1;
942 // debuggerApplyBreakpoint(address, i, 1);
943 debuggerNumOfBreakpoints++;
944 printf("Added ARM breakpoint at %08x\n", address);
945 } else
946 debuggerUsage("ba");
947 }
948
debuggerBreakOnWrite(u32 * mem,u32 oldvalue,u32 value,int size)949 void debuggerBreakOnWrite(u32 *mem, u32 oldvalue, u32 value, int size)
950 {
951 u32 address = 0;
952 if(mem >= (u32*)&workRAM[0] && mem <= (u32*)&workRAM[0x3ffff])
953 address = 0x2000000 + (u32)((u8 *)mem - &workRAM[0]);
954 else
955 address = 0x3000000 + (u32)((u8 *)mem - &internalRAM[0]);
956
957 if(size == 2)
958 printf("Breakpoint (on write) address %08x old:%08x new:%08x\n",
959 address, oldvalue, value);
960 else if(size == 1)
961 printf("Breakpoint (on write) address %08x old:%04x new:%04x\n",
962 address, (u16)oldvalue,(u16)value);
963 else
964 printf("Breakpoint (on write) address %08x old:%02x new:%02x\n",
965 address, (u8)oldvalue, (u8)value);
966 debugger = true;
967 }
968
debuggerBreakWriteClear(int n,char ** args)969 void debuggerBreakWriteClear(int n, char **args)
970 {
971 memset(freezeWorkRAM, false, 0x40000);
972 memset(freezeInternalRAM, false, 0x8000);
973 printf("Cleared all break on write\n");
974 }
975
debuggerBreakWrite(int n,char ** args)976 void debuggerBreakWrite(int n, char **args)
977 {
978 if(n == 3) {
979 if(cheatsNumber != 0) {
980 printf("Cheats are enabled. Cannot continue.\n");
981 return;
982 }
983 u32 address = 0;
984 sscanf(args[1], "%x", &address);
985 int n = 0;
986 sscanf(args[2], "%d", &n);
987
988 if(address < 0x2000000 || address > 0x3007fff) {
989 printf("Invalid address: %08x\n", address);
990 return;
991 }
992
993 if(address > 0x203ffff && address < 0x3000000) {
994 printf("Invalid address: %08x\n", address);
995 return;
996 }
997
998 u32 final = address + n;
999
1000 if(address < 0x2040000 && final > 0x2040000) {
1001 printf("Invalid byte count: %d\n", n);
1002 return;
1003 } else if(address < 0x3008000 && final > 0x3008000) {
1004 printf("Invalid byte count: %d\n", n);
1005 return;
1006 }
1007 printf("Added break on write at %08x for %d bytes\n", address, n);
1008 for(int i = 0; i < n; i++) {
1009 if((address >> 24) == 2)
1010 freezeWorkRAM[address & 0x3ffff] = true;
1011 else
1012 freezeInternalRAM[address & 0x7fff] = true;
1013 address++;
1014 }
1015 } else
1016 debuggerUsage("bpw");
1017 }
1018
debuggerDisassembleArm(int n,char ** args)1019 void debuggerDisassembleArm(int n, char **args)
1020 {
1021 char buffer[80];
1022 u32 pc = reg[15].I;
1023 pc -= 4;
1024 int count = 20;
1025 if(n >= 2) {
1026 sscanf(args[1], "%x", &pc);
1027 }
1028 if(pc & 3) {
1029 printf("Misaligned address %08x\n", pc);
1030 pc &= 0xfffffffc;
1031 }
1032 if(n >= 3) {
1033 sscanf(args[2], "%d", &count);
1034 }
1035 int i = 0;
1036 int len = 0;
1037 char format[30];
1038 for(i = 0; i < count; i++) {
1039 int l = strlen(elfGetAddressSymbol(pc+4*i));
1040 if(l > len)
1041 len = l;
1042 }
1043 sprintf(format, "%%08x %%-%ds %%s\n", len);
1044 for(i = 0; i < count; i++) {
1045 u32 addr = pc;
1046 pc += disArm(pc, buffer, 2);
1047 printf(format, addr, elfGetAddressSymbol(addr), buffer);
1048 }
1049 }
1050
debuggerDisassembleThumb(int n,char ** args)1051 void debuggerDisassembleThumb(int n, char **args)
1052 {
1053 char buffer[80];
1054 u32 pc = reg[15].I;
1055 pc -= 2;
1056 int count = 20;
1057 if(n >= 2) {
1058 sscanf(args[1], "%x", &pc);
1059 }
1060 if(pc & 1) {
1061 printf("Misaligned address %08x\n", pc);
1062 pc &= 0xfffffffe;
1063 }
1064 if(n >= 3) {
1065 sscanf(args[2], "%d", &count);
1066 }
1067
1068 int i = 0;
1069 int len = 0;
1070 char format[30];
1071 for(i = 0; i < count; i++) {
1072 int l = strlen(elfGetAddressSymbol(pc+2*i));
1073 if(l > len)
1074 len = l;
1075 }
1076 sprintf(format, "%%08x %%-%ds %%s\n", len);
1077
1078 for(i = 0; i < count; i++) {
1079 u32 addr = pc;
1080 pc += disThumb(pc, buffer, 2);
1081 printf(format, addr, elfGetAddressSymbol(addr), buffer);
1082 }
1083 }
1084
debuggerDisassemble(int n,char ** args)1085 void debuggerDisassemble(int n, char **args)
1086 {
1087 if(armState)
1088 debuggerDisassembleArm(n, args);
1089 else
1090 debuggerDisassembleThumb(n, args);
1091 }
1092
debuggerContinueAfterBreakpoint()1093 void debuggerContinueAfterBreakpoint()
1094 {
1095 printf("Continuing after breakpoint\n");
1096 debuggerEnableBreakpoints(true);
1097 emulator.emuMain(1);
1098 debuggerAtBreakpoint = false;
1099 }
1100
debuggerRegisters(int,char **)1101 void debuggerRegisters(int, char **)
1102 {
1103 char *command[3];
1104 char buffer[10];
1105
1106 printf("R00=%08x R04=%08x R08=%08x R12=%08x\n",
1107 reg[0].I, reg[4].I, reg[8].I, reg[12].I);
1108 printf("R01=%08x R05=%08x R09=%08x R13=%08x\n",
1109 reg[1].I, reg[5].I, reg[9].I, reg[13].I);
1110 printf("R02=%08x R06=%08x R10=%08x R14=%08x\n",
1111 reg[2].I, reg[6].I, reg[10].I, reg[14].I);
1112 printf("R03=%08x R07=%08x R11=%08x R15=%08x\n",
1113 reg[3].I, reg[7].I, reg[11].I, reg[15].I);
1114 printf("CPSR=%08x (%c%c%c%c%c%c%c Mode: %02x)\n",
1115 reg[16].I,
1116 (N_FLAG ? 'N' : '.'),
1117 (Z_FLAG ? 'Z' : '.'),
1118 (C_FLAG ? 'C' : '.'),
1119 (V_FLAG ? 'V' : '.'),
1120 (armIrqEnable ? '.' : 'I'),
1121 ((!(reg[16].I & 0x40)) ? '.' : 'F'),
1122 (armState ? '.' : 'T'),
1123 armMode);
1124 sprintf(buffer,"%08x", armState ? reg[15].I - 4 : reg[15].I - 2);
1125 command[0]="m";
1126 command[1]=buffer;
1127 command[2]="1";
1128 debuggerDisassemble(3, command);
1129 }
1130
debuggerIoVideo()1131 void debuggerIoVideo()
1132 {
1133 printf("DISPCNT = %04x\n", DISPCNT);
1134 printf("DISPSTAT = %04x\n", DISPSTAT);
1135 printf("VCOUNT = %04x\n", VCOUNT);
1136 printf("BG0CNT = %04x\n", BG0CNT);
1137 printf("BG1CNT = %04x\n", BG1CNT);
1138 printf("BG2CNT = %04x\n", BG2CNT);
1139 printf("BG3CNT = %04x\n", BG3CNT);
1140 printf("WIN0H = %04x\n", WIN0H);
1141 printf("WIN0V = %04x\n", WIN0V);
1142 printf("WIN1H = %04x\n", WIN1H);
1143 printf("WIN1V = %04x\n", WIN1V);
1144 printf("WININ = %04x\n", WININ);
1145 printf("WINOUT = %04x\n", WINOUT);
1146 printf("MOSAIC = %04x\n", MOSAIC);
1147 printf("BLDMOD = %04x\n", BLDMOD);
1148 printf("COLEV = %04x\n", COLEV);
1149 printf("COLY = %04x\n", COLY);
1150 }
1151
debuggerIoVideo2()1152 void debuggerIoVideo2()
1153 {
1154 printf("BG0HOFS = %04x\n", BG0HOFS);
1155 printf("BG0VOFS = %04x\n", BG0VOFS);
1156 printf("BG1HOFS = %04x\n", BG1HOFS);
1157 printf("BG1VOFS = %04x\n", BG1VOFS);
1158 printf("BG2HOFS = %04x\n", BG2HOFS);
1159 printf("BG2VOFS = %04x\n", BG2VOFS);
1160 printf("BG3HOFS = %04x\n", BG3HOFS);
1161 printf("BG3VOFS = %04x\n", BG3VOFS);
1162 printf("BG2PA = %04x\n", BG2PA);
1163 printf("BG2PB = %04x\n", BG2PB);
1164 printf("BG2PC = %04x\n", BG2PC);
1165 printf("BG2PD = %04x\n", BG2PD);
1166 printf("BG2X = %08x\n", (BG2X_H<<16)|BG2X_L);
1167 printf("BG2Y = %08x\n", (BG2Y_H<<16)|BG2Y_L);
1168 printf("BG3PA = %04x\n", BG3PA);
1169 printf("BG3PB = %04x\n", BG3PB);
1170 printf("BG3PC = %04x\n", BG3PC);
1171 printf("BG3PD = %04x\n", BG3PD);
1172 printf("BG3X = %08x\n", (BG3X_H<<16)|BG3X_L);
1173 printf("BG3Y = %08x\n", (BG3Y_H<<16)|BG3Y_L);
1174 }
1175
debuggerIoDMA()1176 void debuggerIoDMA()
1177 {
1178 printf("DM0SAD = %08x\n", (DM0SAD_H<<16)|DM0SAD_L);
1179 printf("DM0DAD = %08x\n", (DM0DAD_H<<16)|DM0DAD_L);
1180 printf("DM0CNT = %08x\n", (DM0CNT_H<<16)|DM0CNT_L);
1181 printf("DM1SAD = %08x\n", (DM1SAD_H<<16)|DM1SAD_L);
1182 printf("DM1DAD = %08x\n", (DM1DAD_H<<16)|DM1DAD_L);
1183 printf("DM1CNT = %08x\n", (DM1CNT_H<<16)|DM1CNT_L);
1184 printf("DM2SAD = %08x\n", (DM2SAD_H<<16)|DM2SAD_L);
1185 printf("DM2DAD = %08x\n", (DM2DAD_H<<16)|DM2DAD_L);
1186 printf("DM2CNT = %08x\n", (DM2CNT_H<<16)|DM2CNT_L);
1187 printf("DM3SAD = %08x\n", (DM3SAD_H<<16)|DM3SAD_L);
1188 printf("DM3DAD = %08x\n", (DM3DAD_H<<16)|DM3DAD_L);
1189 printf("DM3CNT = %08x\n", (DM3CNT_H<<16)|DM3CNT_L);
1190 }
1191
debuggerIoTimer()1192 void debuggerIoTimer()
1193 {
1194 printf("TM0D = %04x\n", TM0D);
1195 printf("TM0CNT = %04x\n", TM0CNT);
1196 printf("TM1D = %04x\n", TM1D);
1197 printf("TM1CNT = %04x\n", TM1CNT);
1198 printf("TM2D = %04x\n", TM2D);
1199 printf("TM2CNT = %04x\n", TM2CNT);
1200 printf("TM3D = %04x\n", TM3D);
1201 printf("TM3CNT = %04x\n", TM3CNT);
1202 }
1203
debuggerIoMisc()1204 void debuggerIoMisc()
1205 {
1206 printf("P1 = %04x\n", P1);
1207 printf("IE = %04x\n", IE);
1208 printf("IF = %04x\n", IF);
1209 printf("IME = %04x\n", IME);
1210 }
1211
debuggerIo(int n,char ** args)1212 void debuggerIo(int n, char **args)
1213 {
1214 if(n == 1) {
1215 debuggerIoVideo();
1216 return;
1217 }
1218 if(!strcmp(args[1], "video"))
1219 debuggerIoVideo();
1220 else if(!strcmp(args[1], "video2"))
1221 debuggerIoVideo2();
1222 else if(!strcmp(args[1], "dma"))
1223 debuggerIoDMA();
1224 else if(!strcmp(args[1], "timer"))
1225 debuggerIoTimer();
1226 else if(!strcmp(args[1], "misc"))
1227 debuggerIoMisc();
1228 else printf("Unrecognized option %s\n", args[1]);
1229 }
1230
debuggerEditByte(int n,char ** args)1231 void debuggerEditByte(int n, char **args)
1232 {
1233 if(n == 3) {
1234 u32 address;
1235 u32 byte;
1236 sscanf(args[1], "%x", &address);
1237 sscanf(args[2], "%x", &byte);
1238 debuggerWriteByte(address, (u8)byte);
1239 } else
1240 debuggerUsage("eb");
1241 }
1242
debuggerEditHalfWord(int n,char ** args)1243 void debuggerEditHalfWord(int n, char **args)
1244 {
1245 if(n == 3) {
1246 u32 address;
1247 u32 byte;
1248 sscanf(args[1], "%x", &address);
1249 if(address & 1) {
1250 printf("Error: address must be half-word aligned\n");
1251 return;
1252 }
1253 sscanf(args[2], "%x", &byte);
1254 debuggerWriteHalfWord(address, (u16)byte);
1255 } else
1256 debuggerUsage("eh");
1257 }
1258
debuggerEdit(int n,char ** args)1259 void debuggerEdit(int n, char **args)
1260 {
1261 if(n == 3) {
1262 u32 address;
1263 u32 byte;
1264 sscanf(args[1], "%x", &address);
1265 if(address & 3) {
1266 printf("Error: address must be word aligned\n");
1267 return;
1268 }
1269 sscanf(args[2], "%x", &byte);
1270 debuggerWriteMemory(address, (u32)byte);
1271 } else
1272 debuggerUsage("ew");
1273 }
1274
1275
1276 #define ASCII(c) (c) < 32 ? '.' : (c) > 127 ? '.' : (c)
1277
debuggerMemoryByte(int n,char ** args)1278 void debuggerMemoryByte(int n, char **args)
1279 {
1280 if(n == 2) {
1281 u32 addr = 0;
1282 sscanf(args[1], "%x", &addr);
1283 for(int i_ = 0; i_ < 16; i_++) {
1284 int a = debuggerReadByte(addr);
1285 int b = debuggerReadByte(addr+1);
1286 int c = debuggerReadByte(addr+2);
1287 int d = debuggerReadByte(addr+3);
1288 int e = debuggerReadByte(addr+4);
1289 int f = debuggerReadByte(addr+5);
1290 int g = debuggerReadByte(addr+6);
1291 int h = debuggerReadByte(addr+7);
1292 int i = debuggerReadByte(addr+8);
1293 int j = debuggerReadByte(addr+9);
1294 int k = debuggerReadByte(addr+10);
1295 int l = debuggerReadByte(addr+11);
1296 int m = debuggerReadByte(addr+12);
1297 int n = debuggerReadByte(addr+13);
1298 int o = debuggerReadByte(addr+14);
1299 int p = debuggerReadByte(addr+15);
1300
1301 printf("%08x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
1302 addr,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,
1303 ASCII(a),ASCII(b),ASCII(c),ASCII(d),
1304 ASCII(e),ASCII(f),ASCII(g),ASCII(h),
1305 ASCII(i),ASCII(j),ASCII(k),ASCII(l),
1306 ASCII(m),ASCII(n),ASCII(o),ASCII(p));
1307 addr += 16;
1308 }
1309 } else
1310 debuggerUsage("mb");
1311 }
1312
debuggerMemoryHalfWord(int n,char ** args)1313 void debuggerMemoryHalfWord(int n, char **args)
1314 {
1315 if(n == 2) {
1316 u32 addr = 0;
1317 sscanf(args[1], "%x", &addr);
1318 addr = addr & 0xfffffffe;
1319 for(int i_ = 0; i_ < 16; i_++) {
1320 int a = debuggerReadByte(addr);
1321 int b = debuggerReadByte(addr+1);
1322 int c = debuggerReadByte(addr+2);
1323 int d = debuggerReadByte(addr+3);
1324 int e = debuggerReadByte(addr+4);
1325 int f = debuggerReadByte(addr+5);
1326 int g = debuggerReadByte(addr+6);
1327 int h = debuggerReadByte(addr+7);
1328 int i = debuggerReadByte(addr+8);
1329 int j = debuggerReadByte(addr+9);
1330 int k = debuggerReadByte(addr+10);
1331 int l = debuggerReadByte(addr+11);
1332 int m = debuggerReadByte(addr+12);
1333 int n = debuggerReadByte(addr+13);
1334 int o = debuggerReadByte(addr+14);
1335 int p = debuggerReadByte(addr+15);
1336
1337 printf("%08x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
1338 addr,b,a,d,c,f,e,h,g,j,i,l,k,n,m,p,o,
1339 ASCII(a),ASCII(b),ASCII(c),ASCII(d),
1340 ASCII(e),ASCII(f),ASCII(g),ASCII(h),
1341 ASCII(i),ASCII(j),ASCII(k),ASCII(l),
1342 ASCII(m),ASCII(n),ASCII(o),ASCII(p));
1343 addr += 16;
1344 }
1345 } else
1346 debuggerUsage("mh");
1347 }
1348
debuggerMemory(int n,char ** args)1349 void debuggerMemory(int n, char **args)
1350 {
1351 if(n == 2) {
1352 u32 addr = 0;
1353 sscanf(args[1], "%x", &addr);
1354 addr = addr & 0xfffffffc;
1355 for(int i_ = 0; i_ < 16; i_++) {
1356 int a = debuggerReadByte(addr);
1357 int b = debuggerReadByte(addr+1);
1358 int c = debuggerReadByte(addr+2);
1359 int d = debuggerReadByte(addr+3);
1360
1361 int e = debuggerReadByte(addr+4);
1362 int f = debuggerReadByte(addr+5);
1363 int g = debuggerReadByte(addr+6);
1364 int h = debuggerReadByte(addr+7);
1365
1366 int i = debuggerReadByte(addr+8);
1367 int j = debuggerReadByte(addr+9);
1368 int k = debuggerReadByte(addr+10);
1369 int l = debuggerReadByte(addr+11);
1370
1371 int m = debuggerReadByte(addr+12);
1372 int n = debuggerReadByte(addr+13);
1373 int o = debuggerReadByte(addr+14);
1374 int p = debuggerReadByte(addr+15);
1375
1376 printf("%08x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %02x%02x%02x%02x %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
1377 addr,d,c,b,a,h,g,f,e,l,k,j,i,p,o,n,m,
1378 ASCII(a),ASCII(b),ASCII(c),ASCII(d),
1379 ASCII(e),ASCII(f),ASCII(g),ASCII(h),
1380 ASCII(i),ASCII(j),ASCII(k),ASCII(l),
1381 ASCII(m),ASCII(n),ASCII(o),ASCII(p));
1382 addr += 16;
1383 }
1384 } else
1385 debuggerUsage("mw");
1386 }
1387
debuggerQuit(int,char **)1388 void debuggerQuit(int, char **)
1389 {
1390 char buffer[10];
1391 printf("Are you sure you want to quit (y/n)? ");
1392 fgets(buffer, sizeof(buffer), stdin);
1393
1394 if(buffer[0] == 'y' || buffer[0] == 'Y') {
1395 debugger = false;
1396 emulating = false;
1397 }
1398 }
1399
debuggerOutput(char * s,u32 addr)1400 void debuggerOutput(char *s, u32 addr)
1401 {
1402 if(s)
1403 printf(s);
1404 else {
1405 char c;
1406
1407 c = debuggerReadByte(addr);
1408 addr++;
1409 while(c) {
1410 putchar(c);
1411 c = debuggerReadByte(addr);
1412 addr++;
1413 }
1414 }
1415 }
1416
debuggerMain()1417 void debuggerMain()
1418 {
1419 char buffer[1024];
1420 char *commands[10];
1421 int commandCount = 0;
1422
1423 if(emulator.emuUpdateCPSR)
1424 emulator.emuUpdateCPSR();
1425 debuggerRegisters(0, NULL);
1426
1427 while(debugger) {
1428 systemSoundPause();
1429 printf("debugger> ");
1430 commandCount = 0;
1431 char *s = fgets(buffer, 1024, stdin);
1432
1433 commands[0] = strtok(s, " \t\n");
1434 if(commands[0] == NULL)
1435 continue;
1436 commandCount++;
1437 while((s = strtok(NULL, " \t\n"))) {
1438 commands[commandCount++] = s;
1439 if(commandCount == 10)
1440 break;
1441 }
1442
1443 for(int j = 0; ; j++) {
1444 if(debuggerCommands[j].name == NULL) {
1445 printf("Unrecognized command %s. Type h for help.\n", commands[0]);
1446 break;
1447 }
1448 if(!strcmp(commands[0], debuggerCommands[j].name)) {
1449 debuggerCommands[j].function(commandCount, commands);
1450 break;
1451 }
1452 }
1453 }
1454 }
1455