all repos — mgba @ a0d223eef7c33382231510db9c851f856c891323

mGBA Game Boy Advance Emulator

Debugger: Modularize CLI debugger
Jeffrey Pfau jeffrey@endrift.com
Tue, 25 Oct 2016 21:12:35 -0700
commit

a0d223eef7c33382231510db9c851f856c891323

parent

474f1c6e9c8b5008d40a0faf1508e685b72cede3

M CHANGESCHANGES

@@ -29,6 +29,7 @@ - GBA Video, GB Video: Colors are now fully scaled

- PSP2: Improved controller rumble - GB, GBA: Prevent loading null ROMs - VFS: Allow truncating memory chunk VFiles + - Debugger: Modularize CLI debugger 0.5.1: (2016-10-05) Bugfixes:
M CMakeLists.txtCMakeLists.txt

@@ -6,7 +6,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-missing-field-initializers -std=c99")

else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146") endif() -set(USE_CLI_DEBUGGER ON CACHE BOOL "Whether or not to enable the CLI-mode ARM debugger") +set(USE_EDITLINE ON CACHE BOOL "Whether or not to enable the CLI-mode debugger") set(USE_GDB_STUB ON CACHE BOOL "Whether or not to enable the GDB stub ARM debugger") set(USE_FFMPEG ON CACHE BOOL "Whether or not to enable FFmpeg support") set(USE_ZLIB ON CACHE BOOL "Whether or not to enable zlib support")

@@ -314,7 +314,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL OpenBSD)

list(APPEND LIBEDIT_LIBRARIES -ltermcap) endif() else() - find_feature(USE_CLI_DEBUGGER "libedit") + find_feature(USE_EDITLINE "libedit") endif() if(BUILD_GL) find_package(OpenGL QUIET)

@@ -350,7 +350,11 @@ find_feature(USE_EPOXY "epoxy")

find_feature(USE_CMOCKA "cmocka") # Features -set(DEBUGGER_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c) +set(DEBUGGER_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/debugger.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c) + set(FEATURE_SRC) set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6")

@@ -358,21 +362,13 @@ if(DISABLE_DEPS)

set(USE_GDB_STUB OFF) endif() -if(USE_CLI_DEBUGGER) - list(APPEND FEATURES CLI_DEBUGGER) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/cli-debugger.c) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/debugger/parser.c) - if(M_CORE_GBA) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/cli.c) - endif() - if(M_CORE_GB) - list(APPEND FEATURE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/cli-debugger.c) - endif() +if(USE_EDITLINE) + list(APPEND FEATURES EDITLINE) include_directories(AFTER ${LIBEDIT_INCLUDE_DIRS}) link_directories(${LIBEDIT_LIBRARY_DIRS}) set(DEBUGGER_LIB ${LIBEDIT_LIBRARIES}) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libedit2") + list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/editline/cli-el-backend.c") else() set(DEBUGGER_LIB "") endif()

@@ -548,6 +544,8 @@ ${LR35902_SRC}

${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/debugger.c ${GB_SRC} ${GB_RENDERER_SRC}) + list(APPEND CLI_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/lr35902/debugger/cli-debugger.c) list(APPEND TEST_SRC ${LR35902_TEST_SRC} ${GB_TEST_SRC})

@@ -562,6 +560,9 @@ ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/memory-debugger.c

${GBA_SRC} ${GBA_CHEATS_SRC} ${GBA_RENDERER_SRC}) + list(APPEND CLI_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/src/arm/debugger/cli-debugger.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/gba/extra/cli.c) list(APPEND TEST_SRC ${ARM_TEST_SRC} ${GBA_TEST_SRC})

@@ -801,7 +802,7 @@ message(STATUS "Platforms:")

message(STATUS " Game Boy Advance: ${M_CORE_GBA}") message(STATUS " Game Boy: ${M_CORE_GB}") message(STATUS "Features:") - message(STATUS " CLI debugger: ${USE_CLI_DEBUGGER}") + message(STATUS " CLI debugger: ${USE_EDITLINE}") message(STATUS " GDB stub: ${USE_GDB_STUB}") message(STATUS " Video recording: ${USE_FFMPEG}") message(STATUS " GIF recording: ${USE_MAGICK}")
M src/arm/debugger/cli-debugger.csrc/arm/debugger/cli-debugger.c

@@ -5,7 +5,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "cli-debugger.h" -#ifdef USE_CLI_DEBUGGER #include "arm/debugger/debugger.h" #include "arm/debugger/memory-debugger.h" #include "arm/decoder.h"

@@ -38,15 +37,15 @@ { "w/r", _writeRegister, CLIDVParse, "Write a register" },

