diff options
author | Ian C <ianc@noddybox.co.uk> | 2023-01-09 15:11:53 +0000 |
---|---|---|
committer | Ian C <ianc@noddybox.co.uk> | 2023-01-09 15:11:53 +0000 |
commit | 2df835d00591d085de589ddf4d40ea3edc8f3fac (patch) | |
tree | 01bce387296a3590a26eb0856a51f12f9f207242 /source | |
parent | 5b9ffe70b622cee65ed5678163bee0e22fc0433d (diff) |
Added support for debug logging over a socket.
Diffstat (limited to 'source')
-rw-r--r-- | source/debug.c | 161 | ||||
-rw-r--r-- | source/gui.c | 151 | ||||
-rw-r--r-- | source/main.c | 59 | ||||
-rw-r--r-- | source/snap.c | 5 |
4 files changed, 341 insertions, 35 deletions
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 <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 <http://www.gnu.org/licenses/> + + ------------------------------------------------------------------------- + + Provides an interface for debug + +*/ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <errno.h> +#include <3ds.h> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <netdb.h> + +#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 <stdlib.h> #include <stdio.h> #include <string.h> +#include <malloc.h> #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 <stdio.h> #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) |