summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/spec.h3
-rw-r--r--source/main.c486
-rw-r--r--source/z80.c5
3 files changed, 456 insertions, 38 deletions
diff --git a/include/spec.h b/include/spec.h
index 8171a4f..1663d37 100644
--- a/include/spec.h
+++ b/include/spec.h
@@ -36,6 +36,9 @@
*/
#define SAMPLE_RATE 22050
+/* The Spectrum's memory
+*/
+extern Z80Byte Z80_MEMORY[];
/* Initialise the SPEC
*/
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;
}