{ 0, 0, 0, 0 } }; -static inline void _printPSR(union PSR psr) { - printf("%08X [%c%c%c%c%c%c%c]\n", psr.packed, - psr.n ? 'N' : '-', - psr.z ? 'Z' : '-', - psr.c ? 'C' : '-', - psr.v ? 'V' : '-', - psr.i ? 'I' : '-', - psr.f ? 'F' : '-', - psr.t ? 'T' : '-'); +static inline void _printPSR(struct CLIDebuggerBackend* be, union PSR psr) { + be->printf(be, "%08X [%c%c%c%c%c%c%c]\n", psr.packed, + psr.n ? 'N' : '-', + psr.z ? 'Z' : '-', + psr.c ? 'C' : '-', + psr.v ? 'V' : '-', + psr.i ? 'I' : '-', + psr.f ? 'F' : '-', + psr.t ? 'T' : '-'); } static void _disassemble(struct CLIDebuggerSystem* debugger, struct CLIDebugVector* dv) {

@@ -95,14 +94,15 @@ }

} static inline uint32_t _printLine(struct CLIDebugger* debugger, uint32_t address, enum ExecutionMode mode) { + struct CLIDebuggerBackend* be = debugger->backend; char disassembly[48]; struct ARMInstructionInfo info; - printf("%08X: ", address); + be->printf(be, "%08X: ", address); if (mode == MODE_ARM) { uint32_t instruction = debugger->d.core->busRead32(debugger->d.core, address); ARMDecodeARM(instruction, &info); ARMDisassemble(&info, address + WORD_SIZE_ARM * 2, disassembly, sizeof(disassembly)); - printf("%08X\t%s\n", instruction, disassembly); + be->printf(be, "%08X\t%s\n", instruction, disassembly); return WORD_SIZE_ARM; } else { struct ARMInstructionInfo info2;

@@ -113,27 +113,28 @@ ARMDecodeThumb(instruction, &info);

ARMDecodeThumb(instruction2, &info2); if (ARMDecodeThumbCombine(&info, &info2, &combined)) { ARMDisassemble(&combined, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); - printf("%04X %04X\t%s\n", instruction, instruction2, disassembly); + be->printf(be, "%04X %04X\t%s\n", instruction, instruction2, disassembly); return WORD_SIZE_THUMB * 2; } else { ARMDisassemble(&info, address + WORD_SIZE_THUMB * 2, disassembly, sizeof(disassembly)); - printf("%04X \t%s\n", instruction, disassembly); + be->printf(be, "%04X \t%s\n", instruction, disassembly); return WORD_SIZE_THUMB; } } } static void _printStatus(struct CLIDebuggerSystem* debugger) { + struct CLIDebuggerBackend* be = debugger->p->backend; struct ARMCore* cpu = debugger->p->d.core->cpu; int r; for (r = 0; r < 4; ++r) { - printf("%08X %08X %08X %08X\n", + be->printf(be, "%08X %08X %08X %08X\n", cpu->gprs[r << 2], cpu->gprs[(r << 2) + 1], cpu->gprs[(r << 2) + 2], cpu->gprs[(r << 2) + 3]); } - _printPSR(cpu->cpsr); + _printPSR(be, cpu->cpsr); int instructionLength; enum ExecutionMode mode = cpu->cpsr.t; if (mode == MODE_ARM) {

@@ -145,13 +146,14 @@ _printLine(debugger->p, cpu->gprs[ARM_PC] - instructionLength, mode);

} static void _writeRegister(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; struct ARMCore* cpu = debugger->d.core->cpu; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t regid = dv->intValue;

@@ -163,8 +165,9 @@ cpu->gprs[regid] = value;

} static void _setBreakpointARM(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -172,8 +175,9 @@ ARMDebuggerSetSoftwareBreakpoint(debugger->d.platform, address, MODE_ARM);

} static void _setBreakpointThumb(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -215,5 +219,3 @@ debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier;

debugger->platformName = "ARM"; debugger->platformCommands = _armCommands; } - -#endif
M src/debugger/cli-debugger.csrc/debugger/cli-debugger.c

@@ -5,11 +5,10 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "cli-debugger.h" -#ifdef USE_CLI_DEBUGGER - #include "core/core.h" #include "core/version.h" -#include "parser.h" +#include "debugger/parser.h" +#include "util/string.h" #include <signal.h>

@@ -19,8 +18,6 @@ #endif

const char* ERROR_MISSING_ARGS = "Arguments missing"; // TODO: share const char* ERROR_OVERFLOW = "Arguments overflow"; - -static struct CLIDebugger* _activeDebugger; #ifndef NDEBUG static void _breakInto(struct CLIDebugger*, struct CLIDebugVector*);

@@ -47,8 +44,6 @@ static void _writeWord(struct CLIDebugger*, struct CLIDebugVector*);

static void _dumpByte(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpHalfword(struct CLIDebugger*, struct CLIDebugVector*); static void _dumpWord(struct CLIDebugger*, struct CLIDebugVector*); - -static void _breakIntoDefault(int signal); static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "b", _setBreakpoint, CLIDVParse, "Set a breakpoint" },

@@ -133,68 +128,64 @@ debugger->system->disassemble(debugger->system, dv);

} static void _print(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - UNUSED(debugger); for (; dv; dv = dv->next) { - printf(" %u", dv->intValue); + debugger->backend->printf(debugger->backend, " %u", dv->intValue); } - printf("\n"); + debugger->backend->printf(debugger->backend, "\n"); } static void _printBin(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - UNUSED(debugger); for (; dv; dv = dv->next) { - printf(" 0b"); + debugger->backend->printf(debugger->backend, " 0b"); int i = 32; while (i--) { - printf("%u", (dv->intValue >> i) & 1); + debugger->backend->printf(debugger->backend, "%u", (dv->intValue >> i) & 1); } } - printf("\n"); + debugger->backend->printf(debugger->backend, "\n"); } static void _printHex(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - UNUSED(debugger); for (; dv; dv = dv->next) { - printf(" 0x%08X", dv->intValue); + debugger->backend->printf(debugger->backend, " 0x%08X", dv->intValue); } - printf("\n"); + debugger->backend->printf(debugger->backend, "\n"); } static void _printHelp(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { - UNUSED(debugger); UNUSED(dv); if (!dv) { - puts("Generic commands:"); + debugger->backend->printf(debugger->backend, "Generic commands:"); int i; for (i = 0; _debuggerCommands[i].name; ++i) { - printf("%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary); + debugger->backend->printf(debugger->backend, "%-10s %s\n", _debuggerCommands[i].name, _debuggerCommands[i].summary); } if (debugger->system) { - printf("%s commands:\n", debugger->system->platformName); + debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->platformName); for (i = 0; debugger->system->platformCommands[i].name; ++i) { - printf("%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary); + debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->platformCommands[i].name, debugger->system->platformCommands[i].summary); } - printf("%s commands:\n", debugger->system->name); + debugger->backend->printf(debugger->backend, "%s commands:\n", debugger->system->name); for (i = 0; debugger->system->commands[i].name; ++i) { - printf("%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary); + debugger->backend->printf(debugger->backend, "%-10s %s\n", debugger->system->commands[i].name, debugger->system->commands[i].summary); } } } else { int i; for (i = 0; _debuggerCommands[i].name; ++i) { if (strcmp(_debuggerCommands[i].name, dv->charValue) == 0) { - printf(" %s\n", _debuggerCommands[i].summary); + debugger->backend->printf(debugger->backend, " %s\n", _debuggerCommands[i].summary); } } if (debugger->system) { for (i = 0; debugger->system->platformCommands[i].name; ++i) { if (strcmp(debugger->system->platformCommands[i].name, dv->charValue) == 0) { - printf(" %s\n", debugger->system->platformCommands[i].summary); + debugger->backend->printf(debugger->backend, " %s\n", debugger->system->platformCommands[i].summary); } } for (i = 0; debugger->system->commands[i].name; ++i) { if (strcmp(debugger->system->commands[i].name, dv->charValue) == 0) { - printf(" %s\n", debugger->system->commands[i].summary); + debugger->backend->printf(debugger->backend, " %s\n", debugger->system->commands[i].summary); } } }

@@ -208,12 +199,12 @@ }

static void _readByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; uint8_t value = debugger->d.core->busRead8(debugger->d.core, address); - printf(" 0x%02X\n", value); + debugger->backend->printf(debugger->backend, " 0x%02X\n", value); } static void _reset(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -224,37 +215,37 @@ }

static void _readHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; uint16_t value = debugger->d.core->busRead16(debugger->d.core, address & ~1); - printf(" 0x%04X\n", value); + debugger->backend->printf(debugger->backend, " 0x%04X\n", value); } static void _readWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; uint32_t value = debugger->d.core->busRead32(debugger->d.core, address & ~3); - printf(" 0x%08X\n", value); + debugger->backend->printf(debugger->backend, " 0x%08X\n", value); } static void _writeByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; uint32_t value = dv->next->intValue; if (value > 0xFF) { - printf("%s\n", ERROR_OVERFLOW); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_OVERFLOW); return; } debugger->d.core->busWrite8(debugger->d.core, address, value);

