home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / sdl / debugger.cpp next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  38.6 KB  |  1,455 lines

  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  328. void debuggerPrintPointer(Type *t, u32 value)
  329. {
  330.   printf("(%s)0x%08x", debuggerPrintType(t), value);
  331. }
  332.  
  333. void debuggerPrintReference(Type *t, u32 value)
  334. {
  335.   printf("(%s)0x%08x", debuggerPrintType(t), value);
  336. }
  337.  
  338. void debuggerPrintFunction(Type *t, u32 value)
  339. {
  340.   printf("(%s)0x%08x", debuggerPrintType(t), value);
  341. }
  342.  
  343. void debuggerPrintArray(Type *t, u32 value)
  344. {
  345.   // todo
  346.   printf("(%s[])0x%08x", debuggerPrintType(t->array->type), value);
  347. }
  348.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  501. void debuggerPrintValue(Function *f, Object *o)
  502. {
  503.   debuggerPrintValueInternal(f, o->type, o->location, 0, 0, 0);
  504.   
  505.   printf("\n");
  506. }
  507.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  686. void debuggerWhere(int n, char **args)
  687. {
  688.   void elfPrintCallChain(u32);
  689.   elfPrintCallChain(armNextPC);
  690. }
  691.  
  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.  
  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.  
  749. void debuggerContinue(int n, char **args)
  750. {
  751.   if(debuggerAtBreakpoint)
  752.     debuggerContinueAfterBreakpoint();
  753.   debuggerEnableBreakpoints(false);
  754.   debugger = false;
  755. }
  756.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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)mem - (u32)&workRAM[0]);
  954.   else
  955.     address = 0x3000000 + ((u32)mem - (u32)&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.  
  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.  
  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.  
  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.  
  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.  
  1085. void debuggerDisassemble(int n, char **args)
  1086. {
  1087.   if(armState)
  1088.     debuggerDisassembleArm(n, args);
  1089.   else
  1090.     debuggerDisassembleThumb(n, args);
  1091. }
  1092.  
  1093. void debuggerContinueAfterBreakpoint()
  1094. {
  1095.   printf("Continuing after breakpoint\n");
  1096.   debuggerEnableBreakpoints(true);
  1097.   emulator.emuMain(1);
  1098.   debuggerAtBreakpoint = false;
  1099. }
  1100.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  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.  
  1388. void debuggerQuit(int, char **)
  1389. {
  1390.   char buffer[10];
  1391.   printf("Are you sure you want to quit (y/n)? ");
  1392.   fgets(buffer, 1024, stdin);
  1393.   
  1394.   if(buffer[0] == 'y' || buffer[0] == 'Y') {
  1395.     debugger = false;
  1396.     emulating = false;
  1397.   }
  1398. }
  1399.  
  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.  
  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.