From 0ef7445dc7fb7b283a480b98ebbe873c7bd04bf1 Mon Sep 17 00:00:00 2001 From: Ian C Date: Wed, 11 Jan 2023 21:40:13 +0000 Subject: Added debug screens. Fixed the emulation of IM 2 which fixes the bad TAPs. --- source/main.c | 486 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- source/z80.c | 5 +- 2 files changed, 453 insertions(+), 38 deletions(-) (limited to 'source') diff --git a/source/main.c b/source/main.c index af91d19..355bf31 100644 --- a/source/main.c +++ b/source/main.c @@ -35,7 +35,7 @@ #include "snap.h" #include "debug.h" -#define DSSPEC_VERSION "0.1" +#define DSSPEC_VERSION "0.1 development" #ifndef TRUE #define TRUE 1 @@ -45,17 +45,9 @@ #define FALSE 0 #endif -#define DEBUG(x) \ - do \ - { \ - printf(x); \ - gfxFlushBuffers(); \ - gfxSwapBuffers(); \ - } while(0); \ - do \ - { \ - hidScanInput(); \ - } while(!(hidKeysDown() & KEY_TOUCH)) \ +/* Macro for PRINT AT in the upper framebuffer +*/ +#define AT(x,y) (x)*8,upper.height-1-(y)*8 /* ---------------------------------------- STATIC DATA */ @@ -69,7 +61,7 @@ static const char *main_menu[]= "Load Memory Snapshot", "Save Joypad/Key State", "Load Joypad/Key State", - "Enable Debug", + "Debug", "Exit 3DSSPEC", "Cancel", NULL @@ -90,6 +82,26 @@ typedef enum } MenuOpt; +static const char *debug_menu[]= + { + "Enable Debug Output", + "Disable Debug Output", + "Disassembler", + "Memory Viewer", + "CPU Info", + "Cancel", + NULL + }; + +typedef enum +{ + DebugMenuEnableOutput, + DebugMenuDisableOutput, + DebugMenuDisassembler, + DebugMenuMemoryView, + DebugMenuCPUInfo, +} DebugMenuOpt; + /* ---------------------------------------- DISPLAY FUNCS */ static void Splash(void) @@ -102,12 +114,13 @@ static void Splash(void) "an hour. And no retro game is complete without a side-scroller... " "Thanks to Slay Radio, Ladytron, the Genki Rockets, the High " "Voltage SID Collection, The Prodigy, Paradise Lost and " - "Retro Gamer for coding fuel." + "Retro Gamer for coding fuel. Extra special thanks to devkitPro for " + "the development environment." }; static const char *text[]= { - "3DSSPEC \177 2021 Ian Cowburn", + "3DSSPEC \177 2023 Ian Cowburn", " ", "Spectrum ROM \177 1982 Amstrad", " ", @@ -232,6 +245,426 @@ static void MapJoypad(void) } } +/* ---------------------------------------- DEBUG FUNCTIONS +*/ +static void DebugDisassembler(Z80 *cpu) +{ + static Z80Word addr = 0; + int done = FALSE; + Z80Word curr_addr = 0; + Framebuffer upper; + Framebuffer lower; + SoftKeyEvent ev; + int f; + + while(!done && aptMainLoop()) + { + FB_StartFrame(&upper, &lower); + + SK_DisplayKeyboard(); + + curr_addr = addr; + + FB_Clear(&upper, COL_WHITE); + + for(f=upper.height - 1; f > 0; f -= 8) + { + FB_printf(&upper, 0, f, COL_RED, COL_TRANSPARENT, + "%4.4x:", (unsigned)curr_addr); + FB_printf(&upper, 6*8, f, COL_BLACK, COL_TRANSPARENT, + "%s", Z80Disassemble(cpu, &curr_addr)); + } + + FB_EndFrame(); + + while(SK_GetBareEvent(&ev)) + { + if (!ev.pressed) + { + switch(ev.key) + { + case SK_PAD_UP: + addr--; + break; + + case SK_PAD_DOWN: + addr++; + break; + + case SK_PAD_R: + addr = curr_addr; + break; + + case SK_PAD_L: + addr -= 20; + break; + + case SK_PAD_START: + done = TRUE; + break; + + case SK_PAD_A: + { + char addrstr[32] = {0}; + + if (GUI_Input("Enter address", addrstr, 31)) + { + addr = (Z80Word)strtoul(addrstr, NULL, 0); + } + + break; + } + + default: + break; + } + } + } + } +} + +static void DebugMemory(Z80 *cpu) +{ + static Z80Word addr = 0; + int done = FALSE; + Z80Word curr_addr = 0; + Framebuffer upper; + Framebuffer lower; + SoftKeyEvent ev; + int f; + int r; + int rows; + + while(!done && aptMainLoop()) + { + FB_StartFrame(&upper, &lower); + + SK_DisplayKeyboard(); + + curr_addr = addr; + + FB_Clear(&upper, COL_WHITE); + + rows = 0; + + for(f=upper.height - 1; f > 0; f -= 8) + { + FB_printf(&upper, 0, f, COL_RED, COL_TRANSPARENT, + "%4.4x:", (unsigned)curr_addr); + + for(r=0; r < 8; r++) + { + char c = '.'; + + FB_printf(&upper, 6*8 + r*24, f, COL_BLACK, COL_TRANSPARENT, + "%2.2x", (unsigned)Z80_MEMORY[curr_addr]); + + if (Z80_MEMORY[curr_addr] >= 32 && Z80_MEMORY[curr_addr] < 128) + { + c = Z80_MEMORY[curr_addr]; + } + + FB_printf(&upper, 31*8 + r*8, f, COL_BLUE, COL_TRANSPARENT, + "%c", c); + + curr_addr++; + } + + rows++; + } + + FB_EndFrame(); + + while(SK_GetBareEvent(&ev)) + { + if (!ev.pressed) + { + switch(ev.key) + { + case SK_PAD_UP: + addr--; + break; + + case SK_PAD_DOWN: + addr++; + break; + + case SK_PAD_R: + addr += rows * 8; + break; + + case SK_PAD_L: + addr -= rows * 8; + break; + + case SK_PAD_START: + done = TRUE; + break; + + case SK_PAD_A: + { + char addrstr[32] = {0}; + + if (GUI_Input("Enter address", addrstr, 31)) + { + addr = (Z80Word)strtoul(addrstr, NULL, 0); + } + + break; + } + + default: + break; + } + } + } + } +} + +static void DebugCPU(Z80 *cpu) +{ + static enum + { + AddrPC, + AddrSP, + AddrHL, + AddrBC, + AddrDE, + AddrIX, + AddrIY, + NumAddr + } addr_type = AddrPC; + + const char *addr_text[]= + { + "PC", "SP", "HL", "BC", "DE", "IX", "IY" + }; + + int done = FALSE; + Framebuffer upper; + Framebuffer lower; + SoftKeyEvent ev; + Z80Word addr; + Z80Word base; + int f; + + while(!done && aptMainLoop()) + { + FB_StartFrame(&upper, &lower); + + SK_DisplayKeyboard(); + + FB_Clear(&upper, COL_WHITE); + + addr = cpu->PC; + + FB_printf(&upper, AT(0,0), COL_BLACK, COL_TRANSPARENT, + "PC: %4.4x %s", (unsigned)cpu->PC, + Z80Disassemble(cpu, &addr)); + + FB_printf(&upper, AT(0,2), COL_BLACK, COL_TRANSPARENT, + "AF: %4.4x", (unsigned)cpu->AF.w); + + FB_printf(&upper, AT(0,3), COL_BLACK, COL_TRANSPARENT, + "BC: %4.4x", (unsigned)cpu->BC.w); + + FB_printf(&upper, AT(0,4), COL_BLACK, COL_TRANSPARENT, + "DE: %4.4x", (unsigned)cpu->DE.w); + + FB_printf(&upper, AT(0,5), COL_BLACK, COL_TRANSPARENT, + "HL: %4.4x", (unsigned)cpu->HL.w); + + FB_printf(&upper, AT(0,6), COL_BLACK, COL_TRANSPARENT, + "IX: %4.4x", (unsigned)cpu->IX.w); + + FB_printf(&upper, AT(0,7), COL_BLACK, COL_TRANSPARENT, + "IY: %4.4x", (unsigned)cpu->IX.w); + + FB_printf(&upper, AT(9,2), COL_BLACK, COL_TRANSPARENT, + "AF': %4.4x", (unsigned)cpu->AF_); + + FB_printf(&upper, AT(9,3), COL_BLACK, COL_TRANSPARENT, + "BC': %4.4x", (unsigned)cpu->BC_); + + FB_printf(&upper, AT(9,4), COL_BLACK, COL_TRANSPARENT, + "DE': %4.4x", (unsigned)cpu->DE_); + + FB_printf(&upper, AT(9,5), COL_BLACK, COL_TRANSPARENT, + "HL': %4.4x", (unsigned)cpu->HL_); + + switch(addr_type) + { + case AddrPC: + addr = cpu->PC; + break; + case AddrSP: + addr = cpu->SP; + break; + case AddrHL: + addr = cpu->HL.w; + break; + case AddrBC: + addr = cpu->BC.w; + break; + case AddrDE: + addr = cpu->DE.w; + break; + case AddrIX: + addr = cpu->IX.w; + break; + case AddrIY: + addr = cpu->IY.w; + break; + default: + break; + } + + base = addr; + addr -= 5; + + for(f=0; f < 11; f++) + { + if (addr == base) + { + FB_printf(&upper, AT(0,9+f), COL_BLACK, COL_LIGHTGREY, + "%s %4.4x: %2.2x", + addr_text[addr_type], + (unsigned)addr, (unsigned)Z80_MEMORY[addr]); + } + else + { + FB_printf(&upper, AT(3,9+f), COL_BLACK, COL_TRANSPARENT, + "%4.4x: %2.2x", + (unsigned)addr, (unsigned)Z80_MEMORY[addr]); + } + + addr++; + } + + FB_printf(&upper, AT(0,21), COL_BLACK, COL_TRANSPARENT, + "IFF1: %2.2x IFF2: %2.2x IM: %2.2x I:%2.2x R:%2.2x", + (unsigned)cpu->IFF1, + (unsigned)cpu->IFF2, + (unsigned)cpu->IM, + (unsigned)cpu->I, + (unsigned)cpu->R); + + FB_printf(&upper, AT(0,23), COL_BLACK, COL_TRANSPARENT, + "Flags: SZ5H3PNC"); + + FB_printf(&upper, AT(7,24), COL_BLACK, + cpu->AF.b.lo & eZ80_Sign ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(8,24), COL_BLACK, + cpu->AF.b.lo & eZ80_Zero ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(9,24), COL_BLACK, + cpu->AF.b.lo & eZ80_Hidden5 ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(10,24), COL_BLACK, + cpu->AF.b.lo & eZ80_HalfCarry ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(11,24), COL_BLACK, + cpu->AF.b.lo & eZ80_Hidden3 ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(12,24), COL_BLACK, + cpu->AF.b.lo & eZ80_PV ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(13,24), COL_BLACK, + cpu->AF.b.lo & eZ80_Neg ? COL_GREEN : COL_RED, " "); + + FB_printf(&upper, AT(14,24), COL_BLACK, + cpu->AF.b.lo & eZ80_Carry ? COL_GREEN : COL_RED, " "); + + FB_EndFrame(); + + if (SK_KeyPressed(SK_PAD_B)) + { + Z80SingleStep(cpu); + } + + while(SK_GetBareEvent(&ev)) + { + if (!ev.pressed) + { + switch(ev.key) + { + case SK_PAD_L: + if (addr_type == AddrPC) + { + addr_type = AddrIY; + } + else + { + addr_type--; + } + break; + + case SK_PAD_R: + addr_type = (addr_type + 1) % NumAddr; + break; + + case SK_PAD_START: + done = TRUE; + break; + + case SK_PAD_A: + Z80SingleStep(cpu); + break; + + default: + break; + } + } + } + } +} + +static void DebugMenu(Z80 *cpu) +{ + switch(GUI_Menu(debug_menu)) + { + case DebugMenuEnableOutput: + { + char host[32] = {0}; + char port[32] = {0}; + + debug_enabled = TRUE; + + GUI_Input("Enter host", host, 31); + GUI_Input("Enter port", port, 31); + + if (!host[0]) + { + strcpy(host, "192.168.0.77"); + } + + if (!port[0]) + { + strcpy(port, "12345"); + } + + DEBUG_SetAddress(host, port); + break; + } + + case DebugMenuDisableOutput: + debug_enabled = FALSE; + break; + + case DebugMenuDisassembler: + DebugDisassembler(cpu); + break; + + case DebugMenuMemoryView: + DebugMemory(cpu); + break; + + case DebugMenuCPUInfo: + DebugCPU(cpu); + break; + } +} /* ---------------------------------------- MAIN */ @@ -376,28 +809,7 @@ int main(int argc, char *argv[]) break; case MenuDebug: - if (soc_initialised) - { - char host[32] = {0}; - char port[32] = {0}; - - debug_enabled = TRUE; - - GUI_Input("Enter host", host, 31); - GUI_Input("Enter port", port, 31); - - if (!host[0]) - { - strcpy(host, "192.168.0.77"); - } - - if (!port[0]) - { - strcpy(port, "12345"); - } - - DEBUG_SetAddress(host, port); - } + DebugMenu(z80); break; case MenuExit: diff --git a/source/z80.c b/source/z80.c index 0f1293a..d18640a 100644 --- a/source/z80.c +++ b/source/z80.c @@ -50,6 +50,8 @@ static void InitTables() static void Z80_CheckInterrupt(Z80 *cpu) { + Z80Word vector; + /* Check interrupts */ if (PRIV->raise) @@ -101,7 +103,8 @@ static void Z80_CheckInterrupt(Z80 *cpu) case 2: PUSH(cpu->PC); - cpu->PC=(Z80Word)cpu->I*256+PRIV->devbyte; + vector=(Z80Word)cpu->I*256+PRIV->devbyte; + cpu->PC=PEEKW(vector); PRIV->memptr.w=cpu->PC; break; } -- cgit v1.2.3