@@ -262,17 +253,17 @@ }

static void _writeHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue; uint32_t value = dv->next->intValue; if (value > 0xFFFF) { - printf("%s\n", ERROR_OVERFLOW); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_OVERFLOW); return; } debugger->d.core->busWrite16(debugger->d.core, address, value);

@@ -280,11 +271,11 @@ }

static void _writeWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } if (!dv->next || dv->next->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -294,7 +285,7 @@ }

static void _dumpByte(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -307,18 +298,18 @@ uint32_t line = 16;

if (line > words) { line = words; } - printf("0x%08X:", address); + debugger->backend->printf(debugger->backend, "0x%08X:", address); for (; line > 0; --line, ++address, --words) { uint32_t value = debugger->d.core->busRead8(debugger->d.core, address); - printf(" %02X", value); + debugger->backend->printf(debugger->backend, " %02X", value); } - printf("\n"); + debugger->backend->printf(debugger->backend, "\n"); } } static void _dumpHalfword(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -331,18 +322,18 @@ uint32_t line = 8;

if (line > words) { line = words; } - printf("0x%08X:", address); + debugger->backend->printf(debugger->backend, "0x%08X:", address); for (; line > 0; --line, address += 2, --words) { uint32_t value = debugger->d.core->busRead16(debugger->d.core, address); - printf(" %04X", value); + debugger->backend->printf(debugger->backend, " %04X", value); } - printf("\n"); + debugger->backend->printf(debugger->backend, "\n"); } } static void _dumpWord(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -355,18 +346,18 @@ uint32_t line = 4;

if (line > words) { line = words; } - printf("0x%08X:", address); + debugger->backend->printf(debugger->backend, "0x%08X:", address); for (; line > 0; --line, address += 4, --words) { uint32_t value = debugger->d.core->busRead32(debugger->d.core, address); - printf(" %08X", value); + debugger->backend->printf(debugger->backend, " %08X", value); } - printf("\n"); + debugger->backend->printf(debugger->backend, "\n"); } } static void _setBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -375,11 +366,11 @@ }

static void _setWatchpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } if (!debugger->d.platform->setWatchpoint) { - printf("Watchpoints are not supported by this platform.\n"); + debugger->backend->printf(debugger->backend, "Watchpoints are not supported by this platform.\n"); return; } uint32_t address = dv->intValue;

@@ -388,7 +379,7 @@ }

static void _clearBreakpoint(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + debugger->backend->printf(debugger->backend, "%s\n", ERROR_MISSING_ARGS); return; } uint32_t address = dv->intValue;

@@ -396,11 +387,6 @@ debugger->d.platform->clearBreakpoint(debugger->d.platform, address);

