From 9b2ba64bc68241da199ca9427b99d1f1547d9305 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Feb 2023 22:05:48 -0800 Subject: [PATCH 01/31] Windows: Fix build clang-cl --- include/mgba-util/platform/windows/getopt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/mgba-util/platform/windows/getopt.h b/include/mgba-util/platform/windows/getopt.h index 5ea2dbe6f..22a196ef6 100644 --- a/include/mgba-util/platform/windows/getopt.h +++ b/include/mgba-util/platform/windows/getopt.h @@ -27,6 +27,8 @@ extern "C" { #endif +struct option; + #define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ #ifdef REPLACE_GETOPT From a64dcf8e43333b6429d08484f6465aa9b9a85890 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 24 Feb 2023 22:34:45 -0800 Subject: [PATCH 02/31] All: Minor warning touching up --- CMakeLists.txt | 4 ++-- src/platform/qt/ConfigController.cpp | 1 + src/platform/qt/MemorySearch.cpp | 12 +++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32551c602..5dc1e38c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,8 +34,8 @@ if(NOT MSVC) # mingw32 likes to complain about using the "wrong" format strings despite them actually working set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-format") endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=implicit-function-declaration -Werror=implicit-int") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS}") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=implicit-function-declaration -Werror=missing-parameter-type -Werror=implicit-int") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") diff --git a/src/platform/qt/ConfigController.cpp b/src/platform/qt/ConfigController.cpp index 1116dba79..73097df09 100644 --- a/src/platform/qt/ConfigController.cpp +++ b/src/platform/qt/ConfigController.cpp @@ -343,6 +343,7 @@ constexpr const char* ConfigController::mruName(ConfigController::MRU mru) { case MRU::Script: return "recentScripts"; } + Q_UNREACHABLE(); } void ConfigController::write() { diff --git a/src/platform/qt/MemorySearch.cpp b/src/platform/qt/MemorySearch.cpp index 8589f9cfe..f61fb9e52 100644 --- a/src/platform/qt/MemorySearch.cpp +++ b/src/platform/qt/MemorySearch.cpp @@ -178,7 +178,7 @@ void MemorySearch::refresh() { mCoreMemorySearchResult* result = mCoreMemorySearchResultsGetPointer(&m_results, i); QTableWidgetItem* item = new QTableWidgetItem(QString("%1").arg(result->address, 8, 16, QChar('0'))); m_ui.results->setItem(i, 0, item); - QTableWidgetItem* type; + QTableWidgetItem* type = nullptr; QByteArray string; if (result->type == mCORE_MEMORY_SEARCH_INT && m_ui.numHex->isChecked()) { switch (result->width) { @@ -213,7 +213,12 @@ void MemorySearch::refresh() { string.append(core->rawRead8(core, result->address + i, result->segment)); } item = new QTableWidgetItem(QLatin1String(string)); // TODO + break; + case mCORE_MEMORY_SEARCH_GUESS: + item = nullptr; + break; } + Q_ASSERT(item); } QString divisor; if (result->guessDivisor > 1) { @@ -231,7 +236,12 @@ void MemorySearch::refresh() { break; case mCORE_MEMORY_SEARCH_STRING: type = new QTableWidgetItem("string"); + break; + case mCORE_MEMORY_SEARCH_GUESS: + break; } + Q_ASSERT(type); + m_ui.results->setItem(i, 1, item); m_ui.results->setItem(i, 2, type); m_ui.opDelta->setEnabled(true); From 5b722311669f328fa017c7be3f817917225551f4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 28 Feb 2023 18:11:21 -0800 Subject: [PATCH 03/31] GBA Overrides: Mark ASL* as no save (fixes #2843) --- src/gba/overrides.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gba/overrides.c b/src/gba/overrides.c index e15db50d8..ee286cfe0 100644 --- a/src/gba/overrides.c +++ b/src/gba/overrides.c @@ -159,6 +159,10 @@ static const struct GBACartridgeOverride _overrides[] = { // Shin Bokura no Taiyou: Gyakushuu no Sabata { "U33J", SAVEDATA_EEPROM, HW_RTC | HW_LIGHT_SENSOR, IDLE_LOOP_NONE, false }, + // Stuart Little 2 + { "ASLE", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, + { "ASLF", SAVEDATA_FORCE_NONE, HW_NONE, IDLE_LOOP_NONE, false }, + // Super Mario Advance 2 { "AA2J", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false }, { "AA2E", SAVEDATA_EEPROM, HW_NONE, 0x800052E, false }, From 5f3ee83bcc23e7ca7f3e1ce85cbdc4cf6f027f69 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 28 Feb 2023 18:20:16 -0800 Subject: [PATCH 04/31] CMake: Fix configure issues on clang --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dc1e38c0..ac498d0d2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,7 +34,7 @@ if(NOT MSVC) # mingw32 likes to complain about using the "wrong" format strings despite them actually working set(WARNING_FLAGS "${WARNING_FLAGS} -Wno-format") endif() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=implicit-function-declaration -Werror=missing-parameter-type -Werror=implicit-int") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} -Werror=implicit-function-declaration -Werror=implicit-int") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} -Woverloaded-virtual") else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146 /wd4267 /Zc:preprocessor-") From 10a31656429b3639a98817fbc1439a19ee754cd8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 15:52:24 -0800 Subject: [PATCH 05/31] Qt: auto -> auto& cleanup --- src/platform/qt/CoreController.cpp | 2 +- src/platform/qt/InputController.cpp | 30 ++++++++++++++--------------- src/platform/qt/SettingsView.cpp | 4 ++-- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 37fc1b01f..1447fedba 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -80,7 +80,7 @@ CoreController::CoreController(mCore* core, QObject* parent) m_threadContext.resetCallback = [](mCoreThread* context) { CoreController* controller = static_cast(context->userData); - for (auto action : controller->m_resetActions) { + for (auto& action : controller->m_resetActions) { action(); } diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index d8b5dd783..3af600a64 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -151,7 +151,7 @@ bool InputController::loadConfiguration(uint32_t type) { if (!mInputMapLoad(&m_inputMap, type, m_config->input())) { return false; } - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return false; } @@ -185,7 +185,7 @@ void InputController::saveConfiguration() { void InputController::saveConfiguration(uint32_t type) { mInputMapSave(&m_inputMap, type, m_config->input()); - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (driver) { driver->saveConfiguration(m_config); } @@ -201,7 +201,7 @@ void InputController::saveProfile(uint32_t type, const QString& profile) { } QString InputController::profileForType(uint32_t type) { - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return {}; } @@ -209,7 +209,7 @@ QString InputController::profileForType(uint32_t type) { } void InputController::setGamepadDriver(uint32_t type) { - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver || !driver->supportsGamepads()) { return; } @@ -220,13 +220,13 @@ QStringList InputController::connectedGamepads(uint32_t type) const { if (!type) { type = m_gamepadDriver; } - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return {}; } QStringList pads; - for (auto pad : driver->connectedGamepads()) { + for (auto& pad : driver->connectedGamepads()) { pads.append(pad->visibleName()); } return pads; @@ -236,7 +236,7 @@ int InputController::gamepadIndex(uint32_t type) const { if (!type) { type = m_gamepadDriver; } - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return -1; } @@ -247,7 +247,7 @@ void InputController::setGamepad(uint32_t type, int index) { if (!type) { type = m_gamepadDriver; } - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return; } @@ -265,7 +265,7 @@ void InputController::setPreferredGamepad(uint32_t type, int index) { if (!type) { type = m_gamepadDriver; } - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return; } @@ -299,7 +299,7 @@ InputMapper InputController::mapper(InputSource* source) { } void InputController::setSensorDriver(uint32_t type) { - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver || !driver->supportsSensors()) { return; } @@ -308,7 +308,7 @@ void InputController::setSensorDriver(uint32_t type) { mRumble* InputController::rumble() { - auto driver = m_inputDrivers.value(m_sensorDriver); + auto& driver = m_inputDrivers.value(m_sensorDriver); if (driver) { return driver->rumble(); } @@ -316,7 +316,7 @@ mRumble* InputController::rumble() { } mRotationSource* InputController::rotationSource() { - auto driver = m_inputDrivers.value(m_sensorDriver); + auto& driver = m_inputDrivers.value(m_sensorDriver); if (driver) { return driver->rotationSource(); } @@ -341,7 +341,7 @@ void InputController::update() { int InputController::pollEvents() { int activeButtons = 0; - for (auto pad : gamepads()) { + for (auto& pad : gamepads()) { InputMapper im(mapper(pad)); activeButtons |= im.mapKeys(pad->currentButtons()); activeButtons |= im.mapAxes(pad->currentAxes()); @@ -356,7 +356,7 @@ int InputController::pollEvents() { } Gamepad* InputController::gamepad(uint32_t type) { - auto driver = m_inputDrivers.value(type); + auto& driver = m_inputDrivers.value(type); if (!driver) { return nullptr; } @@ -464,7 +464,7 @@ void InputController::testGamepad(uint32_t type) { } } } - for (auto axis : oldAxes) { + for (auto& axis : oldAxes) { GamepadAxisEvent* event = new GamepadAxisEvent(axis.first, axis.second, false, type, this); clearPendingEvent(event->platformKey()); sendGamepadEvent(event); diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 4eca3cb46..acf272cf6 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -51,7 +51,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC #ifdef M_CORE_GB m_pageIndex[Page::GB] = 9; - for (auto model : GameBoy::modelList()) { + for (auto& model : GameBoy::modelList()) { m_ui.gbModel->addItem(GameBoy::modelName(model), model); m_ui.sgbModel->addItem(GameBoy::modelName(model), model); m_ui.cgbModel->addItem(GameBoy::modelName(model), model); @@ -350,7 +350,7 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC QLocale englishLocale("en"); m_ui.languages->addItem(englishLocale.nativeLanguageName(), englishLocale); QDir ts(":/translations/"); - for (auto name : ts.entryList()) { + for (auto& name : ts.entryList()) { if (!name.endsWith(".qm") || !name.startsWith(binaryName)) { continue; } From ee21eed29c4acec6c58b9d1c9f06a3b3ac37c2c5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 15:59:46 -0800 Subject: [PATCH 06/31] Qt: Fix full-buffer rewind --- CHANGES | 1 + src/platform/qt/CoreController.cpp | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 0e14f021b..d0bbd604b 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ Other fixes: - Qt: Disable attempted linking betwen incompatible platforms (fixes mgba.io/i/2702) - Qt: Fix modifier key names in shortcut editor (fixes mgba.io/i/2817) - Qt: Fix a handful of edge cases with graphics viewers (fixes mgba.io/i/2827) + - Qt: Fix full-buffer rewind - Scripting: Fix receiving packets for client sockets - Scripting: Fix empty receive calls returning unknown error on Windows Misc: diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index 1447fedba..07902facc 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -518,9 +518,6 @@ void CoreController::setRewinding(bool rewind) { } void CoreController::rewind(int states) { - if (!states) { - return; - } if (!m_threadContext.core->opts.rewindEnable) { emit statusPosted(tr("Rewinding not currently enabled")); } From 2cce155173beaf92c5269278b65e427ed4624423 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 16:02:28 -0800 Subject: [PATCH 07/31] GBA Savedata: Fix sanity check in Load --- 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 455ee0802..7097e4a63 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -184,7 +184,7 @@ size_t GBASavedataSize(const struct GBASavedata* savedata) { bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) { if (savedata->data) { - if (!in && savedata->type != SAVEDATA_FORCE_NONE) { + if (!in || savedata->type != SAVEDATA_FORCE_NONE) { return false; } ssize_t size = GBASavedataSize(savedata); From 7ffa0ff2809b21019e859df4e28e7a89ee92ac00 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 16:08:56 -0800 Subject: [PATCH 08/31] OpenGL: Fix memory leak in failure path --- src/platform/opengl/gles2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index 88ac000a5..ffbac5a04 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -1053,6 +1053,7 @@ bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { for (n = 0; n < inShaders; ++n) { mGLES2ShaderDeinit(&shaderBlock[n]); } + free(shaderBlock); } } } From e504ac36654df863c9019b3811be8eee4a15db51 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 16:10:43 -0800 Subject: [PATCH 09/31] Qt: Fix crash if loading a shader fails --- CHANGES | 1 + src/platform/qt/DisplayGL.cpp | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index d0bbd604b..ffda80576 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Other fixes: - Qt: Fix modifier key names in shortcut editor (fixes mgba.io/i/2817) - Qt: Fix a handful of edge cases with graphics viewers (fixes mgba.io/i/2827) - Qt: Fix full-buffer rewind + - Qt: Fix crash if loading a shader fails - Scripting: Fix receiving packets for client sockets - Scripting: Fix empty receive calls returning unknown error on Windows Misc: diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 469b7e315..95549b0c8 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -915,8 +915,9 @@ void PainterGL::setShaders(struct VDir* dir) { mGLES2ShaderDetach(reinterpret_cast(m_backend)); mGLES2ShaderFree(&m_shader); } - mGLES2ShaderLoad(&m_shader, dir); - mGLES2ShaderAttach(reinterpret_cast(m_backend), static_cast(m_shader.passes), m_shader.nPasses); + if (mGLES2ShaderLoad(&m_shader, dir)) { + mGLES2ShaderAttach(reinterpret_cast(m_backend), static_cast(m_shader.passes), m_shader.nPasses); + } if (!m_started) { m_gl->doneCurrent(); From 622a6e9e2d4cd1eea336aa14edeeafa793e4ec3e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 16:13:35 -0800 Subject: [PATCH 10/31] GB Memory: Fix potential crash when directly accessing invalid SRAM --- src/gb/memory.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/gb/memory.c b/src/gb/memory.c index 5c4d97876..e6cdbdc54 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -474,13 +474,14 @@ uint8_t GBView8(struct SM83Core* cpu, uint16_t address, int segment) { if (memory->rtcAccess) { return memory->rtcRegs[memory->activeRtcReg]; } else if (memory->sramAccess) { - if (segment < 0 && memory->sram) { - return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; - } else if ((size_t) segment * GB_SIZE_EXTERNAL_RAM < gb->sramSize) { - return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM]; - } else { - return 0xFF; + if (memory->sram) { + if (segment < 0) { + return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; + } else if ((size_t) segment * GB_SIZE_EXTERNAL_RAM < gb->sramSize) { + return memory->sram[(address & (GB_SIZE_EXTERNAL_RAM - 1)) + segment *GB_SIZE_EXTERNAL_RAM]; + } } + return 0xFF; } else if (memory->mbcRead) { return memory->mbcRead(memory, address); } else if (memory->mbcType == GB_HuC3) { From e3983d333024b2a72b4fbf6a90dbd799cba5fa30 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 16:16:51 -0800 Subject: [PATCH 11/31] Core: Add missing va_end --- src/core/log.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/log.c b/src/core/log.c index 2d90fe05e..b7feca30c 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -88,6 +88,7 @@ void mLogExplicit(struct mLogger* context, int category, enum mLogLevel level, c if (!context->filter || mLogFilterTest(context->filter, category, level)) { context->log(context, category, level, format, args); } + va_end(args); } void mLogFilterInit(struct mLogFilter* filter) { From 064d6ce1837461ae3ea6b233868bf3289e6357f2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 20:11:26 -0800 Subject: [PATCH 12/31] GB: Fix potential double-free of non-pristine ROM memory --- src/gb/gb.c | 4 +++- src/gb/memory.c | 6 ++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/gb/gb.c b/src/gb/gb.c index a3a870f28..6e3b92b37 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -405,7 +405,9 @@ void GBUnloadROM(struct GB* gb) { if (gb->romVf) { #ifndef FIXED_ROM_BUFFER - gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize); + if (gb->isPristine && gb->memory.rom) { + gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->pristineRomSize); + } #endif gb->romVf->close(gb->romVf); gb->romVf = NULL; diff --git a/src/gb/memory.c b/src/gb/memory.c index e6cdbdc54..325761c1c 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -14,6 +14,7 @@ #include #include +#include mLOG_DEFINE_CATEGORY(GB_MEM, "GB Memory", "gb.memory"); @@ -1006,6 +1007,11 @@ void _pristineCow(struct GB* gb) { if (gb->memory.rom == gb->memory.romBase) { gb->memory.romBase = newRom; } + if (gb->romVf) { + gb->romVf->unmap(gb->romVf, gb->memory.rom, gb->memory.romSize); + gb->romVf->close(gb->romVf); + gb->romVf = NULL; + } gb->memory.rom = newRom; GBMBCSwitchBank(gb, gb->memory.currentBank); gb->isPristine = false; From bba57ce5307f7824e48c24893ca1176dce07a5e6 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 20:16:40 -0800 Subject: [PATCH 13/31] All: Fix handling of strncat bounds --- src/core/config.c | 6 +++--- src/feature/updater-main.c | 2 +- src/gb/core.c | 6 +++--- src/gba/core.c | 2 +- src/script/storage.c | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/core/config.c b/src/core/config.c index 6bfcb8e8b..715628f0f 100644 --- a/src/core/config.c +++ b/src/core/config.c @@ -169,14 +169,14 @@ void mCoreConfigDeinit(struct mCoreConfig* config) { #if !defined(MINIMAL_CORE) || MINIMAL_CORE < 2 bool mCoreConfigLoad(struct mCoreConfig* config) { - char path[PATH_MAX]; + char path[PATH_MAX + 1]; mCoreConfigDirectory(path, PATH_MAX); strncat(path, PATH_SEP "config.ini", PATH_MAX - strlen(path)); return mCoreConfigLoadPath(config, path); } bool mCoreConfigSave(const struct mCoreConfig* config) { - char path[PATH_MAX]; + char path[PATH_MAX + 1]; mCoreConfigDirectory(path, PATH_MAX); strncat(path, PATH_SEP "config.ini", PATH_MAX - strlen(path)); return mCoreConfigSavePath(config, path); @@ -304,7 +304,7 @@ void mCoreConfigPortablePath(char* out, size_t outLength) { CFRelease(suburl); } #endif - strncat(out, PATH_SEP "portable.ini", outLength - strlen(out)); + strncat(out, PATH_SEP "portable.ini", outLength - strlen(out) - 1); #endif } diff --git a/src/feature/updater-main.c b/src/feature/updater-main.c index bc29e5cd4..cd72fc4f3 100644 --- a/src/feature/updater-main.c +++ b/src/feature/updater-main.c @@ -114,7 +114,7 @@ int main(int argc, char* argv[]) { int ok = 1; mCoreConfigDirectory(bin, sizeof(bin)); - strncat(bin, "/updater.log", sizeof(bin)); + strncat(bin, "/updater.log", sizeof(bin) - 1); logfile = fopen(bin, "w"); mCoreConfigInit(&config, "updater"); diff --git a/src/gb/core.c b/src/gb/core.c index 7edb1a607..59fb7c016 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -607,16 +607,16 @@ static void _GBCoreReset(struct mCore* core) { switch (gb->model) { case GB_MODEL_DMG: case GB_MODEL_MGB: // TODO - strncat(path, PATH_SEP "gb_bios.bin", PATH_MAX - strlen(path)); + strncat(path, PATH_SEP "gb_bios.bin", PATH_MAX - strlen(path) - 1); break; case GB_MODEL_SGB: case GB_MODEL_SGB2: // TODO - strncat(path, PATH_SEP "sgb_bios.bin", PATH_MAX - strlen(path)); + strncat(path, PATH_SEP "sgb_bios.bin", PATH_MAX - strlen(path) - 1); break; case GB_MODEL_CGB: case GB_MODEL_AGB: case GB_MODEL_SCGB: - strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path)); + strncat(path, PATH_SEP "gbc_bios.bin", PATH_MAX - strlen(path) - 1); break; default: break; diff --git a/src/gba/core.c b/src/gba/core.c index c5f1946d6..50f0adf93 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -684,7 +684,7 @@ static void _GBACoreReset(struct mCore* core) { if (!found) { char path[PATH_MAX]; mCoreConfigDirectory(path, PATH_MAX); - strncat(path, PATH_SEP "gba_bios.bin", PATH_MAX - strlen(path)); + strncat(path, PATH_SEP "gba_bios.bin", PATH_MAX - strlen(path) - 1); bios = VFileOpen(path, O_RDONLY); if (bios && GBAIsBIOS(bios)) { found = true; diff --git a/src/script/storage.c b/src/script/storage.c index b1b740162..15946cce5 100644 --- a/src/script/storage.c +++ b/src/script/storage.c @@ -149,7 +149,7 @@ MAKE_SCALAR_SETTER(Bool, BOOL) void mScriptStorageGetBucketPath(const char* bucket, char* out) { mCoreConfigDirectory(out, PATH_MAX); - strncat(out, PATH_SEP "storage" PATH_SEP, PATH_MAX); + strncat(out, PATH_SEP "storage" PATH_SEP, PATH_MAX - 1); #ifdef _WIN32 // TODO: Move this to vfs somewhere WCHAR wout[MAX_PATH]; @@ -161,7 +161,7 @@ void mScriptStorageGetBucketPath(const char* bucket, char* out) { char suffix[STORAGE_LEN_MAX + 6]; snprintf(suffix, sizeof(suffix), "%s.json", bucket); - strncat(out, suffix, PATH_MAX); + strncat(out, suffix, PATH_MAX - 1); } static struct json_object* _tableToJson(struct mScriptValue* rootVal) { From bc048094b1d0406ac15163c7561ae1fc3cbeef21 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 20:27:51 -0800 Subject: [PATCH 14/31] Feature: Fix No-Intro cleanup on initial errors --- src/feature/sqlite3/no-intro.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/feature/sqlite3/no-intro.c b/src/feature/sqlite3/no-intro.c index d54e188ff..649364de6 100644 --- a/src/feature/sqlite3/no-intro.c +++ b/src/feature/sqlite3/no-intro.c @@ -17,7 +17,7 @@ struct NoIntroDB { }; struct NoIntroDB* NoIntroDBLoad(const char* path) { - struct NoIntroDB* db = malloc(sizeof(*db)); + struct NoIntroDB* db = calloc(1, sizeof(*db)); if (sqlite3_open_v2(path, &db->db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, NULL)) { goto error; @@ -60,9 +60,6 @@ struct NoIntroDB* NoIntroDBLoad(const char* path) { return db; error: - if (db->crc32) { - sqlite3_finalize(db->crc32); - } NoIntroDBDestroy(db); return NULL; @@ -285,8 +282,12 @@ bool NoIntroDBLoadClrMamePro(struct NoIntroDB* db, struct VFile* vf) { } void NoIntroDBDestroy(struct NoIntroDB* db) { - sqlite3_finalize(db->crc32); - sqlite3_close(db->db); + if (db->crc32) { + sqlite3_finalize(db->crc32); + } + if (db->db) { + sqlite3_close(db->db); + } free(db); } From a2072b67ba6b5b44c3e08cf27a8c7b2d18025d4b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 20:32:18 -0800 Subject: [PATCH 15/31] Core: Fix GBK string memory handling in .cht loading --- src/core/cheats.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/cheats.c b/src/core/cheats.c index 688b32ebe..60f73abcc 100644 --- a/src/core/cheats.c +++ b/src/core/cheats.c @@ -489,8 +489,10 @@ bool mCheatParseEZFChtFile(struct mCheatDevice* device, struct VFile* vf) { return false; } char* name = gbkToUtf8(&cheat[1], end - cheat - 1); - strncpy(cheatName, name, sizeof(cheatName) - 1); - free(name); + if (name) { + strncpy(cheatName, name, sizeof(cheatName) - 1); + free(name); + } cheatNameLength = strlen(cheatName); continue; } @@ -501,7 +503,10 @@ bool mCheatParseEZFChtFile(struct mCheatDevice* device, struct VFile* vf) { } if (strncmp(cheat, "ON", eq - cheat) != 0) { char* subname = gbkToUtf8(cheat, eq - cheat); - snprintf(&cheatName[cheatNameLength], sizeof(cheatName) - cheatNameLength - 1, ": %s", subname); + if (subname) { + snprintf(&cheatName[cheatNameLength], sizeof(cheatName) - cheatNameLength - 1, ": %s", subname); + free(subname); + } } set = device->createSet(device, cheatName); set->enabled = false; From cd4dbaeb60570ddcef4a52dfb8e7a0bd5b472d2a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 21:02:49 -0800 Subject: [PATCH 16/31] Feature: Initialize z_stream more cleanly --- src/feature/video-logger.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/feature/video-logger.c b/src/feature/video-logger.c index ae2fa046e..fb2065b42 100644 --- a/src/feature/video-logger.c +++ b/src/feature/video-logger.c @@ -382,10 +382,7 @@ static void _copyVf(struct VFile* dest, struct VFile* src) { static void _compress(struct VFile* dest, struct VFile* src) { uint8_t writeBuffer[0x800]; uint8_t compressBuffer[0x400]; - z_stream zstr; - zstr.zalloc = Z_NULL; - zstr.zfree = Z_NULL; - zstr.opaque = Z_NULL; + z_stream zstr = {0}; zstr.avail_in = 0; zstr.avail_out = sizeof(compressBuffer); zstr.next_out = (Bytef*) compressBuffer; @@ -425,10 +422,7 @@ static void _compress(struct VFile* dest, struct VFile* src) { static bool _decompress(struct VFile* dest, struct VFile* src, size_t compressedLength) { uint8_t fbuffer[0x400]; uint8_t zbuffer[0x800]; - z_stream zstr; - zstr.zalloc = Z_NULL; - zstr.zfree = Z_NULL; - zstr.opaque = Z_NULL; + z_stream zstr = {0}; zstr.avail_in = 0; zstr.avail_out = sizeof(zbuffer); zstr.next_out = (Bytef*) zbuffer; From 7d014f1ae6b021b379cdf8c05be095b91b5da209 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 22:51:48 -0800 Subject: [PATCH 17/31] Core: Negative log types are invalid --- src/core/log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/log.c b/src/core/log.c index b7feca30c..5fe2fe9ee 100644 --- a/src/core/log.c +++ b/src/core/log.c @@ -50,7 +50,7 @@ const char* mLogCategoryName(int category) { } const char* mLogCategoryId(int category) { - if (category < MAX_CATEGORY) { + if (category >= 0 && category < MAX_CATEGORY) { return _categoryIds[category]; } return NULL; From 222d48efe718d16e117284073e2f99d3501398e4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 22:52:05 -0800 Subject: [PATCH 18/31] Qt: Initialize log-to members --- src/platform/qt/LogController.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/LogController.h b/src/platform/qt/LogController.h index 548be8b4d..6bd4e5707 100644 --- a/src/platform/qt/LogController.h +++ b/src/platform/qt/LogController.h @@ -79,8 +79,8 @@ public slots: private: mLogFilter m_filter; - bool m_logToFile; - bool m_logToStdout; + bool m_logToFile = false; + bool m_logToStdout = false; std::unique_ptr m_logFile; std::unique_ptr m_logStream; From 54b9fbd8815a5d0ecf501ec88d6c097d9cae1d18 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 22:52:23 -0800 Subject: [PATCH 19/31] GBA SIO: Who wrote this code? Oh, me --- src/gba/sio/lockstep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gba/sio/lockstep.c b/src/gba/sio/lockstep.c index 3ea1b5cc9..8e641c539 100644 --- a/src/gba/sio/lockstep.c +++ b/src/gba/sio/lockstep.c @@ -463,7 +463,7 @@ static void _GBASIOLockstepNodeProcessEvents(struct mTiming* timing, void* user, struct GBASIOLockstepNode* node = user; mLockstepLock(&node->p->d); - int32_t cycles = cycles = node->nextEvent; + int32_t cycles = node->nextEvent; node->nextEvent -= cyclesLate; node->eventDiff += cyclesLate; if (node->p->d.attached < 2) { From f45b4e3ef0a8f21fc06d1c063e543353e8301c76 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 23:05:28 -0800 Subject: [PATCH 20/31] Qt: Initialize Shortcut::m_direction --- src/platform/qt/ShortcutController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ShortcutController.h b/src/platform/qt/ShortcutController.h index 7eed7e1d7..6e72649b5 100644 --- a/src/platform/qt/ShortcutController.h +++ b/src/platform/qt/ShortcutController.h @@ -57,7 +57,7 @@ private: int m_shortcut = 0; int m_button = -1; int m_axis = -1; - GamepadAxisEvent::Direction m_direction; + GamepadAxisEvent::Direction m_direction = GamepadAxisEvent::NEUTRAL; }; class ShortcutController : public QObject { From 001135ef914ae158620bd9a5c9139f6768be9b57 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 1 Mar 2023 23:11:23 -0800 Subject: [PATCH 21/31] Qt: Better fps non-zero division check --- src/platform/qt/Window.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 6003b88a3..02f8459cf 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1138,14 +1138,14 @@ void Window::recordFrame() { } void Window::showFPS() { - if (m_frameList.isEmpty()) { - updateTitle(); - return; - } qint64 total = 0; for (qint64 t : m_frameList) { total += t; } + if (!total) { + updateTitle(); + return; + } double fps = (m_frameList.size() * 1e10) / total; m_frameList.clear(); fps = round(fps) / 10.f; From e06fa02d14b44fe321b6be3a6122ac973a6d22c1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Mar 2023 20:28:48 -0800 Subject: [PATCH 22/31] Util: Fix potential socket leak --- include/mgba-util/socket.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mgba-util/socket.h b/include/mgba-util/socket.h index 9f07491bd..96edc3d92 100644 --- a/include/mgba-util/socket.h +++ b/include/mgba-util/socket.h @@ -204,6 +204,7 @@ static inline Socket SocketOpenTCP(int port, const struct Address* bindAddress) err = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)); #endif if (err) { + SocketCloseQuiet(sock); return INVALID_SOCKET; } From 077aa04f48056857ef66745eb795deddcd17cff2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Mar 2023 20:31:11 -0800 Subject: [PATCH 23/31] Qt: Fix potential directory handle leak --- src/platform/qt/Display.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/Display.cpp b/src/platform/qt/Display.cpp index 704f9463a..fcbec86bc 100644 --- a/src/platform/qt/Display.cpp +++ b/src/platform/qt/Display.cpp @@ -113,9 +113,9 @@ void QGBA::Display::configure(ConfigController* config) { config->updateOption("showOSD"); config->updateOption("showFrameCounter"); #if defined(BUILD_GL) || defined(BUILD_GLES2) || defined(BUILD_GLES3) - if (opts->shader) { + if (opts->shader && supportsShaders()) { struct VDir* shader = VDirOpen(opts->shader); - if (shader && supportsShaders()) { + if (shader) { setShaders(shader); shader->close(shader); } From ceb66b133f94d9db1a637e6dde9bcbe81c36cff1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Mar 2023 20:38:59 -0800 Subject: [PATCH 24/31] VFS: Improve zip invariant handling --- src/util/vfs/vfs-zip.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/util/vfs/vfs-zip.c b/src/util/vfs/vfs-zip.c index 2f8234b94..65e1c1e32 100644 --- a/src/util/vfs/vfs-zip.c +++ b/src/util/vfs/vfs-zip.c @@ -309,6 +309,9 @@ ssize_t _vfzRead(struct VFile* vf, void* buffer, size_t size) { if (!vfz->buffer) { vfz->bufferSize = BLOCK_SIZE; vfz->buffer = malloc(BLOCK_SIZE); + if (vfz->readSize) { + abort(); + } } while (bytesRead < size) { @@ -714,7 +717,7 @@ struct VFile* _vdzOpenFile(struct VDir* vd, const char* path, int mode) { } } - struct VFileZip* vfz = malloc(sizeof(struct VFileZip)); + struct VFileZip* vfz = calloc(1, sizeof(struct VFileZip)); vfz->uz = vdz->uz; vfz->z = vdz->z; vfz->buffer = 0; From 30fc0007347748b682ed19a9f027e370327f9c17 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 2 Mar 2023 21:28:16 -0800 Subject: [PATCH 25/31] Scripting: Fix potential crash if a bucket can't be opened --- src/script/storage.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/script/storage.c b/src/script/storage.c index 15946cce5..e1299d53e 100644 --- a/src/script/storage.c +++ b/src/script/storage.c @@ -307,6 +307,9 @@ bool mScriptStorageBucketFlush(struct mScriptStorageBucket* bucket) { char path[PATH_MAX]; mScriptStorageGetBucketPath(bucket->name, path); struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + return false; + } return _mScriptStorageBucketFlushVF(bucket, vf); } @@ -329,6 +332,9 @@ bool mScriptStorageSaveBucket(struct mScriptContext* context, const char* bucket char path[PATH_MAX]; mScriptStorageGetBucketPath(bucketName, path); struct VFile* vf = VFileOpen(path, O_WRONLY | O_CREAT | O_TRUNC); + if (!vf) { + return false; + } return mScriptStorageSaveBucketVF(context, bucketName, vf); } From 59ebf1c12dcbbe0141000cddccf667cd42e386a1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Mar 2023 00:17:08 -0800 Subject: [PATCH 26/31] GB Video: Implement DMG-style sprite ordering --- CHANGES | 1 + cinema/gb/acid/cgb-acid2/baseline_0000.png | Bin 0 -> 1362 bytes cinema/gb/acid/cgb-acid2/test.gbc | Bin 0 -> 32768 bytes cinema/gb/acid/config.ini | 6 ++++ cinema/gb/acid/dmg-acid2/baseline_0000.png | Bin 0 -> 1360 bytes cinema/gb/acid/dmg-acid2/test.gb | Bin 0 -> 32768 bytes .../sprite_priority/baseline_0000.png | Bin 702 -> 703 bytes .../sprite_priority/xbaseline_0000.png | Bin 711 -> 0 bytes src/gb/renderers/software.c | 30 ++++++++++++++---- 9 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 cinema/gb/acid/cgb-acid2/baseline_0000.png create mode 100644 cinema/gb/acid/cgb-acid2/test.gbc create mode 100644 cinema/gb/acid/config.ini create mode 100644 cinema/gb/acid/dmg-acid2/baseline_0000.png create mode 100644 cinema/gb/acid/dmg-acid2/test.gb delete mode 100644 cinema/gb/mooneye-gb/manual-only/sprite_priority/xbaseline_0000.png diff --git a/CHANGES b/CHANGES index ffda80576..169a69a15 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Features: - New unlicensed GB mappers: NT (older types 1 and 2), Li Cheng, GGB-81 - Debugger: Add range watchpoints Emulation fixes: + - GB Video: Implement DMG-style sprite ordering - GBA Audio: Fix improperly deserializing GB audio registers (fixes mgba.io/i/2793) - GBA Memory: Make VRAM access stalls only apply to BG RAM - GBA SIO: Fix SIOCNT SI pin value after attaching player 2 (fixes mgba.io/i/2805) diff --git a/cinema/gb/acid/cgb-acid2/baseline_0000.png b/cinema/gb/acid/cgb-acid2/baseline_0000.png new file mode 100644 index 0000000000000000000000000000000000000000..4baff34257e5a33acb5b125d16ffa5dea6b3be52 GIT binary patch literal 1362 zcmeAS@N?(olHy`uVBq!ia0vp^3xIe62NRHFxc>b*0|Tq1r;B4q#hkZu4pu%^5O8b% zyG=`eGT$AiK0nKohPpeLpTF3)g*|7cYl8z*=9ka=_1jyfwhQ_zGk?0pb67$5=bzYr zx7KejklAi~qqW?@&n`ayp~b<+d%s1@yUZ+_IUlf#{H+iYJK0`apL8d_}?WPa=h1WJk?Xb|MXwI<-v{5-d@zcvGsM|1B+kp zw&uSVJ{D3iNAmu%6j^Ui&HSFYgPgm|UYtF@`huM9u{9+zBKJ$zgl)LwIjy$+b4TyL zAJ2miAM(3?gkNn9lPJC{``3U`SCvo)Yb?rZCc**bgDpR-I+&9d9wBT ze9AL)oL441{cbz`fs-G<7whV|Q;r49-Vk)~)0)o0vMh1+V>2Eq@8XfNW80k&yCEn_ z?EbRl+iF}lCs;f3-doztCzRxMvVVQOy7%w6E!&?;-|hGzactkLoRXGD;<@hcw~DWg zEzo!%aqzxZjPSP78oQhmsSUPB@bXNeAbm{8{L0;F-E|saRi9iW1aLAo|c>SOXuQnnR zWO1$A`d+@r*ld=1>E(j>P?4H#yKlC17iqiR-Tubo6Jwv@`po^mt3`7T?CM{>N@dS8 z6K;TWZ+G=I@7yWr7cHbRiF00Qm4i{cQuqgxwF!$h zKemuQB7Og5=hHb4A1(UG$M@`+oN;bs!|I#77S;-ufAw~{KA+zoUH|Uu4vUut`zP`?c(PL9(%xBFM#Ta)(L<4Vb|^O@os zvoep literal 0 HcmV?d00001 diff --git a/cinema/gb/acid/cgb-acid2/test.gbc b/cinema/gb/acid/cgb-acid2/test.gbc new file mode 100644 index 0000000000000000000000000000000000000000..5f71bd36060b46eefcf7785f81ce16a5a6c5fc67 GIT binary patch literal 32768 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 literal 0 HcmV?d00001 diff --git a/cinema/gb/acid/dmg-acid2/test.gb b/cinema/gb/acid/dmg-acid2/test.gb new file mode 100644 index 0000000000000000000000000000000000000000..a25ef9485e1ab176c80415548f053ca950b3e4f5 GIT binary patch literal 32768 zcmeI4e`s6R700iB*s@&zcyg5DQDaNSPSdg!FIkCFwCCqvjqIhxGgD&v&r~;4#AY(Z zra?)?ldO!AnBqAJ+iXbVtbt}TrD+EnjI_nAsT<)R>0g7eW_=`?&0t%!xH!%%-rc$P zzGumDvi;MI(Vg>ndiQ(JdFP({xli}M_XzoN?9X3Ln*V;5>2AxyU&GQ0^_6`#!=Uc7PR`uLSAhh92d@t3(9pN&sk`Q0wL{kgq6TG~3>cNSJV@vCnx ze}i6|-xrv#33%Trb`jk&O6Io&yvg&jRN=1omwVQpx?nWCn$?vYvk)r_(CjX9&Z6*O zPmxO*Guojd7fD(q3yXoVcDSNb5dArsne^2|iSD~{j>}P@fEV3W{vQ{aVXdPaUwYYTcD5=h}-dAM_x^`Hv zGchy!H@OL ziM&iZ^K9KON$br#x6|yjfSK*hev8ElW=3rCb1#qJDGL4Iwq3AV&Geh^%8|H}WsMa{ck zR15{=_2oC$i#8gx&OtY_Y&avoNv8~zG z*c{m;GELbUT1joJ&#~fItek81(F{a`WwV)OZArT`_4(B2-Q9MnyVu^-+imae?X^dJ z%EeJdx%jCs1lQ2TPo?bvA~k)VNWOj|DR2gUM5NvWL<+$*GC-s#^u-Pm2{zS;uZ%>L zG9?m#vm4IdawQUiGXiI{ob-IlNqYRHq^F;qPU3r}h$zn#6W`$?k8-%!6Z>vu-sDTb zUU?<21DbpHZq$Y9)~#GmNeLliV>!KLi`$*aa+HJ$@ktH8cKqR2)Fx-FWm0sWuXY^>~uOiJI|dnHKXQs z-@9jOao^OGsXMsEVy2e3WipbaX{^s>nCZ9M{r>iLzu(l1+L<#izG!N8RTQ&2LYRMe z_{b5{|HKp9!LD94b!TS_SX-N^>+Ah~k0)2Z*>7G&eWj&Nr`>L|v3;(k#bPNfy?fVg zudWs~o3VIB0!RP}AOR$R1dsp{Kmter2_OL^fCP{L5*^Akz0x=`l1kmYDfH7%cXTv1Zryt5kkH|9Fc=QEg9*KD zTQInPe=ykCDD>c9LqmPN*K59Q$=;o0Z8Z8JFPv6P!z+DIKS0p*IazcwIRj*JnU~3}-r#AS9Pxfn=_#mon%xtR$J?P2_U!ZghJTrl3G?B4oc`U6H~6IVyR}ud zwY=Vxex9D7_vr~%ud3=Fac$%WK11|=rIR1<`mm92+RT?o&<~;gVd5A>fZyQ7|AlP6 zrZ)N1)g_M5PqOFeCy66D=@WwJ~JwK>mPyd zG{p1qz|Zbwqw(?h+J*fMtP1{ov6;YHXK!bJoXwigm;Nd|Pdq-8fxK{-CeUee0?S$##moIKe1Qx=f#-MdVWJs z!)##p z>a+3q`hKv!U&%7;ZVRhp`T{%=G9mE1rs-Ms&wQ|D+VxS-Kho^WF6z~J5}5rU{bbda zM`G`KR@3n1nQEJhjCzS;Atmrdne>5r@ErHtPuG`wvgwK+R9h<|E6JN>Pu?u@tfl82 zfy-Kp)&`%LxvF)*M`mtodoO$8^EJdX|5N~4dc}qL-2wSKnv$l8-|YY4jtAF-y+{BF zAOR$R1dsp{Kmter2_OL^fCP{L5xg88td#JK|n)1Nz+9g%S6IIDjs=}w*FHomy2 z{BPIh=Pj4nQ|VP~z4-C`cjqO2+0M1^yI*9yIyfI(* z#(tfcWq0Mym9(e#emwj2>t*q6OVj(!4{P`lL9oL+qju^J9q+ibny4R9^9~|{=Xv?X z0%U%A0xY=x*-M-=28A0aC^>*(`KR7sPC76$DkcjsnTXwym5-MelPPLC!~g`Iu6{1- HoD!M<*n{Xy delta 459 zcmV;+0W|)<1-=E4Br}CcL_t(|+U?p=a)K}b0MVr5eeo#XIDTYIGbBWab}Z|@FN%R8 zD~L)=DFt!;e0l@)x03+^Auqd>sq6KcCvLafr?*P)lTu14Ez6P~>S>*wr)W3>!xO_6MwkN^pY{g5JLBhuo%~0kmbQy{m|C@?t1FMt3|r&IXeF7 z_MFjV;Iiw-Emwob%RbE+cE6t5!S$HA?K!EL!1XgvDXn%yo>PzC+H2#w?RvtS&IGG9 z11b*8pQ4Z2I;FSs_Z*So;A>@T!TQhcOX}=qF0$$!vGY8ZhjmZpWq*FXb7PG8&(+MM zn|ky#Ti@*R(tiCn=HF(IVy8U%%Ej8C?)O||5w0UN;OAht$-w3Qo-)yWbTFr# zS+BFUXZ+S`5B=Xg+k86nr|A6r+Z(vrd%M~_)qSYDs@2S`@!k3D;&bacHQ$5bd=G{* zFr0zm3=C&rxJ&4Ll^eJ$OPOYTTKHNX!EgqKGccTi;S3DtchPVj!IO~!6czp+4CfIH zXJ9x3!xb*0|Qf^r;B4q#hkad0*jgq7#J=t zdCa+2JSd1XdUD+#}M?WUzGM4RDV{av3`xL>Mom@sD% znr^Uxdj0J=9foZJyW(4pM$|h_V^4qT9DRECYfbiW|Cj5YzxdI9yVz}V(E4^0U60G#Jtjk{C`+D1J&UzE!kZiUPnHlpJ_1~Ix z>Gsp=z7qu>_HO!m-o=}if{dE`{RmD6T+x-_nRN0@Nq;J emKYo$p?!?nozi0Sr7|yq5~!!EpUXO@geCyFDmo?r diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index a5e41162f..d157920fa 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -571,20 +571,38 @@ static void _cleanOAM(struct GBVideoSoftwareRenderer* renderer, int y) { } int o = 0; int i; + int16_t ids[GB_VIDEO_MAX_LINE_OBJ]; for (i = 0; i < GB_VIDEO_MAX_OBJ && o < GB_VIDEO_MAX_LINE_OBJ; ++i) { uint8_t oy = renderer->d.oam->obj[i].y; if (y < oy - 16 || y >= oy - 16 + spriteHeight) { continue; } - // TODO: Sort - renderer->obj[o].obj = renderer->d.oam->obj[i]; - renderer->obj[o].index = i; + ids[o] = (renderer->d.oam->obj[i].x << 7) | i; ++o; - if (o == 10) { - break; - } } renderer->objMax = o; + if (renderer->model < GB_MODEL_CGB) { + // Terrble n^2 sort, but it's only 10 elements so it shouldn't be that bad + int16_t ids2[GB_VIDEO_MAX_LINE_OBJ]; + int min = -1; + int j; + for (i = 0; i < o; ++i) { + int min2 = 0xFFFF; + for (j = 0; j < o; ++j) { + if (ids[j] > min && ids[j] < min2) { + min2 = ids[j]; + } + } + min = min2; + ids2[i] = min; + } + memcpy(ids, ids2, sizeof(ids)); + } + for (i = 0; i < o; ++i) { + int id = ids[i] & 0x7F; + renderer->obj[i].obj = renderer->d.oam->obj[id]; + renderer->obj[i].index = id; + } } static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, int startX, int endX, int y) { From 89f8873df366a99dfdf40347f72e68763fb50bd9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Mar 2023 14:21:47 -0800 Subject: [PATCH 27/31] GBA Saveata: Fix fumbled check --- 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 7097e4a63..2d377a875 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -184,7 +184,7 @@ size_t GBASavedataSize(const struct GBASavedata* savedata) { bool GBASavedataLoad(struct GBASavedata* savedata, struct VFile* in) { if (savedata->data) { - if (!in || savedata->type != SAVEDATA_FORCE_NONE) { + if (!in || savedata->type == SAVEDATA_FORCE_NONE) { return false; } ssize_t size = GBASavedataSize(savedata); From a7c232b2841af19eb66c619d1e06361696494de8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Mar 2023 23:55:54 -0800 Subject: [PATCH 28/31] Qt: Fix black screen when starting with a game (fixes #2781) --- CHANGES | 1 + src/platform/qt/DisplayGL.cpp | 18 +++++++++++++++++- src/platform/qt/DisplayGL.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 169a69a15..11e7601df 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Other fixes: - Qt: Fix a handful of edge cases with graphics viewers (fixes mgba.io/i/2827) - Qt: Fix full-buffer rewind - Qt: Fix crash if loading a shader fails + - Qt: Fix black screen when starting with a game (fixes mgba.io/i/2781) - Scripting: Fix receiving packets for client sockets - Scripting: Fix empty receive calls returning unknown error on Windows Misc: diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 95549b0c8..acc001f9a 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -48,6 +48,11 @@ using QOpenGLFunctions_Baseline = QOpenGLFunctions_3_2_Core; using namespace QGBA; +enum ThreadStartFrom { + START = 1, + PROXY = 2, +}; + QHash DisplayGL::s_supports; uint qHash(const QSurfaceFormat& format, uint seed) { @@ -235,7 +240,16 @@ void DisplayGL::startDrawing(std::shared_ptr controller) { messagePainter()->resize(size(), devicePixelRatio()); #endif - CoreController::Interrupter interrupter(controller); + startThread(ThreadStartFrom::START); +} + +void DisplayGL::startThread(int from) { + m_threadStartPending |= from; + if (m_threadStartPending < 3) { + return; + } + + CoreController::Interrupter interrupter(m_context); QMetaObject::invokeMethod(m_painter.get(), "start"); if (!m_gl) { if (shouldDisableUpdates()) { @@ -310,6 +324,7 @@ void DisplayGL::stopDrawing() { hide(); } setUpdatesEnabled(true); + m_threadStartPending &= ~1; } m_context.reset(); } @@ -435,6 +450,7 @@ void DisplayGL::setupProxyThread() { #if defined(_WIN32) && defined(USE_EPOXY) epoxy_handle_external_wglMakeCurrent(); #endif + QMetaObject::invokeMethod(this, "startThread", Q_ARG(int, ThreadStartFrom::PROXY)); }); connect(m_painter.get(), &PainterGL::texSwapped, m_proxyContext.get(), [this]() { if (!m_context->hardwareAccelerated()) { diff --git a/src/platform/qt/DisplayGL.h b/src/platform/qt/DisplayGL.h index 3ed31a9d8..a0c0c17d4 100644 --- a/src/platform/qt/DisplayGL.h +++ b/src/platform/qt/DisplayGL.h @@ -113,6 +113,7 @@ protected: virtual void resizeEvent(QResizeEvent*) override; private slots: + void startThread(int); void setupProxyThread(); private: @@ -123,6 +124,7 @@ private: bool m_isDrawing = false; bool m_hasStarted = false; + int m_threadStartPending = 0; std::unique_ptr m_painter; QThread m_drawThread; QThread m_proxyThread; From 5265573c0c2f9ac0b1480eed86ac36548a039db0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Mar 2023 00:08:41 -0800 Subject: [PATCH 29/31] Qt: Fix buffer termination issue --- src/platform/qt/CoreManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/platform/qt/CoreManager.cpp b/src/platform/qt/CoreManager.cpp index cac1c2560..7bd6bd309 100644 --- a/src/platform/qt/CoreManager.cpp +++ b/src/platform/qt/CoreManager.cpp @@ -16,6 +16,7 @@ #endif #include +#include #include using namespace QGBA; @@ -161,7 +162,7 @@ CoreController* CoreManager::loadBIOS(int platform, const QString& path) { mCoreConfigSetOverrideIntValue(&core->config, "skipBios", 0); QByteArray bytes(info.baseName().toUtf8()); - strncpy(core->dirs.baseName, bytes.constData(), sizeof(core->dirs.baseName)); + strlcpy(core->dirs.baseName, bytes.constData(), sizeof(core->dirs.baseName)); bytes = info.dir().canonicalPath().toUtf8(); mDirectorySetAttachBase(&core->dirs, VDirOpen(bytes.constData())); From 7386e60ac0367337ede01d72cf8acf649127208b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Mar 2023 14:51:22 -0800 Subject: [PATCH 30/31] GDB: Enable NODELAY on GDB stub connections --- src/debugger/gdb-stub.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index ca8c0d1ec..d83c6a3ab 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -846,6 +846,7 @@ void GDBStubUpdate(struct GDBStub* stub) { } else { goto connectionLost; } + SocketSetTCPPush(stub->connection); } while (true) { if (stub->shouldBlock) { From fe8b436b41244fd52ac001dcad319aef327d238d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Mar 2023 14:57:05 -0800 Subject: [PATCH 31/31] GDB: Ugh --- src/debugger/gdb-stub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index d83c6a3ab..6c318179c 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -846,7 +846,7 @@ void GDBStubUpdate(struct GDBStub* stub) { } else { goto connectionLost; } - SocketSetTCPPush(stub->connection); + SocketSetTCPPush(stub->connection, 1); } while (true) { if (stub->shouldBlock) {