From fb0fed21aa53dd96def972289eed28358e178a27 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 13 Dec 2024 14:48:27 -0800 Subject: [PATCH 01/40] Qt: Skip processing QLocale::C if present --- src/platform/qt/SettingsView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index a72bf0d7b..f4eea01db 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -364,7 +364,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC continue; } QLocale locale(name.remove(QString("%0-").arg(binaryName)).remove(".qm")); - if (locale.language() == QLocale::English) { + if (locale.language() == QLocale::English || locale.language() == QLocale::C) { continue; } QString endonym = locale.nativeLanguageName(); From 1983d0f42cb39dd06114d3aa8941dbf21ed62e1f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 14 Dec 2024 22:28:08 -0800 Subject: [PATCH 02/40] GBA Core: Fix booting into BIOS when skip BIOS is enabled --- CHANGES | 3 ++- src/gba/core.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index f3a8cc539..42fea400e 100644 --- a/CHANGES +++ b/CHANGES @@ -19,8 +19,9 @@ Other fixes: - Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963) - Debugger: Fix writing to specific segment in command-line debugger - GB Serialize: Prevent loading invalid states where LY >= 144 in modes other than 1 - - GBA Hardware: Fix loading states unconditionally overwriting GPIO memory - GBA: Fix getting game info for multiboot ROMs + - GBA Core: Fix booting into BIOS when skip BIOS is enabled + - GBA Hardware: Fix loading states unconditionally overwriting GPIO memory - Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560) - Qt: Fix potential crash when configuring shortcuts Misc: diff --git a/src/gba/core.c b/src/gba/core.c index 1d3fffb9e..da782d06c 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -801,7 +801,7 @@ static void _GBACoreReset(struct mCore* core) { #endif ARMReset(core->cpu); - bool forceSkip = gba->mbVf || core->opts.skipBios; + bool forceSkip = gba->mbVf || (core->opts.skipBios && (gba->romVf || gba->memory.rom)); if (!forceSkip && (gba->romVf || gba->memory.rom) && gba->pristineRomSize >= 0xA0 && gba->biosVf) { uint32_t crc = doCrc32(&gba->memory.rom[1], 0x9C); if (crc != LOGO_CRC32) { From 39ab641953e8c6e977b893527fd260858c3a6402 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 20 Dec 2024 02:14:23 -0800 Subject: [PATCH 03/40] GBA Savedata: Demote savegme time offset message to DEBUG level --- src/gba/savedata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gba/savedata.c b/src/gba/savedata.c index c0d2c889a..50d2be381 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -702,7 +702,7 @@ void GBASavedataRTCRead(struct GBASavedata* savedata) { savedata->gpio->rtc.offset = savedata->gpio->rtc.lastLatch - rtcTime; - mLOG(GBA_SAVE, ERROR, "Savegame time offset set to %li", savedata->gpio->rtc.offset); + mLOG(GBA_SAVE, DEBUG, "Savegame time offset set to %li", savedata->gpio->rtc.offset); } void GBASavedataSerialize(const struct GBASavedata* savedata, struct GBASerializedState* state) { From 08430fc058c4a4ef57ddd40006bb356c1e3024a2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 22 Dec 2024 04:50:46 -0800 Subject: [PATCH 04/40] mGUI: Load parent directory if last used directory is missing (fixes #3379) --- CHANGES | 1 + include/mgba-util/gui/menu.h | 3 +++ src/util/gui/file-select.c | 11 ++++++++++- src/util/gui/menu.c | 2 ++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 42fea400e..847865d26 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Other fixes: - GBA: Fix getting game info for multiboot ROMs - GBA Core: Fix booting into BIOS when skip BIOS is enabled - GBA Hardware: Fix loading states unconditionally overwriting GPIO memory + - mGUI: Load parent directory if last used directory is missing (fixes mgba.io/i/3379) - Qt: Fix savestate preview sizes with different scales (fixes mgba.io/i/2560) - Qt: Fix potential crash when configuring shortcuts Misc: diff --git a/include/mgba-util/gui/menu.h b/include/mgba-util/gui/menu.h index 399ddd8c3..4a1c3651a 100644 --- a/include/mgba-util/gui/menu.h +++ b/include/mgba-util/gui/menu.h @@ -10,9 +10,12 @@ CXX_GUARD_START +#include #include #include +mLOG_DECLARE_CATEGORY(GUI_MENU); + #define GUI_V_V (struct GUIVariant) { .type = GUI_VARIANT_VOID } #define GUI_V_U(U) (struct GUIVariant) { .type = GUI_VARIANT_UNSIGNED, .v.u = (U) } #define GUI_V_I(I) (struct GUIVariant) { .type = GUI_VARIANT_INT, .v.i = (I) } diff --git a/src/util/gui/file-select.c b/src/util/gui/file-select.c index 0cdfba35d..f13668c3f 100644 --- a/src/util/gui/file-select.c +++ b/src/util/gui/file-select.c @@ -163,7 +163,16 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool .subtitle = params->currentPath, }; GUIMenuItemListInit(&menu.items, 0); - _refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents, preselect); + while (true) { + if (_refreshDirectory(params, params->currentPath, &menu.items, filterName, filterContents, preselect)) { + break; + } + if (strncmp(params->currentPath, params->basePath, PATH_MAX) == 0 || !params->currentPath[0]) { + mLOG(GUI_MENU, ERROR, "Failed to load base directory"); + return false; + } + _upDirectory(params->currentPath); + } menu.index = params->fileIndex; while (true) { diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index f0c624f17..2109bf8e1 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -17,6 +17,8 @@ DEFINE_VECTOR(GUIMenuItemList, struct GUIMenuItem); DEFINE_VECTOR(GUIMenuSavedList, struct GUIMenuSavedState); +mLOG_DEFINE_CATEGORY(GUI_MENU, "GUI Menu", "gui.menu"); + void _itemNext(struct GUIMenuItem* item, bool wrap) { if (wrap || item->state < item->nStates - 1) { unsigned oldState = item->state; From d82fc3dec1001dc5fd83e30c4e75e21ff8c69e59 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 24 Dec 2024 18:54:10 -0800 Subject: [PATCH 05/40] FFmpeg: Fix failing to record videos with CRF video (fixes #3368) --- CHANGES | 1 + src/feature/ffmpeg/ffmpeg-encoder.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 847865d26..62f51060c 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ Emulation fixes: Other fixes: - Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963) - Debugger: Fix writing to specific segment in command-line debugger + - FFmpeg: Fix failing to record videos with CRF video (fixes mgba.io/i/3368) - GB Serialize: Prevent loading invalid states where LY >= 144 in modes other than 1 - GBA: Fix getting game info for multiboot ROMs - GBA Core: Fix booting into BIOS when skip BIOS is enabled diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 6202e0fcd..e83aa680c 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -384,7 +384,9 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { encoder->videoStream = avformat_new_stream(encoder->context, vcodec); encoder->video = encoder->videoStream->codec; #endif - encoder->video->bit_rate = encoder->videoBitrate; + if (encoder->videoBitrate >= 0) { + encoder->video->bit_rate = encoder->videoBitrate; + } encoder->video->width = encoder->width; encoder->video->height = encoder->height; encoder->video->time_base = (AVRational) { encoder->frameCycles * encoder->frameskip, encoder->cycles }; From ad0d3972a695e9eddfb45be0072eb94961382e4b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 28 Dec 2024 22:45:39 -0800 Subject: [PATCH 06/40] Updater: Fix rewriting folders and files on Windows (fixes #3384) --- CHANGES | 1 + src/tools/updater-main.c | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 62f51060c..b5b2f4fe1 100644 --- a/CHANGES +++ b/CHANGES @@ -48,6 +48,7 @@ Misc: - Qt: Show a dummy shader settings tab if shaders aren't supported - Res: Port NSO-gba-colors shader (closes mgba.io/i/2834) - Scripting: Add `callbacks:oneshot` for single-call callbacks + - Updater: Fix rewriting folders and files on Windows (fixes mgba.io/i/3384) 0.10.4: (2024-12-07) Emulation fixes: diff --git a/src/tools/updater-main.c b/src/tools/updater-main.c index a27a07a08..b536e3208 100644 --- a/src/tools/updater-main.c +++ b/src/tools/updater-main.c @@ -133,14 +133,11 @@ bool extractArchive(struct VDir* archive, const char* root, bool prefix) { errno = 0; vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); if (!vfOut) { - if (errno == EACCES) { -#ifdef _WIN32 - Sleep(1000); -#else - sleep(1); -#endif - vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); - } else if (errno == EISDIR) { + int error = errno; + struct stat st; + if (error == EISDIR || (stat(path, &st) >= 0 && S_ISDIR(st.st_mode))) { + // Windows maps STATUS_FILE_IS_A_DIRECTORY to ERROR_ACCESS_DENIED, + // which then gets mapped to EACCESS, because everything is awful fprintf(logfile, "rm -r %s\n", path); if (!rmdirRecursive(VDirOpen(path))) { return false; @@ -151,6 +148,13 @@ bool extractArchive(struct VDir* archive, const char* root, bool prefix) { RemoveDirectoryW(wpath); #else rmdir(path); +#endif + vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); + } else if (error == EACCES || error == ETXTBSY) { +#ifdef _WIN32 + Sleep(1000); +#else + sleep(1); #endif vfOut = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); } From 4007e19736706fb320cec5724fec3abf6391021c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 29 Dec 2024 17:38:14 -0800 Subject: [PATCH 07/40] CMake: Fix entitlements plist filename --- src/platform/qt/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 3134512f2..a5fe5b8a8 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -517,7 +517,7 @@ if(APPLE) set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -R "${CROSS_ROOT}") endif() if($ENV{CODESIGN_IDENTITY}) - set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -s "$ENV{CODESIGN_IDENTITY}" -E "${PROJECT_SOURCE_DIR}/res/entitlements.xml") + set(DEPLOY_OPTIONS ${DEPLOY_OPTIONS} -s "$ENV{CODESIGN_IDENTITY}" -E "${PROJECT_SOURCE_DIR}/res/entitlements.plist") endif() install(CODE "execute_process(COMMAND \"${PROJECT_SOURCE_DIR}/tools/deploy-mac.py\" -v ${DEPLOY_OPTIONS} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${APPDIR}/${PROJECT_NAME}.app\")") endif() From 6b5638efda0e615ddae0091c02ba1ad041bbd5b5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 01:35:49 -0800 Subject: [PATCH 08/40] Core: Improve PNG deserialization logging --- src/core/serialize.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/core/serialize.c b/src/core/serialize.c index 4f7c07a4a..7e3426a59 100644 --- a/src/core/serialize.c +++ b/src/core/serialize.c @@ -249,9 +249,16 @@ static int _loadPNGChunkHandler(png_structp png, png_unknown_chunkp chunk) { } const uint8_t* data = chunk->data; data += sizeof(uint32_t) * 2; - uncompress((Bytef*) item.data, &len, data, chunk->size); - item.size = len; - mStateExtdataPut(extdata, tag, &item); + if (uncompress((Bytef*) item.data, &len, data, chunk->size) == Z_OK) { + if (item.size != len) { + mLOG(SAVESTATE, WARN, "Mismatched decompressed extdata %i size (%"PRIz"u vs %"PRIz"u)", tag, item.size, (size_t) len); + item.size = len; + } + mStateExtdataPut(extdata, tag, &item); + } else { + mLOG(SAVESTATE, WARN, "Failed to decompress extdata chunk"); + free(item.data); + } return 1; } return 0; @@ -320,7 +327,7 @@ static void* _loadPNGState(struct mCore* core, struct VFile* vf, struct mStateEx return state; } -static bool _loadPNGExtadata(struct VFile* vf, struct mStateExtdata* extdata) { +static bool _loadPNGExtdata(struct VFile* vf, struct mStateExtdata* extdata) { png_structp png = PNGReadOpen(vf, PNG_HEADER_BYTES); png_infop info = png_create_info_struct(png); png_infop end = png_create_info_struct(png); @@ -511,7 +518,7 @@ void* mCoreExtractState(struct mCore* core, struct VFile* vf, struct mStateExtda bool mCoreExtractExtdata(struct mCore* core, struct VFile* vf, struct mStateExtdata* extdata) { #ifdef USE_PNG if (isPNG(vf)) { - return _loadPNGExtadata(vf, extdata); + return _loadPNGExtdata(vf, extdata); } #endif if (!core) { From abb9bec571ebb511486bd756049cfa3327168f5b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 01:45:03 -0800 Subject: [PATCH 09/40] GB Core: Fix cloning savedata when backing file is outdated (fixes #3388) --- CHANGES | 1 + src/gb/core.c | 35 ++++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index b5b2f4fe1..595943d3d 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Other fixes: - Core: Fix inconsistencies with setting game-specific overrides (fixes mgba.io/i/2963) - Debugger: Fix writing to specific segment in command-line debugger - FFmpeg: Fix failing to record videos with CRF video (fixes mgba.io/i/3368) + - GB Core: Fix cloning savedata when backing file is outdated (fixes mgba.io/i/3388) - GB Serialize: Prevent loading invalid states where LY >= 144 in modes other than 1 - GBA: Fix getting game info for multiboot ROMs - GBA Core: Fix booting into BIOS when skip BIOS is enabled diff --git a/src/gb/core.c b/src/gb/core.c index b97e1ee25..f71b570e0 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -1167,19 +1167,32 @@ static struct mCheatDevice* _GBCoreCheatDevice(struct mCore* core) { static size_t _GBCoreSavedataClone(struct mCore* core, void** sram) { struct GB* gb = core->board; - struct VFile* vf = gb->sramVf; - if (vf) { - *sram = malloc(vf->size(vf)); - vf->seek(vf, 0, SEEK_SET); - return vf->read(vf, *sram, vf->size(vf)); + size_t sramSize = gb->sramSize; + size_t vfSize = 0; + size_t size = sramSize; + uint8_t* view = NULL; + + if (gb->sramVf) { + vfSize = gb->sramVf->size(gb->sramVf); + if (vfSize > size) { + size = vfSize; + } } - if (gb->sramSize) { - *sram = malloc(gb->sramSize); - memcpy(*sram, gb->memory.sram, gb->sramSize); - return gb->sramSize; + if (!size) { + *sram = NULL; + return 0; } - *sram = NULL; - return 0; + + view = malloc(size); + if (sramSize) { + memcpy(view, gb->memory.sram, gb->sramSize); + } + if (vfSize > sramSize) { + gb->sramVf->seek(gb->sramVf, sramSize, SEEK_SET); + gb->sramVf->read(gb->sramVf, &view[sramSize], vfSize - sramSize); + } + *sram = view; + return size; } static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) { From d55ee872e3464bcc89d023de14adefafd35fcf85 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 01:48:05 -0800 Subject: [PATCH 10/40] CHANGES: Remove duplicated line --- CHANGES | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGES b/CHANGES index 595943d3d..b87501580 100644 --- a/CHANGES +++ b/CHANGES @@ -20,7 +20,6 @@ Other fixes: - Debugger: Fix writing to specific segment in command-line debugger - FFmpeg: Fix failing to record videos with CRF video (fixes mgba.io/i/3368) - GB Core: Fix cloning savedata when backing file is outdated (fixes mgba.io/i/3388) - - GB Serialize: Prevent loading invalid states where LY >= 144 in modes other than 1 - GBA: Fix getting game info for multiboot ROMs - GBA Core: Fix booting into BIOS when skip BIOS is enabled - GBA Hardware: Fix loading states unconditionally overwriting GPIO memory From 72ee6f9840362f5327ae3e9e8a627b77f749645c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 02:53:14 -0800 Subject: [PATCH 11/40] Scripting: Expose info table to breakpoint/watchpoint callbacks (closes #3369) --- src/core/scripting.c | 31 +++++++++- src/core/test/scripting.c | 115 ++++++++++++++++++++++++++++++++++---- 2 files changed, 134 insertions(+), 12 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index 9e46b619c..012a739bc 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -769,7 +769,7 @@ static int64_t _addCallbackToBreakpoint(struct mScriptDebugger* debugger, struct return cbid; } -static void _runCallbacks(struct mScriptDebugger* debugger, struct mScriptBreakpoint* point) { +static void _runCallbacks(struct mScriptDebugger* debugger, struct mScriptBreakpoint* point, struct mScriptValue* info) { struct TableIterator iter; if (!HashTableIteratorStart(&point->callbacks, &iter)) { return; @@ -778,6 +778,7 @@ static void _runCallbacks(struct mScriptDebugger* debugger, struct mScriptBreakp struct mScriptValue* fn = HashTableIteratorGetValue(&point->callbacks, &iter); struct mScriptFrame frame; mScriptFrameInit(&frame); + mSCRIPT_PUSH(&frame.stack, WTABLE, info); mScriptContextInvoke(debugger->p->context, fn, &frame); mScriptFrameDeinit(&frame); } while (HashTableIteratorNext(&point->callbacks, &iter)); @@ -826,7 +827,33 @@ static void _scriptDebuggerEntered(struct mDebuggerModule* debugger, enum mDebug return; } - _runCallbacks(scriptDebugger, point); + struct mScriptValue cbInfo = { + .refs = mSCRIPT_VALUE_UNREF, + .flags = 0, + .type = mSCRIPT_TYPE_MS_TABLE, + }; + cbInfo.type->alloc(&cbInfo); + + // TODO: Intern strings + mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("address"), mScriptValueCreateFromUInt(info->address)); + if (info->width > 0) { + mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("width"), mScriptValueCreateFromSInt(info->width)); + } + if (info->segment >= 0) { + mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("segment"), mScriptValueCreateFromSInt(info->segment)); + } + + if (reason == DEBUGGER_ENTER_WATCHPOINT) { + mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("oldValue"), mScriptValueCreateFromSInt(info->type.wp.oldValue)); + if (info->type.wp.accessType != WATCHPOINT_READ) { + mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("newValue"), mScriptValueCreateFromSInt(info->type.wp.newValue)); + } + mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("accessType"), mScriptValueCreateFromSInt(info->type.wp.accessType)); + } + + _runCallbacks(scriptDebugger, point, &cbInfo); + + cbInfo.type->free(&cbInfo); debugger->isPaused = false; } diff --git a/src/core/test/scripting.c b/src/core/test/scripting.c index 63927effe..16692fc14 100644 --- a/src/core/test/scripting.c +++ b/src/core/test/scripting.c @@ -365,8 +365,10 @@ M_TEST_DEFINE(basicBreakpointGBA) { TEST_PROGRAM( "hit = 0\n" - "function bkpt()\n" + "address = nil\n" + "function bkpt(info)\n" " hit = hit + 1\n" + " address = info.address\n" "end" ); TEST_PROGRAM("cbid = emu:setBreakpoint(bkpt, 0x020000C4)"); @@ -379,6 +381,7 @@ M_TEST_DEFINE(basicBreakpointGBA) { assert_int_equal(debugger.state, DEBUGGER_RUNNING); TEST_PROGRAM("assert(hit >= 1)"); + TEST_PROGRAM("assert(address == 0x020000C4)"); mScriptContextDeinit(&context); TEARDOWN_CORE; @@ -404,8 +407,10 @@ M_TEST_DEFINE(basicBreakpointGB) { TEST_PROGRAM( "hit = 0\n" - "function bkpt()\n" + "address = nil\n" + "function bkpt(info)\n" " hit = hit + 1\n" + " address = info.address\n" "end" ); TEST_PROGRAM("cbid = emu:setBreakpoint(bkpt, 0xF0)"); @@ -418,6 +423,7 @@ M_TEST_DEFINE(basicBreakpointGB) { assert_int_equal(debugger.state, DEBUGGER_RUNNING); TEST_PROGRAM("assert(hit >= 1)"); + TEST_PROGRAM("assert(address == 0xF0)"); mScriptContextDeinit(&context); TEARDOWN_CORE; @@ -441,11 +447,22 @@ M_TEST_DEFINE(multipleBreakpoint) { TEST_PROGRAM( "hit = 0\n" - "function bkpt1()\n" + "address = nil\n" + "function bkpt1(info)\n" " hit = hit + 1\n" + " if address then\n" + " address = (address + info.address) / 2\n" + " else\n" + " address = info.address\n" + " end\n" "end\n" - "function bkpt2()\n" + "function bkpt2(info)\n" " hit = hit + 100\n" + " if address then\n" + " address = (address + info.address) / 2\n" + " else\n" + " address = info.address\n" + " end\n" "end" ); #ifdef M_CORE_GBA @@ -465,6 +482,13 @@ M_TEST_DEFINE(multipleBreakpoint) { assert_int_equal(debugger.state, DEBUGGER_RUNNING); TEST_PROGRAM("assert(hit >= 101)"); +#ifdef M_CORE_GBA + TEST_PROGRAM("assert(address >= 0x020000C4)"); + TEST_PROGRAM("assert(address <= 0x020000C8)"); +#else + TEST_PROGRAM("assert(address >= 0xF0)"); + TEST_PROGRAM("assert(address <= 0xF1)"); +#endif mScriptContextDeinit(&context); TEARDOWN_CORE; @@ -479,13 +503,28 @@ M_TEST_DEFINE(basicWatchpoint) { core->reset(core); mScriptContextAttachCore(&context, core); + int i; + for (i = 0; i < 4; ++i) { + core->busWrite8(core, RAM_BASE + i, i + 1); + } + mDebuggerInit(&debugger); mDebuggerAttach(&debugger, core); TEST_PROGRAM( "hit = 0\n" - "function bkpt()\n" + "address = nil\n" + "width = nil\n" + "oldValue = nil\n" + "newValue = nil\n" + "accessType = nil\n" + "function bkpt(info)\n" " hit = hit + 1\n" + " address = info.address\n" + " width = info.width\n" + " oldValue = info.oldValue\n" + " newValue = info.newValue\n" + " accessType = info.accessType\n" "end" ); struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE); @@ -499,7 +538,13 @@ M_TEST_DEFINE(basicWatchpoint) { uint8_t value; // Read - TEST_PROGRAM("hit = 0"); + TEST_PROGRAM( + "hit = 0\n" + "address = nil\n" + "width = nil\n" + "oldValue = nil\n" + "newValue = nil\n" + "accessType = nil\n"); value = core->rawRead8(core, RAM_BASE, -1); TEST_PROGRAM("assert(hit == 0)"); core->busRead8(core, RAM_BASE); @@ -508,31 +553,71 @@ M_TEST_DEFINE(basicWatchpoint) { TEST_PROGRAM("assert(hit == 1)"); core->busWrite8(core, RAM_BASE, ~value); TEST_PROGRAM("assert(hit == 1)"); + TEST_PROGRAM("assert(address == base)"); + TEST_PROGRAM("assert(width == 1)"); + TEST_PROGRAM("assert(oldValue == 1)"); + TEST_PROGRAM("assert(newValue == nil)"); + TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.READ)"); // Write - TEST_PROGRAM("hit = 0"); + TEST_PROGRAM( + "hit = 0\n" + "address = nil\n" + "width = nil\n" + "oldValue = nil\n" + "newValue = nil\n" + "accessType = nil\n"); value = core->rawRead8(core, RAM_BASE + 1, -1); TEST_PROGRAM("assert(hit == 0)"); core->busRead8(core, RAM_BASE + 1); TEST_PROGRAM("assert(hit == 0)"); core->busWrite8(core, RAM_BASE + 1, value); TEST_PROGRAM("assert(hit == 1)"); + TEST_PROGRAM("assert(oldValue == 2)"); + TEST_PROGRAM("assert(newValue == 2)"); core->busWrite8(core, RAM_BASE + 1, ~value); TEST_PROGRAM("assert(hit == 2)"); + TEST_PROGRAM("assert(address == base + 1)"); + TEST_PROGRAM("assert(width == 1)"); + TEST_PROGRAM("assert(oldValue == 2)"); + TEST_PROGRAM("assert(newValue == -3)"); + TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.WRITE)"); // RW - TEST_PROGRAM("hit = 0"); + TEST_PROGRAM( + "hit = 0\n" + "address = nil\n" + "width = nil\n" + "oldValue = nil\n" + "newValue = nil\n" + "accessType = nil\n"); value = core->rawRead8(core, RAM_BASE + 2, -1); TEST_PROGRAM("assert(hit == 0)"); core->busRead8(core, RAM_BASE + 2); + TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.READ)"); TEST_PROGRAM("assert(hit == 1)"); + TEST_PROGRAM("assert(oldValue == 3)"); + TEST_PROGRAM("assert(newValue == nil)"); core->busWrite8(core, RAM_BASE + 2, value); TEST_PROGRAM("assert(hit == 2)"); + TEST_PROGRAM("assert(oldValue == 3)"); + TEST_PROGRAM("assert(newValue == 3)"); core->busWrite8(core, RAM_BASE + 2, ~value); TEST_PROGRAM("assert(hit == 3)"); + TEST_PROGRAM("assert(address == base + 2)"); + TEST_PROGRAM("assert(width == 1)"); + TEST_PROGRAM("assert(oldValue == 3)"); + TEST_PROGRAM("assert(newValue == -4)"); + TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.WRITE)"); // Change - TEST_PROGRAM("hit = 0"); + TEST_PROGRAM( + "hit = 0\n" + "address = nil\n" + "width = nil\n" + "oldValue = nil\n" + "newValue = nil\n" + "accessType = nil\n"); value = core->rawRead8(core, RAM_BASE + 3, -1); TEST_PROGRAM("assert(hit == 0)"); core->busRead8(core, RAM_BASE + 3); @@ -541,6 +626,11 @@ M_TEST_DEFINE(basicWatchpoint) { TEST_PROGRAM("assert(hit == 0)"); core->busWrite8(core, RAM_BASE + 3, ~value); TEST_PROGRAM("assert(hit == 1)"); + TEST_PROGRAM("assert(address == base + 3)"); + TEST_PROGRAM("assert(width == 1)"); + TEST_PROGRAM("assert(oldValue == 4)"); + TEST_PROGRAM("assert(newValue == -5)"); + TEST_PROGRAM("assert(accessType == C.WATCHPOINT_TYPE.WRITE)"); mScriptContextDeinit(&context); TEARDOWN_CORE; @@ -728,8 +818,10 @@ M_TEST_DEFINE(rangeWatchpoint) { TEST_PROGRAM( "hit = 0\n" - "function bkpt()\n" + "address = nil\n" + "function bkpt(info)\n" " hit = hit + 1\n" + " address = info.address\n" "end" ); struct mScriptValue base = mSCRIPT_MAKE_S32(RAM_BASE); @@ -741,10 +833,13 @@ M_TEST_DEFINE(rangeWatchpoint) { TEST_PROGRAM("assert(hit == 0)"); core->busRead8(core, RAM_BASE); TEST_PROGRAM("assert(hit == 1)"); + TEST_PROGRAM("assert(address == base)"); core->busRead8(core, RAM_BASE + 1); TEST_PROGRAM("assert(hit == 3)"); + TEST_PROGRAM("assert(address == base + 1)"); core->busRead8(core, RAM_BASE + 2); TEST_PROGRAM("assert(hit == 4)"); + TEST_PROGRAM("assert(address == base + 2)"); mScriptContextDeinit(&context); TEARDOWN_CORE; From 23531e24b8b95966bb8711ac05749f8b8c45e102 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 03:11:31 -0800 Subject: [PATCH 12/40] Scripting: Remove needless heap allocations --- src/core/scripting.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index 012a739bc..3b331b5b7 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -834,21 +834,38 @@ static void _scriptDebuggerEntered(struct mDebuggerModule* debugger, enum mDebug }; cbInfo.type->alloc(&cbInfo); - // TODO: Intern strings - mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("address"), mScriptValueCreateFromUInt(info->address)); + static struct mScriptValue keyAddress = mSCRIPT_MAKE_CHARP("address"); + static struct mScriptValue keyWidth = mSCRIPT_MAKE_CHARP("width"); + static struct mScriptValue keySegment = mSCRIPT_MAKE_CHARP("segment"); + static struct mScriptValue keyOldValue = mSCRIPT_MAKE_CHARP("oldValue"); + static struct mScriptValue keyNewValue = mSCRIPT_MAKE_CHARP("newValue"); + static struct mScriptValue keyAccessType = mSCRIPT_MAKE_CHARP("accessType"); + + struct mScriptValue valAddress = mSCRIPT_MAKE_U32(info->address); + struct mScriptValue valWidth = mSCRIPT_MAKE_S32(info->width); + struct mScriptValue valSegment = mSCRIPT_MAKE_S32(info->segment); + struct mScriptValue valOldValue; + struct mScriptValue valNewValue; + struct mScriptValue valAccessType; + + mScriptTableInsert(&cbInfo, &keyAddress, &valAddress); if (info->width > 0) { - mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("width"), mScriptValueCreateFromSInt(info->width)); + mScriptTableInsert(&cbInfo, &keyWidth, &valWidth); } if (info->segment >= 0) { - mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("segment"), mScriptValueCreateFromSInt(info->segment)); + mScriptTableInsert(&cbInfo, &keySegment, &valSegment); } if (reason == DEBUGGER_ENTER_WATCHPOINT) { - mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("oldValue"), mScriptValueCreateFromSInt(info->type.wp.oldValue)); + valOldValue = mSCRIPT_MAKE_S32(info->type.wp.oldValue); + valNewValue = mSCRIPT_MAKE_S32(info->type.wp.newValue); + valAccessType = mSCRIPT_MAKE_S32(info->type.wp.accessType); + + mScriptTableInsert(&cbInfo, &keyOldValue, &valOldValue); if (info->type.wp.accessType != WATCHPOINT_READ) { - mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("newValue"), mScriptValueCreateFromSInt(info->type.wp.newValue)); + mScriptTableInsert(&cbInfo, &keyNewValue, &valNewValue); } - mScriptTableInsert(&cbInfo, mScriptStringCreateFromASCII("accessType"), mScriptValueCreateFromSInt(info->type.wp.accessType)); + mScriptTableInsert(&cbInfo, &keyAccessType, &valAccessType); } _runCallbacks(scriptDebugger, point, &cbInfo); From 132293449de246bb19abf453fde06fcfa22fe402 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 16:51:50 -0800 Subject: [PATCH 13/40] Scripting: Attempt to fix Windows build --- src/core/scripting.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index 3b331b5b7..f409b4782 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -834,12 +834,12 @@ static void _scriptDebuggerEntered(struct mDebuggerModule* debugger, enum mDebug }; cbInfo.type->alloc(&cbInfo); - static struct mScriptValue keyAddress = mSCRIPT_MAKE_CHARP("address"); - static struct mScriptValue keyWidth = mSCRIPT_MAKE_CHARP("width"); - static struct mScriptValue keySegment = mSCRIPT_MAKE_CHARP("segment"); - static struct mScriptValue keyOldValue = mSCRIPT_MAKE_CHARP("oldValue"); - static struct mScriptValue keyNewValue = mSCRIPT_MAKE_CHARP("newValue"); - static struct mScriptValue keyAccessType = mSCRIPT_MAKE_CHARP("accessType"); + static struct mScriptValue keyAddress = mSCRIPT_CHARP("address"); + static struct mScriptValue keyWidth = mSCRIPT_CHARP("width"); + static struct mScriptValue keySegment = mSCRIPT_CHARP("segment"); + static struct mScriptValue keyOldValue = mSCRIPT_CHARP("oldValue"); + static struct mScriptValue keyNewValue = mSCRIPT_CHARP("newValue"); + static struct mScriptValue keyAccessType = mSCRIPT_CHARP("accessType"); struct mScriptValue valAddress = mSCRIPT_MAKE_U32(info->address); struct mScriptValue valWidth = mSCRIPT_MAKE_S32(info->width); From 39ced7dd81a11e8bf1ec8d72a8e332075e69db4f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 16:52:34 -0800 Subject: [PATCH 14/40] Windows: Don't redefine WIN32_LEAN_AND_MEAN if already defined --- include/mgba-util/common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index c5008e01f..04018faf4 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -17,7 +17,9 @@ CXX_GUARD_START #ifdef _WIN32 +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif // Require Windows 7 or newer #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0601 From 9f5c2aa00cc470bd20c0c29c5bfcb7a8451704c4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 31 Dec 2024 17:04:52 -0800 Subject: [PATCH 15/40] Scripting: Expose MD5 checksum --- src/core/scripting.c | 3 +++ src/script/stdlib.c | 1 + 2 files changed, 4 insertions(+) diff --git a/src/core/scripting.c b/src/core/scripting.c index f409b4782..b36a91412 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -350,6 +350,9 @@ static struct mScriptValue* _mScriptCoreChecksum(const struct mCore* core, int t case mCHECKSUM_CRC32: size = 4; break; + case mCHECKSUM_MD5: + size = 16; + break; } if (!size) { return &mScriptValueNull; diff --git a/src/script/stdlib.c b/src/script/stdlib.c index 6e81cfd86..8fc1b1404 100644 --- a/src/script/stdlib.c +++ b/src/script/stdlib.c @@ -130,6 +130,7 @@ void mScriptContextAttachStdlib(struct mScriptContext* context) { }); mScriptContextExportConstants(context, "CHECKSUM", (struct mScriptKVPair[]) { mSCRIPT_CONSTANT_PAIR(mCHECKSUM, CRC32), + mSCRIPT_CONSTANT_PAIR(mCHECKSUM, MD5), mSCRIPT_KV_SENTINEL }); #ifdef M_CORE_GBA From 4eb1dbca3617893deb3bfe161f42982e375b1668 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Jan 2025 01:22:08 -0800 Subject: [PATCH 16/40] Core: Quash some warnings --- src/core/serialize.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/serialize.c b/src/core/serialize.c index 7e3426a59..90f066b85 100644 --- a/src/core/serialize.c +++ b/src/core/serialize.c @@ -250,8 +250,8 @@ static int _loadPNGChunkHandler(png_structp png, png_unknown_chunkp chunk) { const uint8_t* data = chunk->data; data += sizeof(uint32_t) * 2; if (uncompress((Bytef*) item.data, &len, data, chunk->size) == Z_OK) { - if (item.size != len) { - mLOG(SAVESTATE, WARN, "Mismatched decompressed extdata %i size (%"PRIz"u vs %"PRIz"u)", tag, item.size, (size_t) len); + if ((uLongf) item.size != len) { + mLOG(SAVESTATE, WARN, "Mismatched decompressed extdata %i size (%d vs %u)", tag, item.size, (uint32_t) len); item.size = len; } mStateExtdataPut(extdata, tag, &item); From e29b5ac047358d54bd4a299cc190487a1aa46e53 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 00:11:04 -0800 Subject: [PATCH 17/40] FFmpeg: Use avcodec_get_supported_config when present --- src/feature/ffmpeg/ffmpeg-common.h | 4 ++ src/feature/ffmpeg/ffmpeg-encoder.c | 57 ++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/feature/ffmpeg/ffmpeg-common.h b/src/feature/ffmpeg/ffmpeg-common.h index 299d5167d..2476ea575 100644 --- a/src/feature/ffmpeg/ffmpeg-common.h +++ b/src/feature/ffmpeg/ffmpeg-common.h @@ -38,6 +38,10 @@ CXX_GUARD_START #define FFMPEG_USE_NEW_CH_LAYOUT #endif +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) +#define FFMPEG_USE_GET_SUPPORTED_CONFIG +#endif + static inline enum AVPixelFormat mColorFormatToFFmpegPixFmt(enum mColorFormat format) { switch (format) { #ifndef USE_LIBAV diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index e83aa680c..96c5e5bea 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -134,18 +134,28 @@ bool FFmpegEncoderSetAudio(struct FFmpegEncoder* encoder, const char* acodec, un return false; } - if (!codec->sample_fmts) { + const enum AVSampleFormat* formats = NULL; +#ifdef FFMPEG_USE_GET_SUPPORTED_CONFIG + if (avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, (const void**) &formats, NULL) < 0) { return false; } +#else + formats = codec->sample_fmts; +#endif + + if (!formats) { + return false; + } + size_t i; size_t j; int priority = INT_MAX; encoder->sampleFormat = AV_SAMPLE_FMT_NONE; - for (i = 0; codec->sample_fmts[i] != AV_SAMPLE_FMT_NONE; ++i) { + for (i = 0; formats[i] != AV_SAMPLE_FMT_NONE; ++i) { for (j = 0; j < sizeof(priorities) / sizeof(*priorities); ++j) { - if (codec->sample_fmts[i] == priorities[j].format && priority > priorities[j].priority) { + if (formats[i] == priorities[j].format && priority > priorities[j].priority) { priority = priorities[j].priority; - encoder->sampleFormat = codec->sample_fmts[i]; + encoder->sampleFormat = formats[i]; } } } @@ -153,18 +163,29 @@ bool FFmpegEncoderSetAudio(struct FFmpegEncoder* encoder, const char* acodec, un return false; } encoder->sampleRate = encoder->isampleRate; - if (codec->supported_samplerates) { + + + + const int* sampleRates = NULL; +#ifdef FFMPEG_USE_GET_SUPPORTED_CONFIG + if (avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0, (const void**) &sampleRates, NULL) < 0) { + return false; + } +#else + sampleRates = codec->sample_rates; +#endif + if (sampleRates) { bool gotSampleRate = false; int highestSampleRate = 0; - for (i = 0; codec->supported_samplerates[i]; ++i) { - if (codec->supported_samplerates[i] > highestSampleRate) { - highestSampleRate = codec->supported_samplerates[i]; + for (i = 0; sampleRates[i]; ++i) { + if (sampleRates[i] > highestSampleRate) { + highestSampleRate = sampleRates[i]; } - if (codec->supported_samplerates[i] < encoder->isampleRate) { + if (sampleRates[i] < encoder->isampleRate) { continue; } - if (!gotSampleRate || encoder->sampleRate > codec->supported_samplerates[i]) { - encoder->sampleRate = codec->supported_samplerates[i]; + if (!gotSampleRate || encoder->sampleRate > sampleRates[i]) { + encoder->sampleRate = sampleRates[i]; gotSampleRate = true; } } @@ -231,11 +252,19 @@ bool FFmpegEncoderSetVideo(struct FFmpegEncoder* encoder, const char* vcodec, in size_t j; int priority = INT_MAX; encoder->pixFormat = AV_PIX_FMT_NONE; - for (i = 0; codec->pix_fmts[i] != AV_PIX_FMT_NONE; ++i) { + const enum AVPixelFormat* formats; +#ifdef FFMPEG_USE_GET_SUPPORTED_CONFIG + if (avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, (const void**) &formats, NULL) < 0) { + return false; + } +#else + formats = codec->pix_fmts; +#endif + for (i = 0; formats[i] != AV_PIX_FMT_NONE; ++i) { for (j = 0; j < sizeof(priorities) / sizeof(*priorities); ++j) { - if (codec->pix_fmts[i] == priorities[j].format && priority > priorities[j].priority) { + if (formats[i] == priorities[j].format && priority > priorities[j].priority) { priority = priorities[j].priority; - encoder->pixFormat = codec->pix_fmts[i]; + encoder->pixFormat = formats[i]; } } } From 3c59429d96e47e192fedc9f479ae1a60360de975 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 00:15:46 -0800 Subject: [PATCH 18/40] FFmpeg: Fix build --- src/feature/ffmpeg/ffmpeg-encoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index 96c5e5bea..0286b6eeb 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -172,7 +172,7 @@ bool FFmpegEncoderSetAudio(struct FFmpegEncoder* encoder, const char* acodec, un return false; } #else - sampleRates = codec->sample_rates; + sampleRates = codec->supported_samplerates; #endif if (sampleRates) { bool gotSampleRate = false; From eb5fc371ff8e5efa93ad0ee6a4c82c604bbf5de1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 01:14:11 -0800 Subject: [PATCH 19/40] Scripting: Let mScriptContextAttachLogger take NULL for logger --- src/script/console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/console.c b/src/script/console.c index d908534f6..c6324452c 100644 --- a/src/script/console.c +++ b/src/script/console.c @@ -82,7 +82,7 @@ static struct mScriptConsole* _ensureConsole(struct mScriptContext* context) { void mScriptContextAttachLogger(struct mScriptContext* context, struct mLogger* logger) { struct mScriptConsole* console = _ensureConsole(context); - console->logger = logger; + console->logger = logger ? logger : mLogGetContext(); } void mScriptContextDetachLogger(struct mScriptContext* context) { From ee21e43bdb022cc9cd649aa1d85e4041b130b1b4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 01:21:20 -0800 Subject: [PATCH 20/40] Scripting: Install callbacks in mScriptContextAttachCore instead of mCoreThread --- src/core/scripting.c | 30 +++++++++++++++++++++++ src/core/thread.c | 58 +++----------------------------------------- 2 files changed, 33 insertions(+), 55 deletions(-) diff --git a/src/core/scripting.c b/src/core/scripting.c index b36a91412..20659f0bc 100644 --- a/src/core/scripting.c +++ b/src/core/scripting.c @@ -1343,6 +1343,24 @@ static uint8_t _readLuminance(struct GBALuminanceSource* luminance) { } #endif +#define CALLBACK(NAME) _mScriptCoreCallback ## NAME +#define DEFINE_CALLBACK(NAME) \ + void CALLBACK(NAME) (void* context) { \ + struct mScriptContext* scriptContext = context; \ + if (!scriptContext) { \ + return; \ + } \ + mScriptContextTriggerCallback(scriptContext, #NAME, NULL); \ + } + +DEFINE_CALLBACK(frame) +DEFINE_CALLBACK(crashed) +DEFINE_CALLBACK(sleep) +DEFINE_CALLBACK(stop) +DEFINE_CALLBACK(keysRead) +DEFINE_CALLBACK(savedataUpdated) +DEFINE_CALLBACK(alarm) + void mScriptContextAttachCore(struct mScriptContext* context, struct mCore* core) { struct mScriptValue* coreValue = mScriptValueAlloc(mSCRIPT_TYPE_MS_S(mScriptCoreAdapter)); struct mScriptCoreAdapter* adapter = calloc(1, sizeof(*adapter)); @@ -1375,6 +1393,18 @@ void mScriptContextAttachCore(struct mScriptContext* context, struct mCore* core } #endif + struct mCoreCallbacks callbacks = { + .videoFrameEnded = CALLBACK(frame), + .coreCrashed = CALLBACK(crashed), + .sleep = CALLBACK(sleep), + .shutdown = CALLBACK(stop), + .keysRead = CALLBACK(keysRead), + .savedataUpdated = CALLBACK(savedataUpdated), + .alarm = CALLBACK(alarm), + .context = context + }; + core->addCoreCallbacks(core, &callbacks); + _rebuildMemoryMap(context, adapter); coreValue->value.opaque = adapter; diff --git a/src/core/thread.c b/src/core/thread.c index 2b16a03c7..988ce0848 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -198,42 +198,6 @@ void _coreShutdown(void* context) { MutexUnlock(&thread->impl->stateMutex); } -#ifdef ENABLE_SCRIPTING -#define ADD_CALLBACK(NAME) \ -void _script_ ## NAME(void* context) { \ - struct mCoreThread* threadContext = context; \ - if (!threadContext->scriptContext) { \ - return; \ - } \ - mScriptContextTriggerCallback(threadContext->scriptContext, #NAME, NULL); \ -} - -ADD_CALLBACK(frame) -ADD_CALLBACK(crashed) -ADD_CALLBACK(sleep) -ADD_CALLBACK(stop) -ADD_CALLBACK(keysRead) -ADD_CALLBACK(savedataUpdated) -ADD_CALLBACK(alarm) - -#undef ADD_CALLBACK -#define SCRIPT(NAME) _script_ ## NAME - -static void _mCoreThreadAddCallbacks(struct mCoreThread* threadContext) { - struct mCoreCallbacks callbacks = { - .videoFrameEnded = SCRIPT(frame), - .coreCrashed = SCRIPT(crashed), - .sleep = SCRIPT(sleep), - .shutdown = SCRIPT(stop), - .keysRead = SCRIPT(keysRead), - .savedataUpdated = SCRIPT(savedataUpdated), - .alarm = SCRIPT(alarm), - .context = threadContext - }; - threadContext->core->addCoreCallbacks(threadContext->core, &callbacks); -} -#endif - static THREAD_ENTRY _mCoreThreadRun(void* context) { struct mCoreThread* threadContext = context; #ifdef USE_PTHREADS @@ -279,7 +243,6 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { struct mScriptContext* scriptContext = threadContext->scriptContext; if (scriptContext) { mScriptContextAttachCore(scriptContext, core); - _mCoreThreadAddCallbacks(threadContext); } #endif @@ -289,12 +252,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { } #ifdef ENABLE_SCRIPTING // startCallback could add a script context - if (scriptContext != threadContext->scriptContext) { - scriptContext = threadContext->scriptContext; - if (scriptContext) { - _mCoreThreadAddCallbacks(threadContext); - } - } + scriptContext = threadContext->scriptContext; if (scriptContext) { mScriptContextTriggerCallback(scriptContext, "start", NULL); } @@ -312,12 +270,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { #ifdef ENABLE_SCRIPTING // resetCallback could add a script context - if (scriptContext != threadContext->scriptContext) { - scriptContext = threadContext->scriptContext; - if (scriptContext) { - _mCoreThreadAddCallbacks(threadContext); - } - } + scriptContext = threadContext->scriptContext; if (scriptContext) { mScriptContextTriggerCallback(scriptContext, "reset", NULL); } @@ -372,12 +325,7 @@ static THREAD_ENTRY _mCoreThreadRun(void* context) { } } #ifdef ENABLE_SCRIPTING - if (scriptContext != threadContext->scriptContext) { - scriptContext = threadContext->scriptContext; - if (scriptContext) { - _mCoreThreadAddCallbacks(threadContext); - } - } + scriptContext = threadContext->scriptContext; #endif if (wasPaused && !(impl->requested & mTHREAD_REQ_PAUSE)) { break; From fe37fa2ab2ddc3ff275d69cf10b5b0a31cd05aaa Mon Sep 17 00:00:00 2001 From: Johan Mattsson <39247600+j-mattsson@users.noreply.github.com> Date: Wed, 1 Jan 2025 15:04:14 +0100 Subject: [PATCH 21/40] Fix potential index out of bounds in DisplayQt.cpp --- src/platform/qt/DisplayQt.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/platform/qt/DisplayQt.cpp b/src/platform/qt/DisplayQt.cpp index b71147c43..3f46872f4 100644 --- a/src/platform/qt/DisplayQt.cpp +++ b/src/platform/qt/DisplayQt.cpp @@ -209,7 +209,7 @@ void DisplayQt::deinit(struct VideoBackend*) { void DisplayQt::setLayerDimensions(struct VideoBackend* v, enum VideoLayer layer, const struct mRectangle* dims) { DisplayQt* self = static_cast(v->user); - if (layer > self->m_layerDims.size()) { + if (layer >= self->m_layerDims.size()) { return; } self->m_layerDims[layer] = QRect(dims->x, dims->y, dims->width, dims->height); @@ -217,7 +217,7 @@ void DisplayQt::setLayerDimensions(struct VideoBackend* v, enum VideoLayer layer void DisplayQt::layerDimensions(const struct VideoBackend* v, enum VideoLayer layer, struct mRectangle* dims) { DisplayQt* self = static_cast(v->user); - if (layer > self->m_layerDims.size()) { + if (layer >= self->m_layerDims.size()) { return; } QRect rect = self->m_layerDims[layer]; @@ -238,7 +238,7 @@ void DisplayQt::contextResized(struct VideoBackend*, unsigned, unsigned, unsigne void DisplayQt::setImageSize(struct VideoBackend* v, enum VideoLayer layer, int w, int h) { DisplayQt* self = static_cast(v->user); - if (layer > self->m_layers.size()) { + if (layer >= self->m_layers.size()) { return; } self->m_layers[layer] = QImage(w, h, QImage::Format_ARGB32); @@ -246,7 +246,7 @@ void DisplayQt::setImageSize(struct VideoBackend* v, enum VideoLayer layer, int void DisplayQt::imageSize(struct VideoBackend* v, enum VideoLayer layer, int* w, int* h) { DisplayQt* self = static_cast(v->user); - if (layer > self->m_layers.size()) { + if (layer >= self->m_layers.size()) { return; } *w = self->m_layers[layer].width(); @@ -255,7 +255,7 @@ void DisplayQt::imageSize(struct VideoBackend* v, enum VideoLayer layer, int* w, void DisplayQt::setImage(struct VideoBackend* v, enum VideoLayer layer, const void* frame) { DisplayQt* self = static_cast(v->user); - if (layer > self->m_layers.size()) { + if (layer >= self->m_layers.size()) { return; } QImage& image = self->m_layers[layer]; From ef6659d5872e9e02f6d7b8656680ceb747a78a75 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 01:43:21 -0800 Subject: [PATCH 22/40] Scripting: Make mScriptContextLoad run the script too --- src/script/context.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/script/context.c b/src/script/context.c index 0d770dfde..fbed31862 100644 --- a/src/script/context.c +++ b/src/script/context.c @@ -421,7 +421,10 @@ bool mScriptContextLoadVF(struct mScriptContext* context, const char* name, stru if (!info.context) { return false; } - return info.context->load(info.context, name, vf); + if (!info.context->load(info.context, name, vf)) { + return false; + } + return info.context->run(info.context); } #ifdef ENABLE_VFS From 69ead6e3c9ff2b09348270c06a56b81623909d00 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 01:44:54 -0800 Subject: [PATCH 23/40] 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); From d9aa7d5103e87f3ee480a8403a32152000ac62ab Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 01:58:41 -0800 Subject: [PATCH 24/40] Headless: Rename mgba-rom-test to mgba-headless --- CMakeLists.txt | 12 ++- .../{test/rom-test-main.c => headless-main.c} | 86 +++++++++---------- src/platform/test/CMakeLists.txt | 7 -- 3 files changed, 53 insertions(+), 52 deletions(-) rename src/platform/{test/rom-test-main.c => headless-main.c} (76%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5daa78976..7f4737fdd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,7 @@ if(NOT LIBMGBA_ONLY) set(BUILD_TEST OFF CACHE BOOL "Build testing harness") set(BUILD_SUITE OFF CACHE BOOL "Build test suite") set(BUILD_CINEMA OFF CACHE BOOL "Build video tests suite") - set(BUILD_ROM_TEST OFF CACHE BOOL "Build ROM test tool") + set(BUILD_HEADLESS OFF CACHE BOOL "Build headless tool") set(BUILD_EXAMPLE OFF CACHE BOOL "Build example frontends") set(BUILD_PYTHON OFF CACHE BOOL "Build Python bindings") set(BUILD_STATIC OFF CACHE BOOL "Build a static library") @@ -1037,6 +1037,13 @@ if(BUILD_QT) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/qt ${CMAKE_CURRENT_BINARY_DIR}/qt) endif() +if(BUILD_HEADLESS) + add_executable(${BINARY_NAME}-headless ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/headless-main.c) + target_link_libraries(${BINARY_NAME}-headless ${BINARY_NAME}) + target_compile_definitions(${BINARY_NAME}-headless PRIVATE "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") + install(TARGETS ${BINARY_NAME}-headless DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-headless) +endif() + if(NOT USE_CMOCKA) set(BUILD_SUITE OFF) endif() @@ -1213,6 +1220,7 @@ elseif(BUILD_STATIC) cpack_add_component(lib${BINARY_NAME} GROUP dev) endif() cpack_add_component(${BINARY_NAME}-dev GROUP dev) +cpack_add_component(${BINARY_NAME}-headless GROUP dev) if(3DS) cpack_add_component(${BINARY_NAME}-3ds GROUP base) @@ -1318,6 +1326,7 @@ if(NOT QUIET AND NOT LIBMGBA_ONLY) message(STATUS "Frontends:") message(STATUS " Qt: ${BUILD_QT}") message(STATUS " SDL (${SDL_VERSION}): ${BUILD_SDL}") + message(STATUS " Headless: ${BUILD_HEADLESS}") message(STATUS " Python bindings: ${BUILD_PYTHON}") message(STATUS " Examples: ${BUILD_EXAMPLE}") message(STATUS "Test tools:") @@ -1325,7 +1334,6 @@ if(NOT QUIET AND NOT LIBMGBA_ONLY) message(STATUS " Test harness: ${BUILD_TEST}") message(STATUS " Test suite: ${BUILD_SUITE}") message(STATUS " Video test suite: ${BUILD_CINEMA}") - message(STATUS " ROM tester: ${BUILD_ROM_TEST}") message(STATUS "Cores:") message(STATUS " Libretro core: ${BUILD_LIBRETRO}") message(STATUS "Libraries:") diff --git a/src/platform/test/rom-test-main.c b/src/platform/headless-main.c similarity index 76% rename from src/platform/test/rom-test-main.c rename to src/platform/headless-main.c index 807f32ec1..f501e52b2 100644 --- a/src/platform/test/rom-test-main.c +++ b/src/platform/headless-main.c @@ -29,8 +29,8 @@ #include #include -#define ROM_TEST_OPTIONS "S:R:" -static const char* const romTestUsage = +#define HEADLESS_OPTIONS "S:R:" +static const char* const headlessUsage = "Additional options:\n" " -S SWI Run until specified SWI call before exiting\n" " -R REGISTER General purpose register to return as exit code\n" @@ -39,18 +39,18 @@ static const char* const romTestUsage = #endif ; -struct RomTestOpts { +struct HeadlessOpts { 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 void _headlessShutdown(int signal); +static bool _parseHeadlessOpts(struct mSubParser* parser, int option, const char* arg); +static bool _parseLongHeadlessOpts(struct mSubParser* parser, const char* option, const char* arg); static bool _parseSwi(const char* regStr, int* oSwi); -static bool _romTestCheckResiger(void); +static bool _headlessCheckResiger(void); static struct mCore* core; @@ -58,10 +58,10 @@ static bool _dispatchExiting = false; static int _exitCode = 0; static struct mStandardLogger _logger; -static void _romTestCallback(void* context); +static void _headlessCallback(void* context); #ifdef M_CORE_GBA -static void _romTestSwi16(struct ARMCore* cpu, int immediate); -static void _romTestSwi32(struct ARMCore* cpu, int immediate); +static void _headlessSwi16(struct ARMCore* cpu, int immediate); +static void _headlessSwi32(struct ARMCore* cpu, int immediate); static int _exitSwiImmediate; static char* _returnCodeRegister; @@ -71,18 +71,18 @@ void (*_armSwi32)(struct ARMCore* cpu, int immediate); #endif int main(int argc, char * argv[]) { - signal(SIGINT, _romTestShutdown); + signal(SIGINT, _headlessShutdown); bool cleanExit = false; int uncleanExit = 1; - struct RomTestOpts romTestOpts = { 3, NULL }; - StringListInit(&romTestOpts.scripts, 0); + struct HeadlessOpts headlessOpts = { 3, NULL }; + StringListInit(&headlessOpts.scripts, 0); struct mSubParser subparser = { - .usage = romTestUsage, - .parse = _parseRomTestOpts, - .parseLong = _parseLongRomTestOpts, - .extraOptions = ROM_TEST_OPTIONS, + .usage = headlessUsage, + .parse = _parseHeadlessOpts, + .parseLong = _parseLongHeadlessOpts, + .extraOptions = HEADLESS_OPTIONS, .longOptions = (struct mOption[]) { { .name = "script", @@ -90,7 +90,7 @@ int main(int argc, char * argv[]) { }, {0} }, - .opts = &romTestOpts + .opts = &headlessOpts }; struct mArguments args; @@ -113,7 +113,7 @@ int main(int argc, char * argv[]) { goto argsExit; } core->init(core); - mCoreInitConfig(core, "romTest"); + mCoreInitConfig(core, "headless"); mArgumentsApply(&args, NULL, 0, &core->config); mCoreConfigSetDefaultValue(&core->config, "idleOptimization", "remove"); @@ -126,8 +126,8 @@ int main(int argc, char * argv[]) { struct mCoreCallbacks callbacks = {0}; - _returnCodeRegister = romTestOpts.returnCodeRegister; - if (!_romTestCheckResiger()) { + _returnCodeRegister = headlessOpts.returnCodeRegister; + if (!_headlessCheckResiger()) { goto loadError; } @@ -135,24 +135,24 @@ int main(int argc, char * argv[]) { #ifdef M_CORE_GBA case mPLATFORM_GBA: ((struct GBA*) core->board)->hardCrash = false; - _exitSwiImmediate = romTestOpts.exitSwiImmediate; + _exitSwiImmediate = headlessOpts.exitSwiImmediate; if (_exitSwiImmediate == 3) { // Hook into SWI 3 (shutdown) - callbacks.shutdown = _romTestCallback; + callbacks.shutdown = _headlessCallback; core->addCoreCallbacks(core, &callbacks); } else { // Custom SWI hooks _armSwi16 = ((struct GBA*) core->board)->cpu->irqh.swi16; - ((struct GBA*) core->board)->cpu->irqh.swi16 = _romTestSwi16; + ((struct GBA*) core->board)->cpu->irqh.swi16 = _headlessSwi16; _armSwi32 = ((struct GBA*) core->board)->cpu->irqh.swi32; - ((struct GBA*) core->board)->cpu->irqh.swi32 = _romTestSwi32; + ((struct GBA*) core->board)->cpu->irqh.swi32 = _headlessSwi32; } break; #endif #ifdef M_CORE_GB case mPLATFORM_GB: - callbacks.shutdown = _romTestCallback; + callbacks.shutdown = _headlessCallback; core->addCoreCallbacks(core, &callbacks); break; #endif @@ -193,7 +193,7 @@ int main(int argc, char * argv[]) { #ifdef ENABLE_SCRIPTING struct mScriptContext scriptContext; - if (StringListSize(&romTestOpts.scripts)) { + if (StringListSize(&headlessOpts.scripts)) { mScriptContextInit(&scriptContext); mScriptContextAttachStdlib(&scriptContext); mScriptContextAttachImage(&scriptContext); @@ -207,9 +207,9 @@ int main(int argc, char * argv[]) { 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)); + for (i = 0; i < StringListSize(&headlessOpts.scripts); ++i) { + if (!mScriptContextLoadFile(&scriptContext, *StringListGetPointer(&headlessOpts.scripts, i))) { + mLOG(STATUS, ERROR, "Failed to load script \"%s\"", *StringListGetPointer(&headlessOpts.scripts, i)); goto scriptsError; } } @@ -232,7 +232,7 @@ scriptsError: core->unloadROM(core); #ifdef ENABLE_SCRIPTING - if (StringListSize(&romTestOpts.scripts)) { + if (StringListSize(&headlessOpts.scripts)) { mScriptContextDeinit(&scriptContext); } #endif @@ -254,21 +254,21 @@ loadError: argsExit: size_t i; - for (i = 0; i < StringListSize(&romTestOpts.scripts); ++i) { - free(*StringListGetPointer(&romTestOpts.scripts, i)); + for (i = 0; i < StringListSize(&headlessOpts.scripts); ++i) { + free(*StringListGetPointer(&headlessOpts.scripts, i)); } - StringListDeinit(&romTestOpts.scripts); + StringListDeinit(&headlessOpts.scripts); mArgumentsDeinit(&args); return cleanExit ? _exitCode : uncleanExit; } -static void _romTestShutdown(int signal) { +static void _headlessShutdown(int signal) { UNUSED(signal); _dispatchExiting = true; } -static bool _romTestCheckResiger(void) { +static bool _headlessCheckResiger(void) { if (!_returnCodeRegister) { return true; } @@ -314,7 +314,7 @@ static bool _romTestCheckResiger(void) { return true; } -static void _romTestCallback(void* context) { +static void _headlessCallback(void* context) { UNUSED(context); if (_returnCodeRegister) { core->readRegister(core, _returnCodeRegister, &_exitCode); @@ -323,7 +323,7 @@ static void _romTestCallback(void* context) { } #ifdef M_CORE_GBA -static void _romTestSwi16(struct ARMCore* cpu, int immediate) { +static void _headlessSwi16(struct ARMCore* cpu, int immediate) { if (immediate == _exitSwiImmediate) { if (_returnCodeRegister) { core->readRegister(core, _returnCodeRegister, &_exitCode); @@ -334,7 +334,7 @@ static void _romTestSwi16(struct ARMCore* cpu, int immediate) { _armSwi16(cpu, immediate); } -static void _romTestSwi32(struct ARMCore* cpu, int immediate) { +static void _headlessSwi32(struct ARMCore* cpu, int immediate) { if (immediate == _exitSwiImmediate) { if (_returnCodeRegister) { core->readRegister(core, _returnCodeRegister, &_exitCode); @@ -346,8 +346,8 @@ static void _romTestSwi32(struct ARMCore* cpu, int immediate) { } #endif -static bool _parseRomTestOpts(struct mSubParser* parser, int option, const char* arg) { - struct RomTestOpts* opts = parser->opts; +static bool _parseHeadlessOpts(struct mSubParser* parser, int option, const char* arg) { + struct HeadlessOpts* opts = parser->opts; errno = 0; switch (option) { case 'S': @@ -360,8 +360,8 @@ 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; +static bool _parseLongHeadlessOpts(struct mSubParser* parser, const char* option, const char* arg) { + struct HeadlessOpts* opts = parser->opts; if (strcmp(option, "script") == 0) { *StringListAppend(&opts->scripts) = strdup(arg); return true; diff --git a/src/platform/test/CMakeLists.txt b/src/platform/test/CMakeLists.txt index 3172c6c88..ce21f8ceb 100644 --- a/src/platform/test/CMakeLists.txt +++ b/src/platform/test/CMakeLists.txt @@ -46,10 +46,3 @@ if(BUILD_CINEMA) add_test(cinema ${BINARY_NAME}-cinema -v) install(TARGETS ${BINARY_NAME}-cinema DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-test) endif() - -if(BUILD_ROM_TEST) - add_executable(${BINARY_NAME}-rom-test ${CMAKE_CURRENT_SOURCE_DIR}/rom-test-main.c) - target_link_libraries(${BINARY_NAME}-rom-test ${BINARY_NAME}) - target_compile_definitions(${BINARY_NAME}-rom-test PRIVATE "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - install(TARGETS ${BINARY_NAME}-rom-test DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-test) -endif() From 0ccd3c84dc9f84b75d0aa09203bf7bc3d70df385 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Jan 2025 02:07:04 -0800 Subject: [PATCH 25/40] Qt: Make --script explanation match headless explanation --- src/platform/qt/ConfigController.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index 819b2479d..ed000ab3b 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -158,8 +158,7 @@ ConfigController::ConfigController(QObject* parent) " Can be passed multiple times for multiple cards\n" " --mb FILE Boot a multiboot image with FILE inserted into the ROM slot" #ifdef ENABLE_SCRIPTING - "\n --script FILE Script file to load on start\n" - " Can be passed multiple times\n" + "\n --script FILE Run a script on start. Can be passed multiple times\n" #endif ; From 419435c35bb3bd31e2b4bdc70c5bb66d345e0889 Mon Sep 17 00:00:00 2001 From: Adam Higerd Date: Thu, 2 Jan 2025 18:45:12 -0600 Subject: [PATCH 26/40] Scripting: send print() to stdout if no console is installed --- src/script/engines/lua.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/script/engines/lua.c b/src/script/engines/lua.c index f4f4026e9..26099b1f0 100644 --- a/src/script/engines/lua.c +++ b/src/script/engines/lua.c @@ -1573,7 +1573,19 @@ static int _luaRequireShim(lua_State* lua) { static int _luaPrintShim(lua_State* lua) { int n = lua_gettop(lua); - lua_getglobal(lua, "console"); + if (lua_getglobal(lua, "console") == LUA_TNIL) { + // There is no console installed, so output to stdout + lua_pop(lua, 1); + for (int i = 1; i <= n; i++) { + const char* str = luaL_tolstring(lua, i, NULL); + if (i > 1) { + printf("\t"); + } + printf("%s", str); + } + printf("\n"); + return 0; + } lua_insert(lua, 1); // The first upvalue is either "log" or "warn" From 20dfbbbe55448618137f026b92acceb3d418af4f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jan 2025 02:24:59 -0800 Subject: [PATCH 27/40] CMake: Strip mgba-headless, fix up packaging a bit --- CMakeLists.txt | 11 ++++++++++- src/platform/cmake/DebugStrip.cmake | 12 ++++++++++++ src/platform/qt/CMakeLists.txt | 12 +----------- src/platform/sdl/CMakeLists.txt | 9 +-------- 4 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 src/platform/cmake/DebugStrip.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f4737fdd..f71f46bf0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -158,6 +158,7 @@ endif() include(FindFeature) include(FindFunction) +include(DebugStrip) # Version information add_custom_target(${BINARY_NAME}-version-info ALL @@ -1040,6 +1041,7 @@ endif() if(BUILD_HEADLESS) add_executable(${BINARY_NAME}-headless ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/headless-main.c) target_link_libraries(${BINARY_NAME}-headless ${BINARY_NAME}) + debug_strip(${BINARY_NAME}-headless) target_compile_definitions(${BINARY_NAME}-headless PRIVATE "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") install(TARGETS ${BINARY_NAME}-headless DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-headless) endif() @@ -1220,7 +1222,6 @@ elseif(BUILD_STATIC) cpack_add_component(lib${BINARY_NAME} GROUP dev) endif() cpack_add_component(${BINARY_NAME}-dev GROUP dev) -cpack_add_component(${BINARY_NAME}-headless GROUP dev) if(3DS) cpack_add_component(${BINARY_NAME}-3ds GROUP base) @@ -1242,6 +1243,11 @@ if(SDL_FOUND) cpack_add_component(${BINARY_NAME}-sdl GROUP sdl) endif() +if(BUILD_HEADLESS) + cpack_add_component_group(headless PARENT_GROUP base) + cpack_add_component(${BINARY_NAME}-headless GROUP headless) +endif() + if(DISTBUILD) cpack_add_component_group(debug PARENT_GROUP dev) if(BUILD_SHARED AND NOT IS_EMBEDDED) @@ -1256,6 +1262,9 @@ if(DISTBUILD) if(SDL_FOUND) cpack_add_component(${BINARY_NAME}-sdl-dbg GROUP debug) endif() + if(BUILD_HEADLESS) + cpack_add_component(${BINARY_NAME}-headless-dbg GROUP debug) + endif() if(WIN32) cpack_add_component_group(installer PARENT_GROUP base) endif() diff --git a/src/platform/cmake/DebugStrip.cmake b/src/platform/cmake/DebugStrip.cmake new file mode 100644 index 000000000..7e2b842a4 --- /dev/null +++ b/src/platform/cmake/DebugStrip.cmake @@ -0,0 +1,12 @@ +function(debug_strip TARGET) + if(DISTBUILD AND NOT APPLE) + if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.debug") + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "${STRIP}" "$") + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "${OBJCOPY}" --add-gnu-debuglink "$.debug" "$") + install(FILES "$.debug" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${TARGET}-dbg) + elseif(BUILD_STATIC AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")) + add_custom_command(TARGET ${TARGET} POST_BUILD COMMAND "${STRIP}" "$") + endif() + endif() +endfunction() diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index a5fe5b8a8..3122c70e0 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -536,17 +536,7 @@ elseif(WIN32) endif() endif() -if(DISTBUILD AND NOT APPLE) - if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.debug") - add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${STRIP}" "$") - add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${OBJCOPY}" --add-gnu-debuglink "$.debug" "$") - install(FILES "$.debug" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-qt-dbg) - elseif(BUILD_STATIC AND (CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "MinSizeRel")) - add_custom_command(TARGET ${BINARY_NAME}-qt POST_BUILD COMMAND "${STRIP}" "$") - endif() -endif() - +debug_strip(${BINARY_NAME}-qt) install(TARGETS ${BINARY_NAME}-qt RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-qt BUNDLE DESTINATION ${APPDIR} COMPONENT ${BINARY_NAME}-qt) diff --git a/src/platform/sdl/CMakeLists.txt b/src/platform/sdl/CMakeLists.txt index 5246f959b..2399dc599 100644 --- a/src/platform/sdl/CMakeLists.txt +++ b/src/platform/sdl/CMakeLists.txt @@ -115,11 +115,4 @@ if(UNIX) install(FILES ${PROJECT_SOURCE_DIR}/doc/mgba.6 DESTINATION ${MANDIR}/man6 COMPONENT ${BINARY_NAME}-sdl) endif() -if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - if(NOT APPLE) - add_custom_command(TARGET ${BINARY_NAME}-sdl POST_BUILD COMMAND "${OBJCOPY}" --only-keep-debug "$" "$.debug") - add_custom_command(TARGET ${BINARY_NAME}-sdl POST_BUILD COMMAND "${STRIP}" "$") - add_custom_command(TARGET ${BINARY_NAME}-sdl POST_BUILD COMMAND "${OBJCOPY}" --add-gnu-debuglink "$.debug" "$") - install(FILES "$.debug" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-sdl-dbg) - endif() -endif() +debug_strip(${BINARY_NAME}-sdl) From 838439dcef803a68deea0a6ea62c6f22210aeb21 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jan 2025 02:44:03 -0800 Subject: [PATCH 28/40] Headless: goto considered harmful --- src/platform/headless-main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/platform/headless-main.c b/src/platform/headless-main.c index f501e52b2..61110b1e8 100644 --- a/src/platform/headless-main.c +++ b/src/platform/headless-main.c @@ -75,6 +75,7 @@ int main(int argc, char * argv[]) { bool cleanExit = false; int uncleanExit = 1; + size_t i; struct HeadlessOpts headlessOpts = { 3, NULL }; StringListInit(&headlessOpts.scripts, 0); @@ -206,7 +207,6 @@ int main(int argc, char * argv[]) { mScriptContextAttachCore(&scriptContext, core); - size_t i; for (i = 0; i < StringListSize(&headlessOpts.scripts); ++i) { if (!mScriptContextLoadFile(&scriptContext, *StringListGetPointer(&headlessOpts.scripts, i))) { mLOG(STATUS, ERROR, "Failed to load script \"%s\"", *StringListGetPointer(&headlessOpts.scripts, i)); @@ -253,7 +253,6 @@ loadError: } argsExit: - size_t i; for (i = 0; i < StringListSize(&headlessOpts.scripts); ++i) { free(*StringListGetPointer(&headlessOpts.scripts, i)); } From 7643a044f42de69486e63d8ffdd401ca621f0fc9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jan 2025 00:37:54 -0800 Subject: [PATCH 29/40] mGUI: Wrap around menu cursor when navigating past end (closes #3356) --- CHANGES | 1 + src/util/gui/menu.c | 20 ++++++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index b87501580..84f785795 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,7 @@ Misc: - Libretro: Add Super Game Boy Color support (closes mgba.io/i/3188) - mGUI: Enable auto-softpatching (closes mgba.io/i/2899) - mGUI: Persist fast forwarding after closing menu (fixes mgba.io/i/2414) + - mGUI: Wrap around menu cursor when navigating past end (closes mgba.io/i/3356) - Qt: Handle multiple save game files for disparate games separately (fixes mgba.io/i/2887) - Qt: Remove maligned double-click-to-fullscreen shortcut (closes mgba.io/i/2632) - Qt: Pass logging context through to video proxy thread (fixes mgba.io/i/3095) diff --git a/src/util/gui/menu.c b/src/util/gui/menu.c index 2109bf8e1..3aeff4533 100644 --- a/src/util/gui/menu.c +++ b/src/util/gui/menu.c @@ -119,12 +119,6 @@ static enum GUIMenuExitReason GUIMenuPollInput(struct GUIParams* params, struct state->cursor = GUIPollCursor(params, &state->cx, &state->cy); // Check for new direction presses - if (newInput & (1 << GUI_INPUT_UP) && menu->index > 0) { - --menu->index; - } - if (newInput & (1 << GUI_INPUT_DOWN) && menu->index < GUIMenuItemListSize(&menu->items) - 1) { - ++menu->index; - } if (newInput & (1 << GUI_INPUT_LEFT)) { struct GUIMenuItem* item = GUIMenuItemListGetPointer(&menu->items, menu->index); if (item->validStates && !item->readonly) { @@ -145,6 +139,20 @@ static enum GUIMenuExitReason GUIMenuPollInput(struct GUIParams* params, struct menu->index = GUIMenuItemListSize(&menu->items) - 1; } } + if (newInput & (1 << GUI_INPUT_UP)) { + if (menu->index > 0) { + --menu->index; + } else { + menu->index = GUIMenuItemListSize(&menu->items) - 1; + } + } + if (newInput & (1 << GUI_INPUT_DOWN)) { + if (menu->index < GUIMenuItemListSize(&menu->items) - 1) { + ++menu->index; + } else { + menu->index = 0; + } + } // Handle cursor movement if (state->cursor != GUI_CURSOR_NOT_PRESENT) { From 080a79fdeebd556645b019f1e33047f6a675655e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 9 Jan 2025 01:54:10 -0800 Subject: [PATCH 30/40] CMake: Work around CMake dependency dedupliation issues --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f71f46bf0..42712e91c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -949,6 +949,14 @@ if(NOT SKIP_LIBRARY) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/mgba-util) + if(BUILD_STATIC) + # Some versions of CMake are remarkably bad about deduplicating this list, + # leading to issues with static linking. Let's do it manually. + list(REVERSE DEPENDENCY_LIB) + list(REMOVE_DUPLICATES DEPENDENCY_LIB) + list(REVERSE DEPENDENCY_LIB) + endif() + target_link_libraries(${BINARY_NAME} ${DEBUGGER_LIB} ${DEPENDENCY_LIB} ${OS_LIB}) install(TARGETS ${BINARY_NAME} LIBRARY DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME} NAMELINK_SKIP ARCHIVE DESTINATION ${LIBDIR} RUNTIME DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}) if(BUILD_SHARED) @@ -1040,7 +1048,7 @@ endif() if(BUILD_HEADLESS) add_executable(${BINARY_NAME}-headless ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/headless-main.c) - target_link_libraries(${BINARY_NAME}-headless ${BINARY_NAME}) + target_link_libraries(${BINARY_NAME}-headless ${PLATFORM_LIBRARY} ${BINARY_NAME}) debug_strip(${BINARY_NAME}-headless) target_compile_definitions(${BINARY_NAME}-headless PRIVATE "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") install(TARGETS ${BINARY_NAME}-headless DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-headless) From 77e50f7aec87d0e5fda0e68b8c0b62af18d66933 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 Jan 2025 02:45:27 -0800 Subject: [PATCH 31/40] Feature: Add ability for subparsers to consume extra arguments --- include/mgba/feature/commandline.h | 1 + src/feature/commandline.c | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/mgba/feature/commandline.h b/include/mgba/feature/commandline.h index 17af655fe..9ce118fd2 100644 --- a/include/mgba/feature/commandline.h +++ b/include/mgba/feature/commandline.h @@ -44,6 +44,7 @@ struct mSubParser { bool (*parse)(struct mSubParser* parser, int option, const char* arg); bool (*parseLong)(struct mSubParser* parser, const char* option, const char* arg); void (*apply)(struct mSubParser* parser, struct mCoreConfig* config); + bool (*handleExtraArg)(struct mSubParser* parser, const char* arg); const char* extraOptions; const struct mOption* longOptions; void* opts; diff --git a/src/feature/commandline.c b/src/feature/commandline.c index fca5c7747..1e22a4f2c 100644 --- a/src/feature/commandline.c +++ b/src/feature/commandline.c @@ -187,7 +187,21 @@ bool mArgumentsParse(struct mArguments* args, int argc, char* const* argv, struc argc -= optind; argv += optind; if (argc > 1) { - return false; + for (j = 0; j < argc; ++j) { + bool handled = false; + for (i = 0; i < nSubparsers; ++i) { + if (!subparsers[i].handleExtraArg) { + continue; + } + handled = subparsers[i].handleExtraArg(&subparsers[i], argv[j]); + if (handled) { + break; + } + } + if (!handled) { + return false; + } + } } else if (argc == 1) { args->fname = strdup(argv[0]); } else { @@ -303,6 +317,7 @@ void mSubParserGraphicsInit(struct mSubParser* parser, struct mGraphicsOpts* opt parser->apply = _applyGraphicsArgs; parser->extraOptions = GRAPHICS_OPTIONS; parser->longOptions = _graphicsLongOpts; + parser->handleExtraArg = NULL; opts->multiplier = 0; opts->fullscreen = false; } From f58f9746d72f4aba3682aec6febcf5d9ad214683 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 Jan 2025 02:46:58 -0800 Subject: [PATCH 32/40] Qt: Allow passing multiple games on command line for multiplayer (closes #3061) --- CHANGES | 1 + src/platform/qt/ConfigController.cpp | 8 ++++++++ src/platform/qt/ConfigController.h | 2 ++ src/platform/qt/GBAApp.cpp | 20 ++++++++++++++++++++ src/platform/qt/GBAApp.h | 2 ++ src/platform/qt/main.cpp | 3 +-- 6 files changed, 34 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 84f785795..68638bb67 100644 --- a/CHANGES +++ b/CHANGES @@ -47,6 +47,7 @@ Misc: - Qt: Pass logging context through to video proxy thread (fixes mgba.io/i/3095) - Qt: Show maker code and game version in ROM info - Qt: Show a dummy shader settings tab if shaders aren't supported + - Qt: Allow passing multiple games on command line for multiplayer (closes mgba.io/i/3061) - Res: Port NSO-gba-colors shader (closes mgba.io/i/2834) - Scripting: Add `callbacks:oneshot` for single-call callbacks - Updater: Fix rewriting folders and files on Windows (fixes mgba.io/i/3384) diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index ed000ab3b..a12768709 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -196,6 +196,14 @@ ConfigController::ConfigController(QObject* parent) m_subparsers[1].extraOptions = nullptr; m_subparsers[1].longOptions = s_frontendOptions; m_subparsers[1].opts = this; + m_subparsers[1].handleExtraArg = [](struct mSubParser* parser, const char* arg) { + ConfigController* self = static_cast(parser->opts); + if (self->m_fnames.count() >= MAX_GBAS) { + return false; + } + self->m_fnames.append(QString::fromUtf8(arg)); + return true; + }; } ConfigController::~ConfigController() { diff --git a/src/platform/qt/ConfigController.h b/src/platform/qt/ConfigController.h index 4325a46ba..5aa9b7ac2 100644 --- a/src/platform/qt/ConfigController.h +++ b/src/platform/qt/ConfigController.h @@ -102,6 +102,7 @@ public: const mArguments* args() const { return &m_args; } const mGraphicsOpts* graphicsOpts() const { return &m_graphicsOpts; } + QStringList fileNames() const { return m_fnames; } void usage(const char* arg0) const; static const QString& configDir(); @@ -129,6 +130,7 @@ private: mArguments m_args{}; mGraphicsOpts m_graphicsOpts{}; std::array m_subparsers; + QStringList m_fnames; bool m_parsed = false; QHash m_argvOptions; diff --git a/src/platform/qt/GBAApp.cpp b/src/platform/qt/GBAApp.cpp index 90fc89170..258df9f0c 100644 --- a/src/platform/qt/GBAApp.cpp +++ b/src/platform/qt/GBAApp.cpp @@ -397,6 +397,26 @@ void GBAApp::finishJob(qint64 jobId) { m_workerJobCallbacks.remove(jobId); } +void GBAApp::initMultiplayer() { + QStringList fnames = m_configController->fileNames(); + if (fnames.count() < 2) { + return; + } + + Window* w = m_windows[0]; + for (const auto& fname : fnames) { + if (!w) { + w = newWindow(); + } + if (!w) { + break; + } + CoreController* core = m_manager.loadGame(fname); + w->setController(core, fname); + w = nullptr; + } +} + GBAApp::WorkerJob::WorkerJob(qint64 id, std::function&& job, GBAApp* owner) : m_id(id) , m_job(std::move(job)) diff --git a/src/platform/qt/GBAApp.h b/src/platform/qt/GBAApp.h index 2388bc297..43848b183 100644 --- a/src/platform/qt/GBAApp.h +++ b/src/platform/qt/GBAApp.h @@ -82,6 +82,8 @@ public: ApplicationUpdater* updater() { return &m_updater; } QString invokeOnExit() { return m_invokeOnExit; } + void initMultiplayer(); + public slots: void restartForUpdate(); Window* newWindow(); diff --git a/src/platform/qt/main.cpp b/src/platform/qt/main.cpp index f98d2cd88..48f1984f7 100644 --- a/src/platform/qt/main.cpp +++ b/src/platform/qt/main.cpp @@ -131,10 +131,9 @@ int main(int argc, char* argv[]) { } Window* w = application.newWindow(); - w->loadConfig(); w->argumentsPassed(); - w->show(); + application.initMultiplayer(); int ret = application.exec(); if (ret != 0) { From a2fda7f44155a5adb9a9477e46955f815dc7740d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 11 Jan 2025 14:50:30 -0800 Subject: [PATCH 33/40] Qt: Split MemoryAccessLogView and MemoryAccessLogController --- src/platform/qt/CMakeLists.txt | 1 + src/platform/qt/CoreController.cpp | 14 ++ src/platform/qt/CoreController.h | 7 + src/platform/qt/MemoryAccessLogController.cpp | 118 +++++++++++++++ src/platform/qt/MemoryAccessLogController.h | 66 +++++++++ src/platform/qt/MemoryAccessLogView.cpp | 135 +++++++----------- src/platform/qt/MemoryAccessLogView.h | 17 +-- src/platform/qt/Window.cpp | 7 +- 8 files changed, 272 insertions(+), 93 deletions(-) create mode 100644 src/platform/qt/MemoryAccessLogController.cpp create mode 100644 src/platform/qt/MemoryAccessLogController.h diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 3122c70e0..910ab9b57 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -261,6 +261,7 @@ if(ENABLE_DEBUGGERS) DebuggerController.cpp DebuggerConsole.cpp DebuggerConsoleController.cpp + MemoryAccessLogController.cpp MemoryAccessLogView.cpp) endif() diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 2496f8039..152efc222 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -8,6 +8,7 @@ #include "ConfigController.h" #include "InputController.h" #include "LogController.h" +#include "MemoryAccessLogController.h" #include "MultiplayerController.h" #include "Override.h" @@ -459,6 +460,15 @@ void CoreController::setLogger(LogController* logger) { connect(this, &CoreController::logPosted, m_log, &LogController::postLog); } +#ifdef ENABLE_DEBUGGERS +std::weak_ptr CoreController::memoryAccessLogController() { + if (!m_malController) { + m_malController = std::make_shared(this); + } + return m_malController; +} +#endif + void CoreController::start() { QSize size(screenDimensions()); m_activeBuffer.resize(size.width() * size.height() * sizeof(mColor)); @@ -479,6 +489,10 @@ void CoreController::start() { void CoreController::stop() { setSync(false); #ifdef ENABLE_DEBUGGERS + if (m_malController) { + m_malController->stop(); + } + detachDebugger(); #endif setPaused(false); diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index 57eb9ffe0..a2ebe410e 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -40,6 +40,7 @@ namespace QGBA { class ConfigController; class InputController; class LogController; +class MemoryAccessLogController; class MultiplayerController; class Override; @@ -113,6 +114,8 @@ public: void detachDebugger(); void attachDebuggerModule(mDebuggerModule*, bool interrupt = true); void detachDebuggerModule(mDebuggerModule*); + + std::weak_ptr memoryAccessLogController(); #endif void setMultiplayerController(MultiplayerController*); @@ -326,6 +329,10 @@ private: GBASIODolphin m_dolphin; #endif +#ifdef ENABLE_DEBUGGERS + std::shared_ptr m_malController; +#endif + mVideoLogContext* m_vl = nullptr; VFile* m_vlVf = nullptr; diff --git a/src/platform/qt/MemoryAccessLogController.cpp b/src/platform/qt/MemoryAccessLogController.cpp new file mode 100644 index 000000000..95200e53e --- /dev/null +++ b/src/platform/qt/MemoryAccessLogController.cpp @@ -0,0 +1,118 @@ +/* Copyright (c) 2013-2025 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 "MemoryAccessLogController.h" + +#include "GBAApp.h" +#include "LogController.h" +#include "utils.h" +#include "VFileDevice.h" + +using namespace QGBA; + +MemoryAccessLogController::MemoryAccessLogController(CoreController* controller, QObject* parent) + : QObject(parent) + , m_controller(controller) +{ + mCore* core = m_controller->thread()->core; + const mCoreMemoryBlock* info; + size_t nBlocks = core->listMemoryBlocks(core, &info); + + for (size_t i = 0; i < nBlocks; ++i) { + if (!(info[i].flags & mCORE_MEMORY_MAPPED)) { + continue; + } + m_regions.append({ + QString::fromUtf8(info[i].longName), + QString::fromUtf8(info[i].internalName) + }); + } +} + +MemoryAccessLogController::~MemoryAccessLogController() { + stop(); +} + +bool MemoryAccessLogController::canExport() const { + return m_regionMapping.contains("cart0"); +} + +void MemoryAccessLogController::updateRegion(const QString& internalName, bool checked) { + if (checked) { + m_watchedRegions += internalName; + } else { + m_watchedRegions -= internalName; + } + if (!m_active) { + return; + } + m_regionMapping[internalName] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, internalName.toUtf8().constData(), activeFlags()); + emit regionMappingChanged(internalName, checked); +} + +void MemoryAccessLogController::setFile(const QString& path) { + m_path = path; +} + +void MemoryAccessLogController::start(bool loadExisting, bool logExtra) { + int flags = O_CREAT | O_RDWR; + if (!loadExisting) { + flags |= O_TRUNC; + } + VFile* vf = VFileDevice::open(m_path, flags); + if (!vf) { + LOG(QT, ERROR) << tr("Failed to open memory log file"); + return; + } + m_logExtra = logExtra; + + mDebuggerAccessLoggerInit(&m_logger); + CoreController::Interrupter interrupter(m_controller); + m_controller->attachDebuggerModule(&m_logger.d); + if (!mDebuggerAccessLoggerOpen(&m_logger, vf, flags)) { + mDebuggerAccessLoggerDeinit(&m_logger); + LOG(QT, ERROR) << tr("Failed to open memory log file"); + return; + } + + m_active = true; + emit loggingChanged(true); + for (const auto& region : m_watchedRegions) { + m_regionMapping[region] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, region.toUtf8().constData(), activeFlags()); + } + interrupter.resume(); +} + +void MemoryAccessLogController::stop() { + if (!m_active) { + return; + } + CoreController::Interrupter interrupter(m_controller); + m_controller->detachDebuggerModule(&m_logger.d); + mDebuggerAccessLoggerDeinit(&m_logger); + emit loggingChanged(false); + interrupter.resume(); + m_active = false; +} + +mDebuggerAccessLogRegionFlags MemoryAccessLogController::activeFlags() const { + mDebuggerAccessLogRegionFlags loggerFlags = 0; + if (m_logExtra) { + loggerFlags = mDebuggerAccessLogRegionFlagsFillHasExBlock(loggerFlags); + } + return loggerFlags; +} + +void MemoryAccessLogController::exportFile(const QString& filename) { + VFile* vf = VFileDevice::open(filename, O_CREAT | O_TRUNC | O_WRONLY); + if (!vf) { + // log error + return; + } + + CoreController::Interrupter interrupter(m_controller); + mDebuggerAccessLoggerCreateShadowFile(&m_logger, m_regionMapping[QString("cart0")], vf, 0); + vf->close(vf); +} diff --git a/src/platform/qt/MemoryAccessLogController.h b/src/platform/qt/MemoryAccessLogController.h new file mode 100644 index 000000000..42ef655c3 --- /dev/null +++ b/src/platform/qt/MemoryAccessLogController.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2013-2025 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/. */ +#pragma once + +#include +#include + +#include + +#include "CoreController.h" + +#include + +namespace QGBA { + +class MemoryAccessLogController : public QObject { +Q_OBJECT + +public: + struct Region { + QString longName; + QString internalName; + }; + + MemoryAccessLogController(CoreController* controller, QObject* parent = nullptr); + ~MemoryAccessLogController(); + + QVector listRegions() const { return m_regions; } + QSet watchedRegions() const { return m_watchedRegions; } + + bool canExport() const; + mPlatform platform() const { return m_controller->platform(); } + + QString file() const { return m_path; } + bool active() const { return m_active; } + +public slots: + void updateRegion(const QString& internalName, bool enable); + void setFile(const QString& path); + + void start(bool loadExisting, bool logExtra); + void stop(); + + void exportFile(const QString& filename); + +signals: + void loggingChanged(bool active); + void regionMappingChanged(const QString& internalName, bool active); + +private: + bool m_logExtra = false; + QString m_path; + CoreController* m_controller; + QSet m_watchedRegions; + QHash m_regionMapping; + QVector m_regions; + struct mDebuggerAccessLogger m_logger{}; + bool m_active = false; + + mDebuggerAccessLogRegionFlags activeFlags() const; +}; + +} diff --git a/src/platform/qt/MemoryAccessLogView.cpp b/src/platform/qt/MemoryAccessLogView.cpp index 3c846b440..97a0c932e 100644 --- a/src/platform/qt/MemoryAccessLogView.cpp +++ b/src/platform/qt/MemoryAccessLogView.cpp @@ -9,104 +9,66 @@ #include "GBAApp.h" #include "LogController.h" +#include "MemoryAccessLogController.h" #include "utils.h" #include "VFileDevice.h" using namespace QGBA; -MemoryAccessLogView::MemoryAccessLogView(std::shared_ptr controller, QWidget* parent) +MemoryAccessLogView::MemoryAccessLogView(std::weak_ptr controller, QWidget* parent) : QWidget(parent) - , m_controller(std::move(controller)) + , m_controller(controller) { m_ui.setupUi(this); + std::shared_ptr controllerPtr = m_controller.lock(); connect(m_ui.browse, &QAbstractButton::clicked, this, &MemoryAccessLogView::selectFile); connect(m_ui.exportButton, &QAbstractButton::clicked, this, &MemoryAccessLogView::exportFile); - connect(this, &MemoryAccessLogView::loggingChanged, m_ui.start, &QWidget::setDisabled); - connect(this, &MemoryAccessLogView::loggingChanged, m_ui.stop, &QWidget::setEnabled); - connect(this, &MemoryAccessLogView::loggingChanged, m_ui.filename, &QWidget::setDisabled); - connect(this, &MemoryAccessLogView::loggingChanged, m_ui.browse, &QWidget::setDisabled); + connect(controllerPtr.get(), &MemoryAccessLogController::regionMappingChanged, this, &MemoryAccessLogView::updateRegion); + connect(controllerPtr.get(), &MemoryAccessLogController::loggingChanged, this, &MemoryAccessLogView::handleStartStop); - mCore* core = m_controller->thread()->core; - const mCoreMemoryBlock* info; - size_t nBlocks = core->listMemoryBlocks(core, &info); + bool active = controllerPtr->active(); + auto watchedRegions = controllerPtr->watchedRegions(); QVBoxLayout* regionBox = static_cast(m_ui.regionBox->layout()); - for (size_t i = 0; i < nBlocks; ++i) { - if (!(info[i].flags & mCORE_MEMORY_MAPPED)) { - continue; - } - QCheckBox* region = new QCheckBox(QString::fromUtf8(info[i].longName)); + for (const auto& info : controllerPtr->listRegions()) { + QCheckBox* region = new QCheckBox(info.longName); regionBox->addWidget(region); - QString name(QString::fromUtf8(info[i].internalName)); + QString name(info.internalName); m_regionBoxes[name] = region; connect(region, &QAbstractButton::toggled, this, [this, name](bool checked) { - updateRegion(name, checked); + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { + return; + } + controllerPtr->updateRegion(name, checked); }); } + + handleStartStop(active); } -MemoryAccessLogView::~MemoryAccessLogView() { - stop(); -} - -void MemoryAccessLogView::updateRegion(const QString& internalName, bool checked) { - if (checked) { - m_watchedRegions += internalName; - } else { - m_watchedRegions -= internalName; - } - if (!m_active) { - return; - } +void MemoryAccessLogView::updateRegion(const QString& internalName, bool) { m_regionBoxes[internalName]->setEnabled(false); - m_regionMapping[internalName] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, internalName.toUtf8().constData(), activeFlags()); } void MemoryAccessLogView::start() { - int flags = O_CREAT | O_RDWR; - if (!m_ui.loadExisting->isChecked()) { - flags |= O_TRUNC; - } - VFile* vf = VFileDevice::open(m_ui.filename->text(), flags); - if (!vf) { - // log error + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { return; } - mDebuggerAccessLoggerInit(&m_logger); - CoreController::Interrupter interrupter(m_controller); - m_controller->attachDebuggerModule(&m_logger.d); - if (!mDebuggerAccessLoggerOpen(&m_logger, vf, flags)) { - mDebuggerAccessLoggerDeinit(&m_logger); - LOG(QT, ERROR) << tr("Failed to open memory log file"); - return; - } - - m_active = true; - emit loggingChanged(true); - for (const auto& region : m_watchedRegions) { - m_regionBoxes[region]->setEnabled(false); - m_regionMapping[region] = mDebuggerAccessLoggerWatchMemoryBlockName(&m_logger, region.toUtf8().constData(), activeFlags()); - } - interrupter.resume(); - - if (m_watchedRegions.contains(QString("cart0"))) { - m_ui.exportButton->setEnabled(true); - } + controllerPtr->setFile(m_ui.filename->text()); + controllerPtr->start(m_ui.loadExisting->isChecked(), m_ui.logExtra->isChecked()); } void MemoryAccessLogView::stop() { - if (!m_active) { + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { return; } - CoreController::Interrupter interrupter(m_controller); - m_controller->detachDebuggerModule(&m_logger.d); - mDebuggerAccessLoggerDeinit(&m_logger); - emit loggingChanged(false); - interrupter.resume(); - - for (const auto& region : m_watchedRegions) { + controllerPtr->stop(); + for (const auto& region : controllerPtr->watchedRegions()) { m_regionBoxes[region]->setEnabled(true); } m_ui.exportButton->setEnabled(false); @@ -119,30 +81,41 @@ void MemoryAccessLogView::selectFile() { } } -mDebuggerAccessLogRegionFlags MemoryAccessLogView::activeFlags() const { - mDebuggerAccessLogRegionFlags loggerFlags = 0; - if (m_ui.logExtra->isChecked()) { - loggerFlags = mDebuggerAccessLogRegionFlagsFillHasExBlock(loggerFlags); - } - return loggerFlags; -} - void MemoryAccessLogView::exportFile() { - if (!m_regionMapping.contains("cart0")) { + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { + return; + } + if (!controllerPtr->canExport()) { return; } - QString filename = GBAApp::app()->getSaveFileName(this, tr("Select access log file"), romFilters(false, m_controller->platform(), true)); + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select access log file"), romFilters(false, controllerPtr->platform(), true)); if (filename.isEmpty()) { return; } - VFile* vf = VFileDevice::open(filename, O_CREAT | O_TRUNC | O_WRONLY); - if (!vf) { - // log error + controllerPtr->exportFile(filename); +} + +void MemoryAccessLogView::handleStartStop(bool start) { + std::shared_ptr controllerPtr = m_controller.lock(); + if (!controllerPtr) { return; } + m_ui.filename->setText(controllerPtr->file()); - CoreController::Interrupter interrupter(m_controller); - mDebuggerAccessLoggerCreateShadowFile(&m_logger, m_regionMapping[QString("cart0")], vf, 0); - vf->close(vf); + auto watchedRegions = controllerPtr->watchedRegions(); + for (const auto& region : watchedRegions) { + m_regionBoxes[region]->setDisabled(start); + m_regionBoxes[region]->setChecked(true); + } + + if (watchedRegions.contains(QString("cart0"))) { + m_ui.exportButton->setEnabled(start); + } + + m_ui.start->setDisabled(start); + m_ui.stop->setEnabled(start); + m_ui.filename->setDisabled(start); + m_ui.browse->setDisabled(start); } diff --git a/src/platform/qt/MemoryAccessLogView.h b/src/platform/qt/MemoryAccessLogView.h index ffe31cc43..e221a5d9d 100644 --- a/src/platform/qt/MemoryAccessLogView.h +++ b/src/platform/qt/MemoryAccessLogView.h @@ -18,12 +18,14 @@ namespace QGBA { +class MemoryAccessLogController; + class MemoryAccessLogView : public QWidget { Q_OBJECT public: - MemoryAccessLogView(std::shared_ptr controller, QWidget* parent = nullptr); - ~MemoryAccessLogView(); + MemoryAccessLogView(std::weak_ptr controller, QWidget* parent = nullptr); + ~MemoryAccessLogView() = default; private slots: void updateRegion(const QString& internalName, bool enable); @@ -34,20 +36,13 @@ private slots: void exportFile(); -signals: - void loggingChanged(bool active); + void handleStartStop(bool start); private: Ui::MemoryAccessLogView m_ui; - std::shared_ptr m_controller; - QSet m_watchedRegions; + std::weak_ptr m_controller; QHash m_regionBoxes; - QHash m_regionMapping; - struct mDebuggerAccessLogger m_logger{}; - bool m_active = false; - - mDebuggerAccessLogRegionFlags activeFlags() const; }; } diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index bc956fcc4..1be4a998c 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1767,7 +1767,12 @@ void Window::setupMenu(QMenuBar* menubar) { addGameAction(tr("View &I/O registers..."), "ioViewer", openControllerTView(), "stateViews"); #ifdef ENABLE_DEBUGGERS - addGameAction(tr("Log memory &accesses..."), "memoryAccessView", openControllerTView(), "tools"); + addGameAction(tr("Log memory &accesses..."), "memoryAccessView", [this]() { + std::weak_ptr controller = m_controller->memoryAccessLogController(); + MemoryAccessLogView* view = new MemoryAccessLogView(controller); + connect(m_controller.get(), &CoreController::stopping, view, &QWidget::close); + openView(view); + }, "tools"); #endif #if defined(USE_FFMPEG) && defined(M_CORE_GBA) From 3e5e20c6f0bcbe33231bebddaf7ba4593a350ada Mon Sep 17 00:00:00 2001 From: Felipe Date: Thu, 12 Dec 2024 13:12:40 +0000 Subject: [PATCH 34/40] Qt: Update translation (Portuguese (Brazil)) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/pt_BR/ --- src/platform/qt/ts/mgba-pt_BR.ts | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index e132eaeb3..9b3ca1750 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -3262,7 +3262,7 @@ Tamanho do download: %3 Info - Informações + Info @@ -3829,12 +3829,12 @@ Tamanho do download: %3 Clearing invalid save ID - + Limpando a ID inválida do save Clearing invalid preferred ID - + Limpando a ID inválida preferida @@ -4367,7 +4367,7 @@ Tamanho do download: %3 File information - + Informação do arquivo @@ -4377,12 +4377,12 @@ Tamanho do download: %3 MD5 - + MD5 ROM header - + Cabeçalho da ROM @@ -4857,7 +4857,9 @@ Tamanho do download: %3 Shaders are not supported when the display driver is not OpenGL. If it is set to OpenGL and you still see this, your graphics card or drivers may be too old. - + Os shaders não são suportados quando o driver de exibição não é OpenGL. + +Se ele está definido como OpenGL e você ainda ver isto sua placa gráfica ou drivers podem ser muito antigos. @@ -5666,17 +5668,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may mGBA Shaders - + Shaders do mGBA Error loading shader - + Erro ao carregar o shader The shader "%1" could not be loaded successfully. - + O shader "%1" não pôde ser carregado com sucesso. From 34c992eb2314930f0bd04519e5925b5cbb85d7c6 Mon Sep 17 00:00:00 2001 From: Daniel Nylander Date: Thu, 12 Dec 2024 13:59:39 +0000 Subject: [PATCH 35/40] Qt: Update translation (Swedish) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/sv/ --- src/platform/qt/ts/mgba-sv.ts | 118 +++++++++++++++++----------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/platform/qt/ts/mgba-sv.ts b/src/platform/qt/ts/mgba-sv.ts index b0ddef6a8..bd6bfb078 100644 --- a/src/platform/qt/ts/mgba-sv.ts +++ b/src/platform/qt/ts/mgba-sv.ts @@ -1158,7 +1158,7 @@ Hämtningsstorlek: %3 B - + B @@ -2742,13 +2742,13 @@ Hämtningsstorlek: %3 Serial - + Serienummer Joypad - + Joypad @@ -2902,28 +2902,28 @@ Hämtningsstorlek: %3 Color 0 shade - + Färg 0-skugga Color 1 shade - + Färg 1-skugga Color 2 shade - + Färg 2-skugga Color 3 shade - + Färg 3-skugga @@ -2938,7 +2938,7 @@ Hämtningsstorlek: %3 VRAM bank - + VRAM-bank @@ -3348,7 +3348,7 @@ Hämtningsstorlek: %3 Offset - Förskjut + Marginal @@ -3482,7 +3482,7 @@ Hämtningsstorlek: %3 Byte Count: - + Antal byte: @@ -4030,7 +4030,7 @@ Hämtningsstorlek: %3 Game Overrides - + Spelförbättringar @@ -4118,7 +4118,7 @@ Hämtningsstorlek: %3 Game Boy Player features - + Game Boy Player-funktioner @@ -4138,7 +4138,7 @@ Hämtningsstorlek: %3 Memory bank controller - + Minnesbankskontroller @@ -4148,12 +4148,12 @@ Hämtningsstorlek: %3 Sprite Colors 1 - + Spritefärger 1 Sprite Colors 2 - + Spritefärger 2 @@ -4367,7 +4367,7 @@ Hämtningsstorlek: %3 File information - + Filinformation @@ -4377,12 +4377,12 @@ Hämtningsstorlek: %3 MD5 - + MD5 ROM header - + ROM-header @@ -4440,7 +4440,7 @@ Hämtningsstorlek: %3 <html><head/><body><p>To file a bug report, please first generate a report file to attach to the bug report you're about to file. It is recommended that you include the save files, as these often help with debugging issues. This will collect some information about the version of {projectName} you're running, your configuration, your computer, and the game you currently have open (if any). Once this collection is completed you can review all of the information gathered below and save it to a zip file. The collection will automatically attempt to redact any personal information, such as your username if it's in any of the paths gathered, but just in case you can edit it afterwards. After you have generated and saved it, please click the button below or go to <a href="https://mgba.io/i/"><span style=" text-decoration: underline; color:#2980b9;">mgba.io/i</span></a> to file the bug report on GitHub. Make sure to attach the report you generated!</p></body></html> - + <html><head/><body><p>För att rapportera en bugg eller fel så måste du generera en rapportfil att lägga till i felrapporten som du håller på att skicka in. Det rekommenderas att du inkluderar sparade filer eftersom dessa hjälper till att felsöka problem. Detta kommer att samla in viss information om versionen av {projectName} som du använder, din konfiguration, din dator samt spelet som du för närvarande har öppet (om något). När detta har samlats in så kan du granska all information nedan och spara det till en zip-fil. Personlig information kommer att undantas från den samlade informationen om det går, så som ditt användarnamn om det finns i någon sökväg, men du kan även redigera det i efterhand. Efter att du har genererat och sparat det, klicka på knappen nedan eller gå till <a href="https://mgba.io/i/"><span style=" text-decoration: underline; color:#2980b9;">mgba.io/i</span></a> för att skicka in felrapporten på GitHub. Försäkra dig om att lägga till rapporten som du genererat!</p></body></html> @@ -4779,13 +4779,13 @@ Hämtningsstorlek: %3 Set Y - + Ställ in Y Set X - + Ställ in X @@ -5122,7 +5122,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may FPS target: - + Bilder/s: @@ -5350,7 +5350,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Periodically autosave state - + Autospara tillstånd periodiskt @@ -5360,7 +5360,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Show frame count in OSD - + Visa bilder/s i OSD @@ -5370,7 +5370,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Custom border: - + Anpassad ram: @@ -5381,32 +5381,32 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Unbounded - Obunden + Obunden Fast forward (held) speed: - + Hastighet för snabbspolning (håll): Autofire interval: - + Intervall för autofire: Enable rewind - + Aktivera tillbakaspolning Rewind history: - + Historik för tillbakaspolning: Rewind speed: - + Hastighet för tillbakaspolning: @@ -5436,7 +5436,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Save state extra data: - + Extradata för sparade tillstånd: @@ -5447,7 +5447,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Load state extra data: - + Extradata för inlästa tillstånd: @@ -5647,7 +5647,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Super Game Boy borders - + Super Game Boy-ramar @@ -5666,17 +5666,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may mGBA Shaders - + mGBA-shaders Error loading shader - + Fel vid inläsning av shader The shader "%1" could not be loaded successfully. - + Shadern "%1" kunde inte läsas in korrekt. @@ -5726,7 +5726,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Unload Shader - + Läs ur shader @@ -6035,7 +6035,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Select e-Reader dotcode - + Välj e-Reader-punktkod @@ -6094,17 +6094,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Unimplemented BIOS call - + Ej implementerat BIOS-anrop This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. - + Detta spel använder ett BIOS-anrop som inte är implementerat. Använd ett officiellt BIOS för bästa upplevelse. Failed to create an appropriate display device, falling back to software display. Games may run slowly, especially with larger windows. - + Misslyckades med att skapa en lämplig visningsenhet, faller tillbaka på programvaruvisning. Spel kan bli långsamma, speciellt med större fönster. @@ -6556,7 +6556,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Frame&skip - + Hoppa över &bildrutor @@ -6566,7 +6566,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may FPS target - + Bilder/s @@ -6621,7 +6621,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Game &overrides... - + Spel&förbättringar... @@ -6636,7 +6636,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Create forwarder... - + Skapa forwarder... @@ -6661,7 +6661,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Game state views - + Visa speltillstånd @@ -6726,62 +6726,62 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may GameShark Button (held) - + GameShark-knapp (håll) Autofire - + Autofire Autofire A - + Autofire A Autofire B - + Autofire B Autofire L - + Autofire L Autofire R - + Autofire R Autofire Start - + Autofire Start Autofire Select - + Autofire Select Autofire Up - + Autofire upp Autofire Right - + Autofire höger Autofire Down - + Autofire ner Autofire Left - + Autofire vänster From 0880b007fa78a5d115b8ac28478bedd0b7380f9f Mon Sep 17 00:00:00 2001 From: Momo cao Date: Thu, 12 Dec 2024 14:50:19 +0000 Subject: [PATCH 36/40] Qt: Update translation (Spanish) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/es/ --- src/platform/qt/ts/mgba-es.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es.ts index 65223278e..d1701d571 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es.ts @@ -3829,12 +3829,12 @@ Tamaño de descarga: %3 Clearing invalid save ID - + Borrando identificador de guardado inválido Clearing invalid preferred ID - + Borrando identificador inválido preferido @@ -4367,7 +4367,7 @@ Tamaño de descarga: %3 File information - + Información de archivo @@ -4377,12 +4377,12 @@ Tamaño de descarga: %3 MD5 - + MD5 ROM header - + Cabecera de ROM @@ -4857,7 +4857,9 @@ Tamaño de descarga: %3 Shaders are not supported when the display driver is not OpenGL. If it is set to OpenGL and you still see this, your graphics card or drivers may be too old. - + Los shader no están disponibles cuando el controlador de pantalla no es OpenGL. + +Si está configurado como OpenGL y estás viendo esto, tu tarjeta gráfica o controladores son demasiado antiguos. @@ -5666,17 +5668,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may mGBA Shaders - + Shaders de mGBA Error loading shader - + Error al cargar shader The shader "%1" could not be loaded successfully. - + El shader "%1" falló al cargarse. From e3f3baed510f0ca18978acb54cc6b678a0683fa6 Mon Sep 17 00:00:00 2001 From: reimu105 Date: Sun, 15 Dec 2024 01:56:41 +0000 Subject: [PATCH 37/40] Qt: Update translation (Chinese (Traditional Han script)) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/zh_Hant/ --- src/platform/qt/ts/mgba-zh_Hant.ts | 266 ++++++++++++++--------------- 1 file changed, 133 insertions(+), 133 deletions(-) diff --git a/src/platform/qt/ts/mgba-zh_Hant.ts b/src/platform/qt/ts/mgba-zh_Hant.ts index 8cbb231b5..5b5c96e52 100644 --- a/src/platform/qt/ts/mgba-zh_Hant.ts +++ b/src/platform/qt/ts/mgba-zh_Hant.ts @@ -6,22 +6,22 @@ Game Boy Advance ROMs (%1) - Game Boy Advance ROMs (%1) + Game Boy Advance ROMs (%1) Game Boy ROMs (%1) - Game Boy ROMs (%1) + Game Boy ROMs (%1) All ROMs (%1) - 所有 ROMs (%1) + 所有 ROMs (%1) %1 Video Logs (*.mvl) - %1 影片記錄檔 (*.mvl) + %1 影片記錄檔 (*.mvl) @@ -29,7 +29,7 @@ About - 關於 + 關於 @@ -193,17 +193,17 @@ Download size: %3 Can't set format of context-less audio device - + 無法設定無上下文音訊設備的格式 Audio device is missing its core - + 音訊設備缺少其核心 Writing data to read-only audio device - + 將資料寫入唯讀音訊設備 @@ -211,7 +211,7 @@ Download size: %3 Can't start an audio processor without input - + 無輸入時無法啟動音訊處理器 @@ -219,7 +219,7 @@ Download size: %3 Can't start an audio processor without input - + 無輸入時無法啟動音訊處理器 @@ -242,12 +242,12 @@ Download size: %3 Save - + 儲存 Load - + 載入 @@ -287,28 +287,28 @@ Download size: %3 BattleChip data missing - + 缺少 BattleChip 數據 BattleChip data is missing. BattleChip Gates will still work, but some graphics will be missing. Would you like to download the data now? - + 缺少 BattleChip 數據。 BattleChip Gate 仍然可以使用,但一些圖形將會遺失。您要立即下載資料嗎? Select deck file - + 選擇卡座文件 Incompatible deck - + 不相容的卡座 The selected deck is not compatible with this Chip Gate - + 所選卡座與此 Chip Gate 不相容 @@ -341,7 +341,7 @@ Download size: %3 Some cheats could not be added. Please ensure they're formatted correctly and/or try other cheat types. - + 無法新增某些作弊碼。請確認它們的格式是否正確並且/或嘗試其它的作弊類型。 @@ -356,12 +356,12 @@ Download size: %3 Load - + 載入 Save - + 儲存 @@ -389,23 +389,23 @@ Download size: %3 Reset r%1-%2 %3 - + 重置 r%1-%2 %3 Rewinding not currently enabled - + 目前未開啟倒帶 Reset the game? - + 要重置遊戲嗎? Most games will require a reset to load the new save. Do you want to reset now? - + 大多數遊戲需要重置才能載入新的檔案。您要立即重啟嗎? @@ -474,7 +474,7 @@ Download size: %3 Could not open CLI history for writing - + 無法開啟用於寫入的 CLI 歷史 @@ -482,7 +482,7 @@ Download size: %3 Failed to create an OpenGL 3 context, trying old-style... - + 建立OpenGL3環境失敗,請嘗試舊形式... @@ -525,12 +525,12 @@ Download size: %3 Couldn't Connect - + 無法連接 Could not connect to Dolphin. - + 無法連線到 Dolphin。 @@ -538,12 +538,12 @@ Download size: %3 3DS - + 3DS Vita - + Vita @@ -551,12 +551,12 @@ Download size: %3 Icon - + 圖示 Banner - + 橫幅 @@ -564,7 +564,7 @@ Download size: %3 Bubble - + 氣泡 @@ -574,7 +574,7 @@ Download size: %3 Startup - + 啟動 @@ -582,17 +582,17 @@ Download size: %3 Create forwarder - + 建立轉發器 Files - + 文件 ROM file: - + ROM 文件: @@ -604,127 +604,127 @@ Download size: %3 Output filename: - + 輸出檔名: Forwarder base: - + 轉發器基礎: Latest stable version - + 最新穩定版本 Latest development build - + 最新開發版本 Specific file - + 指定文件 Base file: - + 基礎文件: System - + 系統 3DS - + 3DS Vita - + Vita Presentation - + 介紹 Title: - + 標題: Images: - + 圖像: Use default image - + 使用預設影像 Preferred size: - + 首選大小: Select image file - + 選擇圖像文件 Select ROM file - + 選擇ROM文件 Select output filename - + 選擇輸出檔名 Select base file - + 選擇基礎文件 Build finished - + 已完成建置 Forwarder finished building - + 已完成建置轉發器 Build failed - + 建置失敗 Failed to build forwarder - + 建立轉發器失敗 %1 installable package (*.%2) - + %1 個可安裝套件 (*.%2) Select an image - + 選擇一個影像 Image files (*.png *.jpg *.bmp) - + 圖片檔案 (*.png *.jpg *.bmp) @@ -866,22 +866,22 @@ Download size: %3 Write watchpoints behavior - + 編寫觀察點行為 Standard GDB - + 標準 GDB Internal change detection - + 內部變化檢測 Break on all writes - + 中斷所有寫入操作 @@ -939,7 +939,7 @@ Download size: %3 Start - + 開始 @@ -983,102 +983,102 @@ Download size: %3 Game Boy (DMG) - + Game Boy (DMG) Game Boy Pocket (MGB) - + Game Boy Pocket (MGB) Super Game Boy (SGB) - + Super Game Boy (SGB) Super Game Boy 2 (SGB) - + Super Game Boy 2 (SGB) Game Boy Color (CGB) - + Game Boy Color (CGB) Game Boy Advance (AGB) - + Game Boy Advance (AGB) Super Game Boy Color (SGB + CGB) - + Super Game Boy Color (SGB + CGB) ROM Only - + 僅 ROM MBC1 - + MBC1 MBC2 - + MBC2 MBC3 - + MBC3 MBC3 + RTC - + MBC3 + 實時時鐘 MBC5 - + MBC5 MBC5 + Rumble - + MBC5 + 震動 MBC6 - + MBC6 MBC7 (Tilt) - + MBC7 (Tilt) MMM01 - + MMM01 HuC-1 - + HuC-1 HuC-3 - + HuC-3 Pocket Cam - + 袖珍攝影機 @@ -1088,57 +1088,57 @@ Download size: %3 Wisdom Tree - + Wisdom Tree NT (old 1) - + NT (舊 1) NT (old 2) - + NT (舊 2) NT (new) - + NT(新) Pokémon Jade/Diamond - + 寶可夢翡翠/鑽石 BBD - + BBD Hitek - + Hitek GGB-81 - + GGB-81 Li Cheng - + Li Cheng Sachen (MMC1) - + Sachen (MMC1) Sachen (MMC2) - + Sachen (MMC2) @@ -3338,7 +3338,7 @@ Download size: %3 Map Addr. - 映射位址 + 映射位址。 @@ -3408,12 +3408,12 @@ Download size: %3 Memory access logging - + 記憶體存取日誌 Log file - + 紀錄檔案 @@ -3423,27 +3423,27 @@ Download size: %3 Log additional information (uses 3× space) - + 記錄額外資訊(使用 3x 空間) Load existing file if present - + 存在的情況下載入已有文件 Regions - + 區域 Export ROM snapshot - + 匯出ROM快照 Start - + 啟動 @@ -3453,18 +3453,18 @@ Download size: %3 Failed to open memory log file - + 打開記憶體日誌檔案失敗 Select access log file - + 選擇訪問日誌文件 Memory access logs (*.mal) - + 記憶體存取日誌(*.mal) @@ -3808,7 +3808,7 @@ Download size: %3 Load - + 載入 @@ -3816,7 +3816,7 @@ Download size: %3 Frame %1 - + 帧 %1 @@ -3824,17 +3824,17 @@ Download size: %3 Trying to detach a multiplayer player that's not attached - + 嘗試斷開與未連接的多人玩家的連接 Clearing invalid save ID - + 清理非法存檔ID Clearing invalid preferred ID - + 清理非法優先ID @@ -4407,7 +4407,7 @@ Download size: %3 Game ID: - 遊戲 ID + 遊戲 ID: @@ -5506,12 +5506,12 @@ Download size: %3 Default sprite colors 1: - 預設角色圖顏色組 1 + 預設角色圖顏色組 1: Default sprite colors 2: - 預設角色圖顏色組 2 + 預設角色圖顏色組 2: @@ -6213,7 +6213,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may %1 of %2 e-Reader cards converted successfully. - %1 張 e-Reader 卡片轉換成功。 (共 %2 張) + %2 張電子閱讀器卡中的 %1 張已成功轉換。 @@ -6243,17 +6243,17 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Scan e-Reader dotcodes... - 掃描 e-Reader 點碼 + 掃描 e-Reader 點碼... Convert e-Reader card image to raw... - 轉換 e-Reader 卡片圖檔為原始資料 + 轉換 e-Reader 卡片圖檔為原始資料... ROM &info... - ROM 資訊 (&I) + ROM 資訊 (&I)... @@ -6344,12 +6344,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Import GameShark Save... - 匯入 GameShark 存檔 + 匯入 GameShark 存檔... Export GameShark Save... - 匯出 GameShark 存檔 + 匯出 GameShark 存檔... @@ -6614,12 +6614,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may View &logs... - 查看記錄檔 (&L) + 查看記錄檔 (&L)... Game &overrides... - 遊戲替代 (&O) + 遊戲替代 (&O)... @@ -6629,7 +6629,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may &Cheats... - 金手指 (&C) + 金手指 (&C)... @@ -6654,7 +6654,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Start &GDB server... - 啟動 GDB 伺服器 (&G) + 啟動 GDB 伺服器 (&G)... @@ -6664,27 +6664,27 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may View &palette... - 檢視調色盤 (&P) + 檢視調色盤 (&P)... View &sprites... - 檢視角色圖 (&S) + 檢視角色圖 (&S)... View &tiles... - 檢視圖塊 (&T) + 檢視圖塊 (&T)... View &map... - 檢視映射 (&M) + 檢視映射 (&M)... &Frame inspector... - 畫格檢視器 (&F) + 畫格檢視器 (&F)... @@ -6699,7 +6699,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may View &I/O registers... - 檢視 I/O 暫存器 (&I) + 檢視 I/O 暫存器 (&I)... From d96ff26983feb612400f54d1aaa141f05f922ade Mon Sep 17 00:00:00 2001 From: Roll8ack Date: Mon, 16 Dec 2024 03:24:29 +0000 Subject: [PATCH 38/40] Qt: Update translation (Chinese (Simplified Han script)) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/zh_Hans/ --- src/platform/qt/ts/mgba-zh_CN.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index a051d76fb..801bacb8f 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -3829,17 +3829,17 @@ Download size: %3 Clearing invalid save ID - + 清理非法存档ID Clearing invalid preferred ID - + 清理非法优先ID Trying to get player ID for a multiplayer player that's not attached - 尝试获取未连接的多人玩家的 ID + 尝试获取多人联机中未连接上的玩家ID From 61d1dc742dad10878bc7c90ab96f467e8627f1c3 Mon Sep 17 00:00:00 2001 From: Artur Dudka Date: Wed, 25 Dec 2024 12:41:21 +0000 Subject: [PATCH 39/40] Qt: Update translation (Polish) Translation: mGBA/Qt Translate-URL: https://hosted.weblate.org/projects/mgba/mgba-qt/pl/ --- src/platform/qt/ts/mgba-pl.ts | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/platform/qt/ts/mgba-pl.ts b/src/platform/qt/ts/mgba-pl.ts index e4b191608..e50eb3d4c 100644 --- a/src/platform/qt/ts/mgba-pl.ts +++ b/src/platform/qt/ts/mgba-pl.ts @@ -3408,12 +3408,12 @@ Rozmiar pobierania: %3 Memory access logging - + Logowanie dostępu do pamięci Log file - + Plik logów @@ -3423,7 +3423,7 @@ Rozmiar pobierania: %3 Log additional information (uses 3× space) - + Loguj dodatkowe informacje (używa 3× miejsca) @@ -3433,12 +3433,12 @@ Rozmiar pobierania: %3 Regions - + Regiony Export ROM snapshot - + Eksportuj zrzut ROMu @@ -3453,7 +3453,7 @@ Rozmiar pobierania: %3 Failed to open memory log file - + Błąd odczytu pliku logów pamięci @@ -4367,7 +4367,7 @@ Rozmiar pobierania: %3 File information - + Informacje o pliku @@ -4377,12 +4377,12 @@ Rozmiar pobierania: %3 MD5 - + MD5 ROM header - + Nagłówek ROMu @@ -4402,7 +4402,7 @@ Rozmiar pobierania: %3 Revision: - + Rewizja: @@ -5668,12 +5668,12 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may mGBA Shaders - + Shadery mGBA Error loading shader - + Błąd wczytywania shaderu From 87bf98233847dad51c1eb8246e05775c92af0c61 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 11 Jan 2025 14:54:53 -0800 Subject: [PATCH 40/40] Qt: Update translations --- src/platform/qt/ts/mgba-de.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-en.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-es.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-fr.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-hu.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-it.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-ja.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-ko.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-ms.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-nb_NO.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-pl.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-pt_BR.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-pt_PT.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-ru.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-sv.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-template.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-tr.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-zh_CN.ts | 74 +++++++++++++++------------- src/platform/qt/ts/mgba-zh_Hant.ts | 76 +++++++++++++++-------------- 19 files changed, 742 insertions(+), 666 deletions(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index b430e2758..726f511d6 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -387,48 +387,48 @@ Download-Größe: %3 QGBA::CoreController - + Reset r%1-%2 %3 r%1-%2 %3 zurücksetzen - - + + Rewinding not currently enabled Zurückspulen ist derzeit nicht aktiviert - + Reset the game? Spiel zurücksetzen? - + Most games will require a reset to load the new save. Do you want to reset now? Die meisten Spiele müssen zurückgesetzt werden, um einen neuen Spielstand zu laden. Möchtest Du das Spiel jetzt zurücksetzen? - + Failed to open save file: %1 Fehler beim Öffnen der Speicherdatei: %1 - + Failed to open game file: %1 Fehler beim Öffnen der Spieldatei: %1 - + Can't yank pack in unexpected platform! Das GamePak kann nur auf unterstützten Plattformen herausgezogen werden! - + Failed to open snapshot file for reading: %1 Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - + Failed to open snapshot file for writing: %1 Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen @@ -3403,6 +3403,15 @@ Download-Größe: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Download-Größe: %3 Stopp - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6187,7 +6191,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may ROM ersetzen... - + Convert e-Reader card image to raw... Lesegerät-Kartenbild in Rohdaten umwandeln … @@ -6498,7 +6502,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Clear Leeren @@ -6714,77 +6718,77 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may &I/O-Register betrachten... - + Record debug video log... Video-Protokoll aufzeichnen... - + Stop debug video log Aufzeichnen des Video-Protokolls beenden - + Exit fullscreen Vollbildmodus beenden - + GameShark Button (held) GameShark-Taste (gehalten) - + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links diff --git a/src/platform/qt/ts/mgba-en.ts b/src/platform/qt/ts/mgba-en.ts index 316c5d2c3..20b0fe65b 100644 --- a/src/platform/qt/ts/mgba-en.ts +++ b/src/platform/qt/ts/mgba-en.ts @@ -381,48 +381,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3397,6 +3397,15 @@ Download size: %3 + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3445,18 +3454,13 @@ Download size: %3 - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6230,7 +6234,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... @@ -6701,82 +6705,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es.ts index d1701d571..6aa86cb78 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es.ts @@ -387,48 +387,48 @@ Tamaño de descarga: %3 QGBA::CoreController - + Reset r%1-%2 %3 Reiniciar r%1-%2 %3 - - + + Rewinding not currently enabled Rebobinado desactivado actualmente - + Reset the game? ¿Reiniciar el juego? - + Most games will require a reset to load the new save. Do you want to reset now? La mayoría de juegos requieren reiniciar para cargar la nueva partida guardada. ¿Quieres reiniciar ahora? - + Failed to open save file: %1 Error al abrir el archivo de guardado: %1 - + Failed to open game file: %1 Error al abrir el archivo del juego: %1 - + Can't yank pack in unexpected platform! ¡No se puede quitar el cartucho en esta plataforma! - + Failed to open snapshot file for reading: %1 Error al leer del archivo de captura: %1 - + Failed to open snapshot file for writing: %1 Error al escribir al archivo de captura: %1 @@ -3403,6 +3403,15 @@ Tamaño de descarga: %3 Gráficos de red portátiles (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + Error al abrir el archivo de registro de memoria + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Tamaño de descarga: %3 Detener - - Failed to open memory log file - Error al abrir el archivo de registro de memoria - - - - + + Select access log file Seleccionar archivo de registro de acceso - + Memory access logs (*.mal) Archivos de registro de memoria (*.mal) @@ -6224,7 +6228,7 @@ Si está configurado como OpenGL y estás viendo esto, tu tarjeta gráfica o con Sensores del cartucho... - + Clear Limpiar @@ -6285,7 +6289,7 @@ Si está configurado como OpenGL y estás viendo esto, tu tarjeta gráfica o con Cargar partida guardada temporal... - + Convert e-Reader card image to raw... Convertir imagen de tarjeta e-Reader a archivo en bruto... @@ -6716,77 +6720,77 @@ Si está configurado como OpenGL y estás viendo esto, tu tarjeta gráfica o con Registrar &accesoa la memoria… - + Record debug video log... Grabar registro de depuración de vídeo... - + Stop debug video log Detener registro de depuración de vídeo - + Exit fullscreen Salir de pantalla completa - + GameShark Button (held) Botón GameShark (mantener) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático arriba - + Autofire Right Disparo automático derecha - + Autofire Down Disparo automático abajo - + Autofire Left Disparo automático izquierda diff --git a/src/platform/qt/ts/mgba-fr.ts b/src/platform/qt/ts/mgba-fr.ts index 04411e5c3..628941e50 100644 --- a/src/platform/qt/ts/mgba-fr.ts +++ b/src/platform/qt/ts/mgba-fr.ts @@ -388,48 +388,48 @@ Taille du téléchargement : %3 QGBA::CoreController - + Reset r%1-%2 %3 Réinitialiser r%1-%2 %3 - - + + Rewinding not currently enabled Le rembobinage n'est pas actuellement activé - + Reset the game? Réinitialiser le jeu ? - + Most games will require a reset to load the new save. Do you want to reset now? La plupart des jeux nécessitent une réinitialisation pour charger la nouvelle sauvegarde. Voulez-vous réinitialiser maintenant ? - + Failed to open save file: %1 Échec de l'ouverture du fichier de sauvegarde : %1 - + Failed to open game file: %1 Échec de l'ouverture du fichier de jeu : %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Échec de l'ouverture de l'instantané pour lire : %1 - + Failed to open snapshot file for writing: %1 Échec de l'ouverture de l'instantané pour écrire : %1 @@ -3421,6 +3421,15 @@ Taille du téléchargement : %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3469,18 +3478,13 @@ Taille du téléchargement : %3 Arrêter - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6241,7 +6245,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... @@ -6728,82 +6732,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Voir les registres d'&E/S... - + Record debug video log... Enregistrer le journal vidéo de débogage... - + Stop debug video log Arrêter le journal vidéo de débogage - + Exit fullscreen Quitter le plein écran - + GameShark Button (held) Bouton GameShark (maintenir) - + Autofire Tir automatique - + Autofire A Tir automatique A - + Autofire B Tir automatique B - + Autofire L Tir automatique L - + Autofire R Tir automatique R - + Autofire Start Tir automatique Start - + Autofire Select Tir automatique Select - + Autofire Up Tir automatique Up - + Autofire Right Tir automatique Right - + Autofire Down Tir automatique Down - + Autofire Left Tir automatique Gauche - + Clear Vider diff --git a/src/platform/qt/ts/mgba-hu.ts b/src/platform/qt/ts/mgba-hu.ts index b7da40d8c..95f654c8a 100644 --- a/src/platform/qt/ts/mgba-hu.ts +++ b/src/platform/qt/ts/mgba-hu.ts @@ -388,48 +388,48 @@ Letöltendő adat: %3 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled Visszatekerés jelenleg nem engedélyezett - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Nem sikerült a mentésfájl megnyitása: %1 - + Failed to open game file: %1 Nem sikerült a játékfájl megnyitása: %1 - + Can't yank pack in unexpected platform! A játékkazettát nem lehet kirántani ismeretlen platformon! - + Failed to open snapshot file for reading: %1 A pillanatkép fájljának olvasásra való megnyitása sikertelen: %1 - + Failed to open snapshot file for writing: %1 A pillanatkép fájljának írásra való megnyitása sikertelen: %1 @@ -3404,6 +3404,15 @@ Letöltendő adat: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3452,18 +3461,13 @@ Letöltendő adat: %3 - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6235,7 +6239,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... @@ -6706,82 +6710,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Napló törlése diff --git a/src/platform/qt/ts/mgba-it.ts b/src/platform/qt/ts/mgba-it.ts index 6aaf5d809..f12794bb1 100644 --- a/src/platform/qt/ts/mgba-it.ts +++ b/src/platform/qt/ts/mgba-it.ts @@ -387,48 +387,48 @@ Dimensione del download: %3 QGBA::CoreController - + Reset r%1-%2 %3 Reset r%1-%2 %3 - - + + Rewinding not currently enabled La funzione 'riavvolgi' non è attualmente abilitata - + Reset the game? Riavviare il gioco? - + Most games will require a reset to load the new save. Do you want to reset now? La maggior parte dei giochi richiede un riavvio per caricare il nuovo salvataggio. Vuoi riavviare ora? - + Failed to open save file: %1 Impossibile aprire il file di salvataggio: %1 - + Failed to open game file: %1 Impossibile aprire il file di gioco: %1 - + Can't yank pack in unexpected platform! Non riesco a strappare il pacchetto in una piattaforma inaspettata! - + Failed to open snapshot file for reading: %1 Impossibile aprire il file snapshot per la lettura: %1 - + Failed to open snapshot file for writing: %1 Impossibile aprire il file snapshot per la scrittura: %1 @@ -3403,6 +3403,15 @@ Dimensione del download: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + Impossibile aprire il file di registro della memoria + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Dimensione del download: %3 Ferma - - Failed to open memory log file - Impossibile aprire il file di registro della memoria - - - - + + Select access log file Seleziona il file di registro di accesso - + Memory access logs (*.mal) Registri degli accessi alla memoria (*.mal) @@ -6187,7 +6191,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Scansiona e-Reader dotcode... - + Convert e-Reader card image to raw... Converti immagini carte e-Reader in raw... @@ -6709,82 +6713,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Registra memoria &accessi... - + Record debug video log... Salva registro video di debug... - + Stop debug video log Ferma registro video di debug - + Exit fullscreen Esci da Schermo Intero - + GameShark Button (held) Pulsante GameShark (tieni premuto) - + Autofire Pulsanti Autofire - + Autofire A Autofire A - + Autofire B Autofire B - + Autofire L Autofire L - + Autofire R Autofire R - + Autofire Start Autofire Start - + Autofire Select Autofire Select - + Autofire Up Autofire Su - + Autofire Right AAutofire Destra - + Autofire Down Autofire Giù - + Autofire Left Autofire Sinistra - + Clear Pulisci diff --git a/src/platform/qt/ts/mgba-ja.ts b/src/platform/qt/ts/mgba-ja.ts index 8a2425753..5d4fa2a78 100644 --- a/src/platform/qt/ts/mgba-ja.ts +++ b/src/platform/qt/ts/mgba-ja.ts @@ -387,48 +387,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 セーブファイルを開けませんでした: %1 - + Failed to open game file: %1 ゲームファイルを開けませんでした: %1 - + Can't yank pack in unexpected platform! 予期しないプラットフォームでパックをヤンクすることはできません! - + Failed to open snapshot file for reading: %1 読み取り用のスナップショットファイルを開けませんでした: %1 - + Failed to open snapshot file for writing: %1 書き込み用のスナップショットファイルを開けませんでした: %1 @@ -3403,6 +3403,15 @@ Download size: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Download size: %3 停止 - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6225,7 +6229,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may カートリッジセンサー... - + Clear 消去 @@ -6286,7 +6290,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... @@ -6712,77 +6716,77 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... デバッグビデオログ... - + Stop debug video log デバッグビデオログを停止 - + Exit fullscreen 全画面表示を終了 - + GameShark Button (held) GameSharkボタン(押し) - + Autofire 連打 - + Autofire A 連打 A - + Autofire B 連打 B - + Autofire L 連打 L - + Autofire R 連打 R - + Autofire Start 連打 Start - + Autofire Select 連打 Select - + Autofire Up 連打 上 - + Autofire Right 連打 右 - + Autofire Down 連打 下 - + Autofire Left 連打 左 diff --git a/src/platform/qt/ts/mgba-ko.ts b/src/platform/qt/ts/mgba-ko.ts index e6363dd49..18fc7ea44 100644 --- a/src/platform/qt/ts/mgba-ko.ts +++ b/src/platform/qt/ts/mgba-ko.ts @@ -387,48 +387,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 r%1-%2 %3 재설정 - - + + Rewinding not currently enabled 현재 활성화되지 않은 되감기 - + Reset the game? 게임을 재설정하겠습니까? - + Most games will require a reset to load the new save. Do you want to reset now? 대부분의 게임은 새로운 저장을 로드하려면 재설정이 필요합니다. 지금 재설정하겠습니까? - + Failed to open save file: %1 저장 파일을 열지 못했습니다: %1 - + Failed to open game file: %1 게임 파일을 열지 못했습니다: %1 - + Can't yank pack in unexpected platform! 예기치 않은 플랫폼에서 팩을 잡아당길 수 없습니다! - + Failed to open snapshot file for reading: %1 읽기 용 스냅샷 파일을 열지 못했습니다: %1 - + Failed to open snapshot file for writing: %1 쓰기 용 스냅샷 파일을 열지 못했습니다: %1 @@ -3403,6 +3403,15 @@ Download size: %3 휴대용 네트워크 그래픽 (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + 메모리 로그 파일을 열 수 없음 + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Download size: %3 정지 - - Failed to open memory log file - 메모리 로그 파일을 열 수 없음 - - - - + + Select access log file 접속 파일 선택 - + Memory access logs (*.mal) 메모리 접속 로그 (*.mal) @@ -6215,7 +6219,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may 게임 상태 보기 - + Convert e-Reader card image to raw... e-리더 카드 이미지를 원시 데이터로 변환... @@ -6707,82 +6711,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may 메모리 및 접속 기록... - + Record debug video log... 디버그 비디오 로그 녹화... - + Stop debug video log 디버그 비디오 로그 중지 - + Exit fullscreen 전체화면 종료 - + GameShark Button (held) 게임샤크 버튼 (누름) - + Autofire 연사 - + Autofire A 연사 A - + Autofire B 연사 B - + Autofire L 연사 L - + Autofire R 연사 R - + Autofire Start 연사 시작 - + Autofire Select 연사 선택 - + Clear 지움 - + Autofire Up 연사 위쪽 - + Autofire Right 연사 오른쪽 - + Autofire Down 연사 아래쪽 - + Autofire Left 연사 왼쪽 diff --git a/src/platform/qt/ts/mgba-ms.ts b/src/platform/qt/ts/mgba-ms.ts index d8b2f9b09..077aad1e6 100644 --- a/src/platform/qt/ts/mgba-ms.ts +++ b/src/platform/qt/ts/mgba-ms.ts @@ -381,48 +381,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Gagal membuka fail tersimpan: %1 - + Failed to open game file: %1 Gagal membuka fail permainan: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Gagal membuka fail snapshot untuk baca: %1 - + Failed to open snapshot file for writing: %1 Gagal membuka fail snapshot untuk menulis: %1 @@ -3397,6 +3397,15 @@ Download size: %3 Grafik Rangkaian Mudah Alih (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3445,18 +3454,13 @@ Download size: %3 Henti - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6230,7 +6234,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... @@ -6701,82 +6705,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... Rakam log video nyahpepijat... - + Stop debug video log Henti log video nyahpepijat - + Exit fullscreen Keluar skrinpenuh - + GameShark Button (held) Butang GameShark (pegang) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Kosongkan diff --git a/src/platform/qt/ts/mgba-nb_NO.ts b/src/platform/qt/ts/mgba-nb_NO.ts index f62f3793a..3042bccf2 100644 --- a/src/platform/qt/ts/mgba-nb_NO.ts +++ b/src/platform/qt/ts/mgba-nb_NO.ts @@ -385,48 +385,48 @@ Nedlastningsstørrelse: %3 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? Vil du starte spillet på nytt? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 Klarte ikke å åpne spillfil: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3401,6 +3401,15 @@ Nedlastningsstørrelse: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3449,18 +3458,13 @@ Nedlastningsstørrelse: %3 Stopp - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6234,7 +6238,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Skann e-Reader-punktkoder... - + Convert e-Reader card image to raw... @@ -6705,82 +6709,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... - + Stop debug video log - + Exit fullscreen Gå ut av fullskjerm - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear Tøm diff --git a/src/platform/qt/ts/mgba-pl.ts b/src/platform/qt/ts/mgba-pl.ts index e50eb3d4c..15b04da90 100644 --- a/src/platform/qt/ts/mgba-pl.ts +++ b/src/platform/qt/ts/mgba-pl.ts @@ -387,48 +387,48 @@ Rozmiar pobierania: %3 QGBA::CoreController - + Reset r%1-%2 %3 Reset r%1-%2 %3 - - + + Rewinding not currently enabled Przewijanie nie jest obecnie włączone - + Reset the game? Zresetować grę? - + Most games will require a reset to load the new save. Do you want to reset now? Większość gier wymaga zresetowania, aby wczytać nowy zapis. Czy chcesz teraz zresetować? - + Failed to open save file: %1 Nie udało się otworzyć pliku zapisu: %1 - + Failed to open game file: %1 Nie udało się otworzyć pliku gry: %1 - + Can't yank pack in unexpected platform! Nie można wyciągnąć pack na nieoczekiwanej platformie! - + Failed to open snapshot file for reading: %1 Nie udało się otworzyć pliku snapshot do odczytu: %1 - + Failed to open snapshot file for writing: %1 Nie udało się otworzyć pliku snapshot do zapisu: %1 @@ -3403,6 +3403,15 @@ Rozmiar pobierania: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + Błąd odczytu pliku logów pamięci + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Rozmiar pobierania: %3 Stop - - Failed to open memory log file - Błąd odczytu pliku logów pamięci - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6240,7 +6244,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Skanuj kody kropkowe czytnika e-Reader... - + Convert e-Reader card image to raw... Konwertuj obraz karty czytnika e-Reader na surowy... @@ -6711,82 +6715,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... Nagraj dziennik wideo debugowania... - + Stop debug video log Zatrzymaj dziennik wideo debugowania - + Exit fullscreen Wyłączyć tryb pełnoekranowy - + GameShark Button (held) Przycisk GameShark (przytrzymany) - + Autofire Turbo - + Autofire A Turbo A - + Autofire B Turbo B - + Autofire L Turbo L - + Autofire R Turbo R - + Autofire Start Turbo Start - + Autofire Select Turbo Select - + Autofire Up Turbo Góra - + Autofire Right Turbo Prawo - + Autofire Down Turbo Dół - + Autofire Left Turbo Lewo - + Clear Wyczyść diff --git a/src/platform/qt/ts/mgba-pt_BR.ts b/src/platform/qt/ts/mgba-pt_BR.ts index 9b3ca1750..dbe2b3b46 100644 --- a/src/platform/qt/ts/mgba-pt_BR.ts +++ b/src/platform/qt/ts/mgba-pt_BR.ts @@ -387,48 +387,48 @@ Tamanho do download: %3 QGBA::CoreController - + Reset r%1-%2 %3 Resetar r%1-%2 %3 - - + + Rewinding not currently enabled O rebobinamento não está ativado atualmente - + Reset the game? Resetar o jogo? - + Most games will require a reset to load the new save. Do you want to reset now? A maioria dos jogos requerirão um reset pra carregar o novo save. Você quer resetar agora? - + Failed to open save file: %1 Falhou em abrir o arquivo do save: %1 - + Failed to open game file: %1 Falhou em abrir o arquivo do jogo: %1 - + Can't yank pack in unexpected platform! Não pode arrancar o pacote numa plataforma inesperada! - + Failed to open snapshot file for reading: %1 Falhou em abrir o arquivo do snapshot pra leitura: %1 - + Failed to open snapshot file for writing: %1 Falhou em abrir o arquivo do snapshot pra gravação: %1 @@ -3403,6 +3403,15 @@ Tamanho do download: %3 Gráficos Portáteis da Rede (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + Falhou em abrir o arquivo do registro da memória + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Tamanho do download: %3 Parar - - Failed to open memory log file - Falhou em abrir o arquivo do registro da memória - - - - + + Select access log file Selecionar o arquivo de registro do acesso - + Memory access logs (*.mal) Registros de acesso a memória (*.mal) @@ -6224,7 +6228,7 @@ Se ele está definido como OpenGL e você ainda ver isto sua placa gráfica ou d Sensores do Game Pak... - + Clear Limpar @@ -6285,7 +6289,7 @@ Se ele está definido como OpenGL e você ainda ver isto sua placa gráfica ou d Carregar save temporário do jogo... - + Convert e-Reader card image to raw... Converter a imagem do cartão do e-Reader pro natural... @@ -6716,77 +6720,77 @@ Se ele está definido como OpenGL e você ainda ver isto sua placa gráfica ou d Registrar os acessos a &memória... - + Record debug video log... Gravar registro do vídeo de debug... - + Stop debug video log Parar o registro do vídeo de debug - + Exit fullscreen Sair da tela cheia - + GameShark Button (held) Botão do GameShark (pressionado) - + Autofire Auto-disparar - + Autofire A Auto-disparar A - + Autofire B Auto-disparar B - + Autofire L Auto-disparar L - + Autofire R Auto-disparar R - + Autofire Start Auto-disparar Start - + Autofire Select Auto-disparar Select - + Autofire Up Auto-disparar Pra Cima - + Autofire Right Auto-disparar Direita - + Autofire Down Auto-disparar Pra Baixo - + Autofire Left Auto-disparar Esquerda diff --git a/src/platform/qt/ts/mgba-pt_PT.ts b/src/platform/qt/ts/mgba-pt_PT.ts index 5f4a2e76f..7953a6d35 100644 --- a/src/platform/qt/ts/mgba-pt_PT.ts +++ b/src/platform/qt/ts/mgba-pt_PT.ts @@ -387,48 +387,48 @@ Tamanho da descarga: %3 QGBA::CoreController - + Reset r%1-%2 %3 Resetar r%1-%2 %3 - - + + Rewinding not currently enabled O rebobinamento não está ativado atualmente - + Reset the game? Resetar o jogo? - + Most games will require a reset to load the new save. Do you want to reset now? A maioria dos jogos requerirão um reset para carregar o novo save. Quer resetar agora? - + Failed to open save file: %1 Falha ao abrir o ficheiro dde gravação: %1 - + Failed to open game file: %1 Falha ao abrir o ficheiro do jogo: %1 - + Can't yank pack in unexpected platform! Não pode arrancar o pacote numa plataforma inesperada! - + Failed to open snapshot file for reading: %1 Falha ao abrir o ficheiro do snapshot para leitura: %1 - + Failed to open snapshot file for writing: %1 Falha ao abrir o ficheiro do snapshot para gravação: %1 @@ -3403,6 +3403,15 @@ Tamanho da descarga: %3 Gráficos Portáteis da Rede (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Tamanho da descarga: %3 Parar - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6238,7 +6242,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Escanear dotcodes do e-Reader... - + Convert e-Reader card image to raw... Converter imagem do cartão do e-Reader para natural... @@ -6709,82 +6713,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... Gravar registo do vídeo de debug... - + Stop debug video log Parar o registo do vídeo de debug - + Exit fullscreen Sair do ecrã inteiro - + GameShark Button (held) Botão do GameShark (segurado) - + Autofire Auto-disparar - + Autofire A Auto-disparar A - + Autofire B Auto-disparar B - + Autofire L Auto-disparar L - + Autofire R Auto-disparar R - + Autofire Start Auto-disparar Start - + Autofire Select Auto-disparar Select - + Autofire Up Auto-disparar Para Cima - + Autofire Right Auto-disparar Direita - + Autofire Down Auto-disparar Para Baixo - + Autofire Left Auto-disparar Esquerda - + Clear Limpar diff --git a/src/platform/qt/ts/mgba-ru.ts b/src/platform/qt/ts/mgba-ru.ts index 35b3f0ecb..40cd31946 100644 --- a/src/platform/qt/ts/mgba-ru.ts +++ b/src/platform/qt/ts/mgba-ru.ts @@ -387,48 +387,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 Сброс r%1-%2 %3 - - + + Rewinding not currently enabled Обратная перемотка выключена - + Reset the game? Перезагрузить игру? - + Most games will require a reset to load the new save. Do you want to reset now? Большинству игр нужна перезагрузка, чтобы загрузить новое сохранение. Перезагрузить сейчас? - + Failed to open save file: %1 Не удалось открыть файл сохранения: %1 - + Failed to open game file: %1 Не удалось открыть файл игры: %1 - + Can't yank pack in unexpected platform! Невозможно пнуть картридж на неожиданной платформе! - + Failed to open snapshot file for reading: %1 Не удалось открыть файл изображения для считывания: %1 - + Failed to open snapshot file for writing: %1 Не удалось открыть файл изображения для записи: %1 @@ -3403,6 +3403,15 @@ Download size: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Download size: %3 - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6240,7 +6244,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Сканировать dot-коды e-Reader... - + Convert e-Reader card image to raw... Конвертировать карту e-Reader в raw... @@ -6711,82 +6715,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... Запись отладочного видеожурнала... - + Stop debug video log Закончить запись отладочного видеожурнала - + Exit fullscreen Выйти из полноэкранного режима - + GameShark Button (held) Кнопка GameShark (удерживается) - + Autofire Автострельба - + Autofire A A (автострельба) - + Autofire B B (автострельба) - + Autofire L L (автострельба) - + Autofire R R (автострельба) - + Autofire Start Start (автострельба) - + Autofire Select Select (автострельба) - + Autofire Up Вверх (автострельба) - + Autofire Right Вправо (автострельба) - + Autofire Down Вниз (автострельба) - + Autofire Left Влево (автострельба) - + Clear Очистить diff --git a/src/platform/qt/ts/mgba-sv.ts b/src/platform/qt/ts/mgba-sv.ts index bd6bfb078..49fdcb432 100644 --- a/src/platform/qt/ts/mgba-sv.ts +++ b/src/platform/qt/ts/mgba-sv.ts @@ -387,48 +387,48 @@ Hämtningsstorlek: %3 QGBA::CoreController - + Reset r%1-%2 %3 Starta om r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? Starta om spelet? - + Most games will require a reset to load the new save. Do you want to reset now? De flesta spel kommer att kräva en omstart för att läsa in ny sparning. Vill du starta om nu? - + Failed to open save file: %1 Misslyckades med att öppna sparad fil: %1 - + Failed to open game file: %1 Misslyckades med att öppna spelfil: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 Misslyckades med att öppna ögonblicksfil för läsning: %1 - + Failed to open snapshot file for writing: %1 Misslyckades med att öppna ögonblicksfil för skrivning: %1 @@ -3403,6 +3403,15 @@ Hämtningsstorlek: %3 Portable Network Graphics (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + Misslyckades med att öppna minnesloggfil + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Hämtningsstorlek: %3 Stoppa - - Failed to open memory log file - Misslyckades med att öppna minnesloggfil - - - - + + Select access log file Välj åtkomstloggfil - + Memory access logs (*.mal) Minnesåtkomstloggar (*.mal) @@ -6238,7 +6242,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Skanna e-Reader-punktkoder... - + Convert e-Reader card image to raw... Konvertera e-Reader-kortavbilder till raw... @@ -6709,82 +6713,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may Logga minneså&tkomster... - + Record debug video log... Spela in felsökningsvideologg... - + Stop debug video log Stoppa felsökningsvideologg - + Exit fullscreen Avsluta helskärm - + GameShark Button (held) GameShark-knapp (håll) - + Autofire Autofire - + Autofire A Autofire A - + Autofire B Autofire B - + Autofire L Autofire L - + Autofire R Autofire R - + Autofire Start Autofire Start - + Autofire Select Autofire Select - + Autofire Up Autofire upp - + Autofire Right Autofire höger - + Autofire Down Autofire ner - + Autofire Left Autofire vänster - + Clear Töm diff --git a/src/platform/qt/ts/mgba-template.ts b/src/platform/qt/ts/mgba-template.ts index 0155d9c06..77294e94d 100644 --- a/src/platform/qt/ts/mgba-template.ts +++ b/src/platform/qt/ts/mgba-template.ts @@ -381,48 +381,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 - + Failed to open game file: %1 - + Can't yank pack in unexpected platform! - + Failed to open snapshot file for reading: %1 - + Failed to open snapshot file for writing: %1 @@ -3397,6 +3397,15 @@ Download size: %3 + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3445,18 +3454,13 @@ Download size: %3 - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6228,7 +6232,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... @@ -6699,82 +6703,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... - + Stop debug video log - + Exit fullscreen - + GameShark Button (held) - + Autofire - + Autofire A - + Autofire B - + Autofire L - + Autofire R - + Autofire Start - + Autofire Select - + Autofire Up - + Autofire Right - + Autofire Down - + Autofire Left - + Clear diff --git a/src/platform/qt/ts/mgba-tr.ts b/src/platform/qt/ts/mgba-tr.ts index aaafaf988..6db0c47a6 100644 --- a/src/platform/qt/ts/mgba-tr.ts +++ b/src/platform/qt/ts/mgba-tr.ts @@ -387,48 +387,48 @@ Yeni sürüm: %2 QGBA::CoreController - + Reset r%1-%2 %3 - - + + Rewinding not currently enabled - + Reset the game? Oyun sıfırlansım mı? - + Most games will require a reset to load the new save. Do you want to reset now? - + Failed to open save file: %1 Kayıt dosyası açılamadı: %1 - + Failed to open game file: %1 Oyun dosyası açılamadı: %1 - + Can't yank pack in unexpected platform! Beklenmedik bir platformda kartı çıkaramazsın! - + Failed to open snapshot file for reading: %1 Anlık görüntü dosyası okuma için açılamadı: %1 - + Failed to open snapshot file for writing: %1 Anlık görüntü dosyası yazma için açılamadı: %1 @@ -3403,6 +3403,15 @@ Yeni sürüm: %2 + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Yeni sürüm: %2 Durdur - - Failed to open memory log file - - - - - + + Select access log file - + Memory access logs (*.mal) @@ -6220,7 +6224,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Convert e-Reader card image to raw... e-Okuyucu kart resimlerini rawa dönüştür... @@ -6707,82 +6711,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may &I/O kayıtlarını görüntüle - + Record debug video log... Hata ayıklama video günlüğünü kaydet... - + Stop debug video log Hata ayıklama video günlüğünü durdur - + Exit fullscreen Tam ekrandan çık - + GameShark Button (held) GameShark Butonu (basılı tutun) - + Autofire Otomatik basma - + Autofire A Otomatik basma A - + Autofire B Otomatik basma B - + Autofire L Otomatik basma L - + Autofire R Otomatik basma R - + Autofire Start Otomatik basma Start - + Autofire Select Otomatik basma Select - + Autofire Up Otomatik basma Up - + Autofire Right Otomatik basma Right - + Autofire Down Otomatik basma Down - + Autofire Left Otomatik basma Sol - + Clear Temizle diff --git a/src/platform/qt/ts/mgba-zh_CN.ts b/src/platform/qt/ts/mgba-zh_CN.ts index 801bacb8f..0518b256b 100644 --- a/src/platform/qt/ts/mgba-zh_CN.ts +++ b/src/platform/qt/ts/mgba-zh_CN.ts @@ -387,48 +387,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 重置 r%1-%2 %3 - - + + Rewinding not currently enabled 当前未开启倒带 - + Reset the game? 要重置游戏吗? - + Most games will require a reset to load the new save. Do you want to reset now? 大多数游戏需要重置才能加载新的存档。您要立即重启吗? - + Failed to open save file: %1 打开存档失败: %1 - + Failed to open game file: %1 打开游戏文件失败: %1 - + Can't yank pack in unexpected platform! 无法在意外平台上抽出卡带! - + Failed to open snapshot file for reading: %1 读取快照文件失败: %1 - + Failed to open snapshot file for writing: %1 写入快照文件失败: %1 @@ -3403,6 +3403,15 @@ Download size: %3 便携式网络图形 (*.png) + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + 打开内存日志文件失败 + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Download size: %3 停止 - - Failed to open memory log file - 打开内存日志文件失败 - - - - + + Select access log file 选择访问日志文件 - + Memory access logs (*.mal) 内存访问日志(*.mal) @@ -6236,7 +6240,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may 扫描 e-Reader 点码... - + Convert e-Reader card image to raw... 将 e-Reader 卡片图像转换为原始数据... @@ -6707,82 +6711,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may 记录内存访问(&a)... - + Record debug video log... 记录调试视频日志... - + Stop debug video log 停止记录调试视频日志 - + Exit fullscreen 退出全屏 - + GameShark Button (held) GameShark 键 (长按) - + Autofire 连发 - + Autofire A 连发 A - + Autofire B 连发 B - + Autofire L 连发 L - + Autofire R 连发 R - + Autofire Start 连发 Start - + Autofire Select 连发 Select - + Autofire Up 连发 上 - + Autofire Right 连发 右 - + Autofire Down 连发 下 - + Autofire Left 连发 左 - + Clear 清除 diff --git a/src/platform/qt/ts/mgba-zh_Hant.ts b/src/platform/qt/ts/mgba-zh_Hant.ts index 5b5c96e52..e764abb92 100644 --- a/src/platform/qt/ts/mgba-zh_Hant.ts +++ b/src/platform/qt/ts/mgba-zh_Hant.ts @@ -387,48 +387,48 @@ Download size: %3 QGBA::CoreController - + Reset r%1-%2 %3 重置 r%1-%2 %3 - - + + Rewinding not currently enabled 目前未開啟倒帶 - + Reset the game? 要重置遊戲嗎? - + Most games will require a reset to load the new save. Do you want to reset now? 大多數遊戲需要重置才能載入新的檔案。您要立即重啟嗎? - + Failed to open save file: %1 存檔開啟失敗: %1 - + Failed to open game file: %1 遊戲開啟失敗: %1 - + Can't yank pack in unexpected platform! 無法在預料外的平台拔除卡帶! - + Failed to open snapshot file for reading: %1 讀取快照失敗: %1 - + Failed to open snapshot file for writing: %1 寫入快照失敗: %1 @@ -3403,6 +3403,15 @@ Download size: %3 複製 + + QGBA::MemoryAccessLogController + + + + Failed to open memory log file + 打開記憶體日誌檔案失敗 + + QGBA::MemoryAccessLogView @@ -3451,18 +3460,13 @@ Download size: %3 停止 - - Failed to open memory log file - 打開記憶體日誌檔案失敗 - - - - + + Select access log file 選擇訪問日誌文件 - + Memory access logs (*.mal) 記憶體存取日誌(*.mal) @@ -4450,7 +4454,7 @@ Download size: %3 Save - + 儲存 @@ -6246,7 +6250,7 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may 掃描 e-Reader 點碼... - + Convert e-Reader card image to raw... 轉換 e-Reader 卡片圖檔為原始資料... @@ -6707,82 +6711,82 @@ If it is set to OpenGL and you still see this, your graphics card or drivers may - + Record debug video log... 錄製除錯影片記錄檔。 - + Stop debug video log 停止除錯影片記錄檔 - + Exit fullscreen 離開全螢幕 - + GameShark Button (held) Gameshark 按鈕 (長按) - + Autofire 自動連射 - + Autofire A 自動連射 A - + Autofire B 自動連射 B - + Autofire L 自動連射 L - + Autofire R 自動連射 R - + Autofire Start 自動連射 Start - + Autofire Select 自動連射 Select - + Autofire Up 自動連射 上 - + Autofire Right 自動連射 右 - + Autofire Down 自動連射 下 - + Autofire Left 自動連射 左 - + Clear 清除