if (debugger->d.platform->clearWatchpoint) { debugger->d.platform->clearWatchpoint(debugger->d.platform, address); } -} - -static void _breakIntoDefault(int signal) { - UNUSED(signal); - mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0); } static void _printStatus(struct CLIDebugger* debugger, struct CLIDebugVector* dv) {

@@ -537,8 +523,7 @@ adjusted = next - string;

} else { adjusted = length; } - dvTemp.charValue = malloc(adjusted); - strncpy(dvTemp.charValue, string, adjusted); + dvTemp.charValue = strndup(string, adjusted); length -= adjusted; string += adjusted;

@@ -579,13 +564,13 @@ if (commands[i].parser) {

if (args) { dv = commands[i].parser(debugger, args, argsLen); if (dv && dv->type == CLIDV_ERROR_TYPE) { - printf("Parse error\n"); + debugger->backend->printf(debugger->backend, "Parse error\n"); _DVFree(dv); return false; } } } else if (args) { - printf("Wrong number of arguments\n"); + debugger->backend->printf(debugger->backend, "Wrong number of arguments\n"); return false; } commands[i].command(debugger, dv);

@@ -617,155 +602,88 @@ result = _tryCommands(debugger, debugger->system->platformCommands, line, cmdLength, args, count - cmdLength - 1);

} } if (result < 0) { - printf("Command not found\n"); + debugger->backend->printf(debugger->backend, "Command not found\n"); } return false; } -static char* _prompt(EditLine* el) { - UNUSED(el); - return "> "; -} - static void _commandLine(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; const char* line; + size_t len; _printStatus(cliDebugger, 0); - int count = 0; - HistEvent ev; while (debugger->state == DEBUGGER_PAUSED) { - line = el_gets(cliDebugger->elstate, &count); - if (!line) { + line = cliDebugger->backend->readline(cliDebugger->backend, &len); + if (!line || len == 0) { debugger->state = DEBUGGER_SHUTDOWN; return; } if (line[0] == '\n') { - if (history(cliDebugger->histate, &ev, H_FIRST) >= 0) { - _parse(cliDebugger, ev.str, strlen(ev.str) - 1); + line = cliDebugger->backend->historyLast(cliDebugger->backend, &len); + if (line && len) { + _parse(cliDebugger, line, len); } } else { - _parse(cliDebugger, line, count - 1); - history(cliDebugger->histate, &ev, H_ENTER, line); + _parse(cliDebugger, line, len); + cliDebugger->backend->historyAppend(cliDebugger->backend, line); } } } static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { - UNUSED(debugger); + struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; switch (reason) { case DEBUGGER_ENTER_MANUAL: case DEBUGGER_ENTER_ATTACHED: break; case DEBUGGER_ENTER_BREAKPOINT: if (info) { - printf("Hit breakpoint at 0x%08X\n", info->address); + cliDebugger->backend->printf(cliDebugger->backend, "Hit breakpoint at 0x%08X\n", info->address); } else { - printf("Hit breakpoint\n"); + cliDebugger->backend->printf(cliDebugger->backend, "Hit breakpoint\n"); } break; case DEBUGGER_ENTER_WATCHPOINT: if (info) { if (info->accessType & WATCHPOINT_WRITE) { - printf("Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->newValue, info->oldValue); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->newValue, info->oldValue); } else { - printf("Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->oldValue); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->oldValue); } } else { - printf("Hit watchpoint\n"); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint\n"); } break; case DEBUGGER_ENTER_ILLEGAL_OP: if (info) { - printf("Hit illegal opcode at 0x%08X: 0x%08X\n", info->address, info->opcode); + cliDebugger->backend->printf(cliDebugger->backend, "Hit illegal opcode at 0x%08X: 0x%08X\n", info->address, info->opcode); } else { - printf("Hit illegal opcode\n"); + cliDebugger->backend->printf(cliDebugger->backend, "Hit illegal opcode\n"); } break; } } -static unsigned char _tabComplete(EditLine* elstate, int ch) { - UNUSED(ch); - const LineInfo* li = el_line(elstate); - if (!li->buffer[0]) { - return CC_ERROR; - } - - const char* commandPtr; - size_t cmd = 0, len = 0; - const char* name = 0; - for (commandPtr = li->buffer; commandPtr <= li->cursor; ++commandPtr, ++len) { - for (; (name = _debuggerCommands[cmd].name); ++cmd) { - int cmp = strncasecmp(name, li->buffer, len); - if (cmp > 0) { - return CC_ERROR; - } - if (cmp == 0) { - break; - } - } - } - if (!name) { - return CC_ERROR; - } - if (_debuggerCommands[cmd + 1].name && strlen(_debuggerCommands[cmd + 1].name) >= len - 1 && name[len - 2] == _debuggerCommands[cmd + 1].name[len - 2]) { - --len; - const char* next = 0; - int i; - for (i = cmd + 1; _debuggerCommands[i].name; ++i) { - if (strncasecmp(name, _debuggerCommands[i].name, len)) { - break; - } - next = _debuggerCommands[i].name; - } - if (!next) { - return CC_ERROR; - } - - for (; name[len]; ++len) { - if (name[len] != next[len]) { - break; - } - char out[2] = { name[len], '\0' }; - el_insertstr(elstate, out); - } - return CC_REDISPLAY; - } - name += len - 1; - el_insertstr(elstate, name); - el_insertstr(elstate, " "); - return CC_REDISPLAY; -} - static void _cliDebuggerInit(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; - // TODO: get argv[0] - cliDebugger->elstate = el_init(binaryName, stdin, stdout, stderr); - el_set(cliDebugger->elstate, EL_PROMPT, _prompt); - el_set(cliDebugger->elstate, EL_EDITOR, "emacs"); - - el_set(cliDebugger->elstate, EL_CLIENTDATA, cliDebugger); - el_set(cliDebugger->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete); - el_set(cliDebugger->elstate, EL_BIND, "\t", "tab-complete", 0); - cliDebugger->histate = history_init(); - HistEvent ev; - history(cliDebugger->histate, &ev, H_SETSIZE, 200); - el_set(cliDebugger->elstate, EL_HIST, history, cliDebugger->histate); - _activeDebugger = cliDebugger; - signal(SIGINT, _breakIntoDefault); + cliDebugger->backend->init(cliDebugger->backend); } static void _cliDebuggerDeinit(struct mDebugger* debugger) { struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; - history_end(cliDebugger->histate); - el_end(cliDebugger->elstate); - if (cliDebugger->system) { if (cliDebugger->system->deinit) { cliDebugger->system->deinit(cliDebugger->system); } free(cliDebugger->system); - cliDebugger->system = 0; + cliDebugger->system = NULL; + } + if (cliDebugger->backend) { + if (cliDebugger->backend->deinit) { + cliDebugger->backend->deinit(cliDebugger->backend); + } + free(cliDebugger->backend); + cliDebugger->backend = NULL; } }

@@ -787,7 +705,8 @@ debugger->d.custom = _cliDebuggerCustom;

debugger->d.paused = _commandLine; debugger->d.entered = _reportEntry; - debugger->system = 0; + debugger->system = NULL; + debugger->backend = NULL; } void CLIDebuggerAttachSystem(struct CLIDebugger* debugger, struct CLIDebuggerSystem* system) {

@@ -802,4 +721,61 @@ debugger->system = system;

system->p = debugger; } -#endif +void CLIDebuggerAttachBackend(struct CLIDebugger* debugger, struct CLIDebuggerBackend* backend) { + if (debugger->backend) { + if (debugger->backend->deinit) { + debugger->backend->deinit(debugger->backend); + } + free(debugger->backend); + } + + debugger->backend = backend; + backend->p = debugger; +} + +bool CLIDebuggerTabComplete(struct CLIDebugger* debugger, const char* token, bool initial, size_t tokenLen) { + size_t cmd = 0; + size_t len; + const char* name = 0; + for (len = 1; len <= tokenLen; ++len) { + for (; (name = _debuggerCommands[cmd].name); ++cmd) { + int cmp = strncasecmp(name, token, len); + if (cmp > 0) { + return false; + } + if (cmp == 0) { + break; + } + } + } + if (!name) { + return false; + } + if (_debuggerCommands[cmd + 1].name && strlen(_debuggerCommands[cmd + 1].name) >= len && name[len - 1] == _debuggerCommands[cmd + 1].name[len - 1]) { + --len; + const char* next = 0; + int i; + for (i = cmd + 1; _debuggerCommands[i].name; ++i) { + if (strncasecmp(name, _debuggerCommands[i].name, len)) { + break; + } + next = _debuggerCommands[i].name; + } + if (!next) { + return false; + } + + for (; name[len]; ++len) { + if (name[len] != next[len]) { + break; + } + char out[2] = { name[len], '\0' }; + debugger->backend->lineAppend(debugger->backend, out); + } + return true; + } + name += len - 1; + debugger->backend->lineAppend(debugger->backend, name); + debugger->backend->lineAppend(debugger->backend, " "); + return true; +}
M src/debugger/cli-debugger.hsrc/debugger/cli-debugger.h

@@ -1,4 +1,4 @@

-/* Copyright (c) 2013-2014 Jeffrey Pfau +/* Copyright (c) 2013-2016 Jeffrey Pfau * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this

@@ -9,9 +9,6 @@

#include "util/common.h" #include "debugger.h" - -#ifdef USE_CLI_DEBUGGER -#include <histedit.h> struct CLIDebugger;

@@ -59,13 +56,25 @@ struct CLIDebuggerCommandSummary* platformCommands;

const char* platformName; }; +struct CLIDebuggerBackend { + struct CLIDebugger* p; + + void (*init)(struct CLIDebuggerBackend*); + void (*deinit)(struct CLIDebuggerBackend*); + + ATTRIBUTE_FORMAT(printf, 2, 3) + void (*printf)(struct CLIDebuggerBackend*, const char* fmt, ...); + const char* (*readline)(struct CLIDebuggerBackend*, size_t* len); + void (*lineAppend)(struct CLIDebuggerBackend*, const char* line); + const char* (*historyLast)(struct CLIDebuggerBackend*, size_t* len); + void (*historyAppend)(struct CLIDebuggerBackend*, const char* line); +}; + struct CLIDebugger { struct mDebugger d; struct CLIDebuggerSystem* system; - - EditLine* elstate; - History* histate; + struct CLIDebuggerBackend* backend; }; struct CLIDebugVector* CLIDVParse(struct CLIDebugger* debugger, const char* string, size_t length);

@@ -73,6 +82,8 @@ struct CLIDebugVector* CLIDVStringParse(struct CLIDebugger* debugger, const char* string, size_t length);

void CLIDebuggerCreate(struct CLIDebugger*); void CLIDebuggerAttachSystem(struct CLIDebugger*, struct CLIDebuggerSystem*); -#endif +void CLIDebuggerAttachBackend(struct CLIDebugger*, struct CLIDebuggerBackend*); + +bool CLIDebuggerTabComplete(struct CLIDebugger*, const char* token, bool initial, size_t len); #endif
M src/debugger/debugger.csrc/debugger/debugger.c

@@ -7,9 +7,7 @@ #include "debugger.h"

#include "core/core.h" -#ifdef USE_CLI_DEBUGGER #include "debugger/cli-debugger.h" -#endif #ifdef USE_GDB_STUB #include "debugger/gdb-stub.h"

@@ -29,9 +27,7 @@ }

union DebugUnion { struct mDebugger d; -#ifdef USE_CLI_DEBUGGER struct CLIDebugger cli; -#endif #ifdef USE_GDB_STUB struct GDBStub gdb; #endif

@@ -40,13 +36,11 @@

union DebugUnion* debugger = malloc(sizeof(union DebugUnion)); switch (type) { -#ifdef USE_CLI_DEBUGGER case DEBUGGER_CLI: CLIDebuggerCreate(&debugger->cli); struct CLIDebuggerSystem* sys = core->cliDebuggerSystem(core); CLIDebuggerAttachSystem(&debugger->cli, sys); break; -#endif #ifdef USE_GDB_STUB case DEBUGGER_GDB: GDBStubCreate(&debugger->gdb);
M src/debugger/debugger.hsrc/debugger/debugger.h

@@ -18,9 +18,7 @@ extern const uint32_t DEBUGGER_ID;

enum mDebuggerType { DEBUGGER_NONE = 0, -#ifdef USE_CLI_DEBUGGER DEBUGGER_CLI, -#endif #ifdef USE_GDB_STUB DEBUGGER_GDB, #endif
M src/feature/commandline.csrc/feature/commandline.c

@@ -31,7 +31,7 @@ static const struct option _options[] = {

{ "bios", required_argument, 0, 'b' }, { "cheats", required_argument, 0, 'c' }, { "frameskip", required_argument, 0, 's' }, -#ifdef USE_CLI_DEBUGGER +#ifdef USE_EDITLINE { "debug", no_argument, 0, 'd' }, #endif #ifdef USE_GDB_STUB

@@ -51,7 +51,7 @@ bool parseArguments(struct mArguments* args, int argc, char* const* argv, struct mSubParser* subparser) {

int ch; char options[64] = "b:c:hl:p:s:v:" -#ifdef USE_CLI_DEBUGGER +#ifdef USE_EDITLINE "d" #endif #ifdef USE_GDB_STUB

@@ -82,7 +82,7 @@ break;

case 'c': args->cheatsFile = strdup(optarg); break; -#ifdef USE_CLI_DEBUGGER +#ifdef USE_EDITLINE case 'd': if (args->debuggerType != DEBUGGER_NONE) { return false;

@@ -209,7 +209,7 @@ printf("usage: %s [option ...] file\n", arg0);

puts("\nGeneric options:"); puts(" -b, --bios FILE GBA BIOS file to use"); puts(" -c, --cheats FILE Apply cheat codes from a file"); -#ifdef USE_CLI_DEBUGGER +#ifdef USE_EDITLINE puts(" -d, --debug Use command-line debugger"); #endif #ifdef USE_GDB_STUB
A src/feature/editline/cli-el-backend.c

@@ -0,0 +1,122 @@

+/* Copyright (c) 2013-2014 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "cli-el-backend.h" + +#include "core/version.h" + +#include <signal.h> + +static struct CLIDebugger* _activeDebugger; + +static char* _prompt(EditLine* el) { + UNUSED(el); + return "> "; +} + +static void _breakIntoDefault(int signal) { + UNUSED(signal); + mDebuggerEnter(&_activeDebugger->d, DEBUGGER_ENTER_MANUAL, 0); +} + +static unsigned char _tabComplete(EditLine* elstate, int ch) { + UNUSED(ch); + const LineInfo* li = el_line(elstate); + if (!li->buffer[0]) { + return CC_ERROR; + } + + struct CLIDebuggerEditLineBackend* elbe; + el_get(elstate, EL_CLIENTDATA, &elbe); + // TODO: not always true + if (CLIDebuggerTabComplete(elbe->d.p, li->buffer, true, li->cursor - li->buffer)) { + return CC_REDISPLAY; + } + return CC_ERROR; +} + +ATTRIBUTE_FORMAT(printf, 2, 3) +void _CLIDebuggerEditLinePrintf(struct CLIDebuggerBackend* be, const char* fmt, ...) { + UNUSED(be); + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); +} + +void _CLIDebuggerEditLineInit(struct CLIDebuggerBackend* be) { + struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; + // TODO: get argv[0] + elbe->elstate = el_init(binaryName, stdin, stdout, stderr); + el_set(elbe->elstate, EL_PROMPT, _prompt); + el_set(elbe->elstate, EL_EDITOR, "emacs"); + + el_set(elbe->elstate, EL_CLIENTDATA, elbe); + el_set(elbe->elstate, EL_ADDFN, "tab-complete", "Tab completion", _tabComplete); + el_set(elbe->elstate, EL_BIND, "\t", "tab-complete", 0); + elbe->histate = history_init(); + HistEvent ev; + history(elbe->histate, &ev, H_SETSIZE, 200); + el_set(elbe->elstate, EL_HIST, history, elbe->histate); + _activeDebugger = be->p; + signal(SIGINT, _breakIntoDefault); +} + +void _CLIDebuggerEditLineDeinit(struct CLIDebuggerBackend* be) { + struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; + history_end(elbe->histate); + el_end(elbe->elstate); +} + +const char* _CLIDebuggerEditLineReadLine(struct CLIDebuggerBackend* be, size_t* len) { + struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; + int count; + *len = 0; + const char* line = el_gets(elbe->elstate, &count); + if (line && count >= 1) { + // Crop off newline + *len = (size_t) count - 1; + } + return line; +} +void _CLIDebuggerEditLineLineAppend(struct CLIDebuggerBackend* be, const char* line) { + struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; + el_insertstr(elbe->elstate, line); +} + +const char* _CLIDebuggerEditLineHistoryLast(struct CLIDebuggerBackend* be, size_t* len) { + struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; + HistEvent ev; + if (history(elbe->histate, &ev, H_FIRST) < 0) { + *len = 0; + return NULL; + } + const char* newline = strchr(ev.str, '\n'); + if (!newline) { + *len = strlen(ev.str); + } else { + *len = newline - ev.str; + } + + return ev.str; +} + +void _CLIDebuggerEditLineHistoryAppend(struct CLIDebuggerBackend* be, const char* line) { + struct CLIDebuggerEditLineBackend* elbe = (struct CLIDebuggerEditLineBackend*) be; + HistEvent ev; + history(elbe->histate, &ev, H_ENTER, line); +} + +struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void) { + struct CLIDebuggerEditLineBackend* elbe = malloc(sizeof(*elbe)); + elbe->d.printf = _CLIDebuggerEditLinePrintf; + elbe->d.init = _CLIDebuggerEditLineInit; + elbe->d.deinit = _CLIDebuggerEditLineDeinit; + elbe->d.readline = _CLIDebuggerEditLineReadLine; + elbe->d.lineAppend = _CLIDebuggerEditLineLineAppend; + elbe->d.historyLast = _CLIDebuggerEditLineHistoryLast; + elbe->d.historyAppend = _CLIDebuggerEditLineHistoryAppend; + return &elbe->d; +}
A src/feature/editline/cli-el-backend.h

@@ -0,0 +1,23 @@

+/* Copyright (c) 2013-2014 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#ifndef CLI_EL_BACKEND_H +#define CLI_EL_BACKEND_H + +#include "debugger/cli-debugger.h" +#include "util/common.h" + +#include <histedit.h> + +struct CLIDebuggerEditLineBackend { + struct CLIDebuggerBackend d; + + EditLine* elstate; + History* histate; +}; + +struct CLIDebuggerBackend* CLIDebuggerEditLineBackendCreate(void); + +#endif
M src/gb/cli.csrc/gb/cli.c

@@ -12,8 +12,6 @@ #include "gb/io.h"

#include "gb/video.h" #include "lr35902/debugger/cli-debugger.h" -#ifdef USE_CLI_DEBUGGER - static void _GBCLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBCLIDebuggerCustom(struct CLIDebuggerSystem*); static uint32_t _GBCLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);

@@ -90,14 +88,15 @@ gbDebugger->inVblank = GBRegisterSTATGetMode(((struct GB*) gbDebugger->core->board)->memory.io[REG_STAT]) == 1;

} static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } int state = dv->intValue; if (state < 1 || state > 9) { - printf("State %u out of range", state); + be->printf(be, "State %u out of range", state); } struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system;

@@ -106,18 +105,18 @@ mCoreLoadState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT);

} static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } int state = dv->intValue; if (state < 1 || state > 9) { - printf("State %u out of range", state); + be->printf(be, "State %u out of range", state); } struct GBCLIDebugger* gbDebugger = (struct GBCLIDebugger*) debugger->system; mCoreSaveState(gbDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT); } -#endif
M src/gb/cli.hsrc/gb/cli.h

@@ -6,7 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GB_CLI_H #define GB_CLI_H -#ifdef USE_CLI_DEBUGGER #include "debugger/cli-debugger.h" struct GBCLIDebugger {

@@ -19,6 +18,5 @@ bool inVblank;

}; struct CLIDebuggerSystem* GBCLIDebuggerCreate(struct mCore*); -#endif #endif
M src/gb/core.csrc/gb/core.c

@@ -430,10 +430,8 @@

static bool _GBCoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { UNUSED(core); switch (type) { -#ifdef USE_CLI_DEBUGGER case DEBUGGER_CLI: return true; -#endif default: return false; }

@@ -448,12 +446,7 @@ return gbcore->debuggerPlatform;

} static struct CLIDebuggerSystem* _GBCoreCliDebuggerSystem(struct mCore* core) { -#ifdef USE_CLI_DEBUGGER return GBCLIDebuggerCreate(core); -#else - UNUSED(core); - return NULL; -#endif } static void _GBCoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
M src/gba/core.csrc/gba/core.c

@@ -442,10 +442,8 @@

static bool _GBACoreSupportsDebuggerType(struct mCore* core, enum mDebuggerType type) { UNUSED(core); switch (type) { -#ifdef USE_CLI_DEBUGGER case DEBUGGER_CLI: return true; -#endif #ifdef USE_GDB_STUB case DEBUGGER_GDB: return true;

@@ -464,12 +462,7 @@ return gbacore->debuggerPlatform;

} static struct CLIDebuggerSystem* _GBACoreCliDebuggerSystem(struct mCore* core) { -#ifdef USE_CLI_DEBUGGER return &GBACLIDebuggerCreate(core)->d; -#else - UNUSED(core); - return NULL; -#endif } static void _GBACoreAttachDebugger(struct mCore* core, struct mDebugger* debugger) {
M src/gba/extra/cli.csrc/gba/extra/cli.c

@@ -10,8 +10,6 @@ #include "core/serialize.h"

#include "gba/io.h" #include "gba/serialize.h" -#ifdef USE_CLI_DEBUGGER - static void _GBACLIDebuggerInit(struct CLIDebuggerSystem*); static bool _GBACLIDebuggerCustom(struct CLIDebuggerSystem*); static uint32_t _GBACLIDebuggerLookupIdentifier(struct CLIDebuggerSystem*, const char* name, struct CLIDebugVector* dv);

@@ -87,14 +85,15 @@ gbaDebugger->inVblank = GBARegisterDISPSTATGetInVblank(((struct GBA*) gbaDebugger->core->board)->memory.io[REG_DISPSTAT >> 1]);

} static void _load(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } int state = dv->intValue; if (state < 1 || state > 9) { - printf("State %u out of range", state); + be->printf(be, "State %u out of range", state); } struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system;

@@ -105,18 +104,18 @@

// TODO: Put back rewind static void _save(struct CLIDebugger* debugger, struct CLIDebugVector* dv) { + struct CLIDebuggerBackend* be = debugger->backend; if (!dv || dv->type != CLIDV_INT_TYPE) { - printf("%s\n", ERROR_MISSING_ARGS); + be->printf(be, "%s\n", ERROR_MISSING_ARGS); return; } int state = dv->intValue; if (state < 1 || state > 9) { - printf("State %u out of range", state); + be->printf(be, "State %u out of range", state); } struct GBACLIDebugger* gbaDebugger = (struct GBACLIDebugger*) debugger->system; mCoreSaveState(gbaDebugger->core, dv->intValue, SAVESTATE_SCREENSHOT); } -#endif
M src/gba/extra/cli.hsrc/gba/extra/cli.h

@@ -6,7 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef GBA_CLI_H #define GBA_CLI_H -#ifdef USE_CLI_DEBUGGER #include "debugger/cli-debugger.h" struct mCore;

@@ -21,6 +20,5 @@ bool inVblank;

}; struct GBACLIDebugger* GBACLIDebuggerCreate(struct mCore*); -#endif #endif
M src/lr35902/debugger/cli-debugger.csrc/lr35902/debugger/cli-debugger.c

@@ -5,7 +5,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "cli-debugger.h" -#ifdef USE_CLI_DEBUGGER #include "core/core.h" #include "debugger/cli-debugger.h" #include "lr35902/lr35902.h"

@@ -16,22 +15,23 @@ static struct CLIDebuggerCommandSummary _lr35902Commands[] = {

{ 0, 0, 0, 0 } }; -static inline void _printFlags(union FlagRegister f) { - printf("[%c%c%c%c]\n", - f.z ? 'Z' : '-', - f.n ? 'N' : '-', - f.h ? 'H' : '-', - f.c ? 'C' : '-'); +static inline void _printFlags(struct CLIDebuggerBackend* be, union FlagRegister f) { + be->printf(be, "[%c%c%c%c]\n", + f.z ? 'Z' : '-', + f.n ? 'N' : '-', + f.h ? 'H' : '-', + f.c ? 'C' : '-'); } static void _printStatus(struct CLIDebuggerSystem* debugger) { + struct CLIDebuggerBackend* be = debugger->p->backend; struct LR35902Core* cpu = debugger->p->d.core->cpu; - printf("A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af); - printf("B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc); - printf("D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de); - printf("H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); - printf("PC: %04X SP: %04X\n", cpu->pc, cpu->sp); - _printFlags(cpu->f); + be->printf(be, "A: %02X F: %02X (AF: %04X)\n", cpu->a, cpu->f.packed, cpu->af); + be->printf(be, "B: %02X C: %02X (BC: %04X)\n", cpu->b, cpu->c, cpu->bc); + be->printf(be, "D: %02X E: %02X (DE: %04X)\n", cpu->d, cpu->e, cpu->de); + be->printf(be, "H: %02X L: %02X (HL: %04X)\n", cpu->h, cpu->l, cpu->hl); + be->printf(be, "PC: %04X SP: %04X\n", cpu->pc, cpu->sp); + _printFlags(be, cpu->f); } static uint32_t _lookupPlatformIdentifier(struct CLIDebuggerSystem* debugger, const char* name, struct CLIDebugVector* dv) {

@@ -89,5 +89,3 @@ debugger->lookupPlatformIdentifier = _lookupPlatformIdentifier;

debugger->platformName = "GB-Z80"; debugger->platformCommands = _lr35902Commands; } - -#endif
M src/platform/sdl/main.csrc/platform/sdl/main.c

@@ -5,12 +5,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this

* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "main.h" -#ifdef USE_CLI_DEBUGGER #include "debugger/cli-debugger.h" -#endif #ifdef USE_GDB_STUB #include "debugger/gdb-stub.h" +#endif +#ifdef USE_EDITLINE +#include "feature/editline/cli-el-backend.h" #endif #include "core/core.h"

@@ -169,6 +170,12 @@ }

mCoreAutoloadSave(renderer->core); struct mDebugger* debugger = mDebuggerCreate(args->debuggerType, renderer->core); if (debugger) { +#ifdef USE_EDITLINE + if (args->debuggerType == DEBUGGER_CLI) { + struct CLIDebugger* cliDebugger = (struct CLIDebugger*) debugger; + CLIDebuggerAttachBackend(cliDebugger, CLIDebuggerEditLineBackendCreate()); + } +#endif mDebuggerAttach(debugger, renderer->core); mDebuggerEnter(debugger, DEBUGGER_ENTER_MANUAL, NULL); }