From 8f1148498e12197745f62e477d9b8e07382cc72e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 18 Jun 2020 01:25:48 -0700 Subject: [PATCH 01/51] GB Core: Fix extracting SRAM when none is present --- CHANGES | 1 + src/gb/core.c | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 006db1256..7b5f316e5 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Other fixes: - All: Improve export headers (fixes mgba.io/i/1738) - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached + - GB Core: Fix extracting SRAM when none is present - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) Misc: diff --git a/src/gb/core.c b/src/gb/core.c index 7ee5828dd..8dee77ce3 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -822,9 +822,13 @@ static size_t _GBCoreSavedataClone(struct mCore* core, void** sram) { vf->seek(vf, 0, SEEK_SET); return vf->read(vf, *sram, vf->size(vf)); } - *sram = malloc(gb->sramSize); - memcpy(*sram, gb->memory.sram, gb->sramSize); - return gb->sramSize; + if (gb->sramSize) { + *sram = malloc(gb->sramSize); + memcpy(*sram, gb->memory.sram, gb->sramSize); + return gb->sramSize; + } + *sram = NULL; + return 0; } static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t size, bool writeback) { From 2f2908240178cd418acc6e4942ad9b78939b85a5 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 18 Jun 2020 01:26:54 -0700 Subject: [PATCH 02/51] GBA Savedata: Fix extracting save when not yet configured in-game --- CHANGES | 1 + src/gba/savedata.c | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 7b5f316e5..2137b5509 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,7 @@ Other fixes: - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached - GB Core: Fix extracting SRAM when none is present + - GBA Savedata: Fix extracting save when not yet configured in-game - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) Misc: diff --git a/src/gba/savedata.c b/src/gba/savedata.c index 0c8207b3a..954d5b218 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -139,6 +139,7 @@ bool GBASavedataClone(struct GBASavedata* savedata, struct VFile* out) { } else if (savedata->vf) { off_t read = 0; uint8_t buffer[2048]; + savedata->vf->seek(savedata->vf, 0, SEEK_SET); do { read = savedata->vf->read(savedata->vf, buffer, sizeof(buffer)); out->write(out, buffer, read); From 3f818f07352bed795b80b6f447d8ae7c2eb82522 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 18 Jun 2020 01:31:52 -0700 Subject: [PATCH 03/51] Core: Warn when savedata fails to load from state --- src/core/serialize.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/serialize.c b/src/core/serialize.c index 5113980ec..ed99107dd 100644 --- a/src/core/serialize.c +++ b/src/core/serialize.c @@ -450,7 +450,9 @@ bool mCoreLoadStateNamed(struct mCore* core, struct VFile* vf, int flags) { if (mStateExtdataGet(&extdata, EXTDATA_SAVEDATA, &item)) { mLOG(SAVESTATE, INFO, "Loading savedata"); if (item.data) { - core->savedataRestore(core, item.data, item.size, flags & SAVESTATE_SAVEDATA); + if (!core->savedataRestore(core, item.data, item.size, flags & SAVESTATE_SAVEDATA)) { + mLOG(SAVESTATE, WARN, "Failed to load savedata from savestate"); + } } } struct mCheatDevice* device; From aed783e1f7e5f89c4d556ead59e7dead97fb5625 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 20 Jun 2020 03:00:44 -0700 Subject: [PATCH 04/51] Qt: Add per-page scrolling to memory view (fixes #1795) --- CHANGES | 1 + src/platform/qt/MemoryModel.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/CHANGES b/CHANGES index 2137b5509..bcc2b9b58 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ Misc: - Qt: Renderer can be changed while a game is running - Qt: Add hex index to palette view - Qt: Add transformation matrix info to sprite view + - Qt: Add per-page scrolling to memory view (fixes mgba.io/i/1795) 0.8.2: (2020-06-14) Emulation fixes: diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index 98d743067..856592a30 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -93,6 +93,10 @@ MemoryModel::MemoryModel(QWidget* parent) ++m_top; } else if (action == QSlider::SliderSingleStepSub) { --m_top; + } else if (action == QSlider::SliderPageStepAdd) { + m_top += (viewport()->size().height() - m_cellHeight) / m_cellHeight; + } else if (action == QSlider::SliderPageStepSub) { + m_top -= (viewport()->size().height() - m_cellHeight) / m_cellHeight; } else { return; } @@ -590,6 +594,12 @@ void MemoryModel::keyPressEvent(QKeyEvent* event) { case Qt::Key_Down: adjustCursor(16, event->modifiers() & Qt::ShiftModifier); return; + case Qt::Key_PageUp: + adjustCursor(-16 * ((viewport()->size().height() - m_cellHeight) / m_cellHeight), event->modifiers() & Qt::ShiftModifier); + return; + case Qt::Key_PageDown: + adjustCursor(16 * ((viewport()->size().height() - m_cellHeight) / m_cellHeight), event->modifiers() & Qt::ShiftModifier); + return; default: return; } From 5ef12b597973c00804a60e303ce50753f46faffc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 20 Jun 2020 03:02:27 -0700 Subject: [PATCH 05/51] All: Correct format strings for some numbers on Windows (fixes #1794) --- CHANGES | 1 + include/mgba-util/common.h | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index bcc2b9b58..ce92bd976 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Emulation fixes: - SM83: Emulate HALT bug Other fixes: - All: Improve export headers (fixes mgba.io/i/1738) + - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached - GB Core: Fix extracting SRAM when none is present diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index a80fbb5c6..0f4a991bb 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -115,10 +115,8 @@ typedef intptr_t ssize_t; #if defined(_3DS) || defined(GEKKO) || defined(PSP2) // newlib doesn't support %z properly by default #define PRIz "" -#elif defined(_WIN64) -#define PRIz "I64" -#elif defined(_WIN32) -#define PRIz "" +#elif defined(_MSC_VER) +#define PRIz "I" #else #define PRIz "z" #endif From dd4619db61d165bc7737f46acd0c93464b0192bb Mon Sep 17 00:00:00 2001 From: Arves100 Date: Tue, 16 Jun 2020 13:13:57 +0200 Subject: [PATCH 06/51] GBA: Fix msvc compilation --- src/gba/ereader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gba/ereader.c b/src/gba/ereader.c index f624c3221..e288f78c6 100644 --- a/src/gba/ereader.c +++ b/src/gba/ereader.c @@ -288,7 +288,7 @@ static void _eReaderAddress(uint8_t* origin, int a) { } static void _eReaderReedSolomon(const uint8_t* input, uint8_t* output) { - uint8_t rsBuffer[64] = {}; + uint8_t rsBuffer[64] = { 0 }; int i; for (i = 0; i < 48; ++i) { rsBuffer[63 - i] = input[i]; From 0230e654a30643c9035007adc3fb323a12405885 Mon Sep 17 00:00:00 2001 From: Mathew Horner Date: Wed, 24 Jun 2020 01:20:42 -0500 Subject: [PATCH 07/51] Qt: Setting to show filename in title bar instead of ROM name. (#1807) * All: Setting to display the file name of the currently loaded ROM instead of the game name in the title bar (closes mgba.io/i/1784) * Utilize ConfigController getOption method and restructured to not use dynamically allocated memory for the temporary title * Grab actual path name, use getOption to avoid having to modify the core, update CHANGES file, and moved core declaration to condense code. * Change CHANGES text * Qt: Simplify settings UI for PR Co-authored-by: Vicki Pfau --- CHANGES | 1 + src/platform/qt/SettingsView.cpp | 2 ++ src/platform/qt/SettingsView.ui | 26 ++++++++++++++++++-------- src/platform/qt/Window.cpp | 23 +++++++++++++++-------- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index ce92bd976..76087f076 100644 --- a/CHANGES +++ b/CHANGES @@ -36,6 +36,7 @@ Misc: - Qt: Add hex index to palette view - Qt: Add transformation matrix info to sprite view - Qt: Add per-page scrolling to memory view (fixes mgba.io/i/1795) + - Qt: Add setting to display ROM filename in title (closes mgba.io/i/1784) 0.8.2: (2020-06-14) Emulation fixes: diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index 510528a12..4eb99c55e 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -400,6 +400,7 @@ void SettingsView::updateConfig() { saveSetting("showFps", m_ui.showFps); saveSetting("cheatAutoload", m_ui.cheatAutoload); saveSetting("cheatAutosave", m_ui.cheatAutosave); + saveSetting("showFilename", m_ui.showFilename); saveSetting("autoload", m_ui.autoload); saveSetting("autosave", m_ui.autosave); saveSetting("logToFile", m_ui.logToFile); @@ -574,6 +575,7 @@ void SettingsView::reloadConfig() { loadSetting("showFps", m_ui.showFps, true); loadSetting("cheatAutoload", m_ui.cheatAutoload, true); loadSetting("cheatAutosave", m_ui.cheatAutosave, true); + loadSetting("showFilename", m_ui.showFilename, false); loadSetting("autoload", m_ui.autoload, true); loadSetting("autosave", m_ui.autosave, false); loadSetting("logToFile", m_ui.logToFile); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 0847639a7..0dfb884d2 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -586,21 +586,21 @@ - + Enable Discord Rich Presence - + Qt::Horizontal - + Automatically save state @@ -610,7 +610,7 @@ - + Automatically load state @@ -620,14 +620,14 @@ - + Qt::Horizontal - + Automatically save cheats @@ -637,7 +637,7 @@ - + Automatically load cheats @@ -647,7 +647,7 @@ - + Show OSD messages @@ -657,6 +657,16 @@ + + + + Show filename instead of ROM name in title bar + + + true + + + diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 8b0b6e2c3..c139ebf31 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1030,18 +1030,25 @@ void Window::updateTitle(float fps) { const NoIntroDB* db = GBAApp::app()->gameDB(); NoIntroGame game{}; uint32_t crc32 = 0; - m_controller->thread()->core->checksum(m_controller->thread()->core, &crc32, CHECKSUM_CRC32); - - char gameTitle[17] = { '\0' }; mCore* core = m_controller->thread()->core; - core->getGameTitle(core, gameTitle); - title = gameTitle; + core->checksum(m_controller->thread()->core, &crc32, CHECKSUM_CRC32); + QString filePath = windowFilePath(); + + if (m_config->getOption("showFilename").toInt() && !filePath.isNull()) { + QFileInfo fileInfo(filePath); + title = fileInfo.fileName(); + } else { + char gameTitle[17] = { '\0' }; + core->getGameTitle(core, gameTitle); + title = gameTitle; #ifdef USE_SQLITE3 - if (db && crc32 && NoIntroDBLookupGameByCRC(db, crc32, &game)) { - title = QLatin1String(game.name); - } + if (db && crc32 && NoIntroDBLookupGameByCRC(db, crc32, &game)) { + title = QLatin1String(game.name); + } #endif + } + MultiplayerController* multiplayer = m_controller->multiplayerController(); if (multiplayer && multiplayer->attached() > 1) { title += tr(" - Player %1 of %2").arg(multiplayer->playerId(m_controller.get()) + 1).arg(multiplayer->attached()); From eaaebf6b2fcdc5a8736e9c0257d30a180a9e79d2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 21 Jun 2020 18:35:23 -0700 Subject: [PATCH 08/51] CMake: Move test lists into test directory --- CMakeLists.txt | 40 +------------------------------- src/platform/test/CMakeLists.txt | 39 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 39 deletions(-) create mode 100644 src/platform/test/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 6acaa51e8..0fd719a42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -928,48 +928,10 @@ if(BUILD_QT) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/qt ${CMAKE_CURRENT_BINARY_DIR}/qt) endif() -if(BUILD_PERF) - set(PERF_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test/perf-main.c) - if(UNIX AND NOT APPLE) - list(APPEND PERF_LIB rt) - endif() - - add_executable(${BINARY_NAME}-perf ${PERF_SRC}) - target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB}) - set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - install(TARGETS ${BINARY_NAME}-perf DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-perf) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) -endif() - -if(BUILD_TEST) - add_executable(${BINARY_NAME}-fuzz ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test/fuzz-main.c) - target_link_libraries(${BINARY_NAME}-fuzz ${BINARY_NAME}) - set_target_properties(${BINARY_NAME}-fuzz PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - add_executable(tbl-fuzz ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test/tbl-fuzz-main.c) - target_link_libraries(tbl-fuzz ${BINARY_NAME}) - set_target_properties(tbl-fuzz PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - install(TARGETS ${BINARY_NAME}-fuzz tbl-fuzz DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-test) -endif() - if(NOT USE_CMOCKA) set(BUILD_SUITE OFF) endif() -if(BUILD_SUITE) - enable_testing() - include_directories(AFTER ${CMOCKA_INCLUDE_DIRS}) - link_directories(${CMOCKA_LIBRARY_DIRS}) - - foreach(TEST IN LISTS TEST_SRC) - string(REPLACE "${CMAKE_SOURCE_DIR}/src/" "" TEST_NAME "${TEST}") - string(REPLACE "/" "-" TEST_NAME "${TEST_NAME}") - string(REPLACE "-test" "" TEST_NAME "${TEST_NAME}") - string(REPLACE ".c" "" TEST_NAME "${TEST_NAME}") - add_executable(test-${TEST_NAME} ${TEST}) - target_link_libraries(test-${TEST_NAME} ${BINARY_NAME} ${PLATFORM_LIBRARY} cmocka) - set_target_properties(test-${TEST_NAME} PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") - add_test(${TEST_NAME} test-${TEST_NAME}) - endforeach() -endif() +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/src/platform/test ${CMAKE_CURRENT_BINARY_DIR}/test) if(BUILD_EXAMPLE) add_executable(${BINARY_NAME}-example-server ${CMAKE_CURRENT_SOURCE_DIR}/src/platform/example/client-server/server.c) diff --git a/src/platform/test/CMakeLists.txt b/src/platform/test/CMakeLists.txt new file mode 100644 index 000000000..49ce9096d --- /dev/null +++ b/src/platform/test/CMakeLists.txt @@ -0,0 +1,39 @@ +if(BUILD_PERF) + set(PERF_SRC ${CMAKE_CURRENT_SOURCE_DIR}/perf-main.c) + if(UNIX AND NOT APPLE) + list(APPEND PERF_LIB rt) + endif() + + add_executable(${BINARY_NAME}-perf ${PERF_SRC}) + target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB}) + set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") + install(TARGETS ${BINARY_NAME}-perf DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-perf) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) +endif() + +if(BUILD_TEST) + add_executable(${BINARY_NAME}-fuzz ${CMAKE_CURRENT_SOURCE_DIR}/fuzz-main.c) + target_link_libraries(${BINARY_NAME}-fuzz ${BINARY_NAME}) + set_target_properties(${BINARY_NAME}-fuzz PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") + add_executable(tbl-fuzz ${CMAKE_CURRENT_SOURCE_DIR}/tbl-fuzz-main.c) + target_link_libraries(tbl-fuzz ${BINARY_NAME}) + set_target_properties(tbl-fuzz PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") + install(TARGETS ${BINARY_NAME}-fuzz tbl-fuzz DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-test) +endif() + +if(BUILD_SUITE) + enable_testing() + include_directories(AFTER ${CMOCKA_INCLUDE_DIRS}) + link_directories(${CMOCKA_LIBRARY_DIRS}) + + foreach(TEST IN LISTS TEST_SRC) + string(REPLACE "${CMAKE_SOURCE_DIR}/src/" "" TEST_NAME "${TEST}") + string(REPLACE "/" "-" TEST_NAME "${TEST_NAME}") + string(REPLACE "-test" "" TEST_NAME "${TEST_NAME}") + string(REPLACE ".c" "" TEST_NAME "${TEST_NAME}") + add_executable(test-${TEST_NAME} ${TEST}) + target_link_libraries(test-${TEST_NAME} ${BINARY_NAME} ${PLATFORM_LIBRARY} cmocka) + set_target_properties(test-${TEST_NAME} PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}") + add_test(${TEST_NAME} test-${TEST_NAME}) + endforeach() +endif() \ No newline at end of file From 27e7837fa1355176cf3317e7fe32d7e604776b41 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 22 Jun 2020 22:05:21 -0700 Subject: [PATCH 09/51] GBA Memory: De-inline GBALoadBad --- src/gba/memory.c | 70 +++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/src/gba/memory.c b/src/gba/memory.c index 1a24f6b04..8adf82b01 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -337,33 +337,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } #define LOAD_BAD \ - if (gba->performingDMA || cpu->gprs[ARM_PC] - gba->dmaPC == (gba->cpu->executionMode == MODE_THUMB ? WORD_SIZE_THUMB : WORD_SIZE_ARM)) { \ - value = gba->bus; \ - } else { \ - value = cpu->prefetch[1]; \ - if (cpu->executionMode == MODE_THUMB) { \ - /* http://ngemu.com/threads/gba-open-bus.170809/ */ \ - switch (cpu->gprs[ARM_PC] >> BASE_OFFSET) { \ - case REGION_BIOS: \ - case REGION_OAM: \ - /* This isn't right half the time, but we don't have $+6 handy */ \ - value <<= 16; \ - value |= cpu->prefetch[0]; \ - break; \ - case REGION_WORKING_IRAM: \ - /* This doesn't handle prefetch clobbering */ \ - if (cpu->gprs[ARM_PC] & 2) { \ - value <<= 16; \ - value |= cpu->prefetch[0]; \ - } else { \ - value |= cpu->prefetch[0] << 16; \ - } \ - break; \ - default: \ - value |= value << 16; \ - } \ - } \ - } + value = GBALoadBad(cpu); #define LOAD_BIOS \ if (address < SIZE_BIOS) { \ @@ -375,7 +349,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } \ } else { \ mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load32: 0x%08X", address); \ - LOAD_BAD; \ + value = GBALoadBad(cpu); \ } #define LOAD_WORKING_RAM \ @@ -427,7 +401,33 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { uint32_t GBALoadBad(struct ARMCore* cpu) { struct GBA* gba = (struct GBA*) cpu->master; uint32_t value = 0; - LOAD_BAD; + if (gba->performingDMA || cpu->gprs[ARM_PC] - gba->dmaPC == (gba->cpu->executionMode == MODE_THUMB ? WORD_SIZE_THUMB : WORD_SIZE_ARM)) { + value = gba->bus; + } else { + value = cpu->prefetch[1]; + if (cpu->executionMode == MODE_THUMB) { + /* http://ngemu.com/threads/gba-open-bus.170809/ */ + switch (cpu->gprs[ARM_PC] >> BASE_OFFSET) { + case REGION_BIOS: + case REGION_OAM: + /* This isn't right half the time, but we don't have $+6 handy */ + value <<= 16; + value |= cpu->prefetch[0]; + break; + case REGION_WORKING_IRAM: + /* This doesn't handle prefetch clobbering */ + if (cpu->gprs[ARM_PC] & 2) { + value <<= 16; + value |= cpu->prefetch[0]; + } else { + value |= cpu->prefetch[0] << 16; + } + break; + default: + value |= value << 16; + } + } + } return value; } @@ -507,8 +507,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } } else { mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address); - LOAD_BAD; - value = (value >> ((address & 2) * 8)) & 0xFFFF; + value = (GBALoadBad(cpu) >> ((address & 2) * 8)) & 0xFFFF; } break; case REGION_WORKING_RAM: @@ -591,8 +590,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; default: mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load16: 0x%08X", address); - LOAD_BAD; - value = (value >> ((address & 2) * 8)) & 0xFFFF; + value = (GBALoadBad(cpu) >> ((address & 2) * 8)) & 0xFFFF; break; } @@ -625,8 +623,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } } else { mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address); - LOAD_BAD; - value = (value >> ((address & 3) * 8)) & 0xFF; + value = (GBALoadBad(cpu) >> ((address & 3) * 8)) & 0xFF; } break; case REGION_WORKING_RAM: @@ -701,8 +698,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; default: mLOG(GBA_MEM, GAME_ERROR, "Bad memory Load8: 0x%08x", address); - LOAD_BAD; - value = (value >> ((address & 3) * 8)) & 0xFF; + value = (GBALoadBad(cpu) >> ((address & 3) * 8)) & 0xFF; break; } From a1daf63cdbde36f1f23e9d030ce9d62446a201be Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 23 Jun 2020 22:59:28 -0700 Subject: [PATCH 10/51] Core: Fix mCoreIsCompatible on null vf --- src/core/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/core.c b/src/core/core.c index 6688bef51..cbab4cfe9 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -62,7 +62,7 @@ struct mCore* mCoreFindVF(struct VFile* vf) { enum mPlatform mCoreIsCompatible(struct VFile* vf) { if (!vf) { - return false; + return PLATFORM_NONE; } const struct mCoreFilter* filter; for (filter = &_filters[0]; filter->filter; ++filter) { From a921c891876e2e7895374742592a66b7e970118e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 23 Jun 2020 23:22:10 -0700 Subject: [PATCH 11/51] CMake: Fix regex on empty libzip version --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0fd719a42..f046ea29b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -617,13 +617,13 @@ if(USE_LIBZIP) list(APPEND DEPENDENCY_LIB ${LIBZIP_LIBRARIES}) list(APPEND FEATURES LIBZIP) list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-zip.c) - string(REGEX MATCH "^[0-9]+" LIBZIP_VERSION_MAJOR ${libzip_VERSION}) + string(REGEX MATCH "^[0-9]+" LIBZIP_VERSION_MAJOR "${libzip_VERSION}") if (LIBZIP_VERSION_MAJOR LESS 1) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libzip2") elseif(LIBZIP_VERSION_MAJOR EQUAL 1) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libzip4|libzip5") else() - message(AUTHOR_WARNING Unknown version of libzip detected: ${libzip_VERSION}) + message(AUTHOR_WARNING "Unknown version of libzip detected: ${libzip_VERSION}") endif() elseif(USE_MINIZIP) include_directories(AFTER ${MINIZIP_INCLUDE_DIRS}) From 879d6983d180e597c06c1a46c528138328b47646 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 23 Jun 2020 23:39:42 -0700 Subject: [PATCH 12/51] CMake: Fix cpack --- src/platform/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/test/CMakeLists.txt b/src/platform/test/CMakeLists.txt index 49ce9096d..62e6b0ac2 100644 --- a/src/platform/test/CMakeLists.txt +++ b/src/platform/test/CMakeLists.txt @@ -8,7 +8,7 @@ if(BUILD_PERF) target_link_libraries(${BINARY_NAME}-perf ${BINARY_NAME} ${PERF_LIB} ${OS_LIB}) set_target_properties(${BINARY_NAME}-perf PROPERTIES COMPILE_DEFINITIONS "${OS_DEFINES};${FEATURE_DEFINES};${FUNCTION_DEFINES}" RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") install(TARGETS ${BINARY_NAME}-perf DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${BINARY_NAME}-perf) - install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tools/perf.py DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) + install(FILES "${CMAKE_SOURCE_DIR}/tools/perf.py" DESTINATION "${LIBDIR}/${BINARY_NAME}" COMPONENT ${BINARY_NAME}-perf) endif() if(BUILD_TEST) From cfe3309da2bf81bf91f699b20f6d1f1edc88230d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 23 Jun 2020 23:41:16 -0700 Subject: [PATCH 13/51] CMake: Fix packaging of test components --- CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f046ea29b..59d4c228d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1141,8 +1141,7 @@ endif() cpack_add_component_group(test PARENT_GROUP dev) cpack_add_component(${BINARY_NAME}-perf GROUP test) -cpack_add_component(${BINARY_NAME}-fuzz GROUP test) -cpack_add_component(tbl-fuzz GROUP test) +cpack_add_component(${BINARY_NAME}-test GROUP test) # Summaries set(SUMMARY_GL_LIST) From 354213515aa51ee4ace637ccb8b5803fb4069a22 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 24 Jun 2020 02:14:29 -0700 Subject: [PATCH 14/51] Core: Fix warning in DISABLE_THREADING build --- src/core/thread.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/core/thread.c b/src/core/thread.c index e9e5cfa7e..887b7fa3f 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -636,12 +636,6 @@ struct mCoreThread* mCoreThreadGet(void) { } #endif -#else -struct mCoreThread* mCoreThreadGet(void) { - return NULL; -} -#endif - static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level, const char* format, va_list args) { UNUSED(logger); UNUSED(level); @@ -650,11 +644,14 @@ static void _mCoreLog(struct mLogger* logger, int category, enum mLogLevel level printf("\n"); struct mCoreThread* thread = mCoreThreadGet(); if (thread && level == mLOG_FATAL) { -#ifndef DISABLE_THREADING mCoreThreadMarkCrashed(thread); -#endif } } +#else +struct mCoreThread* mCoreThreadGet(void) { + return NULL; +} +#endif struct mLogger* mCoreThreadLogger(void) { struct mCoreThread* thread = mCoreThreadGet(); From bbf5a61933272e3c0968d5412df5d0f2aad5a6bc Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 24 Jun 2020 18:09:07 -0700 Subject: [PATCH 15/51] GBA BIOS: Fix reloading video registers after reset (fixes #1808) --- CHANGES | 1 + src/gba/bios.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index 76087f076..35953ef94 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,7 @@ Emulation fixes: - GBA: Fix timing advancing too quickly in rare cases - GBA BIOS: Implement dummy sound driver calls - GBA BIOS: Improve HLE BIOS timing + - GBA BIOS: Fix reloading video registers after reset (fixes mgba.io/i/1808) - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Improve gamepak prefetch timing - GBA SIO: Fix copying Normal mode transfer values diff --git a/src/gba/bios.c b/src/gba/bios.c index 80a0075f6..7fe07f956 100644 --- a/src/gba/bios.c +++ b/src/gba/bios.c @@ -179,6 +179,11 @@ static void _RegisterRamReset(struct GBA* gba) { } if (registers & 0x9C) { gba->video.renderer->reset(gba->video.renderer); + gba->video.renderer->writeVideoRegister(gba->video.renderer, REG_DISPCNT, gba->memory.io[REG_DISPCNT >> 1]); + int i; + for (i = REG_BG0CNT; i < REG_SOUND1CNT_LO; i += 2) { + gba->video.renderer->writeVideoRegister(gba->video.renderer, i, gba->memory.io[i >> 1]); + } } } From 7003d817493a21de7f37ae548d9f7dcfd915f69f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 24 Jun 2020 18:13:54 -0700 Subject: [PATCH 16/51] GBA BIOS: De-magic constant RegisterRamReset --- src/gba/bios.c | 128 ++++++++++++++++++++++++------------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/gba/bios.c b/src/gba/bios.c index 7fe07f956..911fd77bc 100644 --- a/src/gba/bios.c +++ b/src/gba/bios.c @@ -104,78 +104,78 @@ static void _RegisterRamReset(struct GBA* gba) { memset(gba->audio.psg.ch3.wavedata32, 0, sizeof(gba->audio.psg.ch3.wavedata32)); } if (registers & 0x80) { - cpu->memory.store16(cpu, BASE_IO | 0x04, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x06, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x08, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x0A, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x0C, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x0E, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x10, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x12, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x14, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x16, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x18, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x1A, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x1C, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x1E, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DISPSTAT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_VCOUNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG0CNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG1CNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2CNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3CNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG0HOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG0VOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG1HOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG1VOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2HOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG2VOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3HOFS, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BG3VOFS, 0, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG2PA, 0x100, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG2PB, 0, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG2PC, 0, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG2PD, 0x100, 0); - cpu->memory.store32(cpu, BASE_IO | 0x28, 0, 0); - cpu->memory.store32(cpu, BASE_IO | 0x2C, 0, 0); + cpu->memory.store32(cpu, BASE_IO | REG_BG2X_LO, 0, 0); + cpu->memory.store32(cpu, BASE_IO | REG_BG2Y_LO, 0, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG3PA, 0x100, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG3PB, 0, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG3PC, 0, 0); cpu->memory.store16(cpu, BASE_IO | REG_BG3PD, 0x100, 0); - cpu->memory.store32(cpu, BASE_IO | 0x38, 0, 0); - cpu->memory.store32(cpu, BASE_IO | 0x3C, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x40, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x42, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x44, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x46, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x48, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x4A, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x4C, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x50, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x52, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x54, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xB0, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xB2, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xB4, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xB6, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xB8, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xBA, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xBC, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xBE, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xC0, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xC2, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xC4, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xC6, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xC8, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xCA, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xCC, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xCE, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xD0, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xD2, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xD4, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xD6, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xD8, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xDA, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xDC, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0xDE, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x100, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x102, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x104, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x106, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x108, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x10A, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x10C, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x10E, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x200, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x202, 0xFFFF, 0); - cpu->memory.store16(cpu, BASE_IO | 0x204, 0, 0); - cpu->memory.store16(cpu, BASE_IO | 0x208, 0, 0); + cpu->memory.store32(cpu, BASE_IO | REG_BG3X_LO, 0, 0); + cpu->memory.store32(cpu, BASE_IO | REG_BG3Y_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WIN0H, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WIN1H, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WIN0V, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WIN1V, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WININ, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WINOUT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_MOSAIC, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BLDCNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BLDALPHA, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_BLDY, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA0SAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA0SAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA0DAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA0DAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA0CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA0CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA1SAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA1SAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA1DAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA1DAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA1CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA1CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA2SAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA2SAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA2DAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA2DAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA2CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA2CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA3SAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA3SAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA3DAD_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA3DAD_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA3CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_DMA3CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM0CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM0CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM1CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM1CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM2CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM2CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM3CNT_LO, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_TM3CNT_HI, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_IE, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_IF, 0xFFFF, 0); + cpu->memory.store16(cpu, BASE_IO | REG_WAITCNT, 0, 0); + cpu->memory.store16(cpu, BASE_IO | REG_IME, 0, 0); } if (registers & 0x9C) { gba->video.renderer->reset(gba->video.renderer); From 4544177f8b16d0ce2123455260b08dc83c9f4b67 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 24 Jun 2020 02:41:17 -0700 Subject: [PATCH 17/51] Qt: Fix file handle leak on opening an invalid ROM --- CHANGES | 1 + src/platform/qt/CoreManager.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 35953ef94..8ee8ef532 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,7 @@ Other fixes: - GBA Savedata: Fix extracting save when not yet configured in-game - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) + - Qt: Fix file handle leak on opening an invalid ROM Misc: - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG diff --git a/src/platform/qt/CoreManager.cpp b/src/platform/qt/CoreManager.cpp index cdf38f1c9..74c38d1ea 100644 --- a/src/platform/qt/CoreManager.cpp +++ b/src/platform/qt/CoreManager.cpp @@ -83,6 +83,7 @@ CoreController* CoreManager::loadGame(VFile* vf, const QString& path, const QStr mCore* core = mCoreFindVF(vf); if (!core) { + vf->close(vf); LOG(QT, ERROR) << tr("Could not load game. Are you sure it's in the correct format?"); return nullptr; } From 769678f18ae9890427d664b4cf6df6620dd1a0f2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 25 Jun 2020 01:19:06 -0700 Subject: [PATCH 18/51] Qt: Fix a race condition in the frame inspector --- CHANGES | 1 + src/platform/qt/FrameView.cpp | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 8ee8ef532..d322ea764 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,7 @@ Other fixes: - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) - Qt: Fix file handle leak on opening an invalid ROM + - Qt: Fix a race condition in the frame inspector Misc: - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG diff --git a/src/platform/qt/FrameView.cpp b/src/platform/qt/FrameView.cpp index 5c13f2b77..0b97fbd6c 100644 --- a/src/platform/qt/FrameView.cpp +++ b/src/platform/qt/FrameView.cpp @@ -386,12 +386,6 @@ void FrameView::refreshVl() { m_nextFrame = VFileMemChunk(nullptr, 0); if (m_currentFrame) { m_controller->endVideoLog(false); - VFile* currentFrame = VFileMemChunk(nullptr, m_currentFrame->size(m_currentFrame)); - void* buffer = currentFrame->map(currentFrame, m_currentFrame->size(m_currentFrame), MAP_WRITE); - m_currentFrame->seek(m_currentFrame, 0, SEEK_SET); - m_currentFrame->read(m_currentFrame, buffer, m_currentFrame->size(m_currentFrame)); - currentFrame->unmap(currentFrame, buffer, m_currentFrame->size(m_currentFrame)); - m_currentFrame = currentFrame; QMetaObject::invokeMethod(this, "newVl"); } m_controller->endVideoLog(); @@ -403,12 +397,16 @@ void FrameView::newVl() { m_glowTimer.start(); } QMutexLocker locker(&m_mutex); + if (!m_currentFrame) { + return; + } if (m_vl) { m_vl->deinit(m_vl); } m_vl = mCoreFindVF(m_currentFrame); m_vl->init(m_vl); m_vl->loadROM(m_vl, m_currentFrame); + m_currentFrame = nullptr; mCoreInitConfig(m_vl, nullptr); unsigned width, height; m_vl->desiredVideoDimensions(m_vl, &width, &height); From fbce061806e5e5bd19ac6bb1a90d5387c3a7747d Mon Sep 17 00:00:00 2001 From: EddyHg80 Date: Thu, 25 Jun 2020 11:55:06 +0200 Subject: [PATCH 19/51] Fix Italian real time clock translation (#1809) --- src/platform/qt/ts/mgba-it.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ts/mgba-it.ts b/src/platform/qt/ts/mgba-it.ts index 8bfcbac1f..30ddd86bb 100644 --- a/src/platform/qt/ts/mgba-it.ts +++ b/src/platform/qt/ts/mgba-it.ts @@ -4495,7 +4495,7 @@ Game Boy Advance è un marchio registrato di Nintendo Co., Ltd. MM/dd/yy hh:mm:ss AP - gg/MM/aa OO:mm:ss + dd/MM/yy HH:mm:ss From a903fe19d8ae9eff97c25f2595f17e0ed5d6bc34 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 25 Jun 2020 01:54:33 -0700 Subject: [PATCH 20/51] Util: Add PNGRead safety checks --- src/util/png-io.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/util/png-io.c b/src/util/png-io.c index e6c0487ca..1dbadc6e1 100644 --- a/src/util/png-io.c +++ b/src/util/png-io.c @@ -273,6 +273,10 @@ bool PNGIgnorePixels(png_structp png, png_infop info) { } bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) { + if (png_get_channels(png, info) != 3) { + return false; + } + if (setjmp(png_jmpbuf(png))) { return false; } @@ -324,6 +328,10 @@ bool PNGReadPixels(png_structp png, png_infop info, void* pixels, unsigned width } bool PNGReadPixelsA(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) { + if (png_get_channels(png, info) != 4) { + return false; + } + if (setjmp(png_jmpbuf(png))) { return false; } @@ -375,6 +383,10 @@ bool PNGReadPixelsA(png_structp png, png_infop info, void* pixels, unsigned widt } bool PNGReadPixels8(png_structp png, png_infop info, void* pixels, unsigned width, unsigned height, unsigned stride) { + if (png_get_channels(png, info) != 1) { + return false; + } + if (setjmp(png_jmpbuf(png))) { return false; } From 3c73afb7a94e3fab0adc45b04093b3f96fdbe147 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 25 Jun 2020 18:10:55 -0700 Subject: [PATCH 21/51] Core: Const-correctness --- include/mgba/core/core.h | 2 +- src/gb/core.c | 4 ++-- src/gba/core.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mgba/core/core.h b/include/mgba/core/core.h index eeafb2724..18e05cd89 100644 --- a/include/mgba/core/core.h +++ b/include/mgba/core/core.h @@ -70,7 +70,7 @@ struct mCore { void (*loadConfig)(struct mCore*, const struct mCoreConfig*); void (*reloadConfigOption)(struct mCore*, const char* option, const struct mCoreConfig*); - void (*desiredVideoDimensions)(struct mCore*, unsigned* width, unsigned* height); + void (*desiredVideoDimensions)(const struct mCore*, unsigned* width, unsigned* height); void (*setVideoBuffer)(struct mCore*, color_t* buffer, size_t stride); void (*setVideoGLTex)(struct mCore*, unsigned texid); diff --git a/src/gb/core.c b/src/gb/core.c index 8dee77ce3..a3dd7dd79 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -277,8 +277,8 @@ static void _GBCoreReloadConfigOption(struct mCore* core, const char* option, co } } -static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { - struct GB* gb = core->board; +static void _GBCoreDesiredVideoDimensions(const struct mCore* core, unsigned* width, unsigned* height) { + const struct GB* gb = core->board; if (gb && (!(gb->model & GB_MODEL_SGB) || !gb->video.sgbBorders)) { *width = GB_VIDEO_HORIZONTAL_PIXELS; *height = GB_VIDEO_VERTICAL_PIXELS; diff --git a/src/gba/core.c b/src/gba/core.c index c134e5d45..a1cd7f187 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -388,9 +388,9 @@ static void _GBACoreReloadConfigOption(struct mCore* core, const char* option, c } } -static void _GBACoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { +static void _GBACoreDesiredVideoDimensions(const struct mCore* core, unsigned* width, unsigned* height) { #if defined(BUILD_GLES2) || defined(BUILD_GLES3) - struct GBACore* gbacore = (struct GBACore*) core; + const struct GBACore* gbacore = (const struct GBACore*) core; int scale = gbacore->glRenderer.scale; #else UNUSED(core); From 2ec57def29358df37ea5ed0a145bc34d68fad23f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 25 Jun 2020 18:11:16 -0700 Subject: [PATCH 22/51] Qt: The `mutable` keyword exists for a reason --- src/platform/qt/ShortcutModel.cpp | 4 ++-- src/platform/qt/ShortcutModel.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/qt/ShortcutModel.cpp b/src/platform/qt/ShortcutModel.cpp index aa37bff90..331fa6c37 100644 --- a/src/platform/qt/ShortcutModel.cpp +++ b/src/platform/qt/ShortcutModel.cpp @@ -80,7 +80,7 @@ QModelIndex ShortcutModel::index(int row, int column, const QModelIndex& parent) pmenu = static_cast(parent.internalPointer())->name; } QString name = m_controller->name(row, pmenu); - Item* item = &(*const_cast*>(&m_cache))[name]; + Item* item = &m_cache[name]; item->name = name; item->shortcut = m_controller->shortcut(name); return createIndex(row, column, item); @@ -95,7 +95,7 @@ QModelIndex ShortcutModel::parent(const QModelIndex& index) const { if (parent.isNull()) { return QModelIndex(); } - Item* pitem = &(*const_cast*>(&m_cache))[parent]; + Item* pitem = &m_cache[parent]; pitem->name = parent; pitem->shortcut = m_controller->shortcut(parent); return createIndex(m_controller->indexIn(parent), 0, pitem); diff --git a/src/platform/qt/ShortcutModel.h b/src/platform/qt/ShortcutModel.h index 69893ef9c..3eb3b1178 100644 --- a/src/platform/qt/ShortcutModel.h +++ b/src/platform/qt/ShortcutModel.h @@ -44,7 +44,7 @@ private: const Shortcut* shortcut = nullptr; }; - QHash m_cache; + mutable QHash m_cache; }; } \ No newline at end of file From 8ef0427885279738a9af3ad7b8d4df26ed0b8bd9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 26 Jun 2020 01:17:19 -0700 Subject: [PATCH 23/51] ARM: Fix LDM^ writeback to user-mode register --- CHANGES | 1 + src/arm/isa-arm.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index d322ea764..0984d6286 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Features: Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation + - ARM: Fix LDM^ writeback to user-mode register - GB: Partially fix timing for skipped BIOS - GB Memory: Fix OAM DMA from top 8 kB - GB MBC: Fix MBC1 mode changing behavior diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index 7201f6160..fa9026001 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -446,9 +446,9 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { uint32_t address = cpu->gprs[rn]; \ S_PRE; \ address = cpu->memory. LS ## Multiple(cpu, address, rs, LSM_ ## DIRECTION, ¤tCycles); \ + WRITEBACK; \ S_POST; \ - POST_BODY; \ - WRITEBACK;) + POST_BODY;) #define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, LS, POST_BODY) \ From 5e003d1e7a5e6e8f7ef56bda07f39128fdffc57f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 26 Jun 2020 01:20:00 -0700 Subject: [PATCH 24/51] ARM: Fix LDM^ {pc} differences (fixes #1698) --- CHANGES | 1 + src/arm/isa-arm.c | 57 +++++++++++++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index 0984d6286..0a48bcd19 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation - ARM: Fix LDM^ writeback to user-mode register + - ARM: Fix LDM^ {pc} differences (fixes mgba.io/i/1698) - GB: Partially fix timing for skipped BIOS - GB Memory: Fix OAM DMA from top 8 kB - GB MBC: Fix MBC1 mode changing behavior diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index fa9026001..f62786d85 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -433,11 +433,26 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE)), LS, BODY) \ DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE)), LS, BODY) \ -#define ARM_MS_PRE \ +#define ARM_MS_PRE_store \ enum PrivilegeMode privilegeMode = cpu->privilegeMode; \ ARMSetPrivilegeMode(cpu, MODE_SYSTEM); -#define ARM_MS_POST ARMSetPrivilegeMode(cpu, privilegeMode); +#define ARM_MS_PRE_load \ + enum PrivilegeMode privilegeMode; \ + if (!(rs & 0x8000)) { \ + privilegeMode = cpu->privilegeMode; \ + ARMSetPrivilegeMode(cpu, MODE_SYSTEM); \ + } + +#define ARM_MS_POST_store ARMSetPrivilegeMode(cpu, privilegeMode); + +#define ARM_MS_POST_load \ + if ((rs & 0x8000) && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ + cpu->cpsr = cpu->spsr; \ + _ARMReadCPSR(cpu); \ + } else { \ + ARMSetPrivilegeMode(cpu, privilegeMode); \ + } \ #define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, LS, WRITEBACK, S_PRE, S_POST, DIRECTION, POST_BODY) \ DEFINE_INSTRUCTION_ARM(NAME, \ @@ -452,22 +467,22 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { #define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, LS, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, LS, , , , DA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , DA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, LS, , , , DB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , DB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IA, LS, , , , IA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, LS, , , , IB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, LS, , ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, LS, , ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, LS, , ARM_MS_PRE, ARM_MS_POST, IA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, IA, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, LS, , ARM_MS_PRE, ARM_MS_POST, IB, POST_BODY) \ - DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, IB, POST_BODY) + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, LS, , , , DA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , DA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, LS, , , , DB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , DB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IA, LS, , , , IA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, LS, , , , IB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IA, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IB, POST_BODY) \ + DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IB, POST_BODY) // Begin ALU definitions @@ -603,7 +618,11 @@ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM, load, currentCycles += cpu->memory.activeNonseqCycles32 - cpu->memory.activeSeqCycles32; if ((rs & 0x8000) || !rs) { - currentCycles += ARMWritePC(cpu); + if (cpu->executionMode == MODE_THUMB) { + currentCycles += ThumbWritePC(cpu); + } else { + currentCycles += ARMWritePC(cpu); + } }) DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM, From f6522ea08468cea5c18784a948db145c8bb7f316 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 26 Jun 2020 01:24:25 -0700 Subject: [PATCH 25/51] CHANGES: Update --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 0a48bcd19..020715b13 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,7 @@ Other fixes: - Qt: Fix static compilation in MinGW (fixes mgba.io/i/1769) - Qt: Fix file handle leak on opening an invalid ROM - Qt: Fix a race condition in the frame inspector + - Qt: Fix Italian RTC translation (fixes mgba.io/i/1798) Misc: - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG From b68c393223ed73d81f4c9896c3d6e0e7262243e3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 28 Jun 2020 00:40:24 -0700 Subject: [PATCH 26/51] Util: Fix crash if PNG header fails to write --- CHANGES | 1 + src/util/png-io.c | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 020715b13..2815b229c 100644 --- a/CHANGES +++ b/CHANGES @@ -35,6 +35,7 @@ Other fixes: - Qt: Fix file handle leak on opening an invalid ROM - Qt: Fix a race condition in the frame inspector - Qt: Fix Italian RTC translation (fixes mgba.io/i/1798) + - Util: Fix crash if PNG header fails to write Misc: - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG diff --git a/src/util/png-io.c b/src/util/png-io.c index 1dbadc6e1..530ea8f0b 100644 --- a/src/util/png-io.c +++ b/src/util/png-io.c @@ -47,19 +47,16 @@ static png_infop _pngWriteHeader(png_structp png, unsigned width, unsigned heigh return 0; } png_set_IHDR(png, info, width, height, 8, type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_write_info(png, info); return info; } png_infop PNGWriteHeader(png_structp png, unsigned width, unsigned height) { - png_infop info = _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_RGB); - png_write_info(png, info); - return info; + return _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_RGB); } png_infop PNGWriteHeaderA(png_structp png, unsigned width, unsigned height) { - png_infop info = _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_RGB_ALPHA); - png_write_info(png, info); - return info; + return _pngWriteHeader(png, width, height, PNG_COLOR_TYPE_RGB_ALPHA); } png_infop PNGWriteHeader8(png_structp png, unsigned width, unsigned height) { From 8a7f8c67fce5b760320c0758662d7528cf979bd9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 28 Jun 2020 15:42:10 -0700 Subject: [PATCH 27/51] GBA Video: Fix invalid read in mode 4 mosaic --- CHANGES | 1 + src/gba/renderers/software-bg.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 2815b229c..d145b1ca4 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Emulation fixes: - GBA SIO: Fix copying Normal mode transfer values - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing + - GBA Video: Fix invalid read in mode 4 mosaic - SM83: Emulate HALT bug Other fixes: - All: Improve export headers (fixes mgba.io/i/1738) diff --git a/src/gba/renderers/software-bg.c b/src/gba/renderers/software-bg.c index db4b33e71..742e126b5 100644 --- a/src/gba/renderers/software-bg.c +++ b/src/gba/renderers/software-bg.c @@ -128,7 +128,7 @@ void GBAVideoSoftwareRendererDrawBackgroundMode3(struct GBAVideoSoftwareRenderer void GBAVideoSoftwareRendererDrawBackgroundMode4(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int inY) { BACKGROUND_BITMAP_INIT; - uint16_t color = renderer->normalPalette[0]; + uint16_t color = 0; uint32_t offset = 0; if (GBARegisterDISPCNTIsFrameSelect(renderer->dispcnt)) { offset = 0xA000; From 8137a432339f6f734c4a6674d8b2c4c41fde5ff7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 29 Jun 2020 14:47:31 -0700 Subject: [PATCH 28/51] Qt: Don't use non-C++14 designated initializers --- src/platform/qt/VideoView.cpp | 104 +++++++++++----------------------- src/platform/qt/VideoView.h | 9 +++ 2 files changed, 42 insertions(+), 71 deletions(-) diff --git a/src/platform/qt/VideoView.cpp b/src/platform/qt/VideoView.cpp index 9f3767ea2..b554c670e 100644 --- a/src/platform/qt/VideoView.cpp +++ b/src/platform/qt/VideoView.cpp @@ -112,96 +112,58 @@ VideoView::VideoView(QWidget* parent) void VideoView::updatePresets() { m_presets.clear(); - addPreset(m_ui.preset4K, { - .container = QString(), - .vcodec = QString(), - .acodec = QString(), - .vbr = 0, - .abr = 0, - .dims = maintainAspect(QSize(3840, 2160)) - }); - - addPreset(m_ui.preset1080, { - .container = QString(), - .vcodec = QString(), - .acodec = QString(), - .vbr = 0, - .abr = 0, - .dims = maintainAspect(QSize(1920, 1080)) - }); - - addPreset(m_ui.preset720, { - .container = QString(), - .vcodec = QString(), - .acodec = QString(), - .vbr = 0, - .abr = 0, - .dims = maintainAspect(QSize(1280, 720)) - }); - - addPreset(m_ui.preset480, { - .container = QString(), - .vcodec = QString(), - .acodec = QString(), - .vbr = 0, - .abr = 0, - .dims = maintainAspect(QSize(720, 480)) - }); + addPreset(m_ui.preset4K, { maintainAspect(QSize(3840, 2160)) }); + addPreset(m_ui.preset1080, { maintainAspect(QSize(1920, 1080)) }); + addPreset(m_ui.preset720, { maintainAspect(QSize(1280, 720)) }); + addPreset(m_ui.preset480, { maintainAspect(QSize(720, 480)) }); if (m_nativeWidth && m_nativeHeight) { - addPreset(m_ui.presetNative, { - .container = QString(), - .vcodec = QString(), - .acodec = QString(), - .vbr = 0, - .abr = 0, - .dims = QSize(m_nativeWidth, m_nativeHeight) - }); + addPreset(m_ui.presetNative, { QSize(m_nativeWidth, m_nativeHeight) }); m_ui.presetNative->setEnabled(true); } addPreset(m_ui.presetHQ, { - .container = "MP4", - .vcodec = "h.264", - .acodec = "AAC", - .vbr = 8000, - .abr = 384, - .dims = maintainAspect(QSize(1920, 1080)) + "MP4", + "h.264", + "AAC", + 8000, + 384, + maintainAspect({ 1920, 1080 }) }); addPreset(m_ui.presetYoutube, { - .container = "MP4", - .vcodec = "h.264", - .acodec = "AAC", - .vbr = 5000, - .abr = 256, - .dims = maintainAspect(QSize(1280, 720)) + "MP4", + "h.264", + "AAC", + 5000, + 256, + maintainAspect({ 1280, 720 }) }); addPreset(m_ui.presetWebM, { - .container = "WebM", - .vcodec = "VP9", - .acodec = "Opus", - .vbr = 800, - .abr = 128 + "WebM", + "VP9", + "Opus", + 800, + 128 }); addPreset(m_ui.presetMP4, { - .container = "MP4", - .vcodec = "h.264", - .acodec = "AAC", - .vbr = 800, - .abr = 128 + "MP4", + "h.264", + "AAC", + 800, + 128 }); if (m_nativeWidth && m_nativeHeight) { addPreset(m_ui.presetLossless, { - .container = "MKV", - .vcodec = "h.264", - .acodec = "FLAC", - .vbr = -1, - .abr = 0, - .dims = QSize(m_nativeWidth, m_nativeHeight) + "MKV", + "h.264", + "FLAC", + -1, + 0, + { m_nativeWidth, m_nativeHeight } }); } } diff --git a/src/platform/qt/VideoView.h b/src/platform/qt/VideoView.h index 3535535ae..865c2aafc 100644 --- a/src/platform/qt/VideoView.h +++ b/src/platform/qt/VideoView.h @@ -70,6 +70,15 @@ private: int abr; QSize dims; + Preset() {} + Preset(QString container, QString vcodec, QString acodec, int vbr, int abr, QSize dims = QSize()) + : container(container) + , vcodec(vcodec) + , acodec(acodec) + , vbr(vbr) + , abr(abr) + , dims(dims) {} + Preset(QSize dims) : dims(dims) {} bool compatible(const Preset&) const; }; From 6e88fc1acc2ef5933651fef911bb22491626605a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 29 Jun 2020 15:02:39 -0700 Subject: [PATCH 29/51] Qt: Missed a few --- src/platform/qt/VideoView.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/platform/qt/VideoView.cpp b/src/platform/qt/VideoView.cpp index b554c670e..307245aa8 100644 --- a/src/platform/qt/VideoView.cpp +++ b/src/platform/qt/VideoView.cpp @@ -99,12 +99,11 @@ VideoView::VideoView(QWidget* parent) updatePresets(); setPreset({ - .container = "MKV", - .vcodec = "h.264", - .acodec = "FLAC", - .vbr = -1, - .abr = 0, - .dims = QSize(), + "MKV", + "h.264", + "FLAC", + -1, + 0, }); showAdvanced(false); } @@ -413,12 +412,12 @@ void VideoView::updateAspectRatio(int width, int height, bool force) { void VideoView::uncheckIncompatible() { Preset current = { - .container = m_container, - .vcodec = m_videoCodec, - .acodec = m_audioCodec, - .vbr = m_vbr / 1000, - .abr = m_abr / 1000, - .dims = QSize(m_width, m_height) + m_container, + m_videoCodec, + m_audioCodec, + m_vbr / 1000, + m_abr / 1000, + { m_width, m_height } }; m_ui.presets->setExclusive(false); From 55768a03d9961e44024737a36979ac80bb3f7bfe Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 30 Jun 2020 02:11:01 +0000 Subject: [PATCH 30/51] Windows: Get CMake barely working with vcpkg badness --- CMakeLists.txt | 56 ++++++++++++++++++------------- src/platform/cmake/FindSDL2.cmake | 43 +++++++----------------- src/platform/qt/CMakeLists.txt | 4 +++ src/platform/sdl/CMakeLists.txt | 2 ++ 4 files changed, 52 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 59d4c228d..7faef50e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,7 +465,15 @@ set(WANT_PNG ${USE_PNG}) set(WANT_SQLITE3 ${USE_SQLITE3}) set(USE_CMOCKA ${BUILD_SUITE}) -find_feature(USE_FFMPEG "libavcodec;libavfilter;libavformat;libavutil;libswscale") +if(DEFINED VCPKG_TARGET_TRIPLET) + find_feature(USE_FFMPEG "FFMPEG") + if(FFMPEG_FOUND) + set(USE_LIBAVRESAMPLE OFF) + set(USE_LIBSWRESAMPLE ON) + endif() +else() + find_feature(USE_FFMPEG "libavcodec;libavfilter;libavformat;libavutil;libswscale") +endif() find_feature(USE_ZLIB "ZLIB") find_feature(USE_MINIZIP "minizip") find_feature(USE_PNG "PNG") @@ -476,7 +484,7 @@ find_feature(USE_SQLITE3 "sqlite3") find_feature(USE_ELF "libelf") find_feature(ENABLE_PYTHON "PythonLibs") -if(USE_FFMPEG) +if(USE_FFMPEG AND NOT DEFINED VCPKG_TARGET_TRIPLET) set(USE_LIBAVRESAMPLE ON) set(USE_LIBSWRESAMPLE ON) find_feature(USE_LIBAVRESAMPLE "libavresample") @@ -515,31 +523,33 @@ if(USE_FFMPEG) list(APPEND FEATURES LIBAVRESAMPLE) list(APPEND FEATURES LIBAV) endif() - include_directories(AFTER ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFILTER_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) - link_directories(${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFILTER_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) + include_directories(AFTER ${FFMPEG_INCLUDE_DIRS} ${LIBAVCODEC_INCLUDE_DIRS} ${LIBAVFILTER_INCLUDE_DIRS} ${LIBAVFORMAT_INCLUDE_DIRS} ${LIBAVRESAMPLE_INCLUDE_DIRS} ${LIBAVUTIL_INCLUDE_DIRS} ${LIBSWRESAMPLE_INCLUDE_DIRS} ${LIBSWSCALE_INCLUDE_DIRS}) + link_directories(${FFMPEG_LIBRARY_DIRS} ${LIBAVCODEC_LIBRARY_DIRS} ${LIBAVFILTER_LIBRARY_DIRS} ${LIBAVFORMAT_LIBRARY_DIRS} ${LIBAVRESAMPLE_LIBRARY_DIRS} ${LIBAVUTIL_LIBRARY_DIRS} ${LIBSWRESAMPLE_LIBRARY_DIRS} ${LIBSWSCALE_LIBRARY_DIRS}) list(APPEND FEATURE_SRC "${CMAKE_CURRENT_SOURCE_DIR}/src/feature/ffmpeg/ffmpeg-encoder.c") - string(REGEX MATCH "^[0-9]+" LIBAVCODEC_VERSION_MAJOR ${libavcodec_VERSION}) - string(REGEX MATCH "^[0-9]+" LIBAVFILTER_VERSION_MAJOR ${libavfilter_VERSION}) - string(REGEX MATCH "^[0-9]+" LIBAVFORMAT_VERSION_MAJOR ${libavformat_VERSION}) - string(REGEX MATCH "^[0-9]+" LIBAVUTIL_VERSION_MAJOR ${libavutil_VERSION}) - string(REGEX MATCH "^[0-9]+" LIBSWSCALE_VERSION_MAJOR ${libswscale_VERSION}) - list(APPEND DEPENDENCY_LIB ${LIBAVCODEC_LIBRARIES} ${LIBAVFILTER_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES}) - if(WIN32) + list(APPEND DEPENDENCY_LIB ${FFMPEG_LIBRARIES} ${LIBAVCODEC_LIBRARIES} ${LIBAVFILTER_LIBRARIES} ${LIBAVFORMAT_LIBRARIES} ${LIBAVRESAMPLE_LIBRARIES} ${LIBAVUTIL_LIBRARIES} ${LIBSWSCALE_LIBRARIES} ${LIBSWRESAMPLE_LIBRARIES}) + if(WIN32 AND NOT DEFINED VCPKG_TARGET_TRIPLET) list(APPEND DEPENDENCY_LIB bcrypt) endif() - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavcodec${LIBAVCODEC_VERSION_MAJOR}|libavcodec-extra-${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavfilter${LIBAVFILTER_VERSION_MAJOR}|libavfilter-ffmpeg${LIBAVFILTER_VERSION_MAJOR}") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavformat${LIBAVFORMAT_VERSION_MAJOR}|libavformat-ffmpeg${LIBAVFORMAT_VERSION_MAJOR}") - if(USE_LIBSWRESAMPLE) - string(REGEX MATCH "^[0-9]+" LIBSWRESAMPLE_VERSION_MAJOR ${libswresample_VERSION}) - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswresample${LIBSWRESAMPLE_VERSION_MAJOR}|libswresample-ffmpeg${LIBSWRESAMPLE_VERSION_MAJOR}") - else() - string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION}) - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}") + if(UNIX) + string(REGEX MATCH "^[0-9]+" LIBAVCODEC_VERSION_MAJOR ${libavcodec_VERSION}) + string(REGEX MATCH "^[0-9]+" LIBAVFILTER_VERSION_MAJOR ${libavfilter_VERSION}) + string(REGEX MATCH "^[0-9]+" LIBAVFORMAT_VERSION_MAJOR ${libavformat_VERSION}) + string(REGEX MATCH "^[0-9]+" LIBAVUTIL_VERSION_MAJOR ${libavutil_VERSION}) + string(REGEX MATCH "^[0-9]+" LIBSWSCALE_VERSION_MAJOR ${libswscale_VERSION}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavcodec${LIBAVCODEC_VERSION_MAJOR}|libavcodec-extra-${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg${LIBAVCODEC_VERSION_MAJOR}|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavfilter${LIBAVFILTER_VERSION_MAJOR}|libavfilter-ffmpeg${LIBAVFILTER_VERSION_MAJOR}") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavformat${LIBAVFORMAT_VERSION_MAJOR}|libavformat-ffmpeg${LIBAVFORMAT_VERSION_MAJOR}") + if(USE_LIBSWRESAMPLE) + string(REGEX MATCH "^[0-9]+" LIBSWRESAMPLE_VERSION_MAJOR ${libswresample_VERSION}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswresample${LIBSWRESAMPLE_VERSION_MAJOR}|libswresample-ffmpeg${LIBSWRESAMPLE_VERSION_MAJOR}") + else() + string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION}) + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavresample${LIBAVRESAMPLE_VERSION_MAJOR}|libavresample-ffmpeg${LIBAVRESAMPLE_VERSION_MAJOR}") + endif() + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavutil${LIBAVUTIL_VERSION_MAJOR}|libavutil-ffmpeg${LIBAVUTIL_VERSION_MAJOR}") + set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswscale${LIBSWSCALE_VERSION_MAJOR}|libswscale-ffmpeg${LIBSWSCALE_VERSION_MAJOR}") + set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") endif() - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libavutil${LIBAVUTIL_VERSION_MAJOR}|libavutil-ffmpeg${LIBAVUTIL_VERSION_MAJOR}") - set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswscale${LIBSWSCALE_VERSION_MAJOR}|libswscale-ffmpeg${LIBSWSCALE_VERSION_MAJOR}") - set(CPACK_DEBIAN_PACKAGE_RECOMMENDS "libavcodec-extra|libavcodec-ffmpeg-extra${LIBAVCODEC_VERSION_MAJOR}") if(APPLE) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -framework VideoDecodeAcceleration -framework CoreVideo") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework VideoDecodeAcceleration -framework CoreVideo") diff --git a/src/platform/cmake/FindSDL2.cmake b/src/platform/cmake/FindSDL2.cmake index be210361c..c6ad7e3dc 100644 --- a/src/platform/cmake/FindSDL2.cmake +++ b/src/platform/cmake/FindSDL2.cmake @@ -2,14 +2,6 @@ # SDL2_FOUND, if false, do not try to link to SDL2 # SDL2_INCLUDE_DIRS, where to find SDL.h # -# This module responds to the the flag: -# SDL2_BUILDING_LIBRARY -# If this is defined, then no SDL2main will be linked in because -# only applications need main(). -# Otherwise, it is assumed you are building an application and this -# module will attempt to locate and set the the proper link flags -# as part of the returned SDL2_LIBRARIES variable. -# # Don't forget to include SDLmain.h and SDLmain.m your project for the # OS X framework based version. (Other versions link to -lSDL2main which # this module will try to find on your behalf.) Also for OS X, this @@ -109,21 +101,19 @@ FIND_LIBRARY(SDL2_LIBRARIES_TEMP PATHS ${SDL2_SEARCH_PATHS} ${SDL2_INCLUDE_DIRS}/../.. ) -IF(NOT SDL2_BUILDING_LIBRARY) - IF(NOT ${SDL2_INCLUDE_DIRS} MATCHES ".framework") - # Non-OS X framework versions expect you to also dynamically link to - # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms - # seem to provide SDL2main for compatibility even though they don't - # necessarily need it. - FIND_LIBRARY(SDL2MAIN_LIBRARY - NAMES SDL2main - HINTS - $ENV{SDL2DIR} - PATH_SUFFIXES lib64 lib - PATHS ${SDL2_SEARCH_PATHS} - ) - ENDIF(NOT ${SDL2_INCLUDE_DIRS} MATCHES ".framework") -ENDIF(NOT SDL2_BUILDING_LIBRARY) +IF(NOT ${SDL2_INCLUDE_DIRS} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2main for compatibility even though they don't + # necessarily need it. + FIND_LIBRARY(SDL2MAIN_LIBRARY + NAMES SDL2main + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES lib64 lib + PATHS ${SDL2_SEARCH_PATHS} + ) +ENDIF(NOT ${SDL2_INCLUDE_DIRS} MATCHES ".framework") # SDL2 may require threads on your system. # The Apple build may not need an explicit flag because one of the @@ -141,13 +131,6 @@ IF(MINGW) ENDIF(MINGW) IF(SDL2_LIBRARIES_TEMP) - # For SDL2main - IF(NOT SDL2_BUILDING_LIBRARY) - IF(SDL2MAIN_LIBRARY) - SET(SDL2_LIBRARIES_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARIES_TEMP}) - ENDIF(SDL2MAIN_LIBRARY) - ENDIF(NOT SDL2_BUILDING_LIBRARY) - # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. # CMake doesn't display the -framework Cocoa string in the UI even # though it actually is there if I modify a pre-used variable. diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 66db780e6..165a23f2a 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -282,6 +282,10 @@ qt5_wrap_ui(UI_SRC ${UI_FILES}) add_executable(${BINARY_NAME}-qt WIN32 MACOSX_BUNDLE main.cpp ${CMAKE_SOURCE_DIR}/res/mgba.icns ${SOURCE_FILES} ${PLATFORM_SRC} ${UI_SRC} ${AUDIO_SRC} ${RESOURCES}) set_target_properties(${BINARY_NAME}-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/info.plist.in COMPILE_DEFINITIONS "${FEATURE_DEFINES};${FUNCTION_DEFINES};${OS_DEFINES};${QT_DEFINES}" COMPILE_OPTIONS "${FEATURE_FLAGS}") +if(WIN32) + set_target_properties(${BINARY_NAME}-qt PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") +endif() + list(APPEND QT_LIBRARIES Qt5::Widgets Qt5::Network) if(BUILD_GL OR BUILD_GLES2 OR BUILD_EPOXY) list(APPEND QT_LIBRARIES Qt5::OpenGL ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) diff --git a/src/platform/sdl/CMakeLists.txt b/src/platform/sdl/CMakeLists.txt index f5e003b7f..b79e91142 100644 --- a/src/platform/sdl/CMakeLists.txt +++ b/src/platform/sdl/CMakeLists.txt @@ -114,6 +114,8 @@ set_target_properties(${BINARY_NAME}-sdl PROPERTIES COMPILE_DEFINITIONS "${FEATU target_link_libraries(${BINARY_NAME}-sdl ${BINARY_NAME} ${PLATFORM_LIBRARY} ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) if(NOT WIN32) set_target_properties(${BINARY_NAME}-sdl PROPERTIES OUTPUT_NAME ${BINARY_NAME}) +else() + set_target_properties(${BINARY_NAME}-sdl PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") endif() if (WIN32 AND MSVC) set_target_properties(${BINARY_NAME}-sdl PROPERTIES LINK_FLAGS "/SUBSYSTEM:CONSOLE") From 98a6b5a16fdbecfdb4771fb972390c9f6076794b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 30 Jun 2020 02:32:31 +0000 Subject: [PATCH 31/51] gitignore: Update for MSVC build products --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3e6aea460..20c19fc41 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /build /build-* +/.vs *.a *.dylib @@ -14,4 +15,5 @@ *.so CMakeCache.txt CMakeFiles +CMakeSettings.json version.c From 2cad00cc0f1f867830d8e954a964155fd0e45917 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 30 Jun 2020 02:32:56 +0000 Subject: [PATCH 32/51] README: Preliminary MSVC build instructions --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index e93aa8670..f5e91a5be 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,8 @@ Note that you should not do a `make install` on macOS, as it will not work prope #### Windows developer building +##### MSYS2 + To build on Windows for development, using MSYS2 is recommended. Follow the installation steps found on their [website](https://msys2.github.io). Make sure you're running the 32-bit version ("MSYS2 MinGW 32-bit") (or the 64-bit version "MSYS2 MinGW 64-bit" if you want to build for x86_64) and run this additional command (including the braces) to install the needed dependencies (please note that this involves downloading over 1100MiB of packages, so it will take a long time): For x86 (32 bit) builds: @@ -181,6 +183,20 @@ Then finally build it by running these commands: Please note that this build of mGBA for Windows is not suitable for distribution, due to the scattering of DLLs it needs to run, but is perfect for development. However, if distributing such a build is desired (e.g. for testing on machines that don't have the MSYS2 environment installed), running `cpack -G ZIP` will prepare a zip file with all of the necessary DLLs. +##### Visual Studio + +To build using Visual Studio is a similarly complicated setup. To begin you will need to install [vcpkg](https://github.com/Microsoft/vcpkg). After installing vcpkg you will need to install several additional packages: + + vcpkg install ffmpeg[vpx,x264] libepoxy libpng libzip sdl2 sqlite3 + +Note that this installation won't support hardware accelerated video encoding on Nvidia hardware. If you care about this, you'll need to install CUDA beforehand, and then substitute `ffmpeg[vpx,x264,nvcodec]` into the previous command. + +You will also need to install Qt. Unfortunately due to Qt being owned and run by an ailing company as opposed to a reasonable organization there is no longer an offline open source edition installer for the latest version, so you'll need to either fall back to an [old version installer](https://download.qt.io/official_releases/qt/5.12/5.12.9/qt-opensource-windows-x86-5.12.9.exe) (which wants you to create an otherwise-useless account, but you can bypass temporarily setting an invalid proxy or otherwise disabling networking), use the online installer (which requires an account regardless), or use vcpkg to build it (slowly). None of these are great options. For the installer you'll want to install the applicable MSVC versions. Note that the offline installers do not support MSVC 2019. For vcpkg you'll want to install it as such, which will take quite a while, especially on quad core or less computers: + + vcpkg install qt5-base qt5-multimedia + +Next, open Visual Studio, select Clone Repository, and enter `https://github.com/mgba-emu/mgba.git`. When Visual Studio is done cloning, go to File > CMake and open the CMakeLists.txt file at the root of the checked out repository. From there, mGBA can be developed in Visual Studio similarly to other Visual Studio CMake projects. + #### Toolchain building If you have devkitARM (for 3DS), devkitPPC (for Wii), devkitA64 (for Switch), or vitasdk (for PS Vita), you can use the following commands for building: From ab562e38f9d8fe233ab8fa91c91b463cd51749dd Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 29 Jun 2020 20:45:18 -0700 Subject: [PATCH 33/51] Windows: Fix installer build --- src/platform/windows/setup/setup.iss.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/windows/setup/setup.iss.in b/src/platform/windows/setup/setup.iss.in index fc6950a91..fb164136a 100644 --- a/src/platform/windows/setup/setup.iss.in +++ b/src/platform/windows/setup/setup.iss.in @@ -78,8 +78,8 @@ Name: "sgbfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Super Game Name: "gbafileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Game Boy Advance}"; GroupDescription: "{cm:FileAssoc}" [Files] -Source: "{#BinDir}\qt\{#AppName}.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "{#BinDir}\sdl\{#AppName2}-sdl.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#BinDir}\{#AppName}.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "{#BinDir}\{#AppName2}-sdl.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "{#BinDir}\CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme Source: "{#BinDir}\LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion Source: "{#ResDir}\nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion From 7bc45acd619038b880825dfa8112ddba3a21cf2e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 29 Jun 2020 21:52:39 -0700 Subject: [PATCH 34/51] README: Remove ImageMagick mention --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index f5e91a5be..2ed176151 100644 --- a/README.md +++ b/README.md @@ -221,9 +221,8 @@ mGBA has no hard dependencies, however, the following optional dependencies are - SDL: for a more basic frontend and gamepad support in the Qt frontend. SDL 2 is recommended, but 1.2 is supported. - zlib and libpng: for screenshot support and savestate-in-PNG support. - libedit: for command-line debugger support. -- ffmpeg or libav: for video recording. +- ffmpeg or libav: for video and GIF recording. - libzip or zlib: for loading ROMs stored in zip files. -- ImageMagick: for GIF recording. - SQLite3: for game databases. - libelf: for ELF loading. From d9cc9b20ff8d231a15c3b62c85ac4979c24b41d9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 30 Jun 2020 03:12:14 -0700 Subject: [PATCH 35/51] GBA Memory: Stall on VRAM access in mode 2 (fixes #190) --- CHANGES | 1 + include/mgba/internal/gba/video.h | 2 +- src/gba/memory.c | 45 +++++++++++++++++++++++++++++-- src/gba/video.c | 5 ++++ 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index d145b1ca4..6d6daa436 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Emulation fixes: - GBA BIOS: Fix reloading video registers after reset (fixes mgba.io/i/1808) - GBA DMA: Linger last DMA on bus (fixes mgba.io/i/301 and mgba.io/i/1320) - GBA Memory: Improve gamepak prefetch timing + - GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190) - GBA SIO: Fix copying Normal mode transfer values - GBA Video: Latch scanline at end of Hblank (fixes mgba.io/i/1319) - GBA Video: Fix Hblank timing diff --git a/include/mgba/internal/gba/video.h b/include/mgba/internal/gba/video.h index 82c4a45b5..87e5c38cc 100644 --- a/include/mgba/internal/gba/video.h +++ b/include/mgba/internal/gba/video.h @@ -206,8 +206,8 @@ struct GBAVideo { struct GBAVideoRenderer* renderer; struct mTimingEvent event; - // VCOUNT int vcount; + int shouldStall; uint16_t palette[512]; uint16_t* vram; diff --git a/src/gba/memory.c b/src/gba/memory.c index 8adf82b01..8a0238a9f 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -29,6 +29,7 @@ static uint8_t _agbPrintFunc[4] = { 0xFA, 0xDF /* swi 0xFF */, 0x70, 0x47 /* bx static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region); static int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait); +static int32_t GBAMemoryStallVRAM(struct GBA* gba, int32_t wait, int extra); static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 }; static const char GBA_BASE_WAITSTATES_32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 9 }; @@ -374,7 +375,10 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } else { \ LOAD_32(value, address & 0x0001FFFC, gba->video.vram); \ } \ - wait += waitstatesRegion[REGION_VRAM]; + ++wait; \ + if (gba->video.shouldStall) { \ + wait += GBAMemoryStallVRAM(gba, wait, 1); \ + } #define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); @@ -534,6 +538,9 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } else { LOAD_16(value, address & 0x0001FFFE, gba->video.vram); } + if (gba->video.shouldStall) { + wait += GBAMemoryStallVRAM(gba, wait, 0); + } break; case REGION_OAM: LOAD_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw); @@ -650,6 +657,9 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } else { value = ((uint8_t*) gba->video.vram)[address & 0x0001FFFF]; } + if (gba->video.shouldStall) { + wait += GBAMemoryStallVRAM(gba, wait, 0); + } break; case REGION_OAM: value = ((uint8_t*) gba->video.oam.raw)[address & (SIZE_OAM - 1)]; @@ -751,7 +761,10 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \ } \ } \ - wait += waitstatesRegion[REGION_VRAM]; + ++wait; \ + if (gba->video.shouldStall) { \ + wait += GBAMemoryStallVRAM(gba, wait, 1); \ + } #define STORE_OAM \ LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw); \ @@ -876,6 +889,9 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); } } + if (gba->video.shouldStall) { + wait += GBAMemoryStallVRAM(gba, wait, 0); + } break; case REGION_OAM: LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw); @@ -977,6 +993,9 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo gba->video.renderer->vram[(address & 0x1FFFE) >> 1] = ((uint8_t) value) | (value << 8); gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); } + if (gba->video.shouldStall) { + wait += GBAMemoryStallVRAM(gba, wait, 0); + } break; case REGION_OAM: mLOG(GBA_MEM, GAME_ERROR, "Cannot Store8 to OAM: 0x%08X", address); @@ -1658,6 +1677,28 @@ int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) { return wait; } +int32_t GBAMemoryStallVRAM(struct GBA* gba, int32_t wait, int extra) { + UNUSED(extra); + // TODO + uint16_t dispcnt = gba->memory.io[REG_DISPCNT >> 1]; + int32_t stall = 0; + switch (GBARegisterDISPCNTGetMode(dispcnt)) { + case 2: + if (GBARegisterDISPCNTIsBg2Enable(dispcnt) && GBARegisterDISPCNTIsBg3Enable(dispcnt)) { + // If both backgrounds are enabled, VRAM access is entirely blocked during hdraw + stall = mTimingUntil(&gba->timing, &gba->video.event); + } + break; + default: + return 0; + } + stall -= wait; + if (stall < 0) { + return 0; + } + return stall; +} + void GBAMemorySerialize(const struct GBAMemory* memory, struct GBASerializedState* state) { memcpy(state->wram, memory->wram, SIZE_WORKING_RAM); memcpy(state->iwram, memory->iwram, SIZE_WORKING_IRAM); diff --git a/src/gba/video.c b/src/gba/video.c index fdd5d8115..751a49295 100644 --- a/src/gba/video.c +++ b/src/gba/video.c @@ -95,6 +95,7 @@ void GBAVideoReset(struct GBAVideo* video) { video->frameCounter = 0; video->frameskipCounter = 0; video->renderer->vram = video->vram; + video->shouldStall = 0; memset(video->palette, 0, sizeof(video->palette)); memset(video->oam.raw, 0, sizeof(video->oam.raw)); @@ -139,6 +140,7 @@ void _startHdraw(struct mTiming* timing, void* context, uint32_t cyclesLate) { if (video->vcount < GBA_VIDEO_VERTICAL_PIXELS && video->frameskipCounter <= 0) { video->renderer->drawScanline(video->renderer, video->vcount); + video->shouldStall = 1; } GBARegisterDISPSTAT dispstat = video->p->memory.io[REG_DISPSTAT >> 1]; @@ -198,6 +200,7 @@ void _startHblank(struct mTiming* timing, void* context, uint32_t cyclesLate) { if (GBARegisterDISPSTATIsHblankIRQ(dispstat)) { GBARaiseIRQ(video->p, IRQ_HBLANK, cyclesLate); } + video->shouldStall = 0; video->p->memory.io[REG_DISPSTAT >> 1] = dispstat; } @@ -338,6 +341,7 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState } LOAD_32(video->frameCounter, 0, &state->video.frameCounter); + video->shouldStall = 0; int32_t flags; LOAD_32(flags, 0, &state->video.flags); GBARegisterDISPSTAT dispstat = state->io[REG_DISPSTAT >> 1]; @@ -354,6 +358,7 @@ void GBAVideoDeserialize(struct GBAVideo* video, const struct GBASerializedState break; case 2: video->event.callback = _startHblank; + video->shouldStall = 1; break; case 3: video->event.callback = _midHblank; From a42c6aa1f63115ec1851868c5390039ffd55d089 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 3 Jul 2020 03:50:12 -0700 Subject: [PATCH 36/51] FFmpeg: Use range coder for FFV1 to reduce output size --- CHANGES | 1 + src/feature/ffmpeg/ffmpeg-encoder.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index 6d6daa436..3e11a0ec4 100644 --- a/CHANGES +++ b/CHANGES @@ -41,6 +41,7 @@ Other fixes: Misc: - Debugger: Keep track of global cycle count - FFmpeg: Add looping option for GIF/APNG + - FFmpeg: Use range coder for FFV1 to reduce output size - Qt: Renderer can be changed while a game is running - Qt: Add hex index to palette view - Qt: Add transformation matrix info to sprite view diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index ca6272f4f..b47fca6aa 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -383,6 +383,11 @@ bool FFmpegEncoderOpen(struct FFmpegEncoder* encoder, const char* outfile) { // QuickTime and a few other things require YUV420 encoder->video->pix_fmt = AV_PIX_FMT_YUV420P; } +#if LIBAVCODEC_VERSION_MAJOR >= 57 + if (encoder->video->codec->id == AV_CODEC_ID_FFV1) { + av_opt_set(encoder->video->priv_data, "coder", "range_tab", 0); + } +#endif if (strcmp(vcodec->name, "libx264") == 0) { // Try to adaptively figure out when you can use a slower encoder From 8cdd8497ba6f7ac6ded3b8842fe31824eff34863 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 29 Jun 2020 22:11:06 -0700 Subject: [PATCH 37/51] AppVeyor: Add test --- .appveyor.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 000000000..294c63514 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,17 @@ +image: +- Visual Studio 2019 +platform: +- x64 +configuration: +- Release +cache: +- C:\Tools\vcpkg +install: +- git -C C:\Tools\vcpkg pull --quiet +- C:\Tools\vcpkg\bootstrap-vcpkg +- vcpkg --triplet x64-windows install ffmpeg libepoxy libpng libzip sdl2 sqlite3 +before_build: +- cmake . -DCMAKE_PREFIX_PATH=C:\Qt\5.12\msvc2017_64 -DCMAKE_TOOLCHAIN_FILE=C:\Tools\vcpkg\scripts\buildsystems\vcpkg.cmake +build: + parallel: true + project: mGBA.sln From 136cc9b9cefa12e157920ce89ed4653c02d1387b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jul 2020 17:39:17 -0700 Subject: [PATCH 38/51] AppVeyor: Slightly better cleanup --- .appveyor.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.appveyor.yml b/.appveyor.yml index 294c63514..f946baef8 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -10,6 +10,8 @@ install: - git -C C:\Tools\vcpkg pull --quiet - C:\Tools\vcpkg\bootstrap-vcpkg - vcpkg --triplet x64-windows install ffmpeg libepoxy libpng libzip sdl2 sqlite3 +- vcpkg --no-dry-run upgrade +- rd /Q /S C:\Tools\vcpkg\buildtrees before_build: - cmake . -DCMAKE_PREFIX_PATH=C:\Qt\5.12\msvc2017_64 -DCMAKE_TOOLCHAIN_FILE=C:\Tools\vcpkg\scripts\buildsystems\vcpkg.cmake build: From ed976920fdd8a5a1c6091228fa351423b641c272 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 5 Jul 2020 20:11:36 -0700 Subject: [PATCH 39/51] Qt: Fix logging config section width --- src/platform/qt/RotatedHeaderView.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/qt/RotatedHeaderView.cpp b/src/platform/qt/RotatedHeaderView.cpp index 15d927628..dd4ed52df 100644 --- a/src/platform/qt/RotatedHeaderView.cpp +++ b/src/platform/qt/RotatedHeaderView.cpp @@ -12,6 +12,8 @@ using namespace QGBA; RotatedHeaderView::RotatedHeaderView(Qt::Orientation orientation, QWidget* parent) : QHeaderView(orientation, parent) { + int margin = 2 * style()->pixelMetric(QStyle::PM_HeaderMargin, 0, this); + setMinimumSectionSize(fontMetrics().height() + margin); } void RotatedHeaderView::paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const { From 7762b8c5980557fc2f7a4db1bf743a609ae7a806 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jul 2020 00:22:11 -0700 Subject: [PATCH 40/51] Third-Party: Update inih --- README.md | 2 +- src/third-party/inih/LICENSE.txt | 0 src/third-party/inih/README.md | 61 +++++++++++- src/third-party/inih/ini.c | 157 +++++++++++++++++++++++++------ src/third-party/inih/ini.h | 81 ++++++++++++++-- 5 files changed, 260 insertions(+), 41 deletions(-) mode change 100755 => 100644 src/third-party/inih/LICENSE.txt mode change 100755 => 100644 src/third-party/inih/README.md mode change 100755 => 100644 src/third-party/inih/ini.c mode change 100755 => 100644 src/third-party/inih/ini.h diff --git a/README.md b/README.md index 2ed176151..f5f005d35 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ mGBA is Copyright © 2013 – 2020 Jeffrey Pfau. It is distributed under the [Mo mGBA contains the following third-party libraries: -- [inih](https://github.com/benhoyt/inih), which is copyright © 2009 Ben Hoyt and used under a BSD 3-clause license. +- [inih](https://github.com/benhoyt/inih), which is copyright © 2009 – 2020 Ben Hoyt and used under a BSD 3-clause license. - [blip-buf](https://code.google.com/archive/p/blip-buf), which is copyright © 2003 – 2009 Shay Green and used under a Lesser GNU Public License. - [LZMA SDK](http://www.7-zip.org/sdk.html), which is public domain. - [MurmurHash3](https://github.com/aappleby/smhasher) implementation by Austin Appleby, which is public domain. diff --git a/src/third-party/inih/LICENSE.txt b/src/third-party/inih/LICENSE.txt old mode 100755 new mode 100644 diff --git a/src/third-party/inih/README.md b/src/third-party/inih/README.md old mode 100755 new mode 100644 index d32dfe4a5..dc587beb1 --- a/src/third-party/inih/README.md +++ b/src/third-party/inih/README.md @@ -1,20 +1,40 @@ +# inih (INI Not Invented Here) + +[![TravisCI Build](https://travis-ci.org/benhoyt/inih.svg)](https://travis-ci.org/benhoyt/inih) + **inih (INI Not Invented Here)** is a simple [.INI file](http://en.wikipedia.org/wiki/INI_file) parser written in C. It's only a couple of pages of code, and it was designed to be _small and simple_, so it's good for embedded systems. It's also more or less compatible with Python's [ConfigParser](http://docs.python.org/library/configparser.html) style of .INI files, including RFC 822-style multi-line syntax and `name: value` entries. To use it, just give `ini_parse()` an INI file, and it will call a callback for every `name=value` pair parsed, giving you strings for the section, name, and value. It's done this way ("SAX style") because it works well on low-memory embedded systems, but also because it makes for a KISS implementation. -You can also call `ini_parse_file()` to parse directly from a `FILE*` object, or `ini_parse_stream()` to parse using a custom reader to implement string-based or other custom I/O ([see example code](https://github.com/benhoyt/inih/blob/master/examples/ini_buffer.c)). +You can also call `ini_parse_file()` to parse directly from a `FILE*` object, `ini_parse_string()` to parse data from a string, or `ini_parse_stream()` to parse using a custom fgets-style reader function for custom I/O. Download a release, browse the source, or read about [how to use inih in a DRY style](http://blog.brush.co.nz/2009/08/xmacros/) with X-Macros. ## Compile-time options ## +You can control various aspects of inih using preprocessor defines: + +### Syntax options ### + * **Multi-line entries:** By default, inih supports multi-line entries in the style of Python's ConfigParser. To disable, add `-DINI_ALLOW_MULTILINE=0`. * **UTF-8 BOM:** By default, inih allows a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of INI files. To disable, add `-DINI_ALLOW_BOM=0`. - * **Stack vs heap:** By default, inih allocates its line buffer on the stack. To allocate on the heap using `malloc` instead, specify `-DINI_USE_STACK=0`. - * **Stop on first error:** By default, inih keeps parsing the rest of the file after an error. To stop parsing on the first error, add `-DINI_STOP_ON_FIRST_ERROR=1`. - * **Maximum line length:** The default maximum line length is 200 bytes. To override this, add something like `-DINI_MAX_LINE=1000`. + * **Inline comments:** By default, inih allows inline comments with the `;` character. To disable, add `-DINI_ALLOW_INLINE_COMMENTS=0`. You can also specify which character(s) start an inline comment using `INI_INLINE_COMMENT_PREFIXES`. + * **Start-of-line comments:** By default, inih allows both `;` and `#` to start a comment at the beginning of a line. You can override this by changing `INI_START_COMMENT_PREFIXES`. + * **Allow no value:** By default, inih treats a name with no value (no `=` or `:` on the line) as an error. To allow names with no values, add `-DINI_ALLOW_NO_VALUE=1`, and inih will call your handler function with value set to NULL. +### Parsing options ### + + * **Stop on first error:** By default, inih keeps parsing the rest of the file after an error. To stop parsing on the first error, add `-DINI_STOP_ON_FIRST_ERROR=1`. + * **Report line numbers:** By default, the `ini_handler` callback doesn't receive the line number as a parameter. If you need that, add `-DINI_HANDLER_LINENO=1`. + * **Call handler on new section:** By default, inih only calls the handler on each `name=value` pair. To detect new sections (e.g., the INI file has multiple sections with the same name), add `-DINI_CALL_HANDLER_ON_NEW_SECTION=1`. Your handler function will then be called each time a new section is encountered, with `section` set to the new section name but `name` and `value` set to NULL. + +### Memory options ### + + * **Stack vs heap:** By default, inih creates a fixed-sized line buffer on the stack. To allocate on the heap using `malloc` instead, specify `-DINI_USE_STACK=0`. + * **Maximum line length:** The default maximum line length (for stack or heap) is 200 bytes. To override this, add something like `-DINI_MAX_LINE=1000`. Note that `INI_MAX_LINE` must be 3 more than the longest line (due to `\r`, `\n`, and the NUL). + * **Initial malloc size:** `INI_INITIAL_ALLOC` specifies the initial malloc size when using the heap. It defaults to 200 bytes. + * **Allow realloc:** By default when using the heap (`-DINI_USE_STACK=0`), inih allocates a fixed-sized buffer of `INI_INITIAL_ALLOC` bytes. To allow this to grow to `INI_MAX_LINE` bytes, doubling if needed, set `-DINI_ALLOW_REALLOC=1`. ## Simple example in C ## @@ -102,3 +122,36 @@ Some differences between inih and Python's [ConfigParser](http://docs.python.org * INI name=value pairs given above any section headers are treated as valid items with no section (section name is an empty string). In ConfigParser having no section is an error. * Line continuations are handled with leading whitespace on continued lines (like ConfigParser). However, instead of concatenating continued lines together, they are treated as separate values for the same key (unlike ConfigParser). + + +## Platform-specific notes ## + +* Windows/Win32 uses UTF-16 filenames natively, so to handle Unicode paths you need to call `_wfopen()` to open a file and then `ini_parse_file()` to parse it; inih does not include `wchar_t` or Unicode handling. + +## Meson notes ## + +* The `meson.build` file is not required to use or compile inih, its main purpose is for distributions. +* By default Meson only creates a static library for inih, but Meson can be used to configure this behavior: +* with `-Ddefault_library=shared` a shared library is build. +* with `-Ddistro_install=true` the library will be installed with the header and a pkg-config entry, you may want to set `-Ddefault_library=shared` when using this. +* with `-Dwith_INIReader` you can build (and install if selected) the C++ library. +* all compile-time options are implemented in Meson as well, you can take a look at [meson_options.txt](https://github.com/benhoyt/inih/blob/master/meson_options.txt) for their definition. These won't work if `distro_install` is set to `true`. +* If you want to use inih for programs which may be shipped in a distro, consider linking against the shared libraries. The pkg-config entries are `inih` and `INIReader`. +* In case you use inih as a subproject, you can use the `inih_dep` and `INIReader_dep` dependency variables. + +## Building from vcpkg ## + +You can build and install inih using [vcpkg](https://github.com/microsoft/vcpkg/) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install inih + +The inih port in vcpkg is kept up to date by microsoft team members and community contributors. +If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + +## Related links ## + +* [Conan package for inih](https://github.com/mohamedghita/conan-inih) (Conan is a C/C++ package manager) diff --git a/src/third-party/inih/ini.c b/src/third-party/inih/ini.c old mode 100755 new mode 100644 index 932efba8c..ad040fa4e --- a/src/third-party/inih/ini.c +++ b/src/third-party/inih/ini.c @@ -1,5 +1,9 @@ /* inih -- simple .INI file parser +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2020, Ben Hoyt + inih is released under the New BSD license (see LICENSE.txt). Go to the project home page for more info: @@ -7,7 +11,7 @@ https://github.com/benhoyt/inih */ -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS #endif @@ -24,6 +28,12 @@ https://github.com/benhoyt/inih #define MAX_SECTION 128 #define MAX_NAME 128 +/* Used by ini_parse_string() to keep track of string parsing state. */ +typedef struct { + const char* ptr; + size_t num_left; +} ini_parse_string_ctx; + /* Strip whitespace chars off end of given string, in place. Return s. */ static char* rstrip(char* s) { @@ -41,24 +51,35 @@ static char* lskip(const char* s) return (char*)s; } -/* Return pointer to first char c or ';' comment in given string, or pointer to - null at end of string if neither found. ';' must be prefixed by a whitespace - character to register as a comment. */ -static char* find_char_or_comment(const char* s, char c) +/* Return pointer to first char (of chars) or inline comment in given string, + or pointer to NUL at end of string if neither found. Inline comment must + be prefixed by a whitespace character to register as a comment. */ +static char* find_chars_or_comment(const char* s, const char* chars) { - int was_whitespace = 0; - while (*s && *s != c && !(was_whitespace && *s == ';')) { - was_whitespace = isspace((unsigned char)(*s)); +#if INI_ALLOW_INLINE_COMMENTS + int was_space = 0; + while (*s && (!chars || !strchr(chars, *s)) && + !(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) { + was_space = isspace((unsigned char)(*s)); s++; } +#else + while (*s && (!chars || !strchr(chars, *s))) { + s++; + } +#endif return (char*)s; } -/* Version of strncpy that ensures dest (size bytes) is null-terminated. */ +/* Similar to strncpy, but ensures dest (size bytes) is + NUL-terminated, and doesn't pad with NULs. */ static char* strncpy0(char* dest, const char* src, size_t size) { - strncpy(dest, src, size); - dest[size - 1] = '\0'; + /* Could use strncpy internally, but it causes gcc warnings (see issue #91) */ + size_t i; + for (i = 0; i < size - 1 && src[i]; i++) + dest[i] = src[i]; + dest[i] = '\0'; return dest; } @@ -69,8 +90,14 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, /* Uses a fair bit of stack (use heap instead if you need to) */ #if INI_USE_STACK char line[INI_MAX_LINE]; + int max_line = INI_MAX_LINE; #else char* line; + size_t max_line = INI_INITIAL_ALLOC; +#endif +#if INI_ALLOW_REALLOC && !INI_USE_STACK + char* new_line; + size_t offset; #endif char section[MAX_SECTION] = ""; char prev_name[MAX_NAME] = ""; @@ -83,14 +110,40 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, int error = 0; #if !INI_USE_STACK - line = (char*)malloc(INI_MAX_LINE); + line = (char*)malloc(INI_INITIAL_ALLOC); if (!line) { return -2; } #endif +#if INI_HANDLER_LINENO +#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno) +#else +#define HANDLER(u, s, n, v) handler(u, s, n, v) +#endif + /* Scan through stream line by line */ - while (reader(line, INI_MAX_LINE, stream) != NULL) { + while (reader(line, (int)max_line, stream) != NULL) { +#if INI_ALLOW_REALLOC && !INI_USE_STACK + offset = strlen(line); + while (offset == max_line - 1 && line[offset - 1] != '\n') { + max_line *= 2; + if (max_line > INI_MAX_LINE) + max_line = INI_MAX_LINE; + new_line = realloc(line, max_line); + if (!new_line) { + free(line); + return -2; + } + line = new_line; + if (reader(line + offset, (int)(max_line - offset), stream) == NULL) + break; + if (max_line >= INI_MAX_LINE) + break; + offset += strlen(line + offset); + } +#endif + lineno++; start = line; @@ -103,53 +156,64 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, #endif start = lskip(rstrip(start)); - if (*start == ';' || *start == '#') { - /* Per Python ConfigParser, allow '#' comments at start of line */ + if (strchr(INI_START_COMMENT_PREFIXES, *start)) { + /* Start-of-line comment */ } #if INI_ALLOW_MULTILINE else if (*prev_name && *start && start > line) { - /* Non-black line with leading whitespace, treat as continuation - of previous name's value (as per Python ConfigParser). */ - if (!handler(user, section, prev_name, start) && !error) + /* Non-blank line with leading whitespace, treat as continuation + of previous name's value (as per Python configparser). */ + if (!HANDLER(user, section, prev_name, start) && !error) error = lineno; } #endif else if (*start == '[') { /* A "[section]" line */ - end = find_char_or_comment(start + 1, ']'); + end = find_chars_or_comment(start + 1, "]"); if (*end == ']') { *end = '\0'; strncpy0(section, start + 1, sizeof(section)); *prev_name = '\0'; +#if INI_CALL_HANDLER_ON_NEW_SECTION + if (!HANDLER(user, section, NULL, NULL) && !error) + error = lineno; +#endif } else if (!error) { /* No ']' found on section line */ error = lineno; } } - else if (*start && *start != ';') { + else if (*start) { /* Not a comment, must be a name[=:]value pair */ - end = find_char_or_comment(start, '='); - if (*end != '=') { - end = find_char_or_comment(start, ':'); - } + end = find_chars_or_comment(start, "=:"); if (*end == '=' || *end == ':') { *end = '\0'; name = rstrip(start); - value = lskip(end + 1); - end = find_char_or_comment(value, '\0'); - if (*end == ';') + value = end + 1; +#if INI_ALLOW_INLINE_COMMENTS + end = find_chars_or_comment(value, NULL); + if (*end) *end = '\0'; +#endif + value = lskip(value); rstrip(value); /* Valid name[=:]value pair found, call handler */ strncpy0(prev_name, name, sizeof(prev_name)); - if (!handler(user, section, name, value) && !error) + if (!HANDLER(user, section, name, value) && !error) error = lineno; } else if (!error) { /* No '=' or ':' found on name[=:]value line */ +#if INI_ALLOW_NO_VALUE + *end = '\0'; + name = rstrip(start); + if (!HANDLER(user, section, name, NULL) && !error) + error = lineno; +#else error = lineno; +#endif } } @@ -185,3 +249,40 @@ int ini_parse(const char* filename, ini_handler handler, void* user) fclose(file); return error; } + +/* An ini_reader function to read the next line from a string buffer. This + is the fgets() equivalent used by ini_parse_string(). */ +static char* ini_reader_string(char* str, int num, void* stream) { + ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream; + const char* ctx_ptr = ctx->ptr; + size_t ctx_num_left = ctx->num_left; + char* strp = str; + char c; + + if (ctx_num_left == 0 || num < 2) + return NULL; + + while (num > 1 && ctx_num_left != 0) { + c = *ctx_ptr++; + ctx_num_left--; + *strp++ = c; + if (c == '\n') + break; + num--; + } + + *strp = '\0'; + ctx->ptr = ctx_ptr; + ctx->num_left = ctx_num_left; + return str; +} + +/* See documentation in header file. */ +int ini_parse_string(const char* string, ini_handler handler, void* user) { + ini_parse_string_ctx ctx; + + ctx.ptr = string; + ctx.num_left = strlen(string); + return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, + user); +} diff --git a/src/third-party/inih/ini.h b/src/third-party/inih/ini.h old mode 100755 new mode 100644 index d75196f26..441f560bb --- a/src/third-party/inih/ini.h +++ b/src/third-party/inih/ini.h @@ -1,5 +1,9 @@ /* inih -- simple .INI file parser +SPDX-License-Identifier: BSD-3-Clause + +Copyright (C) 2009-2020, Ben Hoyt + inih is released under the New BSD license (see LICENSE.txt). Go to the project home page for more info: @@ -17,9 +21,20 @@ extern "C" { #include +/* Nonzero if ini_handler callback should accept lineno parameter. */ +#ifndef INI_HANDLER_LINENO +#define INI_HANDLER_LINENO 0 +#endif + /* Typedef for prototype of handler function. */ +#if INI_HANDLER_LINENO +typedef int (*ini_handler)(void* user, const char* section, + const char* name, const char* value, + int lineno); +#else typedef int (*ini_handler)(void* user, const char* section, const char* name, const char* value); +#endif /* Typedef for prototype of fgets-style reader function. */ typedef char* (*ini_reader)(char* str, int num, void* stream); @@ -27,7 +42,7 @@ typedef char* (*ini_reader)(char* str, int num, void* stream); /* Parse given INI-style file. May have [section]s, name=value pairs (whitespace stripped), and comments starting with ';' (semicolon). Section is "" if name=value pair parsed before any section heading. name:value - pairs are also supported as a concession to Python's ConfigParser. + pairs are also supported as a concession to Python's configparser. For each name=value pair parsed, call handler function with given user pointer as well as section, name, and value (data only valid for duration @@ -44,36 +59,86 @@ int ini_parse(const char* filename, ini_handler handler, void* user); int ini_parse_file(FILE* file, ini_handler handler, void* user); /* Same as ini_parse(), but takes an ini_reader function pointer instead of - filename. Used for implementing custom or string-based I/O. */ + filename. Used for implementing custom or string-based I/O (see also + ini_parse_string). */ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler, void* user); +/* Same as ini_parse(), but takes a zero-terminated string with the INI data +instead of a file. Useful for parsing INI data from a network socket or +already in memory. */ +int ini_parse_string(const char* string, ini_handler handler, void* user); + /* Nonzero to allow multi-line value parsing, in the style of Python's - ConfigParser. If allowed, ini_parse() will call the handler with the same + configparser. If allowed, ini_parse() will call the handler with the same name for each subsequent line parsed. */ #ifndef INI_ALLOW_MULTILINE #define INI_ALLOW_MULTILINE 1 #endif /* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of - the file. See http://code.google.com/p/inih/issues/detail?id=21 */ + the file. See https://github.com/benhoyt/inih/issues/21 */ #ifndef INI_ALLOW_BOM #define INI_ALLOW_BOM 1 #endif -/* Nonzero to use stack, zero to use heap (malloc/free). */ +/* Chars that begin a start-of-line comment. Per Python configparser, allow + both ; and # comments at the start of a line by default. */ +#ifndef INI_START_COMMENT_PREFIXES +#define INI_START_COMMENT_PREFIXES ";#" +#endif + +/* Nonzero to allow inline comments (with valid inline comment characters + specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match + Python 3.2+ configparser behaviour. */ +#ifndef INI_ALLOW_INLINE_COMMENTS +#define INI_ALLOW_INLINE_COMMENTS 1 +#endif +#ifndef INI_INLINE_COMMENT_PREFIXES +#define INI_INLINE_COMMENT_PREFIXES ";" +#endif + +/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */ #ifndef INI_USE_STACK #define INI_USE_STACK 1 #endif +/* Maximum line length for any line in INI file (stack or heap). Note that + this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */ +#ifndef INI_MAX_LINE +#define INI_MAX_LINE 200 +#endif + +/* Nonzero to allow heap line buffer to grow via realloc(), zero for a + fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is + zero. */ +#ifndef INI_ALLOW_REALLOC +#define INI_ALLOW_REALLOC 0 +#endif + +/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK + is zero. */ +#ifndef INI_INITIAL_ALLOC +#define INI_INITIAL_ALLOC 200 +#endif + /* Stop parsing on first error (default is to keep parsing). */ #ifndef INI_STOP_ON_FIRST_ERROR #define INI_STOP_ON_FIRST_ERROR 0 #endif -/* Maximum line length for any line in INI file. */ -#ifndef INI_MAX_LINE -#define INI_MAX_LINE 200 +/* Nonzero to call the handler at the start of each new section (with + name and value NULL). Default is to only call the handler on + each name=value pair. */ +#ifndef INI_CALL_HANDLER_ON_NEW_SECTION +#define INI_CALL_HANDLER_ON_NEW_SECTION 0 +#endif + +/* Nonzero to allow a name without a value (no '=' or ':' on the line) and + call the handler with value NULL in this case. Default is to treat + no-value lines as an error. */ +#ifndef INI_ALLOW_NO_VALUE +#define INI_ALLOW_NO_VALUE 0 #endif #ifdef __cplusplus From 3be21bf5954d73b7714620fd8e389ff94ec68157 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jul 2020 15:16:08 -0700 Subject: [PATCH 41/51] Core: Add missing BUILD_GLES3 flag --- src/core/flags.h.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/flags.h.in b/src/core/flags.h.in index f214c7a8f..273e2c708 100644 --- a/src/core/flags.h.in +++ b/src/core/flags.h.in @@ -15,6 +15,10 @@ #cmakedefine BUILD_GLES2 #endif +#ifndef BUILD_GLES3 +#cmakedefine BUILD_GLES3 +#endif + // Miscellaneous flags #ifndef COLOR_16_BIT From 2f066a979031136e7686ceee91af9e8a2e7cc754 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 6 Jul 2020 16:08:23 -0700 Subject: [PATCH 42/51] Util: Start cleaning up some bounded string copies --- CMakeLists.txt | 5 +++ include/mgba-util/string.h | 4 ++ src/arm/decoder.c | 87 +++++++++++++++++++------------------- src/sm83/decoder.c | 27 ++++++------ src/util/gui/file-select.c | 3 +- src/util/string.c | 17 ++++++++ 6 files changed, 86 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7faef50e0..1cabb0887 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -281,6 +281,7 @@ include(CheckFunctionExists) include(CheckIncludeFiles) check_function_exists(strdup HAVE_STRDUP) check_function_exists(strndup HAVE_STRNDUP) +check_function_exists(strlcpy HAVE_STRLCPY) if(NOT DEFINED PSP2) check_function_exists(localtime_r HAVE_LOCALTIME_R) endif() @@ -359,6 +360,10 @@ if(HAVE_STRNDUP) list(APPEND FUNCTION_DEFINES HAVE_STRNDUP) endif() +if(HAVE_STRLCPY) + list(APPEND FUNCTION_DEFINES HAVE_STRLCPY) +endif() + if(HAVE_LOCALTIME_R) list(APPEND FUNCTION_DEFINES HAVE_LOCALTIME_R) endif() diff --git a/include/mgba-util/string.h b/include/mgba-util/string.h index af8375cca..306a35257 100644 --- a/include/mgba-util/string.h +++ b/include/mgba-util/string.h @@ -19,6 +19,10 @@ char* strndup(const char* start, size_t len); char* strdup(const char* str); #endif +#ifndef HAVE_STRLCPY +size_t strlcpy(char* restrict dst, const char* restrict src, size_t dstsize); +#endif + char* strnrstr(const char* restrict s1, const char* restrict s2, size_t len); bool endswith(const char* restrict s1, const char* restrict end); bool startswith(const char* restrict s1, const char* restrict start); diff --git a/src/arm/decoder.c b/src/arm/decoder.c index b95ff1126..8ebdbcaa0 100644 --- a/src/arm/decoder.c +++ b/src/arm/decoder.c @@ -6,6 +6,7 @@ #include #include +#include #define ADVANCE(AMOUNT) \ if (AMOUNT >= blen) { \ @@ -45,22 +46,22 @@ static const char* _armConditions[] = { static int _decodeRegister(int reg, char* buffer, int blen) { switch (reg) { case ARM_SP: - strncpy(buffer, "sp", blen - 1); + strlcpy(buffer, "sp", blen); return 2; case ARM_LR: - strncpy(buffer, "lr", blen - 1); + strlcpy(buffer, "lr", blen); return 2; case ARM_PC: - strncpy(buffer, "pc", blen - 1); + strlcpy(buffer, "pc", blen); return 2; case ARM_CPSR: - strncpy(buffer, "cpsr", blen - 1); + strlcpy(buffer, "cpsr", blen); return 4; case ARM_SPSR: - strncpy(buffer, "spsr", blen - 1); + strlcpy(buffer, "spsr", blen); return 4; default: - return snprintf(buffer, blen - 1, "r%i", reg); + return snprintf(buffer, blen, "r%i", reg); } } @@ -69,7 +70,7 @@ static int _decodeRegisterList(int list, char* buffer, int blen) { return 0; } int total = 0; - strncpy(buffer, "{", blen - 1); + strlcpy(buffer, "{", blen); ADVANCE(1); int i; int start = -1; @@ -86,12 +87,12 @@ static int _decodeRegisterList(int list, char* buffer, int blen) { if (end > start) { written = _decodeRegister(start, buffer, blen); ADVANCE(written); - strncpy(buffer, "-", blen - 1); + strlcpy(buffer, "-", blen); ADVANCE(1); } written = _decodeRegister(end, buffer, blen); ADVANCE(written); - strncpy(buffer, ",", blen - 1); + strlcpy(buffer, ",", blen); ADVANCE(1); start = i; end = i; @@ -103,13 +104,13 @@ static int _decodeRegisterList(int list, char* buffer, int blen) { if (end > start) { written = _decodeRegister(start, buffer, blen); ADVANCE(written); - strncpy(buffer, "-", blen - 1); + strlcpy(buffer, "-", blen); ADVANCE(1); } written = _decodeRegister(end, buffer, blen); ADVANCE(written); } - strncpy(buffer, "}", blen - 1); + strlcpy(buffer, "}", blen); ADVANCE(1); return total; } @@ -119,29 +120,29 @@ static int _decodePSR(int psrBits, char* buffer, int blen) { return 0; } int total = 0; - strncpy(buffer, "_", blen - 1); + strlcpy(buffer, "_", blen); ADVANCE(1); if (psrBits & ARM_PSR_C) { - strncpy(buffer, "c", blen - 1); + strlcpy(buffer, "c", blen); ADVANCE(1); } if (psrBits & ARM_PSR_X) { - strncpy(buffer, "x", blen - 1); + strlcpy(buffer, "x", blen); ADVANCE(1); } if (psrBits & ARM_PSR_S) { - strncpy(buffer, "s", blen - 1); + strlcpy(buffer, "s", blen); ADVANCE(1); } if (psrBits & ARM_PSR_F) { - strncpy(buffer, "f", blen - 1); + strlcpy(buffer, "f", blen); ADVANCE(1); } return total; } static int _decodePCRelative(uint32_t address, uint32_t pc, char* buffer, int blen) { - return snprintf(buffer, blen - 1, "$%08X", address + pc); + return snprintf(buffer, blen, "$%08X", address + pc); } static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, int blen) { @@ -149,7 +150,7 @@ static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, in return 0; } int total = 0; - strncpy(buffer, "[", blen - 1); + strlcpy(buffer, "[", blen); ADVANCE(1); int written; if (memory.format & ARM_MEMORY_REGISTER_BASE) { @@ -160,26 +161,26 @@ static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, in written = _decodeRegister(memory.baseReg, buffer, blen); ADVANCE(written); if (memory.format & (ARM_MEMORY_REGISTER_OFFSET | ARM_MEMORY_IMMEDIATE_OFFSET) && !(memory.format & ARM_MEMORY_POST_INCREMENT)) { - strncpy(buffer, ", ", blen - 1); + strlcpy(buffer, ", ", blen); ADVANCE(2); } } } if (memory.format & ARM_MEMORY_POST_INCREMENT) { - strncpy(buffer, "], ", blen - 1); + strlcpy(buffer, "], ", blen); ADVANCE(3); } if (memory.format & ARM_MEMORY_IMMEDIATE_OFFSET && memory.baseReg != ARM_PC) { if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) { - written = snprintf(buffer, blen - 1, "#-%i", memory.offset.immediate); + written = snprintf(buffer, blen, "#-%i", memory.offset.immediate); ADVANCE(written); } else { - written = snprintf(buffer, blen - 1, "#%i", memory.offset.immediate); + written = snprintf(buffer, blen, "#%i", memory.offset.immediate); ADVANCE(written); } } else if (memory.format & ARM_MEMORY_REGISTER_OFFSET) { if (memory.format & ARM_MEMORY_OFFSET_SUBTRACT) { - strncpy(buffer, "-", blen - 1); + strlcpy(buffer, "-", blen); ADVANCE(1); } written = _decodeRegister(memory.offset.reg, buffer, blen); @@ -191,11 +192,11 @@ static int _decodeMemory(struct ARMMemoryAccess memory, int pc, char* buffer, in } if (!(memory.format & ARM_MEMORY_POST_INCREMENT)) { - strncpy(buffer, "]", blen - 1); + strlcpy(buffer, "]", blen); ADVANCE(1); } if ((memory.format & (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) == (ARM_MEMORY_PRE_INCREMENT | ARM_MEMORY_WRITEBACK)) { - strncpy(buffer, "!", blen - 1); + strlcpy(buffer, "!", blen); ADVANCE(1); } return total; @@ -206,33 +207,33 @@ static int _decodeShift(union ARMOperand op, bool reg, char* buffer, int blen) { return 0; } int total = 0; - strncpy(buffer, ", ", blen - 1); + strlcpy(buffer, ", ", blen); ADVANCE(2); int written; switch (op.shifterOp) { case ARM_SHIFT_LSL: - strncpy(buffer, "lsl ", blen - 1); + strlcpy(buffer, "lsl ", blen); ADVANCE(4); break; case ARM_SHIFT_LSR: - strncpy(buffer, "lsr ", blen - 1); + strlcpy(buffer, "lsr ", blen); ADVANCE(4); break; case ARM_SHIFT_ASR: - strncpy(buffer, "asr ", blen - 1); + strlcpy(buffer, "asr ", blen); ADVANCE(4); break; case ARM_SHIFT_ROR: - strncpy(buffer, "ror ", blen - 1); + strlcpy(buffer, "ror ", blen); ADVANCE(4); break; case ARM_SHIFT_RRX: - strncpy(buffer, "rrx", blen - 1); + strlcpy(buffer, "rrx", blen); ADVANCE(3); return total; } if (!reg) { - written = snprintf(buffer, blen - 1, "#%i", op.shifterImm); + written = snprintf(buffer, blen, "#%i", op.shifterImm); } else { written = _decodeRegister(op.shifterReg, buffer, blen); } @@ -369,7 +370,7 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i default: break; } - written = snprintf(buffer, blen - 1, "%s%s%s ", mnemonic, cond, flags); + written = snprintf(buffer, blen, "%s%s%s ", mnemonic, cond, flags); ADVANCE(written); switch (info->mnemonic) { @@ -378,15 +379,15 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i written = _decodeRegister(info->memory.baseReg, buffer, blen); ADVANCE(written); if (info->memory.format & ARM_MEMORY_WRITEBACK) { - strncpy(buffer, "!", blen - 1); + strlcpy(buffer, "!", blen); ADVANCE(1); } - strncpy(buffer, ", ", blen - 1); + strlcpy(buffer, ", ", blen); ADVANCE(2); written = _decodeRegisterList(info->op1.immediate, buffer, blen); ADVANCE(written); if (info->memory.format & ARM_MEMORY_SPSR_SWAP) { - strncpy(buffer, "^", blen - 1); + strlcpy(buffer, "^", blen); ADVANCE(1); } break; @@ -399,7 +400,7 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i break; default: if (info->operandFormat & ARM_OPERAND_IMMEDIATE_1) { - written = snprintf(buffer, blen - 1, "#%i", info->op1.immediate); + written = snprintf(buffer, blen, "#%i", info->op1.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_1) { written = _decodeMemory(info->memory, pc, buffer, blen); @@ -420,11 +421,11 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i ADVANCE(written); } if (info->operandFormat & ARM_OPERAND_2) { - strncpy(buffer, ", ", blen); + strlcpy(buffer, ", ", blen); ADVANCE(2); } if (info->operandFormat & ARM_OPERAND_IMMEDIATE_2) { - written = snprintf(buffer, blen - 1, "#%i", info->op2.immediate); + written = snprintf(buffer, blen, "#%i", info->op2.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_2) { written = _decodeMemory(info->memory, pc, buffer, blen); @@ -441,11 +442,11 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i ADVANCE(written); } if (info->operandFormat & ARM_OPERAND_3) { - strncpy(buffer, ", ", blen - 1); + strlcpy(buffer, ", ", blen); ADVANCE(2); } if (info->operandFormat & ARM_OPERAND_IMMEDIATE_3) { - written = snprintf(buffer, blen - 1, "#%i", info->op3.immediate); + written = snprintf(buffer, blen, "#%i", info->op3.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_3) { written = _decodeMemory(info->memory, pc, buffer, blen); @@ -462,11 +463,11 @@ int ARMDisassemble(struct ARMInstructionInfo* info, uint32_t pc, char* buffer, i ADVANCE(written); } if (info->operandFormat & ARM_OPERAND_4) { - strncpy(buffer, ", ", blen - 1); + strlcpy(buffer, ", ", blen); ADVANCE(2); } if (info->operandFormat & ARM_OPERAND_IMMEDIATE_4) { - written = snprintf(buffer, blen - 1, "#%i", info->op4.immediate); + written = snprintf(buffer, blen, "#%i", info->op4.immediate); ADVANCE(written); } else if (info->operandFormat & ARM_OPERAND_MEMORY_4) { written = _decodeMemory(info->memory, pc, buffer, blen); diff --git a/src/sm83/decoder.c b/src/sm83/decoder.c index 949a8119a..7ad565d68 100644 --- a/src/sm83/decoder.c +++ b/src/sm83/decoder.c @@ -7,6 +7,7 @@ #include #include +#include typedef size_t (*SM83Decoder)(uint8_t opcode, struct SM83InstructionInfo* info); @@ -504,39 +505,39 @@ static int _decodeOperand(struct SM83Operand op, uint16_t pc, char* buffer, int return 0; } - strncpy(buffer, " ", blen - 1); + strlcpy(buffer, " ", blen); ADVANCE(1); if (op.flags & SM83_OP_FLAG_MEMORY) { - strncpy(buffer, "[", blen - 1); + strlcpy(buffer, "[", blen); ADVANCE(1); } if (op.reg) { - int written = snprintf(buffer, blen - 1, "%s", _sm83Registers[op.reg]); + int written = snprintf(buffer, blen, "%s", _sm83Registers[op.reg]); ADVANCE(written); } else { int written; if (op.flags & SM83_OP_FLAG_RELATIVE) { - written = snprintf(buffer, blen - 1, "$%04X", pc + (int8_t) op.immediate); + written = snprintf(buffer, blen, "$%04X", pc + (int8_t) op.immediate); } else { - written = snprintf(buffer, blen - 1, "$%02X", op.immediate); + written = snprintf(buffer, blen, "$%02X", op.immediate); } ADVANCE(written); if (op.reg) { - strncpy(buffer, "+", blen - 1); + strlcpy(buffer, "+", blen); ADVANCE(1); } } if (op.flags & SM83_OP_FLAG_INCREMENT) { - strncpy(buffer, "+", blen - 1); + strlcpy(buffer, "+", blen); ADVANCE(1); } if (op.flags & SM83_OP_FLAG_DECREMENT) { - strncpy(buffer, "-", blen - 1); + strlcpy(buffer, "-", blen); ADVANCE(1); } if (op.flags & SM83_OP_FLAG_MEMORY) { - strncpy(buffer, "]", blen - 1); + strlcpy(buffer, "]", blen); ADVANCE(1); } return total; @@ -548,15 +549,15 @@ int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, int total = 0; const char* cond = _sm83Conditions[info->condition]; - written = snprintf(buffer, blen - 1, "%s", mnemonic); + written = snprintf(buffer, blen, "%s", mnemonic); ADVANCE(written); if (cond) { - written = snprintf(buffer, blen - 1, " %s", cond); + written = snprintf(buffer, blen, " %s", cond); ADVANCE(written); if (info->op1.reg || info->op1.immediate || info->op2.reg || info->op2.immediate) { - strncpy(buffer, ",", blen - 1); + strlcpy(buffer, ",", blen); ADVANCE(1); } } @@ -568,7 +569,7 @@ int SM83Disassemble(struct SM83InstructionInfo* info, uint16_t pc, char* buffer, if (info->op2.reg || (!info->op1.immediate && info->opcodeSize > 1 && info->opcode[0] != 0xCB)) { if (written) { - strncpy(buffer, ",", blen - 1); + strlcpy(buffer, ",", blen); ADVANCE(1); } written = _decodeOperand(info->op2, pc, buffer, blen); diff --git a/src/util/gui/file-select.c b/src/util/gui/file-select.c index 2e6abaed5..1d75e88b9 100644 --- a/src/util/gui/file-select.c +++ b/src/util/gui/file-select.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -200,7 +201,7 @@ bool GUISelectFile(struct GUIParams* params, char* outPath, size_t outLen, bool _cleanFiles(&menu.items); GUIMenuItemListDeinit(&menu.items); menu.items = newFiles; - strncpy(params->currentPath, outPath, PATH_MAX); + strlcpy(params->currentPath, outPath, PATH_MAX); } } params->fileIndex = 0; diff --git a/src/util/string.c b/src/util/string.c index 46e52fba7..102a8cfbc 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -31,6 +31,23 @@ char* strdup(const char* str) { } #endif +#ifndef HAVE_STRLCPY +size_t strlcpy(char* restrict dst, const char* restrict src, size_t dstsize) { + size_t i = 0; + for (; src[i] && dstsize > 1; ++i) { + dst[i] = src[i]; + --dstsize; + } + if (dstsize) { + dst[i] = '\0'; + } + while (src[i]) { + ++i; + } + return i; +} +#endif + char* strnrstr(const char* restrict haystack, const char* restrict needle, size_t len) { char* last = 0; const char* next = haystack; From 029b0b937a098f1a202e0c3dfc626458b66dcb43 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jul 2020 18:02:34 -0700 Subject: [PATCH 43/51] All: Use calloc instead of malloc in several places --- include/mgba-util/vector.h | 2 +- src/core/bitmap-cache.c | 2 +- src/core/input.c | 6 +++--- src/core/tile-cache.c | 4 ++-- src/debugger/cli-debugger.c | 2 +- src/platform/3ds/gui-font.c | 2 +- src/platform/opengl/gles2.c | 4 ++-- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/mgba-util/vector.h b/include/mgba-util/vector.h index c18b6c8b5..c73644cfa 100644 --- a/include/mgba-util/vector.h +++ b/include/mgba-util/vector.h @@ -41,7 +41,7 @@ CXX_GUARD_START capacity = 4; \ } \ vector->capacity = capacity; \ - vector->vector = malloc(sizeof(TYPE) * capacity); \ + vector->vector = calloc(capacity, sizeof(TYPE)); \ } \ void NAME ## Deinit(struct NAME* vector) { \ free(vector->vector); \ diff --git a/src/core/bitmap-cache.c b/src/core/bitmap-cache.c index cdbc90a0e..81aa84ffe 100644 --- a/src/core/bitmap-cache.c +++ b/src/core/bitmap-cache.c @@ -42,7 +42,7 @@ static void _redoCacheSize(struct mBitmapCache* cache) { cache->cache = anonymousMemoryMap(mBitmapCacheSystemInfoGetWidth(cache->sysConfig) * size * sizeof(color_t)); cache->status = anonymousMemoryMap(size * sizeof(*cache->status)); if (mBitmapCacheSystemInfoIsUsesPalette(cache->sysConfig)) { - cache->palette = malloc((1 << (1 << mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig))) * sizeof(color_t)); + cache->palette = calloc((1 << (1 << mBitmapCacheSystemInfoGetEntryBPP(cache->sysConfig))), sizeof(color_t)); } else { cache->palette = NULL; } diff --git a/src/core/input.c b/src/core/input.c index fe24d0822..307fed216 100644 --- a/src/core/input.c +++ b/src/core/input.c @@ -88,7 +88,7 @@ static struct mInputMapImpl* _guaranteeMap(struct mInputMap* map, uint32_t type) map->numMaps = 1; impl = &map->maps[0]; impl->type = type; - impl->map = malloc(map->info->nKeys * sizeof(int)); + impl->map = calloc(map->info->nKeys, sizeof(int)); size_t i; for (i = 0; i < map->info->nKeys; ++i) { impl->map[i] = -1; @@ -108,7 +108,7 @@ static struct mInputMapImpl* _guaranteeMap(struct mInputMap* map, uint32_t type) } if (impl) { impl->type = type; - impl->map = malloc(map->info->nKeys * sizeof(int)); + impl->map = calloc(map->info->nKeys, sizeof(int)); size_t i; for (i = 0; i < map->info->nKeys; ++i) { impl->map[i] = -1; @@ -122,7 +122,7 @@ static struct mInputMapImpl* _guaranteeMap(struct mInputMap* map, uint32_t type) map->numMaps *= 2; impl = &map->maps[m]; impl->type = type; - impl->map = malloc(map->info->nKeys * sizeof(int)); + impl->map = calloc(map->info->nKeys, sizeof(int)); size_t i; for (i = 0; i < map->info->nKeys; ++i) { impl->map[i] = -1; diff --git a/src/core/tile-cache.c b/src/core/tile-cache.c index 89b4a52cb..249cd0116 100644 --- a/src/core/tile-cache.c +++ b/src/core/tile-cache.c @@ -46,8 +46,8 @@ static void _redoCacheSize(struct mTileCache* cache) { unsigned tiles = mTileCacheSystemInfoGetMaxTiles(cache->sysConfig); cache->cache = anonymousMemoryMap(8 * 8 * sizeof(color_t) * tiles * size); cache->status = anonymousMemoryMap(tiles * size * sizeof(*cache->status)); - cache->globalPaletteVersion = malloc(size * sizeof(*cache->globalPaletteVersion)); - cache->palette = malloc(size * bpp * sizeof(*cache->palette)); + cache->globalPaletteVersion = calloc(size, sizeof(*cache->globalPaletteVersion)); + cache->palette = calloc(size * bpp, sizeof(*cache->palette)); } void mTileCacheConfigure(struct mTileCache* cache, mTileCacheConfiguration config) { diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index ad125e04c..ddac46952 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -174,7 +174,7 @@ static bool _parseExpression(struct mDebugger* debugger, struct CLIDebugVector* for (accum = dv; accum; accum = accum->next) { ++args; } - const char** arglist = malloc(sizeof(const char*) * (args + 1)); + const char** arglist = calloc(args + 1, sizeof(const char*)); args = 0; for (accum = dv; accum; accum = accum->next) { arglist[args] = accum->charValue; diff --git a/src/platform/3ds/gui-font.c b/src/platform/3ds/gui-font.c index 761cd7c55..4d4a4f01e 100644 --- a/src/platform/3ds/gui-font.c +++ b/src/platform/3ds/gui-font.c @@ -31,7 +31,7 @@ struct GUIFont* GUIFontCreate(void) { guiFont->font = fontGetSystemFont(); TGLP_s* glyphInfo = fontGetGlyphInfo(guiFont->font); guiFont->size = FONT_SIZE / glyphInfo->cellHeight; - guiFont->sheets = malloc(sizeof(*guiFont->sheets) * glyphInfo->nSheets); + guiFont->sheets = calloc(glyphInfo->nSheets, sizeof(*guiFont->sheets)); int i; for (i = 0; i < glyphInfo->nSheets; ++i) { diff --git a/src/platform/opengl/gles2.c b/src/platform/opengl/gles2.c index fbb0fa601..a8052cab1 100644 --- a/src/platform/opengl/gles2.c +++ b/src/platform/opengl/gles2.c @@ -921,7 +921,7 @@ bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { success = false; } if (success) { - struct mGLES2Shader* shaderBlock = malloc(sizeof(struct mGLES2Shader) * inShaders); + struct mGLES2Shader* shaderBlock = calloc(inShaders, sizeof(struct mGLES2Shader)); int n; for (n = 0; n < inShaders; ++n) { char passName[12]; @@ -980,7 +980,7 @@ bool mGLES2ShaderLoad(struct VideoShader* shader, struct VDir* dir) { } } u = mGLES2UniformListSize(&uniformVector); - struct mGLES2Uniform* uniformBlock = malloc(sizeof(*uniformBlock) * u); + struct mGLES2Uniform* uniformBlock = calloc(u, sizeof(*uniformBlock)); memcpy(uniformBlock, mGLES2UniformListGetPointer(&uniformVector, 0), sizeof(*uniformBlock) * u); mGLES2UniformListDeinit(&uniformVector); From 66be69151c55b9411c78435324a7d491e65203a2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jul 2020 18:03:29 -0700 Subject: [PATCH 44/51] GBA Video: Move some macros out of a header --- src/gba/renderers/software-bg.c | 52 ++++++++++++++++++++++++++++ src/gba/renderers/software-private.h | 52 ---------------------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/gba/renderers/software-bg.c b/src/gba/renderers/software-bg.c index 742e126b5..dea3388b0 100644 --- a/src/gba/renderers/software-bg.c +++ b/src/gba/renderers/software-bg.c @@ -8,6 +8,58 @@ #include #include +#define BACKGROUND_BITMAP_INIT \ + int32_t x = background->sx + (renderer->start - 1) * background->dx; \ + int32_t y = background->sy + (renderer->start - 1) * background->dy; \ + int mosaicH = 0; \ + int mosaicWait = 0; \ + if (background->mosaic) { \ + int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1; \ + y -= (inY % mosaicV) * background->dmy; \ + x -= (inY % mosaicV) * background->dmx; \ + mosaicH = GBAMosaicControlGetBgH(renderer->mosaic); \ + mosaicWait = renderer->start % (mosaicH + 1); \ + } \ + int32_t localX; \ + int32_t localY; \ + \ + uint32_t flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \ + flags |= FLAG_TARGET_2 * background->target2; \ + int objwinFlags = FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \ + GBAWindowControlIsBlendEnable(renderer->objwin.packed)); \ + objwinFlags |= flags; \ + flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \ + GBAWindowControlIsBlendEnable(renderer->currentWindow.packed)); \ + if (renderer->blendEffect == BLEND_ALPHA && renderer->blda == 0x10 && renderer->bldb == 0) { \ + flags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \ + objwinFlags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \ + } \ + int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && \ + (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \ + color_t* palette = renderer->normalPalette; \ + if (renderer->d.highlightAmount && background->highlight) { \ + palette = renderer->highlightPalette; \ + } \ + if (variant) { \ + palette = renderer->variantPalette; \ + if (renderer->d.highlightAmount && background->highlight) { \ + palette = renderer->highlightVariantPalette; \ + } \ + } \ + UNUSED(palette); \ + PREPARE_OBJWIN; + +#define BACKGROUND_BITMAP_ITERATE(W, H) \ + x += background->dx; \ + y += background->dy; \ + \ + if (x < 0 || y < 0 || (x >> 8) >= W || (y >> 8) >= H) { \ + continue; \ + } else { \ + localX = x; \ + localY = y; \ + } + #define MODE_2_COORD_OVERFLOW \ localX = x & (sizeAdjusted - 1); \ localY = y & (sizeAdjusted - 1); \ diff --git a/src/gba/renderers/software-private.h b/src/gba/renderers/software-private.h index 07e588439..87fa9aaa7 100644 --- a/src/gba/renderers/software-private.h +++ b/src/gba/renderers/software-private.h @@ -177,58 +177,6 @@ static inline void _compositeNoBlendNoObjwin(struct GBAVideoSoftwareRenderer* re } \ } -#define BACKGROUND_BITMAP_INIT \ - int32_t x = background->sx + (renderer->start - 1) * background->dx; \ - int32_t y = background->sy + (renderer->start - 1) * background->dy; \ - int mosaicH = 0; \ - int mosaicWait = 0; \ - if (background->mosaic) { \ - int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1; \ - y -= (inY % mosaicV) * background->dmy; \ - x -= (inY % mosaicV) * background->dmx; \ - mosaicH = GBAMosaicControlGetBgH(renderer->mosaic); \ - mosaicWait = renderer->start % (mosaicH + 1); \ - } \ - int32_t localX; \ - int32_t localY; \ - \ - uint32_t flags = (background->priority << OFFSET_PRIORITY) | (background->index << OFFSET_INDEX) | FLAG_IS_BACKGROUND; \ - flags |= FLAG_TARGET_2 * background->target2; \ - int objwinFlags = FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \ - GBAWindowControlIsBlendEnable(renderer->objwin.packed)); \ - objwinFlags |= flags; \ - flags |= FLAG_TARGET_1 * (background->target1 && renderer->blendEffect == BLEND_ALPHA && \ - GBAWindowControlIsBlendEnable(renderer->currentWindow.packed)); \ - if (renderer->blendEffect == BLEND_ALPHA && renderer->blda == 0x10 && renderer->bldb == 0) { \ - flags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \ - objwinFlags &= ~(FLAG_TARGET_1 | FLAG_TARGET_2); \ - } \ - int variant = background->target1 && GBAWindowControlIsBlendEnable(renderer->currentWindow.packed) && \ - (renderer->blendEffect == BLEND_BRIGHTEN || renderer->blendEffect == BLEND_DARKEN); \ - color_t* palette = renderer->normalPalette; \ - if (renderer->d.highlightAmount && background->highlight) { \ - palette = renderer->highlightPalette; \ - } \ - if (variant) { \ - palette = renderer->variantPalette; \ - if (renderer->d.highlightAmount && background->highlight) { \ - palette = renderer->highlightVariantPalette; \ - } \ - } \ - UNUSED(palette); \ - PREPARE_OBJWIN; - -#define BACKGROUND_BITMAP_ITERATE(W, H) \ - x += background->dx; \ - y += background->dy; \ - \ - if (x < 0 || y < 0 || (x >> 8) >= W || (y >> 8) >= H) { \ - continue; \ - } else { \ - localX = x; \ - localY = y; \ - } - static inline unsigned _brighten(unsigned color, int y) { unsigned c = 0; unsigned a; From 6a7bec5eecdaf5226ff38ed3bdeb60a94e273458 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jul 2020 18:04:17 -0700 Subject: [PATCH 45/51] Qt: Disable deprecation warnings on newer Qts --- src/platform/qt/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 165a23f2a..cba2de1d7 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -45,6 +45,10 @@ if(APPLE) endif() endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") +endif() + get_target_property(QT_TYPE Qt5::Core TYPE) if(QT_TYPE STREQUAL STATIC_LIBRARY) set(QT_STATIC ON) From 3062a6a2d740593e14c99feb102169c83926c2e6 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jul 2020 18:05:03 -0700 Subject: [PATCH 46/51] Qt: Add missing option for Wisdom Tree in overrides list --- CHANGES | 1 + src/platform/qt/OverrideView.cpp | 1 + src/platform/qt/OverrideView.ui | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index 3e11a0ec4..b66a17472 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,7 @@ Other fixes: - Qt: Fix file handle leak on opening an invalid ROM - Qt: Fix a race condition in the frame inspector - Qt: Fix Italian RTC translation (fixes mgba.io/i/1798) + - Qt: Add missing option for Wisdom Tree in overrides list - Util: Fix crash if PNG header fails to write Misc: - Debugger: Keep track of global cycle count diff --git a/src/platform/qt/OverrideView.cpp b/src/platform/qt/OverrideView.cpp index f0d1fe772..3479352b6 100644 --- a/src/platform/qt/OverrideView.cpp +++ b/src/platform/qt/OverrideView.cpp @@ -49,6 +49,7 @@ OverrideView::OverrideView(ConfigController* config, QWidget* parent) s_mbcList.append(GB_TAMA5); s_mbcList.append(GB_HuC1); s_mbcList.append(GB_HuC3); + s_mbcList.append(GB_UNL_WISDOM_TREE); } if (s_gbModelList.isEmpty()) { // NB: Keep in sync with OverrideView.ui diff --git a/src/platform/qt/OverrideView.ui b/src/platform/qt/OverrideView.ui index 6d908247d..6a0d60c1a 100644 --- a/src/platform/qt/OverrideView.ui +++ b/src/platform/qt/OverrideView.ui @@ -354,6 +354,11 @@ HuC-3 + + + Wisdom Tree (Unlicensed) + + From cdf9105f56182a207662c93da1e7a3a7f6bb2040 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 7 Jul 2020 18:11:18 -0700 Subject: [PATCH 47/51] GB MBC: Support for unlicensed Pokemon Jade/Diamond Game Boy mapper --- CHANGES | 1 + README.md | 1 + include/mgba/gb/interface.h | 5 +- include/mgba/internal/gb/memory.h | 6 +++ src/core/core.c | 4 ++ src/gb/mbc.c | 88 ++++++++++++++++++++++++++++--- src/gb/memory.c | 2 +- src/gb/overrides.c | 1 + src/platform/qt/OverrideView.cpp | 1 + src/platform/qt/OverrideView.ui | 5 ++ 10 files changed, 105 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index b66a17472..b025def76 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Features: - e-Reader card scanning - Add APNG recording + - Support for unlicensed Pokemon Jade/Diamond Game Boy mapper Emulation fixes: - ARM: Fix ALU reading PC after shifting - ARM: Fix STR storing PC after address calculation diff --git a/README.md b/README.md index f5f005d35..bec608b75 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ The following mappers are fully supported: - MBC5+Rumble - MBC7 - Wisdom Tree (unlicensed) +- Pokémon Jade/Diamond (unlicensed) The following mappers are partially supported: diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index d17593f21..99c4fb01b 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -34,9 +34,10 @@ enum GBMemoryBankControllerType { GB_HuC3 = 0x12, GB_POCKETCAM = 0x13, GB_TAMA5 = 0x14, - GB_UNL_WISDOM_TREE = 0x20, GB_MBC3_RTC = 0x103, - GB_MBC5_RUMBLE = 0x105 + GB_MBC5_RUMBLE = 0x105, + GB_UNL_WISDOM_TREE = 0x200, + GB_UNL_PKJD = 0x203, }; struct GBSIODriver { diff --git a/include/mgba/internal/gb/memory.h b/include/mgba/internal/gb/memory.h index 514311351..ca55b672c 100644 --- a/include/mgba/internal/gb/memory.h +++ b/include/mgba/internal/gb/memory.h @@ -146,6 +146,10 @@ struct GBTAMA5State { uint8_t registers[GBTAMA5_MAX]; }; +struct GBPKJDState { + uint8_t reg[2]; +}; + union GBMBCState { struct GBMBC1State mbc1; struct GBMBC6State mbc6; @@ -153,6 +157,7 @@ union GBMBCState { struct GBMMM01State mmm01; struct GBPocketCamState pocketCam; struct GBTAMA5State tama5; + struct GBPKJDState pkjd; }; struct mRotationSource; @@ -171,6 +176,7 @@ struct GBMemory { int wramCurrentBank; bool sramAccess; + bool directSramAccess; uint8_t* sram; uint8_t* sramBank; int sramCurrentBank; diff --git a/src/core/core.c b/src/core/core.c index cbab4cfe9..e8cf25e82 100644 --- a/src/core/core.c +++ b/src/core/core.c @@ -162,6 +162,10 @@ bool mCorePreloadVFCB(struct mCore* core, struct VFile* vf, void (cb)(size_t, si } } vf->close(vf); + if (read < 0) { + vfm->close(vfm); + return false; + } bool ret = core->loadROM(core, vfm); if (!ret) { vfm->close(vfm); diff --git a/src/gb/mbc.c b/src/gb/mbc.c index ca94cb534..b87885964 100644 --- a/src/gb/mbc.c +++ b/src/gb/mbc.c @@ -36,6 +36,7 @@ static void _GBHuC3(struct GB*, uint16_t address, uint8_t value); static void _GBPocketCam(struct GB* gb, uint16_t address, uint8_t value); static void _GBTAMA5(struct GB* gb, uint16_t address, uint8_t value); static void _GBWisdomTree(struct GB* gb, uint16_t address, uint8_t value); +static void _GBPKJD(struct GB* gb, uint16_t address, uint8_t value); static uint8_t _GBMBC2Read(struct GBMemory*, uint16_t address); static uint8_t _GBMBC6Read(struct GBMemory*, uint16_t address); @@ -43,6 +44,7 @@ static uint8_t _GBMBC7Read(struct GBMemory*, uint16_t address); static void _GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value); static uint8_t _GBTAMA5Read(struct GBMemory*, uint16_t address); +static uint8_t _GBPKJDRead(struct GBMemory*, uint16_t address); static uint8_t _GBPocketCamRead(struct GBMemory*, uint16_t address); static void _GBPocketCamCapture(struct GBMemory*); @@ -273,6 +275,7 @@ void GBMBCInit(struct GB* gb) { gb->memory.mbcType = GB_MBC_NONE; } gb->memory.mbcRead = NULL; + gb->memory.directSramAccess = true; switch (gb->memory.mbcType) { case GB_MBC_NONE: gb->memory.mbcWrite = _GBMBCNone; @@ -288,6 +291,7 @@ void GBMBCInit(struct GB* gb) { case GB_MBC2: gb->memory.mbcWrite = _GBMBC2; gb->memory.mbcRead = _GBMBC2Read; + gb->memory.directSramAccess = false; gb->sramSize = 0x100; break; case GB_MBC3: @@ -300,9 +304,9 @@ void GBMBCInit(struct GB* gb) { gb->memory.mbcWrite = _GBMBC5; break; case GB_MBC6: - mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6"); gb->memory.mbcWrite = _GBMBC6; gb->memory.mbcRead = _GBMBC6Read; + gb->memory.directSramAccess = false; break; case GB_MBC7: gb->memory.mbcWrite = _GBMBC7; @@ -342,6 +346,10 @@ void GBMBCInit(struct GB* gb) { case GB_UNL_WISDOM_TREE: gb->memory.mbcWrite = _GBWisdomTree; break; + case GB_UNL_PKJD: + gb->memory.mbcWrite = _GBPKJD; + gb->memory.mbcRead = _GBPKJDRead; + break; } gb->memory.currentBank = 1; @@ -626,10 +634,10 @@ void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) { case 0: switch (value) { case 0: - memory->mbcState.mbc6.sramAccess = false; + memory->sramAccess = false; break; case 0xA: - memory->mbcState.mbc6.sramAccess = true; + memory->sramAccess = true; break; default: // TODO @@ -655,7 +663,7 @@ void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) { case 0x29: case 0x2A: case 0x2B: - if (memory->mbcState.mbc6.sramAccess) { + if (memory->sramAccess) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value; } break; @@ -663,7 +671,7 @@ void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) { case 0x2D: case 0x2E: case 0x2F: - if (memory->mbcState.mbc6.sramAccess) { + if (memory->sramAccess) { memory->mbcState.mbc6.sramBank1[address & (GB_SIZE_EXTERNAL_RAM_HALFBANK - 1)] = value; } break; @@ -674,7 +682,7 @@ void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) { } uint8_t _GBMBC6Read(struct GBMemory* memory, uint16_t address) { - if (!memory->mbcState.mbc6.sramAccess) { + if (!memory->sramAccess) { return 0xFF; } switch (address >> 12) { @@ -1229,6 +1237,74 @@ void _GBWisdomTree(struct GB* gb, uint16_t address, uint8_t value) { } } +void _GBPKJD(struct GB* gb, uint16_t address, uint8_t value) { + struct GBMemory* memory = &gb->memory; + switch (address >> 13) { + case 0x2: + if (value < 8) { + memory->directSramAccess = true; + memory->activeRtcReg = 0; + } else if (value >= 0xD && value <= 0xF) { + memory->directSramAccess = false; + memory->rtcAccess = false; + memory->activeRtcReg = value - 8; + } + break; + case 0x5: + if (!memory->sramAccess) { + return; + } + switch (memory->activeRtcReg) { + case 0: + memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; + break; + case 5: + case 6: + memory->mbcState.pkjd.reg[memory->activeRtcReg - 5] = value; + break; + case 7: + switch (value) { + case 0x11: + memory->mbcState.pkjd.reg[0]--; + break; + case 0x12: + memory->mbcState.pkjd.reg[1]--; + break; + case 0x41: + memory->mbcState.pkjd.reg[0] += memory->mbcState.pkjd.reg[1]; + break; + case 0x42: + memory->mbcState.pkjd.reg[1] += memory->mbcState.pkjd.reg[0]; + break; + case 0x51: + memory->mbcState.pkjd.reg[0]++; + break; + case 0x52: + memory->mbcState.pkjd.reg[1]--; + break; + } + break; + } + return; + } + _GBMBC3(gb, address, value); +} + +static uint8_t _GBPKJDRead(struct GBMemory* memory, uint16_t address) { + if (!memory->sramAccess) { + return 0xFF; + } + switch (memory->activeRtcReg) { + case 0: + return memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)]; + case 5: + case 6: + return memory->mbcState.pkjd.reg[memory->activeRtcReg - 5]; + default: + return 0; + } +} + void GBMBCRTCRead(struct GB* gb) { struct GBMBCRTCSaveBuffer rtcBuffer; struct VFile* vf = gb->sramVf; diff --git a/src/gb/memory.c b/src/gb/memory.c index b070ff601..a856b6635 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -361,7 +361,7 @@ void GBStore8(struct SM83Core* cpu, uint16_t address, int8_t value) { case GB_REGION_EXTERNAL_RAM + 1: if (memory->rtcAccess) { memory->rtcRegs[memory->activeRtcReg] = value; - } else if (memory->sramAccess && memory->sram && memory->mbcType != GB_MBC2) { + } else if (memory->sramAccess && memory->sram && memory->directSramAccess) { memory->sramBank[address & (GB_SIZE_EXTERNAL_RAM - 1)] = value; } else { memory->mbcWrite(gb, address, value); diff --git a/src/gb/overrides.c b/src/gb/overrides.c index 8e2265662..38a8ca6ff 100644 --- a/src/gb/overrides.c +++ b/src/gb/overrides.c @@ -495,6 +495,7 @@ static const struct GBCartridgeOverride _overrides[] = { { 0x630ed957, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Gold (non-debug) { 0x5aff0038, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (debug) { 0xa61856bd, GB_MODEL_AUTODETECT, GB_MBC3_RTC, { 0 } }, // Silver (non-debug) + { 0x30f8f86c, GB_MODEL_AUTODETECT, GB_UNL_PKJD, { 0 } }, // Pokemon Jade Version (Telefang Speed bootleg) { 0, 0, 0, { 0 } } }; diff --git a/src/platform/qt/OverrideView.cpp b/src/platform/qt/OverrideView.cpp index 3479352b6..e73f657ba 100644 --- a/src/platform/qt/OverrideView.cpp +++ b/src/platform/qt/OverrideView.cpp @@ -50,6 +50,7 @@ OverrideView::OverrideView(ConfigController* config, QWidget* parent) s_mbcList.append(GB_HuC1); s_mbcList.append(GB_HuC3); s_mbcList.append(GB_UNL_WISDOM_TREE); + s_mbcList.append(GB_UNL_PKJD); } if (s_gbModelList.isEmpty()) { // NB: Keep in sync with OverrideView.ui diff --git a/src/platform/qt/OverrideView.ui b/src/platform/qt/OverrideView.ui index 6a0d60c1a..61d4449fb 100644 --- a/src/platform/qt/OverrideView.ui +++ b/src/platform/qt/OverrideView.ui @@ -359,6 +359,11 @@ Wisdom Tree (Unlicensed) + + + Pokémon Jade/Diamond (Unlicensed) + + From 145a31868a21454ab91e2070ed6103bde333bbc9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 Jul 2020 01:22:44 -0700 Subject: [PATCH 48/51] FFmpeg: Fix some small memory leaks --- CHANGES | 1 + src/feature/ffmpeg/ffmpeg-encoder.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/CHANGES b/CHANGES index b025def76..6ca8a08e9 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,7 @@ Other fixes: - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached + - FFmpeg: Fix some small memory leaks - GB Core: Fix extracting SRAM when none is present - GBA Savedata: Fix extracting save when not yet configured in-game - Qt: Force OpenGL paint engine creation thread (fixes mgba.io/i/1642) diff --git a/src/feature/ffmpeg/ffmpeg-encoder.c b/src/feature/ffmpeg/ffmpeg-encoder.c index b47fca6aa..7f58d28df 100644 --- a/src/feature/ffmpeg/ffmpeg-encoder.c +++ b/src/feature/ffmpeg/ffmpeg-encoder.c @@ -546,8 +546,12 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { #endif } if (encoder->audio) { +#ifdef FFMPEG_USE_CODECPAR + avcodec_free_context(&encoder->audio); +#else avcodec_close(encoder->audio); encoder->audio = NULL; +#endif } if (encoder->resampleContext) { @@ -569,6 +573,7 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { } if (encoder->videoFrame) { + av_freep(encoder->videoFrame->data); #if LIBAVCODEC_VERSION_MAJOR >= 55 av_frame_free(&encoder->videoFrame); #else @@ -586,8 +591,12 @@ void FFmpegEncoderClose(struct FFmpegEncoder* encoder) { } if (encoder->video) { +#ifdef FFMPEG_USE_CODECPAR + avcodec_free_context(&encoder->video); +#else avcodec_close(encoder->video); encoder->video = NULL; +#endif } if (encoder->scaleContext) { From 73c38b95b6be95ab9c58369fe7186fc197e1255e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 11 Jul 2020 15:34:45 -0700 Subject: [PATCH 49/51] All: Correct more format strings on Windows (fixes #1817) --- CHANGES | 1 + CMakeLists.txt | 4 ++++ include/mgba-util/common.h | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/CHANGES b/CHANGES index 6ca8a08e9..3166536fc 100644 --- a/CHANGES +++ b/CHANGES @@ -29,6 +29,7 @@ Emulation fixes: Other fixes: - All: Improve export headers (fixes mgba.io/i/1738) - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) + - All: Correct more format strings on Windows (fixes mgba.io/i/1817) - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached - FFmpeg: Fix some small memory leaks diff --git a/CMakeLists.txt b/CMakeLists.txt index 1cabb0887..114f95360 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,10 @@ if(NOT MSVC) set(CMAKE_C_EXTENSIONS ON) endif() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-missing-field-initializers") + if(WIN32) + # mingw32 likes to complain about using the "wrong" format strings despite them actually working + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format") + endif() else() set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS /wd4003 /wd4244 /wd4146") endif() diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index 0f4a991bb..00193f6ff 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -14,6 +14,10 @@ #define CXX_GUARD_END #endif +#ifdef __MINGW32__ +#define __USE_MINGW_ANSI_STDIO 1 +#endif + CXX_GUARD_START #include From 9295c3c893646713d8fce7f9d15be320787b9d97 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jul 2020 00:21:42 -0700 Subject: [PATCH 50/51] CMake: Fix build with libzip 1.7 --- CHANGES | 1 + CMakeLists.txt | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 3166536fc..924e2889a 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,7 @@ Other fixes: - All: Improve export headers (fixes mgba.io/i/1738) - All: Correct format strings for some numbers on Windows (fixes mgba.io/i/1794) - All: Correct more format strings on Windows (fixes mgba.io/i/1817) + - CMake: Fix build with libzip 1.7 - Core: Ensure ELF regions can be written before trying - Debugger: Don't skip undefined instructions when debugger attached - FFmpeg: Fix some small memory leaks diff --git a/CMakeLists.txt b/CMakeLists.txt index 114f95360..f91a2adad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -631,15 +631,19 @@ if(WANT_SQLITE3 AND NOT USE_SQLITE3) endif() if(USE_LIBZIP) - include_directories(AFTER ${LIBZIP_INCLUDE_DIRS}) - link_directories(${LIBZIP_LIBRARY_DIRS}) - list(APPEND DEPENDENCY_LIB ${LIBZIP_LIBRARIES}) + if(TARGET libzip::zip) + list(APPEND DEPENDENCY_LIB libzip::zip) + else() + include_directories(AFTER ${LIBZIP_INCLUDE_DIRS}) + link_directories(${LIBZIP_LIBRARY_DIRS}) + list(APPEND DEPENDENCY_LIB ${LIBZIP_LIBRARIES}) + endif() list(APPEND FEATURES LIBZIP) list(APPEND VFS_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/util/vfs/vfs-zip.c) string(REGEX MATCH "^[0-9]+" LIBZIP_VERSION_MAJOR "${libzip_VERSION}") if (LIBZIP_VERSION_MAJOR LESS 1) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libzip2") - elseif(LIBZIP_VERSION_MAJOR EQUAL 1) + elseif(LIBZIP_VERSION_MAJOR EQUAL 1 OR NOT LIBZIP_VERSION_MAJOR) set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libzip4|libzip5") else() message(AUTHOR_WARNING "Unknown version of libzip detected: ${libzip_VERSION}") From 007baef3b03daf1e00123eb485c4ec92448c04db Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 12 Jul 2020 14:26:13 -0700 Subject: [PATCH 51/51] ARM: Fix edge case with Thumb SBC flags (fixes #1818) --- CHANGES | 1 + src/arm/isa-thumb.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 924e2889a..8410325b9 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ Emulation fixes: - ARM: Fix STR storing PC after address calculation - ARM: Fix LDM^ writeback to user-mode register - ARM: Fix LDM^ {pc} differences (fixes mgba.io/i/1698) + - ARM: Fix edge case with Thumb SBC flags (fixes mgba.io/i/1818) - GB: Partially fix timing for skipped BIOS - GB Memory: Fix OAM DMA from top 8 kB - GB MBC: Fix MBC1 mode changing behavior diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index edd15fe2c..bae46a3bb 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -25,6 +25,13 @@ cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \ cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); +#define THUMB_SUBTRACTION_CARRY_S(M, N, D, C) \ + cpu->cpsr.flags = 0; \ + cpu->cpsr.n = ARM_SIGN(D); \ + cpu->cpsr.z = !(D); \ + cpu->cpsr.c = ARM_BORROW_FROM_CARRY(M, N, D, C); \ + cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); + #define THUMB_NEUTRAL_S(M, N, D) \ cpu->cpsr.n = ARM_SIGN(D); \ cpu->cpsr.z = !(D); @@ -203,10 +210,11 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC, THUMB_ADDITION_S(d, n, cpu->gprs[rd]);) DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(SBC, - int n = cpu->gprs[rn] + !cpu->cpsr.c; + int n = cpu->gprs[rn]; int d = cpu->gprs[rd]; - cpu->gprs[rd] = d - n; - THUMB_SUBTRACTION_S(d, n, cpu->gprs[rd]);) + cpu->gprs[rd] = d - n - !cpu->cpsr.c; + THUMB_SUBTRACTION_CARRY_S(d, n, cpu->gprs[rd], !cpu->cpsr.c);) + DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ROR, int rs = cpu->gprs[rn] & 0xFF; if (rs) {