From 2df835d00591d085de589ddf4d40ea3edc8f3fac Mon Sep 17 00:00:00 2001 From: Ian C Date: Mon, 9 Jan 2023 15:11:53 +0000 Subject: Added support for debug logging over a socket. --- include/debug.h | 53 +++++++++++++++++++ include/gui.h | 1 + source/debug.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ source/gui.c | 151 ++++++++++++++++++++++++++++++++++++++++------------ source/main.c | 59 +++++++++++++++++++++ source/snap.c | 5 ++ 6 files changed, 395 insertions(+), 35 deletions(-) create mode 100644 include/debug.h create mode 100644 source/debug.c diff --git a/include/debug.h b/include/debug.h new file mode 100644 index 0000000..2f01b84 --- /dev/null +++ b/include/debug.h @@ -0,0 +1,53 @@ +/* + + 3dsspec - Nintendo 3DS Spectrum emulator + + Copyright (C) 2021 Ian Cowburn (ianc@noddybox.co.uk) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see + + ------------------------------------------------------------------------- + + Provides an interface for debug + +*/ + +#ifndef DSSPEC_DEBUG_H +#define DSSPEC_DEBUG_H + +/* This variable is TRUE if debug is enabled. Also use this for setting the + mode. +*/ +extern int debug_enabled; + +/* Use this macro to use debug. It saves a function call if debug is disabled. +*/ +#define SPEC_DEBUG(...) \ +do \ +{ \ + if (debug_enabled) DEBUG_Output(__VA_ARGS__); \ +} while(0) + +/* The host and port to use for the debug +*/ +void DEBUG_SetAddress(const char *host, const char *port); + +/* The debug interface. Takes a printf style format and parameters. +*/ +void DEBUG_Output(const char *format, ...); + +#endif + + +/* END OF FILE */ diff --git a/include/gui.h b/include/gui.h index 392571b..7a1608c 100644 --- a/include/gui.h +++ b/include/gui.h @@ -31,6 +31,7 @@ int GUI_FileSelect(char pwd[], char selected_file[], const char *filter); int GUI_InputName(const char *prompt, const char *ext, char name[], int maxlen); +int GUI_Input(const char *prompt, char text[], int maxlen); extern char last_dir[FILENAME_MAX]; diff --git a/source/debug.c b/source/debug.c new file mode 100644 index 0000000..f297238 --- /dev/null +++ b/source/debug.c @@ -0,0 +1,161 @@ +/* + 3dsspec - Nintendo 3DS Spectrum emulator + + Copyright (C) 2021 Ian Cowburn + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see + + ------------------------------------------------------------------------- + + Provides an interface for debug + +*/ +#include +#include +#include +#include +#include +#include <3ds.h> + +#include +#include +#include +#include +#include +#include + +#include "debug.h" +#include "gui.h" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +/* ---------------------------------------- GLOBAL EXTERNALS +*/ +int debug_enabled = FALSE; + +/* ---------------------------------------- PRIVATE DAYA +*/ +static char debug_host[256]; +static char debug_port[32]; +static int sock = -1; + +/* ---------------------------------------- PRIVATE FUNCTIONS +*/ +static void Error(const char *format, ...) +{ + static char buff[4096]; + va_list va; + + va_start(va, format); + vsnprintf(buff, 4096, format, va); + buff[4095] = 0; + va_end(va); + + GUI_Alert(FALSE, buff); +} + +static void OpenDebugConnection(void) +{ + if (sock == -1) + { + struct addrinfo *addr, *addr_p; + struct addrinfo hints = {0}; + + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if (getaddrinfo(debug_host, debug_port, &hints, &addr) == 0) + { + for(addr_p = addr; addr_p && sock == -1; addr_p = addr_p->ai_next) + { + sock = socket(addr_p->ai_family, + addr_p->ai_socktype, + addr_p->ai_protocol); + + if (sock != -1) + { + if (connect(sock, addr_p->ai_addr, addr_p->ai_addrlen) + == -1) + { + Error("Failed to connect socket"); + close(sock); + sock = -1; + } + } + else + { + Error("Failed to create socket(%d,%d,%d)\n%d %s", + addr_p->ai_family, + addr_p->ai_socktype, + addr_p->ai_protocol, + errno, + strerror(errno)); + } + } + } + else + { + Error("Failed to getaddrinfo(%s,%s)", debug_host, debug_port); + } + } +} + +/* ---------------------------------------- EXPORTED INTERFACES +*/ +void DEBUG_SetAddress(const char *host, const char *port) +{ + strncpy(debug_host, host, (sizeof debug_host) - 1); + strncpy(debug_port, port, (sizeof debug_port) - 1); + + debug_host[(sizeof debug_host) - 1] = 0; + debug_port[(sizeof debug_port) - 1] = 0; + + if (sock != -1) + { + close(sock); + sock = -1; + } +} + + +void DEBUG_Output(const char *format, ...) +{ + static char buff[4096]; + + if (debug_enabled) + { + va_list va; + + OpenDebugConnection(); + + va_start(va, format); + vsnprintf(buff, 4096, format, va); + buff[4095] = 0; + va_end(va); + + if (sock != -1) + { + send(sock, buff, strlen(buff), 0); + } + } +} + + +/* END OF FILE */ diff --git a/source/gui.c b/source/gui.c index c3b402d..5e31ac5 100644 --- a/source/gui.c +++ b/source/gui.c @@ -802,41 +802,13 @@ int GUI_InputName(const char *prompt, const char *ext, char name[], int maxlen) int ascii; } keymap[] = { - {SK_1, '1'}, - {SK_2, '2'}, - {SK_3, '3'}, - {SK_4, '4'}, - {SK_5, '5'}, - {SK_6, '6'}, - {SK_7, '7'}, - {SK_8, '8'}, - {SK_9, '9'}, - {SK_0, '0'}, - {SK_A, 'A'}, - {SK_B, 'B'}, - {SK_C, 'C'}, - {SK_D, 'D'}, - {SK_E, 'E'}, - {SK_F, 'F'}, - {SK_G, 'G'}, - {SK_H, 'H'}, - {SK_I, 'I'}, - {SK_J, 'J'}, - {SK_K, 'K'}, - {SK_L, 'L'}, - {SK_M, 'M'}, - {SK_N, 'N'}, - {SK_O, 'O'}, - {SK_P, 'P'}, - {SK_Q, 'Q'}, - {SK_R, 'R'}, - {SK_S, 'S'}, - {SK_T, 'T'}, - {SK_U, 'U'}, - {SK_V, 'V'}, - {SK_W, 'W'}, - {SK_X, 'X'}, - {SK_Y, 'Y'}, + {SK_1, '1'}, {SK_2, '2'}, {SK_3, '3'}, {SK_4, '4'}, {SK_5, '5'}, + {SK_6, '6'}, {SK_7, '7'}, {SK_8, '8'}, {SK_9, '9'}, {SK_0, '0'}, + {SK_A, 'A'}, {SK_B, 'B'}, {SK_C, 'C'}, {SK_D, 'D'}, {SK_E, 'E'}, + {SK_F, 'F'}, {SK_G, 'G'}, {SK_H, 'H'}, {SK_I, 'I'}, {SK_J, 'J'}, + {SK_K, 'K'}, {SK_L, 'L'}, {SK_M, 'M'}, {SK_N, 'N'}, {SK_O, 'O'}, + {SK_P, 'P'}, {SK_Q, 'Q'}, {SK_R, 'R'}, {SK_S, 'S'}, {SK_T, 'T'}, + {SK_U, 'U'}, {SK_V, 'V'}, {SK_W, 'W'}, {SK_X, 'X'}, {SK_Y, 'Y'}, {SK_Z, 'Z'}, {0, 0} }; @@ -928,3 +900,112 @@ int GUI_InputName(const char *prompt, const char *ext, char name[], int maxlen) return accept; } + +int GUI_Input(const char *prompt, char text[], int maxlen) +{ + struct + { + SoftKey key; + int ascii; + } keymap[] = + { + {SK_1, '1'}, {SK_2, '2'}, {SK_3, '3'}, {SK_4, '4'}, {SK_5, '5'}, + {SK_6, '6'}, {SK_7, '7'}, {SK_8, '8'}, {SK_9, '9'}, {SK_0, '0'}, + {SK_A, 'A'}, {SK_B, 'B'}, {SK_C, 'C'}, {SK_D, 'D'}, {SK_E, 'E'}, + {SK_F, 'F'}, {SK_G, 'G'}, {SK_H, 'H'}, {SK_I, 'I'}, {SK_J, 'J'}, + {SK_K, 'K'}, {SK_L, 'L'}, {SK_M, 'M'}, {SK_N, 'N'}, {SK_O, 'O'}, + {SK_P, 'P'}, {SK_Q, 'Q'}, {SK_R, 'R'}, {SK_S, 'S'}, {SK_T, 'T'}, + {SK_U, 'U'}, {SK_V, 'V'}, {SK_W, 'W'}, {SK_X, 'X'}, {SK_Y, 'Y'}, + {SK_Z, 'Z'}, {SK_SHIFT, '.'}, + {0, 0} + }; + + SoftKeyEvent ev; + int done = FALSE; + int accept = FALSE; + Framebuffer upper; + + text[0] = 0; + + while(!done) + { + FB_StartFrame(&upper, NULL); + + FB_Clear(&upper, COL_WHITE); + SK_DisplayKeyboard(); + + FB_printf(&upper, 0, 16, COL_BLACK, COL_TRANSPARENT, "%s", prompt); + FB_printf(&upper, 0, 8, COL_BLACK, COL_TRANSPARENT, "\"%s\001L\001\"", + text); + + FB_Print(&upper, "PRESS ENTER TO ACCEPT", 0, 32, + COL_BLACK, COL_TRANSPARENT); + FB_Print(&upper, "PRESS SYMBOL SHIFT TO BACKSPACE", 0, 40, + COL_BLACK, COL_TRANSPARENT); + FB_Print(&upper, "PRESS CAPS SHIFT FOR PERIOD", 0, 48, + COL_BLACK, COL_TRANSPARENT); + FB_Print(&upper, "PRESS SPACE/BREAK TO CANCEL", 0, 56, + COL_BLACK, COL_TRANSPARENT); + + FB_EndFrame(); + + while(SK_GetBareEvent(&ev)) + { + if (!ev.pressed) + { + size_t l; + int f; + int ascii; + + l = strlen(text); + + switch(ev.key) + { + case SK_SYMBOL: + if (l) + { + text[--l] = 0; + } + break; + + case SK_SPACE: + done = TRUE; + accept = FALSE; + break; + + case SK_NEWLINE: + done = TRUE; + accept = TRUE; + break; + + default: + if (l < maxlen) + { + f = 0; + ascii = 0; + + while(!ascii && keymap[f].ascii) + { + if (ev.key == keymap[f].key) + { + ascii = keymap[f].ascii; + } + + f++; + } + + if (ascii) + { + text[l++] = ascii; + text[l] = 0; + } + } + break; + } + } + } + } + + return accept; +} + diff --git a/source/main.c b/source/main.c index b5f9c72..30e9359 100644 --- a/source/main.c +++ b/source/main.c @@ -22,6 +22,7 @@ #include #include #include +#include #include <3ds.h> #include "framebuffer.h" @@ -32,6 +33,7 @@ #include "config.h" #include "snapshot.h" #include "snap.h" +#include "debug.h" #define DSSPEC_VERSION "0.1" @@ -67,6 +69,7 @@ static const char *main_menu[]= "Load Memory Snapshot", "Save Joypad/Key State", "Load Joypad/Key State", + "Enable Debug", "Exit 3DSSPEC", "Cancel", NULL @@ -82,6 +85,7 @@ typedef enum MenuLoadSnapshot, MenuSaveMappings, MenuLoadMappings, + MenuDebug, MenuExit } MenuOpt; @@ -236,6 +240,8 @@ int main(int argc, char *argv[]) Z80 *z80; int quit = FALSE; float mix[12] = {1.0, 1.0}; + u32 *SOC_buffer; + int soc_initialised = FALSE; gfxInit(GSP_RGB565_OES, GSP_RGB565_OES, FALSE); ndspInit(); @@ -249,6 +255,29 @@ int main(int argc, char *argv[]) FB_Init(); GUI_Init(); + SOC_buffer = (u32*)memalign(0x1000,0x100000); + + if (SOC_buffer) + { + int ret; + + if ((ret = socInit(SOC_buffer, 0x100000)) == 0) + { + soc_initialised = TRUE; + } + else + { + char msg[256]; + snprintf(msg, sizeof msg, "Failed to initialise SOC\n0x%08X", + (unsigned int)ret); + GUI_Alert(FALSE, msg); + } + } + else + { + GUI_Alert(FALSE, "Failed to allocate memory for SOC!"); + } + z80 = Z80Init(SPECReadPort, SPECWritePort); if (!z80) @@ -343,6 +372,31 @@ int main(int argc, char *argv[]) SNAP_Load(z80, NULL, SNAP_TYPE_KEYBOARD); 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); + } + break; + case MenuExit: quit = TRUE; break; @@ -360,5 +414,10 @@ int main(int argc, char *argv[]) ndspExit(); gfxExit(); + if (soc_initialised) + { + socExit(); + } + return 0; } diff --git a/source/snap.c b/source/snap.c index e998ba2..db8c785 100644 --- a/source/snap.c +++ b/source/snap.c @@ -25,6 +25,7 @@ #include #include "snap.h" +#include "debug.h" /* ---------------------------------------- MACROS */ @@ -111,6 +112,10 @@ int TAPLoad(Z80Byte id, Z80Word *addr, Z80Word *len, SNAP_Poke poke) type=GetTAPByte(); csum=id; + SPEC_DEBUG("Read block. len=%u type=%u\n", (unsigned)blen, (unsigned)type); + SPEC_DEBUG("Requested block len=%u type=%u addr=%u\n", + (unsigned)*len, (unsigned)id, (unsigned)*addr); + /* Have we found the requested block? */ if (id==type) -- cgit v1.2.3