in cores/snes/debug.cpp [1365:1921]
static void debug_process_command (char *Line)
{
uint8 Bank = Registers.PB;
uint32 Address = Registers.PCw;
uint16 Hold = 0;
uint16 Number;
short ErrorCode;
char string[512];
if (strncasecmp(Line, "dump", 4) == 0)
{
int Count;
if (sscanf(&Line[4], "%x %d", &Address, &Count) == 2)
{
FILE *fs;
sprintf(string, "%06x%05d.sd2", Address, Count);
fs = fopen(string, "wb");
if (fs)
{
for (int i = 0; i < Count; i++)
putc(S9xDebugGetByte(Address + i), fs);
fclose(fs);
}
else
printf("Can't open %s for writing\n", string);
}
else
printf("Usage: dump start_address_in_hex count_in_decimal\n");
return;
}
if (*Line == 'i')
{
printf("Vectors:\n");
sprintf(string, " 8 Bit 16 Bit ");
debug_line_print(string);
sprintf(string, "ABT $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF8), S9xDebugGetWord(0xFFE8));
debug_line_print(string);
sprintf(string, "BRK $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFE6));
debug_line_print(string);
sprintf(string, "COP $00:%04X|$00:%04X", S9xDebugGetWord(0xFFF4), S9xDebugGetWord(0xFFE4));
debug_line_print(string);
sprintf(string, "IRQ $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFE), S9xDebugGetWord(0xFFEE));
debug_line_print(string);
sprintf(string, "NMI $00:%04X|$00:%04X", S9xDebugGetWord(0xFFFA), S9xDebugGetWord(0xFFEA));
debug_line_print(string);
sprintf(string, "RES $00:%04X", S9xDebugGetWord(0xFFFC));
debug_line_print(string);
}
/*
if (strncmp(Line, "ai", 2) == 0)
{
printf("APU vectors:");
for (int i = 0; i < 0x40; i += 2)
{
if (i % 16 == 0)
printf("\n%04x ", 0xffc0 + i);
printf("%04x ", APU.ExtraRAM[i]);
}
printf("\n");
}
*/
if (*Line == 's')
{
Registers.PCw += debug_cpu_op_print(string, Bank, Address);
Bank = Registers.PB;
Address = Registers.PCw;
*Line = 'r';
}
if (*Line == 'z')
{
uint16 *p = (uint16 *) &Memory.VRAM[PPU.BG[2].SCBase << 1];
for (int l = 0; l < 32; l++)
{
for (int c = 0; c < 32; c++, p++)
printf("%04x,", *p++);
printf("\n");
}
}
if (*Line == 'c')
{
printf("Colours:\n");
for (int i = 0; i < 256; i++)
printf("%02x%02x%02x ", PPU.CGDATA[i] & 0x1f, (PPU.CGDATA[i] >> 5) & 0x1f, (PPU.CGDATA[i] >> 10) & 0x1f);
printf("\n");
}
if (*Line == 'S')
{
int SmallWidth, LargeWidth, SmallHeight, LargeHeight;
switch ((Memory.FillRAM[0x2101] >> 5) & 7)
{
case 0:
SmallWidth = SmallHeight = 8;
LargeWidth = LargeHeight = 16;
break;
case 1:
SmallWidth = SmallHeight = 8;
LargeWidth = LargeHeight = 32;
break;
case 2:
SmallWidth = SmallHeight = 8;
LargeWidth = LargeHeight = 64;
break;
case 3:
SmallWidth = SmallHeight = 16;
LargeWidth = LargeHeight = 32;
break;
case 4:
SmallWidth = SmallHeight = 16;
LargeWidth = LargeHeight = 64;
break;
default:
case 5:
SmallWidth = SmallHeight = 32;
LargeWidth = LargeHeight = 64;
break;
case 6:
SmallWidth = 16;
SmallHeight = 32;
LargeWidth = 32;
LargeHeight = 64;
break;
case 7:
SmallWidth = 16;
SmallHeight = 32;
LargeWidth = LargeHeight = 32;
break;
}
printf("Sprites: Small: %dx%d, Large: %dx%d, OAMAddr: 0x%04x, OBJNameBase: 0x%04x, OBJNameSelect: 0x%04x, First: %d\n",
SmallWidth, SmallHeight, LargeWidth, LargeHeight, PPU.OAMAddr, PPU.OBJNameBase, PPU.OBJNameSelect, PPU.FirstSprite);
for (int i = 0; i < 128; i++)
{
printf("X:%3d Y:%3d %c%c%d%c ",
PPU.OBJ[i].HPos,
PPU.OBJ[i].VPos,
PPU.OBJ[i].VFlip ? 'V' : 'v',
PPU.OBJ[i].HFlip ? 'H' : 'h',
PPU.OBJ[i].Priority,
PPU.OBJ[i].Size ? 'S' : 's');
if (i % 4 == 3)
printf("\n");
}
}
if (*Line == 'T')
{
if (Line[1] == 'S')
{
SA1.Flags ^= TRACE_FLAG;
if (SA1.Flags & TRACE_FLAG)
{
printf("SA1 CPU instruction tracing enabled.\n");
ENSURE_TRACE_OPEN(trace2, "trace_sa1.log", "wb")
}
else
{
printf("SA1 CPU instruction tracing disabled.\n");
fclose(trace2);
trace2 = NULL;
}
}
else
{
CPU.Flags ^= TRACE_FLAG;
if (CPU.Flags & TRACE_FLAG)
{
printf("CPU instruction tracing enabled.\n");
ENSURE_TRACE_OPEN(trace, "trace.log", "wb")
}
else
{
printf("CPU instruction tracing disabled.\n");
fclose(trace);
trace = NULL;
}
}
}
if (*Line == 'E')
{
Settings.TraceHCEvent = !Settings.TraceHCEvent;
printf("HC event tracing %s.\n", Settings.TraceHCEvent ? "enabled" : "disabled");
}
if (*Line == 'A')
spc_core->debug_toggle_trace();
/*
if (*Line == 'B')
{
Settings.TraceSoundDSP = !Settings.TraceSoundDSP;
printf("Sound DSP register tracing %s.\n", Settings.TraceSoundDSP ? "enabled" : "disabled");
}
if (*Line == 'x')
S9xPrintSoundDSPState();
if (*Line == 'C')
{
printf("SPC700 sample addresses at 0x%04x:\n", APU.DSP[APU_DIR] << 8);
for (int i = 0; i < 256; i++)
{
uint8 *dir = IAPU.RAM + (((APU.DSP[APU_DIR] << 8) + i * 4) & 0xffff);
int addr = *dir + (*(dir + 1) << 8);
int addr2 = *(dir + 2) + (*(dir + 3) << 8);
printf("%04X %04X;", addr, addr2);
if (i % 8 == 7)
printf("\n");
}
}
*/
if (*Line == 'R')
{
S9xReset();
printf("SNES reset.\n");
CPU.Flags |= DEBUG_MODE_FLAG;
}
/*
if (strncmp(Line, "ad", 2) == 0)
{
uint32 Count = 16;
Address = 0;
if (sscanf(Line + 2, "%x,%x", &Address, &Count) != 2)
{
if (sscanf(Line + 2, "%x", &Address) == 1)
Count = 16;
}
printf("APU RAM dump:\n");
for (uint32 l = 0; l < Count; l += 16)
{
printf("%04X ", Address);
for (int i = 0; i < 16; i++)
printf("%02X ", IAPU.RAM[Address++]);
printf("\n");
}
*Line = 0;
}
if (*Line == 'a')
{
printf("APU in-ports : %02X %02X %02X %02X\n", IAPU.RAM[0xF4], IAPU.RAM[0xF5], IAPU.RAM[0xF6], IAPU.RAM[0xF7]);
printf("APU out-ports: %02X %02X %02X %02X\n", APU.OutPorts[0], APU.OutPorts[1], APU.OutPorts[2], APU.OutPorts[3]);
printf("ROM/RAM switch: %s\n", (IAPU.RAM[0xf1] & 0x80) ? "ROM" : "RAM");
for (int i = 0; i < 3; i++)
if (APU.TimerEnabled[i])
printf("Timer%d enabled, Value: 0x%03X, 4-bit: 0x%02X, Target: 0x%03X\n",
i, APU.Timer[i], IAPU.RAM[0xfd + i], APU.TimerTarget[i]);
}
if (*Line == 'P')
{
Settings.TraceDSP = !Settings.TraceDSP;
printf("DSP tracing %s.\n", Settings.TraceDSP ? "enabled" : "disabled");
}
*/
if (*Line == 'p')
{
S9xBreakpoint[5].Enabled = FALSE;
Address += debug_cpu_op_print(string, Bank, Address);
if (strncmp(&string[18], "JMP", 3) != 0 &&
strncmp(&string[18], "JML", 3) != 0 &&
strncmp(&string[18], "RT" , 2) != 0 &&
strncmp(&string[18], "BRA", 3))
{
S9xBreakpoint[5].Enabled = TRUE;
S9xBreakpoint[5].Bank = Bank;
S9xBreakpoint[5].Address = Address;
}
else
{
CPU.Flags |= SINGLE_STEP_FLAG;
CPU.Flags &= ~DEBUG_MODE_FLAG;
}
}
if (*Line == 'b')
{
if (Line[1] == 's')
{
debug_get_number(Line + 2, &Hold);
if (Hold > 4)
Hold = 0;
if (Hold < 5)
{
if (debug_get_start_address(Line + 5, &Bank, &Address) == -1)
S9xBreakpoint[Hold].Enabled = FALSE;
else
{
S9xBreakpoint[Hold].Enabled = TRUE;
S9xBreakpoint[Hold].Bank = Bank;
S9xBreakpoint[Hold].Address = Address;
CPU.Flags |= BREAK_FLAG;
}
}
Line[1] = 'v';
}
if (Line[1] == 'v')
{
Number = 0;
if (debug_get_number(Line + 2, &Number) == -1 && Number < 5)
{
debug_line_print("Breakpoints:");
for (Number = 0; Number != 5; Number++)
{
if (S9xBreakpoint[Number].Enabled)
sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);
else
sprintf(string, "%i @ Disabled", Number);
debug_line_print(string);
}
}
else
{
debug_line_print("Breakpoint:");
if (S9xBreakpoint[Number].Enabled)
sprintf(string, "%i @ $%02X:%04X", Number, S9xBreakpoint[Number].Bank, S9xBreakpoint[Number].Address);
else
sprintf(string, "%i @ Disabled", Number);
debug_line_print(string);
}
}
}
if (*Line == '?' || strcasecmp(Line, "help") == 0)
{
for (int i = 0; HelpMessage[i] != NULL; i++)
debug_line_print(HelpMessage[i]);
}
if (*Line == 't')
{
CPU.Flags |= SINGLE_STEP_FLAG;
CPU.Flags &= ~DEBUG_MODE_FLAG;
}
if (*Line == 'f')
{
CPU.Flags |= FRAME_ADVANCE_FLAG;
CPU.Flags &= ~DEBUG_MODE_FLAG;
IPPU.RenderThisFrame = TRUE;
IPPU.FrameSkip = 0;
if (sscanf(&Line[1], "%u", &ICPU.FrameAdvanceCount) != 1)
ICPU.Frame = 0;
}
if (*Line == 'g')
{
S9xBreakpoint[5].Enabled = FALSE;
bool8 found = FALSE;
for (int i = 0; i < 5; i++)
{
if (S9xBreakpoint[i].Enabled)
{
found = TRUE;
if (S9xBreakpoint[i].Bank == Registers.PB && S9xBreakpoint[i].Address == Registers.PCw)
{
S9xBreakpoint[i].Enabled = 2;
break;
}
}
}
if (!found)
CPU.Flags &= ~BREAK_FLAG;
ErrorCode = debug_get_start_address(Line, &Bank, &Address);
if (ErrorCode == 1)
{
S9xBreakpoint[5].Enabled = TRUE;
S9xBreakpoint[5].Bank = Bank;
S9xBreakpoint[5].Address = Address;
CPU.Flags |= BREAK_FLAG;
}
CPU.Flags &= ~DEBUG_MODE_FLAG;
}
if (*Line == 'D')
{
Settings.TraceDMA = !Settings.TraceDMA;
printf("DMA tracing %s.\n", Settings.TraceDMA ? "enabled" : "disabled");
}
if (*Line == 'V')
{
Settings.TraceVRAM = !Settings.TraceVRAM;
printf("Non-DMA VRAM write tracing %s.\n", Settings.TraceVRAM ? "enabled" : "disabled");
}
if (*Line == 'H')
{
Settings.TraceHDMA = !Settings.TraceHDMA;
printf("HDMA tracing %s.\n", Settings.TraceHDMA ? "enabled" : "disabled");
}
if (*Line == 'U')
{
Settings.TraceUnknownRegisters = !Settings.TraceUnknownRegisters;
printf("Unknown registers read/write tracing %s.\n", Settings.TraceUnknownRegisters ? "enabled" : "disabled");
}
if (*Line == 'd')
{
int CLine;
int CByte;
uint8 MemoryByte;
if (Debug.Dump.Bank != 0 || Debug.Dump.Address != 0)
{
Bank = Debug.Dump.Bank;
Address = Debug.Dump.Address;
}
ErrorCode = debug_get_start_address(Line, &Bank, &Address);
for (CLine = 0; CLine != 10; CLine++)
{
sprintf(string, "$%02X:%04X", Bank, Address);
for (CByte = 0; CByte != 16; CByte++)
{
if (Address + CByte == 0x2140 ||
Address + CByte == 0x2141 ||
Address + CByte == 0x2142 ||
Address + CByte == 0x2143 ||
Address + CByte == 0x4210)
MemoryByte = 0;
else
MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);
sprintf(string, "%s %02X", string, MemoryByte);
}
sprintf(string, "%s-", string);
for (CByte = 0; CByte != 16; CByte++)
{
if (Address + CByte == 0x2140 ||
Address + CByte == 0x2141 ||
Address + CByte == 0x2142 ||
Address + CByte == 0x2143 ||
Address + CByte == 0x4210)
MemoryByte = 0;
else
MemoryByte = S9xDebugGetByte((Bank << 16) + Address + CByte);
if (MemoryByte < 32 || MemoryByte >= 127)
MemoryByte = '?';
sprintf(string, "%s%c", string, MemoryByte);
}
Address += 16;
debug_line_print(string);
}
Debug.Dump.Bank = Bank;
Debug.Dump.Address = Address;
}
if (*Line == 'q')
S9xExit();
if (*Line == 'W')
debug_whats_missing();
if (*Line == 'w')
debug_whats_used();
if (*Line == 'r')
{
debug_cpu_op_print(string, Bank, Address);
debug_line_print(string);
}
if (*Line == 'u')
{
if (Debug.Unassemble.Bank != 0 || Debug.Unassemble.Address != 0)
{
Bank = Debug.Unassemble.Bank;
Address = Debug.Unassemble.Address;
}
ErrorCode = debug_get_start_address(Line, &Bank, &Address);
for (int i = 0; i != 10; i++)
{
Address += debug_cpu_op_print(string, Bank, Address);
debug_line_print(string);
}
Debug.Unassemble.Bank = Bank;
Debug.Unassemble.Address = Address;
}
debug_line_print("");
return;
}