From 69ead6e3c9ff2b09348270c06a56b81623909d00 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 01:44:54 -0800 Subject: [PATCH] ROM Tester: Add script running --- src/platform/test/rom-test-main.c | 97 +++++++++++++++++++++++++++---- 1 file changed, 85 insertions(+), 12 deletions(-) diff --git a/src/platform/test/rom-test-main.c b/src/platform/test/rom-test-main.c index be9f36e8e..807f32ec1 100644 --- a/src/platform/test/rom-test-main.c +++ b/src/platform/test/rom-test-main.c @@ -17,26 +17,37 @@ #ifdef M_CORE_GB #include #endif +#ifdef ENABLE_SCRIPTING +#include +#include +#endif #include +#include #include #include #include #define ROM_TEST_OPTIONS "S:R:" -#define ROM_TEST_USAGE \ - "Additional options:\n" \ - " -S SWI Run until specified SWI call before exiting\n" \ - " -R REGISTER General purpose register to return as exit code\n" \ +static const char* const romTestUsage = + "Additional options:\n" + " -S SWI Run until specified SWI call before exiting\n" + " -R REGISTER General purpose register to return as exit code\n" +#ifdef ENABLE_SCRIPTING + " --script FILE Run a script on start. Can be passed multiple times\n" +#endif + ; struct RomTestOpts { int exitSwiImmediate; char* returnCodeRegister; + struct StringList scripts; }; static void _romTestShutdown(int signal); static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg); +static bool _parseLongRomTestOpts(struct mSubParser* parser, const char* option, const char* arg); static bool _parseSwi(const char* regStr, int* oSwi); static bool _romTestCheckResiger(void); @@ -62,11 +73,23 @@ void (*_armSwi32)(struct ARMCore* cpu, int immediate); int main(int argc, char * argv[]) { signal(SIGINT, _romTestShutdown); + bool cleanExit = false; + int uncleanExit = 1; + struct RomTestOpts romTestOpts = { 3, NULL }; + StringListInit(&romTestOpts.scripts, 0); struct mSubParser subparser = { - .usage = ROM_TEST_USAGE, + .usage = romTestUsage, .parse = _parseRomTestOpts, + .parseLong = _parseLongRomTestOpts, .extraOptions = ROM_TEST_OPTIONS, + .longOptions = (struct mOption[]) { + { + .name = "script", + .arg = true, + }, + {0} + }, .opts = &romTestOpts }; @@ -77,15 +100,17 @@ int main(int argc, char * argv[]) { } if (!parsed || args.showHelp) { usage(argv[0], NULL, NULL, &subparser, 1); - return !parsed; + uncleanExit = !parsed; + goto argsExit; } if (args.showVersion) { version(argv[0]); - return 0; + uncleanExit = 0; + goto argsExit; } core = mCoreFind(args.fname); if (!core) { - return 1; + goto argsExit; } core->init(core); mCoreInitConfig(core, "romTest"); @@ -99,7 +124,6 @@ int main(int argc, char * argv[]) { mStandardLoggerConfig(&_logger, &core->config); mLogSetDefaultLogger(&_logger.d); - bool cleanExit = false; struct mCoreCallbacks callbacks = {0}; _returnCodeRegister = romTestOpts.returnCodeRegister; @@ -166,6 +190,32 @@ int main(int argc, char * argv[]) { savestate->close(savestate); } +#ifdef ENABLE_SCRIPTING + struct mScriptContext scriptContext; + + if (StringListSize(&romTestOpts.scripts)) { + mScriptContextInit(&scriptContext); + mScriptContextAttachStdlib(&scriptContext); + mScriptContextAttachImage(&scriptContext); + mScriptContextAttachLogger(&scriptContext, NULL); + mScriptContextAttachSocket(&scriptContext); +#ifdef USE_JSON_C + mScriptContextAttachStorage(&scriptContext); +#endif + mScriptContextRegisterEngines(&scriptContext); + + mScriptContextAttachCore(&scriptContext, core); + + size_t i; + for (i = 0; i < StringListSize(&romTestOpts.scripts); ++i) { + if (!mScriptContextLoadFile(&scriptContext, *StringListGetPointer(&romTestOpts.scripts, i))) { + mLOG(STATUS, ERROR, "Failed to load script \"%s\"", *StringListGetPointer(&romTestOpts.scripts, i)); + goto scriptsError; + } + } + } +#endif + #ifdef ENABLE_DEBUGGERS if (hasDebugger) { do { @@ -176,19 +226,25 @@ int main(int argc, char * argv[]) { do { core->runLoop(core); } while (!_dispatchExiting); + cleanExit = true; +scriptsError: core->unloadROM(core); +#ifdef ENABLE_SCRIPTING + if (StringListSize(&romTestOpts.scripts)) { + mScriptContextDeinit(&scriptContext); + } +#endif + #ifdef ENABLE_DEBUGGERS if (hasDebugger) { core->detachDebugger(core); mDebuggerDeinit(&debugger); } #endif - cleanExit = true; loadError: - mArgumentsDeinit(&args); mStandardLoggerDeinit(&_logger); mCoreConfigDeinit(&core->config); core->deinit(core); @@ -196,7 +252,15 @@ loadError: free(_returnCodeRegister); } - return cleanExit ? _exitCode : 1; +argsExit: + size_t i; + for (i = 0; i < StringListSize(&romTestOpts.scripts); ++i) { + free(*StringListGetPointer(&romTestOpts.scripts, i)); + } + StringListDeinit(&romTestOpts.scripts); + mArgumentsDeinit(&args); + + return cleanExit ? _exitCode : uncleanExit; } static void _romTestShutdown(int signal) { @@ -296,6 +360,15 @@ static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* } } +static bool _parseLongRomTestOpts(struct mSubParser* parser, const char* option, const char* arg) { + struct RomTestOpts* opts = parser->opts; + if (strcmp(option, "script") == 0) { + *StringListAppend(&opts->scripts) = strdup(arg); + return true; + } + return false; +} + static bool _parseSwi(const char* swiStr, int* oSwi) { char* parseEnd; long swi = strtol(swiStr, &parseEnd, 0);