From 5fa1638b1df3e16984bc356653fe405de6e944c7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 10:58:24 -0700 Subject: [PATCH 01/60] Qt: Separate fast forward volume control (fixes #846, #1143) --- CHANGES | 1 + src/platform/qt/CoreController.cpp | 16 ++++++++ src/platform/qt/CoreController.h | 2 + src/platform/qt/SettingsView.cpp | 24 ++++++++++-- src/platform/qt/SettingsView.h | 2 +- src/platform/qt/SettingsView.ui | 62 ++++++++++++++++++++++++------ src/platform/qt/Window.cpp | 10 +++++ 7 files changed, 101 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index a7652188a..275df4108 100644 --- a/CHANGES +++ b/CHANGES @@ -101,6 +101,7 @@ Misc: Changes from beta 1: Features: - Libretro: Add Game Boy cheat support + - Qt: Separate fast forward volume control (fixes mgba.io/i/846, mgba.io/i/1143) Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index b8ac73de5..b07b01be7 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -245,6 +245,8 @@ void CoreController::loadConfig(ConfigController* config) { m_autosave = config->getOption("autosave", false).toInt(); m_autoload = config->getOption("autoload", true).toInt(); m_autofireThreshold = config->getOption("autofireThreshold", m_autofireThreshold).toInt(); + m_fastForwardVolume = config->getOption("fastForwardVolume", -1).toInt(); + m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt(); mCoreLoadForeignConfig(m_threadContext.core, config->config()); if (hasStarted()) { updateFastForward(); @@ -810,15 +812,29 @@ void CoreController::finishFrame() { void CoreController::updateFastForward() { if (m_fastForward || m_fastForwardForced) { + if (m_fastForwardVolume >= 0) { + m_threadContext.core->opts.volume = m_fastForwardVolume; + } + if (m_fastForwardMute >= 0) { + m_threadContext.core->opts.mute = m_fastForwardMute; + } if (m_fastForwardRatio > 0) { m_threadContext.impl->sync.fpsTarget = m_fpsTarget * m_fastForwardRatio; } else { setSync(false); } } else { + if (!mCoreConfigGetIntValue(&m_threadContext.core->config, "volume", &m_threadContext.core->opts.volume)) { + m_threadContext.core->opts.volume = 0x100; + } + int fakeBool = 0; + mCoreConfigGetIntValue(&m_threadContext.core->config, "mute", &fakeBool); + m_threadContext.core->opts.mute = fakeBool; m_threadContext.impl->sync.fpsTarget = m_fpsTarget; setSync(true); } + // XXX: Have a way of just updating opts + m_threadContext.core->loadConfig(m_threadContext.core, &m_threadContext.core->config); } CoreController::Interrupter::Interrupter(CoreController* parent, bool fromThread) diff --git a/src/platform/qt/CoreController.h b/src/platform/qt/CoreController.h index ec6b7d998..9d9537c6c 100644 --- a/src/platform/qt/CoreController.h +++ b/src/platform/qt/CoreController.h @@ -204,6 +204,8 @@ private: int m_fastForward = false; int m_fastForwardForced = false; + int m_fastForwardVolume = -1; + int m_fastForwardMute = -1; float m_fastForwardRatio = -1.f; float m_fpsTarget; diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index a4fd9a015..07f38edf9 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -43,6 +43,18 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC reloadConfig(); + connect(m_ui.volume, static_cast(&QSlider::valueChanged), [this](int v) { + if (v < m_ui.volumeFf->value()) { + m_ui.volumeFf->setValue(v); + } + }); + + connect(m_ui.mute, &QAbstractButton::toggled, [this](bool e) { + if (e) { + m_ui.muteFf->setChecked(e); + } + }); + if (m_ui.savegamePath->text().isEmpty()) { m_ui.savegameSameDir->setChecked(true); } @@ -339,6 +351,8 @@ void SettingsView::updateConfig() { saveSetting("lockIntegerScaling", m_ui.lockIntegerScaling); saveSetting("volume", m_ui.volume); saveSetting("mute", m_ui.mute); + saveSetting("fastForwardVolume", m_ui.volumeFf); + saveSetting("fastForwardMute", m_ui.muteFf); saveSetting("rewindEnable", m_ui.rewind); saveSetting("rewindBufferCapacity", m_ui.rewindCapacity); saveSetting("resampleVideo", m_ui.resampleVideo); @@ -460,8 +474,10 @@ void SettingsView::reloadConfig() { loadSetting("autofireThreshold", m_ui.autofireThreshold); loadSetting("lockAspectRatio", m_ui.lockAspectRatio); loadSetting("lockIntegerScaling", m_ui.lockIntegerScaling); - loadSetting("volume", m_ui.volume); - loadSetting("mute", m_ui.mute); + loadSetting("volume", m_ui.volume, 0x100); + loadSetting("mute", m_ui.mute, false); + loadSetting("fastForwardVolume", m_ui.volumeFf, m_ui.volume->value()); + loadSetting("fastForwardMute", m_ui.muteFf, m_ui.mute->isChecked()); loadSetting("rewindEnable", m_ui.rewind); loadSetting("rewindBufferCapacity", m_ui.rewindCapacity); loadSetting("resampleVideo", m_ui.resampleVideo); @@ -592,9 +608,9 @@ void SettingsView::loadSetting(const char* key, QLineEdit* field) { field->setText(option); } -void SettingsView::loadSetting(const char* key, QSlider* field) { +void SettingsView::loadSetting(const char* key, QSlider* field, int defaultVal) { QString option = loadSetting(key); - field->setValue(option.toInt()); + field->setValue(option.isNull() ? defaultVal : option.toInt()); } void SettingsView::loadSetting(const char* key, QSpinBox* field) { diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 653dd6139..2be49d32d 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -72,7 +72,7 @@ private: void loadSetting(const char* key, QComboBox*); void loadSetting(const char* key, QDoubleSpinBox*); void loadSetting(const char* key, QLineEdit*); - void loadSetting(const char* key, QSlider*); + void loadSetting(const char* key, QSlider*, int defaultVal = 0); void loadSetting(const char* key, QSpinBox*); QString loadSetting(const char* key); }; diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index d09a6d221..5c8469d8c 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -263,21 +263,61 @@ - + + + + Fast forward volume: + + + + + + + + + + 128 + 0 + + + + 256 + + + 16 + + + 256 + + + Qt::Horizontal + + + + + + + Mute + + + + + + Qt::Horizontal - + Display driver: - + @@ -287,14 +327,14 @@ - + Frameskip: - + @@ -315,14 +355,14 @@ - + FPS target: - + @@ -349,21 +389,21 @@ - + Qt::Horizontal - + Sync: - + @@ -381,7 +421,7 @@ - + Lock aspect ratio diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index c0b71f4c5..e8bdcb5fd 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1610,6 +1610,16 @@ void Window::setupMenu(QMenuBar* menubar) { reloadConfig(); }, this); + ConfigOption* volumeFf = m_config->addOption("fastForwardVolume"); + volumeFf->connect([this](const QVariant& value) { + reloadConfig(); + }, this); + + ConfigOption* muteFf = m_config->addOption("fastForwardMute"); + muteFf->connect([this](const QVariant& value) { + reloadConfig(); + }, this); + ConfigOption* rewindEnable = m_config->addOption("rewindEnable"); rewindEnable->connect([this](const QVariant& value) { reloadConfig(); From a3a9fb467c03a80741261c2b1edf18b5a2160c96 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 11:38:33 -0700 Subject: [PATCH 02/60] GBA Video: Fix caching with background toggling (fixes #1118) --- CHANGES | 1 + src/gba/renderers/video-software.c | 10 ++++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 275df4108..b319c2242 100644 --- a/CHANGES +++ b/CHANGES @@ -106,6 +106,7 @@ Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full - 3DS: Fix unused screens not clearing (fixes mgba.io/i/1184) + - GBA Video: Fix caching with background toggling (fixes mgba.io/i/1118) Misc: - mGUI: Add SGB border configuration option diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 2b80ac998..0f82d44a8 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -554,6 +554,8 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render return; } + CLEAN_SCANLINE(softwareRenderer, y); + color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y]; if (GBARegisterDISPCNTIsForcedBlank(softwareRenderer->dispcnt)) { int x; @@ -675,7 +677,6 @@ static void GBAVideoSoftwareRendererDrawScanline(struct GBAVideoRenderer* render #else memcpy(row, softwareRenderer->row, VIDEO_HORIZONTAL_PIXELS * sizeof(*row)); #endif - CLEAN_SCANLINE(softwareRenderer, y); } static void GBAVideoSoftwareRendererFinishFrame(struct GBAVideoRenderer* renderer) { @@ -722,9 +723,10 @@ static void GBAVideoSoftwareRendererPutPixels(struct GBAVideoRenderer* renderer, } static void _enableBg(struct GBAVideoSoftwareRenderer* renderer, int bg, bool active) { + int wasActive = renderer->bg[bg].enabled; if (!active) { renderer->bg[bg].enabled = 0; - } else if (!renderer->bg[bg].enabled && active) { + } else if (!wasActive && active) { if (renderer->nextY == 0) { renderer->bg[bg].enabled = 4; } else { @@ -901,15 +903,19 @@ static void _drawScanline(struct GBAVideoSoftwareRenderer* renderer, int y) { if (renderer->bg[0].enabled > 0 && renderer->bg[0].enabled < 4) { ++renderer->bg[0].enabled; + DIRTY_SCANLINE(renderer, y); } if (renderer->bg[1].enabled > 0 && renderer->bg[1].enabled < 4) { ++renderer->bg[1].enabled; + DIRTY_SCANLINE(renderer, y); } if (renderer->bg[2].enabled > 0 && renderer->bg[2].enabled < 4) { ++renderer->bg[2].enabled; + DIRTY_SCANLINE(renderer, y); } if (renderer->bg[3].enabled > 0 && renderer->bg[3].enabled < 4) { ++renderer->bg[3].enabled; + DIRTY_SCANLINE(renderer, y); } } From bdb17ef99d1c12ef1fbb52d351dd0dd30ad8d4e0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 11:41:28 -0700 Subject: [PATCH 03/60] Qt: Add missing change --- src/platform/qt/SettingsView.ui | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 5c8469d8c..43725c118 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -429,19 +429,19 @@ - - - Bilinear filtering - - - - Force integer scaling + + + + Bilinear filtering + + + From 03c3ae219ba58748e89591624024f3b52ec7079c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 12:18:41 -0700 Subject: [PATCH 04/60] cinema: Rebaseline fixed test --- .../unaligned-256-linear/baseline_0001.png | Bin 22852 -> 23051 bytes .../unaligned-256-linear/baseline_0003.png | Bin 21873 -> 22080 bytes .../unaligned-256-linear/baseline_0004.png | Bin 21873 -> 22080 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/cinema/gba/obj/unaligned-256-linear/baseline_0001.png b/cinema/gba/obj/unaligned-256-linear/baseline_0001.png index f658bc32f2d1436d08eca08f63745fec3aef6119..4be2744f72ca0f1ab799dea2fc3bb1a54810cfc4 100644 GIT binary patch literal 23051 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

Th?LswHCOKk&0)$2PHHPr4fKI6vLnBt= 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 O0000-Sxp;io3fz2mN@zAG^tBbLGlR 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 Z{||X&TA4k~C;I>Z002ovPDHLkV1g^@d<_5q literal 21873 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 Z{||X&TA4k~C;I>Z002ovPDHLkV1g^@d<_5q literal 21873 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 Date: Fri, 28 Sep 2018 15:02:13 -0700 Subject: [PATCH 05/60] CMake: Add symbol builds for homebrew ports --- CMakeLists.txt | 11 +++++++---- src/platform/3ds/CMakeLists.txt | 2 ++ src/platform/psp2/CMakeLists.txt | 1 + src/platform/switch/CMakeLists.txt | 1 + src/platform/wii/CMakeLists.txt | 2 ++ 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8a402504..88bf9a5d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1064,13 +1064,13 @@ if(DISTBUILD) set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) endif() elseif(3DS) - set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-3ds ${BINARY_NAME}-perf) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-3ds ${BINARY_NAME}-perf) elseif(WII) - set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-wii) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-wii) elseif(PSP2) - set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-psp2) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-psp2) elseif(SWITCH) - set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-switch) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-switch) endif() endif() @@ -1114,6 +1114,9 @@ if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") if(BUILD_SHARED AND NOT IS_EMBEDDED) cpack_add_component(lib${BINARY_NAME}-dbg GROUP debug) endif() + if(IS_EMBEDDED) + cpack_add_component(${BINARY_NAME}-dbg GROUP debug) + endif() if(BUILD_QT) cpack_add_component(${BINARY_NAME}-qt-dbg GROUP debug) endif() diff --git a/src/platform/3ds/CMakeLists.txt b/src/platform/3ds/CMakeLists.txt index 4891c0f64..bf5364085 100644 --- a/src/platform/3ds/CMakeLists.txt +++ b/src/platform/3ds/CMakeLists.txt @@ -113,6 +113,8 @@ if(BUILD_PERF) endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cia.rsf.in ${CMAKE_CURRENT_BINARY_DIR}/cia.rsf) + +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.3dsx ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.smdh diff --git a/src/platform/psp2/CMakeLists.txt b/src/platform/psp2/CMakeLists.txt index 34ea754e7..1fb0c9928 100644 --- a/src/platform/psp2/CMakeLists.txt +++ b/src/platform/psp2/CMakeLists.txt @@ -61,4 +61,5 @@ vita_create_vpk(${BINARY_NAME}.vpk MGBA00001 ${BINARY_NAME}.self FILE ${CMAKE_CURRENT_SOURCE_DIR}/startup.png sce_sys/livearea/contents/startup.png FILE ${CMAKE_CURRENT_BINARY_DIR}/template.xml sce_sys/livearea/contents/template.xml) +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.vpk DESTINATION . COMPONENT ${BINARY_NAME}-psp2) diff --git a/src/platform/switch/CMakeLists.txt b/src/platform/switch/CMakeLists.txt index f33d6a937..6666b8a01 100644 --- a/src/platform/switch/CMakeLists.txt +++ b/src/platform/switch/CMakeLists.txt @@ -50,4 +50,5 @@ add_custom_target(${BINARY_NAME}.nro ALL ${ELF2NRO} ${BINARY_NAME}.elf ${BINARY_NAME}.nro --romfs=romfs.bin --nacp=control.nacp --icon="${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg" DEPENDS ${BINARY_NAME}.elf control.nacp ${CMAKE_CURRENT_SOURCE_DIR}/icon.jpg romfs.bin) +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.nro DESTINATION . COMPONENT ${BINARY_NAME}-switch) diff --git a/src/platform/wii/CMakeLists.txt b/src/platform/wii/CMakeLists.txt index 165dba60b..4caf73d10 100644 --- a/src/platform/wii/CMakeLists.txt +++ b/src/platform/wii/CMakeLists.txt @@ -40,5 +40,7 @@ add_custom_target(run ${WIILOAD} ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.dol DEPENDS ${BINARY_NAME}.dol) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/meta.xml.in ${CMAKE_CURRENT_BINARY_DIR}/meta.xml) + +install(TARGETS ${BINARY_NAME}.elf DESTINATION . COMPONENT ${BINARY_NAME}-dbg) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/icon.png ${CMAKE_CURRENT_BINARY_DIR}/meta.xml DESTINATION . COMPONENT ${BINARY_NAME}-wii) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${BINARY_NAME}.dol DESTINATION . RENAME boot.dol COMPONENT ${BINARY_NAME}-wii) From 69382109b77c2fcd90fbbd082a9a6efc4b31d6c8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 15:40:01 -0700 Subject: [PATCH 06/60] CMake: Don't strip non-release builds --- CMakeLists.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 88bf9a5d9..87deecf63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1045,9 +1045,11 @@ set(CPACK_PACKAGE_CONTACT "Jeffrey Pfau ") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md") set(CPACK_DEBIAN_PACKAGE_SECTION "games") -SET(CPACK_DEB_COMPONENT_INSTALL ON) +set(CPACK_DEB_COMPONENT_INSTALL ON) -set(CPACK_STRIP_FILES ON) +if(CMAKE_BUILD_TYPE STREQUAL "Release") + set(CPACK_STRIP_FILES ON) +endif() if(DISTBUILD) set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) From d566185b399402d8c3853404e280905abc70f9d2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 18:08:03 -0700 Subject: [PATCH 07/60] CHANGES: Minor text fixes --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b319c2242..3da905129 100644 --- a/CHANGES +++ b/CHANGES @@ -110,7 +110,7 @@ Bugfixes: Misc: - mGUI: Add SGB border configuration option -0.6 beta 1: (2018-09-24) +0.7 beta 1: (2018-09-24) - Initial beta for 0.6 0.6.3: (2018-04-14) From 20f900520d7e3e6047ba5169befe3ed26e3f9a04 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Sep 2018 18:08:31 -0700 Subject: [PATCH 08/60] Travis: Replace artful with cosmic --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ee7e322ed..c35d58b3b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,8 @@ services: os: linux env: - DOCKER_TAG=ubuntu:xenial -- DOCKER_TAG=ubuntu:artful - DOCKER_TAG=ubuntu:bionic +- DOCKER_TAG=ubuntu:cosmic - DOCKER_TAG=3ds - DOCKER_TAG=wii - DOCKER_TAG=vita From 9061620e582edc37b85a913cb297a1b451578fb0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 10:05:43 -0700 Subject: [PATCH 09/60] Wii: Fix drawing caching regression (fixes #1185) --- CHANGES | 1 + src/platform/wii/main.c | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 3da905129..83f32d434 100644 --- a/CHANGES +++ b/CHANGES @@ -107,6 +107,7 @@ Bugfixes: - PSP2: Fix audio crackling when buffer is full - 3DS: Fix unused screens not clearing (fixes mgba.io/i/1184) - GBA Video: Fix caching with background toggling (fixes mgba.io/i/1118) + - Wii: Fix drawing caching regression (fixes mgba.io/i/1185) Misc: - mGUI: Add SGB border configuration option diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index 1885f5c37..f1df0c86c 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -195,18 +195,18 @@ static void reconfigureScreen(struct mGUIRunner* runner) { break; } - free(framebuffer[0]); - free(framebuffer[1]); - VIDEO_SetBlack(true); VIDEO_Configure(vmode); + free(framebuffer[0]); + free(framebuffer[1]); + framebuffer[0] = SYS_AllocateFramebuffer(vmode); framebuffer[1] = SYS_AllocateFramebuffer(vmode); - VIDEO_ClearFrameBuffer(vmode, framebuffer[0], COLOR_BLACK); - VIDEO_ClearFrameBuffer(vmode, framebuffer[1], COLOR_BLACK); + VIDEO_ClearFrameBuffer(vmode, MEM_K0_TO_K1(framebuffer[0]), COLOR_BLACK); + VIDEO_ClearFrameBuffer(vmode, MEM_K0_TO_K1(framebuffer[1]), COLOR_BLACK); - VIDEO_SetNextFramebuffer(framebuffer[whichFb]); + VIDEO_SetNextFramebuffer(MEM_K0_TO_K1(framebuffer[whichFb])); VIDEO_Flush(); VIDEO_WaitVSync(); if (vmode->viTVMode & VI_NON_INTERLACE) { @@ -595,7 +595,7 @@ static void _drawStart(void) { static void _drawEnd(void) { GX_CopyDisp(framebuffer[whichFb], GX_TRUE); GX_DrawDone(); - VIDEO_SetNextFramebuffer(framebuffer[whichFb]); + VIDEO_SetNextFramebuffer(MEM_K0_TO_K1(framebuffer[whichFb])); VIDEO_Flush(); whichFb = !whichFb; From 927f8b0d8859fbfb8fe3f75e8ff8460ff74adf26 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 10:20:08 -0700 Subject: [PATCH 10/60] CHANGES: Minor text fixes --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 83f32d434..9f8683392 100644 --- a/CHANGES +++ b/CHANGES @@ -112,7 +112,7 @@ Misc: - mGUI: Add SGB border configuration option 0.7 beta 1: (2018-09-24) -- Initial beta for 0.6 +- Initial beta for 0.7 0.6.3: (2018-04-14) Bugfixes: From 32c5fd6d90508ce5291d400fee17044062e12a78 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 11:09:16 -0700 Subject: [PATCH 11/60] mGUI: Add variants --- CHANGES | 2 ++ include/mgba-util/gui/menu.h | 25 +++++++++++++ src/feature/gui/gui-config.c | 68 ++++++++++++++++++++++++++++++++++-- src/platform/switch/main.c | 17 +++++++++ 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 9f8683392..fa169c8d9 100644 --- a/CHANGES +++ b/CHANGES @@ -108,8 +108,10 @@ Bugfixes: - 3DS: Fix unused screens not clearing (fixes mgba.io/i/1184) - GBA Video: Fix caching with background toggling (fixes mgba.io/i/1118) - Wii: Fix drawing caching regression (fixes mgba.io/i/1185) + - Switch: Fix incorrect mapping for fast forward cap Misc: - mGUI: Add SGB border configuration option + - mGUI: Add support for different settings types 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/include/mgba-util/gui/menu.h b/include/mgba-util/gui/menu.h index 72a099a15..dca1d60b3 100644 --- a/include/mgba-util/gui/menu.h +++ b/include/mgba-util/gui/menu.h @@ -12,12 +12,37 @@ CXX_GUARD_START #include +#define GUI_V_V (struct GUIVariant) { .type = GUI_VARIANT_VOID } +#define GUI_V_U(U) (struct GUIVariant) { .type = GUI_VARIANT_UNSIGNED, .v.u = (U) } +#define GUI_V_I(I) (struct GUIVariant) { .type = GUI_VARIANT_INT, .v.i = (I) } +#define GUI_V_F(F) (struct GUIVariant) { .type = GUI_VARIANT_FLOAT, .v.f = (F) } +#define GUI_V_S(S) (struct GUIVariant) { .type = GUI_VARIANT_STRING, .v.s = (S) } + +enum GUIVariantType { + GUI_VARIANT_VOID = 0, + GUI_VARIANT_UNSIGNED, + GUI_VARIANT_INT, + GUI_VARIANT_FLOAT, + GUI_VARIANT_STRING +}; + +struct GUIVariant { + enum GUIVariantType type; + union { + unsigned u; + int i; + float f; + const char* s; + } v; +}; + struct GUIMenu; struct GUIMenuItem { const char* title; void* data; unsigned state; const char* const* validStates; + const struct GUIVariant* stateMappings; unsigned nStates; struct GUIMenu* submenu; }; diff --git a/src/feature/gui/gui-config.c b/src/feature/gui/gui-config.c index 3a938fade..65e8ee4e7 100644 --- a/src/feature/gui/gui-config.c +++ b/src/feature/gui/gui-config.c @@ -162,7 +162,50 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t if (!item->validStates || !item->data) { continue; } - mCoreConfigGetUIntValue(&runner->config, item->data, &item->state); + if (item->stateMappings) { + item->state = 0; + + size_t j; + for (j = 0; j < item->nStates; ++j) { + const struct GUIVariant* v = &item->stateMappings[j]; + struct GUIVariant test; + switch (v->type) { + case GUI_VARIANT_VOID: + if (!mCoreConfigGetValue(&runner->config, item->data)) { + item->state = j; + break; + } + break; + case GUI_VARIANT_UNSIGNED: + if (mCoreConfigGetUIntValue(&runner->config, item->data, &test.v.u) && test.v.u == v->v.u) { + item->state = j; + break; + } + break; + case GUI_VARIANT_INT: + if (mCoreConfigGetIntValue(&runner->config, item->data, &test.v.i) && test.v.i == v->v.i) { + item->state = j; + break; + } + break; + case GUI_VARIANT_FLOAT: + if (mCoreConfigGetFloatValue(&runner->config, item->data, &test.v.f) && fabsf(test.v.f - v->v.f) <= 1e-3f) { + item->state = j; + break; + } + break; + case GUI_VARIANT_STRING: + test.v.s = mCoreConfigGetValue(&runner->config, item->data); + if (test.v.s && strcmp(test.v.s, v->v.s) == 0) { + item->state = j; + break; + } + break; + } + } + } else { + mCoreConfigGetUIntValue(&runner->config, item->data, &item->state); + } } while (true) { @@ -188,7 +231,28 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t if (!item->validStates || !item->data) { continue; } - mCoreConfigSetUIntValue(&runner->config, item->data, item->state); + if (item->stateMappings) { + const struct GUIVariant* v = &item->stateMappings[item->state]; + switch (v->type) { + case GUI_VARIANT_VOID: + mCoreConfigSetValue(&runner->config, item->data, NULL); + break; + case GUI_VARIANT_UNSIGNED: + mCoreConfigSetUIntValue(&runner->config, item->data, v->v.u); + break; + case GUI_VARIANT_INT: + mCoreConfigSetUIntValue(&runner->config, item->data, v->v.i); + break; + case GUI_VARIANT_FLOAT: + mCoreConfigSetFloatValue(&runner->config, item->data, v->v.f); + break; + case GUI_VARIANT_STRING: + mCoreConfigSetValue(&runner->config, item->data, v->v.s); + break; + } + } else { + mCoreConfigSetUIntValue(&runner->config, item->data, item->state); + } } if (runner->keySources) { size_t i; diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 55be2f910..9fd7e3649 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -528,6 +528,23 @@ int main(int argc, char* argv[]) { "10", "11", "12", "13", "14", "15", "20", "30" }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_U(3), + GUI_V_U(4), + GUI_V_U(5), + GUI_V_U(6), + GUI_V_U(7), + GUI_V_U(8), + GUI_V_U(9), + GUI_V_U(10), + GUI_V_U(11), + GUI_V_U(12), + GUI_V_U(13), + GUI_V_U(14), + GUI_V_U(15), + GUI_V_U(20), + GUI_V_U(30), + }, .nStates = 15 }, }, From 8a006bc9c47b033ccb0f6e7492e59c7726def637 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 11:56:11 -0700 Subject: [PATCH 12/60] Wii: Disable use of strtof_l (fixes #1106) --- CHANGES | 1 + src/util/formatting.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGES b/CHANGES index fa169c8d9..bca96600f 100644 --- a/CHANGES +++ b/CHANGES @@ -112,6 +112,7 @@ Bugfixes: Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types + - Wii: Disable use of strtof_l (fixes mgba.io/i/1106) 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/util/formatting.c b/src/util/formatting.c index 1305edfc9..c6aa1e7b8 100644 --- a/src/util/formatting.c +++ b/src/util/formatting.c @@ -59,6 +59,11 @@ int ftostr_u(char* restrict str, size_t size, float f) { } float strtof_u(const char* restrict str, char** restrict end) { +#ifdef GEKKO + // strtof_l appears to have broken in devkitPPC sometime around r28 + // TODO: Investigate further + float res = strtof(str, end); +#else #if HAVE_LOCALE locale_t l = newlocale(LC_NUMERIC_MASK, "C", 0); #else @@ -67,6 +72,7 @@ float strtof_u(const char* restrict str, char** restrict end) { float res = strtof_l(str, end, l); #if HAVE_LOCALE freelocale(l); +#endif #endif return res; } From eabdbe97eaf5fdbd109660d80874c3c0b7c297a4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 12:05:41 -0700 Subject: [PATCH 13/60] mGUI: Don't save config menu markers --- src/feature/gui/gui-config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/feature/gui/gui-config.c b/src/feature/gui/gui-config.c index 65e8ee4e7..7aa397833 100644 --- a/src/feature/gui/gui-config.c +++ b/src/feature/gui/gui-config.c @@ -228,7 +228,7 @@ void mGUIShowConfig(struct mGUIRunner* runner, struct GUIMenuItem* extra, size_t } for (i = 0; i < GUIMenuItemListSize(&menu.items); ++i) { item = GUIMenuItemListGetPointer(&menu.items, i); - if (!item->validStates || !item->data) { + if (!item->validStates || !item->data || ((const char*) item->data)[0] == '*') { continue; } if (item->stateMappings) { From 46953b279151adff7778c530926a62996ab247ed Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 12:07:43 -0700 Subject: [PATCH 14/60] Wii: Expose stretch configuration in settings --- CHANGES | 1 + src/platform/wii/main.c | 53 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index bca96600f..2a81dbbac 100644 --- a/CHANGES +++ b/CHANGES @@ -113,6 +113,7 @@ Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types - Wii: Disable use of strtof_l (fixes mgba.io/i/1106) + - Wii: Expose stretch configuration in settings 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index f1df0c86c..ff6e39045 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -469,9 +469,49 @@ int main(int argc, char* argv[]) { "Bilinear (pixelated)", }, .nStates = 3 - } + }, + { + .title = "Horizontal stretch", + .data = "stretchWidth", + .submenu = 0, + .state = 7, + .validStates = (const char*[]) { + "1/2x", "0.6x", "1/3x", "0.7x", "1/4x", "0.8x", "0.9x", "1.0x" + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_F(0.5f), + GUI_V_F(0.6f), + GUI_V_F(1.f / 3.f), + GUI_V_F(0.7f), + GUI_V_F(0.75f), + GUI_V_F(0.8f), + GUI_V_F(0.9f), + GUI_V_F(1.0f), + }, + .nStates = 8 + }, + { + .title = "Vertical stretch", + .data = "stretchHeight", + .submenu = 0, + .state = 6, + .validStates = (const char*[]) { + "1/2x", "0.6x", "1/3x", "0.7x", "1/4x", "0.8x", "0.9x", "1.0x" + }, + .stateMappings = (const struct GUIVariant[]) { + GUI_V_F(0.5f), + GUI_V_F(0.6f), + GUI_V_F(1.f / 3.f), + GUI_V_F(0.7f), + GUI_V_F(0.75f), + GUI_V_F(0.8f), + GUI_V_F(0.9f), + GUI_V_F(1.0f), + }, + .nStates = 8 + }, }, - .nConfigExtra = 3, + .nConfigExtra = 5, .setup = _setup, .teardown = 0, .gameLoaded = _gameLoaded, @@ -517,6 +557,15 @@ int main(int argc, char* argv[]) { _mapKey(&runner.params.keyMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_LEFT, GUI_INPUT_LEFT); _mapKey(&runner.params.keyMap, CLASSIC_INPUT, WPAD_CLASSIC_BUTTON_RIGHT, GUI_INPUT_RIGHT); + + float stretch = 0; + if (mCoreConfigGetFloatValue(&runner.config, "stretchWidth", &stretch)) { + wStretch = fminf(1.0f, fmaxf(0.5f, stretch)); + } + if (mCoreConfigGetFloatValue(&runner.config, "stretchHeight", &stretch)) { + hStretch = fminf(1.0f, fmaxf(0.5f, stretch)); + } + if (argc > 1) { size_t i; for (i = 0; runner.keySources[i].id; ++i) { From eec39a4324386a8b853e871c23ed79b09bc397d2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 12:08:21 -0700 Subject: [PATCH 15/60] Wii: Stretch now sets pixel-accurate mode size cap --- CHANGES | 1 + src/platform/wii/main.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 2a81dbbac..5243ebc50 100644 --- a/CHANGES +++ b/CHANGES @@ -114,6 +114,7 @@ Misc: - mGUI: Add support for different settings types - Wii: Disable use of strtof_l (fixes mgba.io/i/1106) - Wii: Expose stretch configuration in settings + - Wii: Stretch now sets pixel-accurate mode size cap 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/platform/wii/main.c b/src/platform/wii/main.c index ff6e39045..8c37c1f4c 100644 --- a/src/platform/wii/main.c +++ b/src/platform/wii/main.c @@ -911,8 +911,8 @@ void _drawFrame(struct mGUIRunner* runner, bool faded) { GX_LoadTexObj(&rescaleTex, GX_TEXMAP0); } - int hfactor = vmode->fbWidth / (corew * wAdjust); - int vfactor = vmode->efbHeight / (coreh * hAdjust); + int hfactor = (vmode->fbWidth * wStretch) / (corew * wAdjust); + int vfactor = (vmode->efbHeight * hStretch) / (coreh * hAdjust); if (hfactor > vfactor) { scaleFactor = vfactor; } else { From 479bee3707070e46ca4ff1688c57802fa34fa4f0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 12:55:31 -0700 Subject: [PATCH 16/60] GB, GBA: Fix broken opposing button filter (fixes #1191) --- CHANGES | 1 + include/mgba/internal/gb/gb.h | 2 ++ src/gb/core.c | 6 +++++- src/gb/io.c | 19 ++++++++++++++++++- src/gba/core.c | 5 +++++ 5 files changed, 31 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 5243ebc50..95361c9ef 100644 --- a/CHANGES +++ b/CHANGES @@ -109,6 +109,7 @@ Bugfixes: - GBA Video: Fix caching with background toggling (fixes mgba.io/i/1118) - Wii: Fix drawing caching regression (fixes mgba.io/i/1185) - Switch: Fix incorrect mapping for fast forward cap + - GB, GBA: Fix broken opposing button filter (fixes mgba.io/i/1191) Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types diff --git a/include/mgba/internal/gb/gb.h b/include/mgba/internal/gb/gb.h index 47c3a03df..ac9d6230d 100644 --- a/include/mgba/internal/gb/gb.h +++ b/include/mgba/internal/gb/gb.h @@ -117,6 +117,8 @@ struct GB { bool earlyExit; struct mTimingEvent eiPending; unsigned doubleSpeed; + + bool allowOpposingDirections; }; struct GBCartridge { diff --git a/src/gb/core.c b/src/gb/core.c index f1c2ce120..a5b29d6a9 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -210,8 +210,12 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf mCoreConfigCopyValue(&core->config, config, "gb.model"); mCoreConfigCopyValue(&core->config, config, "sgb.model"); mCoreConfigCopyValue(&core->config, config, "cgb.model"); + mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); + + int fakeBool = 0; + mCoreConfigGetIntValue(config, "allowOpposingDirections", &fakeBool); + gb->allowOpposingDirections = fakeBool; - int fakeBool; if (mCoreConfigGetIntValue(config, "sgb.borders", &fakeBool)) { gb->video.sgbBorders = fakeBool; gb->video.renderer->enableSGBBorder(gb->video.renderer, fakeBool); diff --git a/src/gb/io.c b/src/gb/io.c index d24576333..492553780 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -105,6 +105,7 @@ static const uint8_t _registerMask[] = { }; static uint8_t _readKeys(struct GB* gb); +static uint8_t _readKeysFiltered(struct GB* gb); static void _writeSGBBits(struct GB* gb, int bits) { if (!bits) { @@ -557,10 +558,26 @@ static uint8_t _readKeys(struct GB* gb) { return gb->memory.io[REG_JOYP]; } +static uint8_t _readKeysFiltered(struct GB* gb) { + uint8_t keys = _readKeys(gb); + if (!gb->allowOpposingDirections && (keys & 0x30) == 0x20) { + unsigned rl = keys & 0x03; + unsigned ud = keys & 0x0C; + keys &= 0xF0; + if (rl != 0x03) { + keys |= rl; + } + if (ud != 0x0C) { + keys |= ud; + } + } + return keys; +} + uint8_t GBIORead(struct GB* gb, unsigned address) { switch (address) { case REG_JOYP: - return _readKeys(gb); + return _readKeysFiltered(gb); case REG_IE: return gb->memory.ie; case REG_WAVE_0: diff --git a/src/gba/core.c b/src/gba/core.c index 9513ab899..05225bc56 100644 --- a/src/gba/core.c +++ b/src/gba/core.c @@ -239,6 +239,11 @@ static void _GBACoreLoadConfig(struct mCore* core, const struct mCoreConfig* con } } + int fakeBool = 0; + mCoreConfigGetIntValue(config, "allowOpposingDirections", &fakeBool); + gba->allowOpposingDirections = fakeBool; + + mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); mCoreConfigCopyValue(&core->config, config, "gba.bios"); #ifndef DISABLE_THREADING From 2865c9ab2bf454041660d04508d82b1db436c26b Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 23:11:16 -0700 Subject: [PATCH 17/60] Switch: Rumble support --- CHANGES | 1 + src/platform/switch/main.c | 58 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 95361c9ef..577b69116 100644 --- a/CHANGES +++ b/CHANGES @@ -102,6 +102,7 @@ Changes from beta 1: Features: - Libretro: Add Game Boy cheat support - Qt: Separate fast forward volume control (fixes mgba.io/i/846, mgba.io/i/1143) + - Switch: Rumble support Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 9fd7e3649..3888ff66c 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -75,6 +75,12 @@ static GLuint tex; static color_t* frameBuffer; static struct mAVStream stream; +static struct mSwitchRumble { + struct mRumble d; + int up; + int down; + HidVibrationValue value; +} rumble; static int audioBufferActive; static struct GBAStereoSample audioBuffer[N_BUFFERS][SAMPLES] __attribute__((__aligned__(0x1000))); static AudioOutBuffer audoutBuffer[N_BUFFERS]; @@ -82,6 +88,8 @@ static int enqueuedBuffers; static bool frameLimiter = true; static unsigned framecount = 0; static unsigned framecap = 10; +static u32 vibrationDeviceHandles[4]; +static HidVibrationValue vibrationStop = { .freq_low = 160.f, .freq_high = 320.f }; static bool initEgl() { s_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); @@ -226,6 +234,7 @@ static void _setup(struct mGUIRunner* runner) { _mapKey(&runner->core->inputMap, AUTO_INPUT, KEY_R, GBA_KEY_R); runner->core->setVideoBuffer(runner->core, frameBuffer, 256); + runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d); runner->core->setAVStream(runner->core, &stream); } @@ -237,6 +246,18 @@ static void _gameLoaded(struct mGUIRunner* runner) { blip_set_rates(runner->core->getAudioChannel(runner->core, 1), runner->core->frequency(runner->core), samplerate * ratio); mCoreConfigGetUIntValue(&runner->config, "fastForwardCap", &framecap); + + rumble.up = 0; + rumble.down = 0; +} + +static void _gameUnloaded(struct mGUIRunner* runner) { + HidVibrationValue values[4]; + memcpy(&values[0], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[1], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[2], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[3], &vibrationStop, sizeof(rumble.value)); + hidSendVibrationValues(vibrationDeviceHandles, values, 4); } static void _drawTex(struct mGUIRunner* runner, unsigned width, unsigned height, bool faded) { @@ -299,6 +320,24 @@ static void _drawFrame(struct mGUIRunner* runner, bool faded) { glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); _drawTex(runner, width, height, faded); + + HidVibrationValue values[4]; + if (rumble.up) { + rumble.value.amp_low = rumble.up / (float) (rumble.up + rumble.down); + rumble.value.amp_high = rumble.up / (float) (rumble.up + rumble.down); + memcpy(&values[0], &rumble.value, sizeof(rumble.value)); + memcpy(&values[1], &rumble.value, sizeof(rumble.value)); + memcpy(&values[2], &rumble.value, sizeof(rumble.value)); + memcpy(&values[3], &rumble.value, sizeof(rumble.value)); + } else { + memcpy(&values[0], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[1], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[2], &vibrationStop, sizeof(rumble.value)); + memcpy(&values[3], &vibrationStop, sizeof(rumble.value)); + } + hidSendVibrationValues(vibrationDeviceHandles, values, 4); + rumble.up = 0; + rumble.down = 0; } static void _drawScreenshot(struct mGUIRunner* runner, const color_t* pixels, unsigned width, unsigned height, bool faded) { @@ -355,6 +394,15 @@ static void _postAudioBuffer(struct mAVStream* stream, blip_t* left, blip_t* rig ++enqueuedBuffers; } +void _setRumble(struct mRumble* rumble, int enable) { + struct mSwitchRumble* sr = (struct mSwitchRumble*) rumble; + if (enable) { + ++sr->up; + } else { + ++sr->down; + } +} + static int _batteryState(void) { u32 charge; int state = 0; @@ -455,6 +503,12 @@ int main(int argc, char* argv[]) { glEnableVertexAttribArray(offsetLocation); glBindVertexArray(0); + rumble.d.setRumble = _setRumble; + rumble.value.freq_low = 120.0; + rumble.value.freq_high = 180.0; + hidInitializeVibrationDevices(&vibrationDeviceHandles[0], 2, CONTROLLER_HANDHELD, TYPE_HANDHELD | TYPE_JOYCON_PAIR); + hidInitializeVibrationDevices(&vibrationDeviceHandles[2], 2, CONTROLLER_PLAYER_1, TYPE_HANDHELD | TYPE_JOYCON_PAIR); + stream.videoDimensionsChanged = NULL; stream.postVideoFrame = NULL; stream.postAudioFrame = NULL; @@ -552,11 +606,11 @@ int main(int argc, char* argv[]) { .setup = _setup, .teardown = NULL, .gameLoaded = _gameLoaded, - .gameUnloaded = NULL, + .gameUnloaded = _gameUnloaded, .prepareForFrame = _prepareForFrame, .drawFrame = _drawFrame, .drawScreenshot = _drawScreenshot, - .paused = NULL, + .paused = _gameUnloaded, .unpaused = _gameLoaded, .incrementScreenMode = NULL, .setFrameLimiter = _setFrameLimiter, From 426993bbbb57cbcd06afd3c0ae5dc03254dff2a8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 29 Sep 2018 23:14:43 -0700 Subject: [PATCH 18/60] GB I/O: Fix inverted button filter --- src/gb/io.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/gb/io.c b/src/gb/io.c index 492553780..2d3efec2f 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -563,12 +563,11 @@ static uint8_t _readKeysFiltered(struct GB* gb) { if (!gb->allowOpposingDirections && (keys & 0x30) == 0x20) { unsigned rl = keys & 0x03; unsigned ud = keys & 0x0C; - keys &= 0xF0; - if (rl != 0x03) { - keys |= rl; + if (!rl) { + keys |= 0x03; } - if (ud != 0x0C) { - keys |= ud; + if (!ud) { + keys |= 0x0C; } } return keys; From b192330166b2b25f5e71c2b4e1eb5c78a9871e99 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 30 Sep 2018 13:34:26 -0700 Subject: [PATCH 19/60] Qt: Fix jumbled background when paused --- CHANGES | 1 + src/platform/qt/Window.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 577b69116..486778c87 100644 --- a/CHANGES +++ b/CHANGES @@ -111,6 +111,7 @@ Bugfixes: - Wii: Fix drawing caching regression (fixes mgba.io/i/1185) - Switch: Fix incorrect mapping for fast forward cap - GB, GBA: Fix broken opposing button filter (fixes mgba.io/i/1191) + - Qt: Fix jumbled background when paused Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index e8bdcb5fd..e5e33566b 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -1820,7 +1820,7 @@ void Window::focusCheck() { void Window::updateFrame() { QSize size = m_controller->screenDimensions(); QImage currentImage(reinterpret_cast(m_controller->drawContext()), size.width(), size.height(), - 256 * BYTES_PER_PIXEL, QImage::Format_RGBX8888); + size.width() * BYTES_PER_PIXEL, QImage::Format_RGBX8888); QPixmap pixmap; pixmap.convertFromImage(currentImage); m_screenWidget->setPixmap(pixmap); From 1247dec1ba725ff21307429a3a9f417685ef1218 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 30 Sep 2018 14:05:06 -0700 Subject: [PATCH 20/60] Switch: Rotation support --- CHANGES | 1 + src/platform/switch/main.c | 40 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/CHANGES b/CHANGES index 486778c87..1580cbae0 100644 --- a/CHANGES +++ b/CHANGES @@ -103,6 +103,7 @@ Features: - Libretro: Add Game Boy cheat support - Qt: Separate fast forward volume control (fixes mgba.io/i/846, mgba.io/i/1143) - Switch: Rumble support + - Switch: Rotation support Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full diff --git a/src/platform/switch/main.c b/src/platform/switch/main.c index 3888ff66c..6c1018712 100644 --- a/src/platform/switch/main.c +++ b/src/platform/switch/main.c @@ -81,6 +81,7 @@ static struct mSwitchRumble { int down; HidVibrationValue value; } rumble; +static struct mRotationSource rotation = {0}; static int audioBufferActive; static struct GBAStereoSample audioBuffer[N_BUFFERS][SAMPLES] __attribute__((__aligned__(0x1000))); static AudioOutBuffer audoutBuffer[N_BUFFERS]; @@ -235,6 +236,7 @@ static void _setup(struct mGUIRunner* runner) { runner->core->setVideoBuffer(runner->core, frameBuffer, 256); runner->core->setPeripheral(runner->core, mPERIPH_RUMBLE, &rumble.d); + runner->core->setPeripheral(runner->core, mPERIPH_ROTATION, &rotation); runner->core->setAVStream(runner->core, &stream); } @@ -403,6 +405,27 @@ void _setRumble(struct mRumble* rumble, int enable) { } } +int32_t _readTiltX(struct mRotationSource* source) { + UNUSED(source); + SixAxisSensorValues sixaxis; + hidSixAxisSensorValuesRead(&sixaxis, CONTROLLER_P1_AUTO, 1); + return sixaxis.accelerometer.x * 3e8f; +} + +int32_t _readTiltY(struct mRotationSource* source) { + UNUSED(source); + SixAxisSensorValues sixaxis; + hidSixAxisSensorValuesRead(&sixaxis, CONTROLLER_P1_AUTO, 1); + return sixaxis.accelerometer.y * -3e8f; +} + +int32_t _readGyroZ(struct mRotationSource* source) { + UNUSED(source); + SixAxisSensorValues sixaxis; + hidSixAxisSensorValuesRead(&sixaxis, CONTROLLER_P1_AUTO, 1); + return sixaxis.gyroscope.z * 1.1e9f; +} + static int _batteryState(void) { u32 charge; int state = 0; @@ -509,6 +532,18 @@ int main(int argc, char* argv[]) { hidInitializeVibrationDevices(&vibrationDeviceHandles[0], 2, CONTROLLER_HANDHELD, TYPE_HANDHELD | TYPE_JOYCON_PAIR); hidInitializeVibrationDevices(&vibrationDeviceHandles[2], 2, CONTROLLER_PLAYER_1, TYPE_HANDHELD | TYPE_JOYCON_PAIR); + u32 handles[4]; + hidGetSixAxisSensorHandles(&handles[0], 2, CONTROLLER_PLAYER_1, TYPE_JOYCON_PAIR); + hidGetSixAxisSensorHandles(&handles[2], 1, CONTROLLER_PLAYER_1, TYPE_PROCONTROLLER); + hidGetSixAxisSensorHandles(&handles[3], 1, CONTROLLER_HANDHELD, TYPE_HANDHELD); + hidStartSixAxisSensor(handles[0]); + hidStartSixAxisSensor(handles[1]); + hidStartSixAxisSensor(handles[2]); + hidStartSixAxisSensor(handles[3]); + rotation.readTiltX = _readTiltX; + rotation.readTiltY = _readTiltY; + rotation.readGyroZ = _readGyroZ; + stream.videoDimensionsChanged = NULL; stream.postVideoFrame = NULL; stream.postAudioFrame = NULL; @@ -648,6 +683,11 @@ int main(int argc, char* argv[]) { glDeleteProgram(program); glDeleteVertexArrays(1, &vao); + hidStopSixAxisSensor(handles[0]); + hidStopSixAxisSensor(handles[1]); + hidStopSixAxisSensor(handles[2]); + hidStopSixAxisSensor(handles[3]); + psmExit(); audoutExit(); deinitEgl(); From da80c5a9714a2c6d717a9dc8b11d3e37ac6fc585 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 30 Sep 2018 16:14:17 -0700 Subject: [PATCH 21/60] Qt: Fix FPS counter on Windows --- CHANGES | 1 + src/platform/qt/Window.cpp | 26 ++++++++------------------ src/platform/qt/Window.h | 9 +++------ 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index 1580cbae0..75cbe1fe9 100644 --- a/CHANGES +++ b/CHANGES @@ -113,6 +113,7 @@ Bugfixes: - Switch: Fix incorrect mapping for fast forward cap - GB, GBA: Fix broken opposing button filter (fixes mgba.io/i/1191) - Qt: Fix jumbled background when paused + - Qt: Fix FPS counter on Windows Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index e5e33566b..10254984f 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -138,13 +138,11 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi connect(this, &Window::shutdown, m_logView, &QWidget::hide); connect(&m_fpsTimer, &QTimer::timeout, this, &Window::showFPS); - connect(&m_frameTimer, &QTimer::timeout, this, &Window::delimitFrames); connect(&m_focusCheck, &QTimer::timeout, this, &Window::focusCheck); connect(&m_inputController, &InputController::profileLoaded, m_shortcutController, &ShortcutController::loadProfile); m_log.setLevels(mLOG_WARN | mLOG_ERROR | mLOG_FATAL); m_fpsTimer.setInterval(FPS_TIMER_INTERVAL); - m_frameTimer.setInterval(FRAME_LIST_INTERVAL); m_focusCheck.setInterval(200); m_shortcutController->setConfigController(m_config); @@ -773,7 +771,6 @@ void Window::gameStopped() { m_audioChannels->clear(); m_fpsTimer.stop(); - m_frameTimer.stop(); m_focusCheck.stop(); emit paused(false); @@ -903,19 +900,8 @@ void Window::mustRestart() { } void Window::recordFrame() { - if (m_frameList.isEmpty()) { - m_frameList.append(1); - } else { - ++m_frameList.back(); - } -} - -void Window::delimitFrames() { - if (m_frameList.size() >= FRAME_LIST_SIZE) { - m_frameCounter -= m_frameList.takeAt(0); - } - m_frameCounter += m_frameList.back(); - m_frameList.append(0); + m_frameList.append(m_frameTimer.nsecsElapsed()); + m_frameTimer.restart(); } void Window::showFPS() { @@ -923,7 +909,12 @@ void Window::showFPS() { updateTitle(); return; } - float fps = m_frameCounter * 10000.f / (FRAME_LIST_INTERVAL * (m_frameList.size() - 1)); + qint64 total = 0; + for (qint64 t : m_frameList) { + total += t; + } + double fps = (m_frameList.size() * 1e10) / total; + m_frameList.clear(); fps = round(fps) / 10.f; updateTitle(fps); } @@ -1655,7 +1646,6 @@ void Window::setupMenu(QMenuBar* menubar) { showFps->connect([this](const QVariant& value) { if (!value.toInt()) { m_fpsTimer.stop(); - m_frameTimer.stop(); updateTitle(); } else if (m_controller) { m_fpsTimer.start(); diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 401a851cd..44b8e812a 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -132,7 +133,6 @@ private slots: void mustRestart(); void recordFrame(); - void delimitFrames(); void showFPS(); void focusCheck(); @@ -140,8 +140,6 @@ private slots: private: static const int FPS_TIMER_INTERVAL = 2000; - static const int FRAME_LIST_INTERVAL = 100; - static const int FRAME_LIST_SIZE = 40; void setupMenu(QMenuBar*); void openStateWindow(LoadSave); @@ -189,10 +187,9 @@ private: QPixmap m_logo{":/res/mgba-1024.png"}; ConfigController* m_config; InputController m_inputController; - QList m_frameList; - int m_frameCounter = 0; + QList m_frameList; + QElapsedTimer m_frameTimer; QTimer m_fpsTimer; - QTimer m_frameTimer; QList m_mruFiles; QMenu* m_mruMenu = nullptr; QMenu* m_videoLayers; From 2bfc3e0ca623e4140e0f44ea75ab04512e41681a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 1 Oct 2018 11:15:20 -0700 Subject: [PATCH 22/60] Wii: Define _GNU_SOURCE --- CHANGES | 2 +- CMakeLists.txt | 2 +- src/util/formatting.c | 6 ------ 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 75cbe1fe9..5aa4681af 100644 --- a/CHANGES +++ b/CHANGES @@ -117,7 +117,7 @@ Bugfixes: Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types - - Wii: Disable use of strtof_l (fixes mgba.io/i/1106) + - Wii: Define _GNU_SOURCE (fixes mgba.io/i/1106) - Wii: Expose stretch configuration in settings - Wii: Stretch now sets pixel-accurate mode size cap diff --git a/CMakeLists.txt b/CMakeLists.txt index 87deecf63..2281a45c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -321,7 +321,7 @@ if(WII) add_definitions(-U__STRICT_ANSI__) endif() -if(DEFINED 3DS) +if(3DS OR WII) add_definitions(-D_GNU_SOURCE) endif() diff --git a/src/util/formatting.c b/src/util/formatting.c index c6aa1e7b8..1305edfc9 100644 --- a/src/util/formatting.c +++ b/src/util/formatting.c @@ -59,11 +59,6 @@ int ftostr_u(char* restrict str, size_t size, float f) { } float strtof_u(const char* restrict str, char** restrict end) { -#ifdef GEKKO - // strtof_l appears to have broken in devkitPPC sometime around r28 - // TODO: Investigate further - float res = strtof(str, end); -#else #if HAVE_LOCALE locale_t l = newlocale(LC_NUMERIC_MASK, "C", 0); #else @@ -72,7 +67,6 @@ float strtof_u(const char* restrict str, char** restrict end) { float res = strtof_l(str, end, l); #if HAVE_LOCALE freelocale(l); -#endif #endif return res; } From 2d5bfe33211e897a78e28283797376f752764010 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 1 Oct 2018 12:07:56 -0700 Subject: [PATCH 23/60] Qt: Ensure camera image is valid --- CHANGES | 1 + src/platform/qt/InputController.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 5aa4681af..077514bfb 100644 --- a/CHANGES +++ b/CHANGES @@ -120,6 +120,7 @@ Misc: - Wii: Define _GNU_SOURCE (fixes mgba.io/i/1106) - Wii: Expose stretch configuration in settings - Wii: Stretch now sets pixel-accurate mode size cap + - Qt: Ensure camera image is valid 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/platform/qt/InputController.cpp b/src/platform/qt/InputController.cpp index 36afa1841..ce73a5255 100644 --- a/src/platform/qt/InputController.cpp +++ b/src/platform/qt/InputController.cpp @@ -678,13 +678,13 @@ void InputController::releaseFocus(QWidget* focus) { } void InputController::loadCamImage(const QString& path) { - QMutexLocker locker(&m_image.mutex); - m_image.image.load(path); - m_image.resizedImage = QImage(); - m_image.outOfDate = true; + setCamImage(QImage(path)); } void InputController::setCamImage(const QImage& image) { + if (image.isNull()) { + return; + } QMutexLocker locker(&m_image.mutex); m_image.image = image; m_image.resizedImage = QImage(); From 12cf61f9fc0f3a38104d69bd61964d0099e136b3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 1 Oct 2018 12:15:16 -0700 Subject: [PATCH 24/60] Qt: Copy volume and mute settings into core config (fixes #1194) --- src/platform/qt/CoreController.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platform/qt/CoreController.cpp b/src/platform/qt/CoreController.cpp index b07b01be7..e16e1c5da 100644 --- a/src/platform/qt/CoreController.cpp +++ b/src/platform/qt/CoreController.cpp @@ -247,6 +247,8 @@ void CoreController::loadConfig(ConfigController* config) { m_autofireThreshold = config->getOption("autofireThreshold", m_autofireThreshold).toInt(); m_fastForwardVolume = config->getOption("fastForwardVolume", -1).toInt(); m_fastForwardMute = config->getOption("fastForwardMute", -1).toInt(); + mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "volume"); + mCoreConfigCopyValue(&m_threadContext.core->config, config->config(), "mute"); mCoreLoadForeignConfig(m_threadContext.core, config->config()); if (hasStarted()) { updateFastForward(); From ac2c1417ad3acd412d254095161f1c7451b77c53 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 1 Oct 2018 16:36:31 -0700 Subject: [PATCH 25/60] Qt: Slow down sensor view polling --- src/platform/qt/SensorView.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/SensorView.cpp b/src/platform/qt/SensorView.cpp index 9deb4f5e0..54c49cc2c 100644 --- a/src/platform/qt/SensorView.cpp +++ b/src/platform/qt/SensorView.cpp @@ -32,7 +32,7 @@ SensorView::SensorView(InputController* input, QWidget* parent) m_ui.time->setDateTime(QDateTime::currentDateTime()); }); - m_timer.setInterval(2); + m_timer.setInterval(15); connect(&m_timer, &QTimer::timeout, this, &SensorView::updateSensors); if (!m_rotation || !m_rotation->readTiltX || !m_rotation->readTiltY) { m_ui.tilt->hide(); From 08ab254fef35139139744d773bdfa6ee689e4fee Mon Sep 17 00:00:00 2001 From: lacastri <43101266+lacastri@users.noreply.github.com> Date: Mon, 1 Oct 2018 22:25:55 -0500 Subject: [PATCH 26/60] cmake libretro "visual studio 15 2017" --- CMakeLists.txt | 6 +++++- include/mgba-util/common.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2281a45c4..b2daddb35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -913,7 +913,11 @@ if(BUILD_LIBRETRO) add_library(${BINARY_NAME}_libretro SHARED ${CORE_SRC} ${RETRO_SRC}) set_target_properties(${BINARY_NAME}_libretro PROPERTIES PREFIX "" COMPILE_DEFINITIONS "COLOR_16_BIT;COLOR_5_6_5;DISABLE_THREADING;${OS_DEFINES};${FUNCTION_DEFINES};MINIMAL_CORE=2") target_link_libraries(${BINARY_NAME}_libretro ${OS_LIB}) - install(TARGETS ${BINARY_NAME}_libretro LIBRARY DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro NAMELINK_SKIP) + if(MSVC) + install(TARGETS ${BINARY_NAME}_libretro RUNTIME DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro) + else() + install(TARGETS ${BINARY_NAME}_libretro LIBRARY DESTINATION ${LIBRETRO_LIBDIR} COMPONENT ${BINARY_NAME}_libretro NAMELINK_SKIP) + endif() endif() if(BUILD_OPENEMU) diff --git a/include/mgba-util/common.h b/include/mgba-util/common.h index daac8686e..9a24663e9 100644 --- a/include/mgba-util/common.h +++ b/include/mgba-util/common.h @@ -178,8 +178,12 @@ typedef intptr_t ssize_t; #define STORE_64LE(SRC, ADDR, ARR) *(uint64_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC #define STORE_32LE(SRC, ADDR, ARR) *(uint32_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC #define STORE_16LE(SRC, ADDR, ARR) *(uint16_t*) ((uintptr_t) (ARR) + (size_t) (ADDR)) = SRC +#ifdef _MSC_VER +#define LOAD_32BE(DEST, ADDR, ARR) DEST = _byteswap_ulong(((uint32_t*) ARR)[(ADDR) >> 2]) +#else #define LOAD_32BE(DEST, ADDR, ARR) DEST = __builtin_bswap32(((uint32_t*) ARR)[(ADDR) >> 2]) #endif +#endif #define MAKE_MASK(START, END) (((1 << ((END) - (START))) - 1) << (START)) #define CHECK_BITS(SRC, START, END) ((SRC) & MAKE_MASK(START, END)) From e26eeed02a91cc12a979af380ef5515c7bbe935e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 2 Oct 2018 08:19:47 -0700 Subject: [PATCH 27/60] GB, GBA Savedata: Fix leaks when loading masked save (fixes #1197) --- CHANGES | 1 + src/gb/gb.c | 4 ++++ src/gba/gba.c | 2 ++ src/gba/memory.c | 7 ------- src/gba/savedata.c | 4 ++++ 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 077514bfb..63ba1d53e 100644 --- a/CHANGES +++ b/CHANGES @@ -114,6 +114,7 @@ Bugfixes: - GB, GBA: Fix broken opposing button filter (fixes mgba.io/i/1191) - Qt: Fix jumbled background when paused - Qt: Fix FPS counter on Windows + - GB, GBA Savedata: Fix leaks when loading masked save (fixes mgba.io/i/1197) Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types diff --git a/src/gb/gb.c b/src/gb/gb.c index 29b12df2d..fa5408107 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -249,7 +249,11 @@ void GBSramClean(struct GB* gb, uint32_t frameCount) { } void GBSavedataMask(struct GB* gb, struct VFile* vf, bool writeback) { + struct VFile* oldVf = gb->sramVf; GBSramDeinit(gb); + if (oldVf && oldVf != gb->sramRealVf) { + oldVf->close(oldVf); + } gb->sramVf = vf; gb->sramMaskWriteback = writeback; gb->memory.sram = vf->map(vf, gb->sramSize, MAP_READ); diff --git a/src/gba/gba.c b/src/gba/gba.c index 38fa0fc7a..057957161 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -138,6 +138,8 @@ void GBAUnloadROM(struct GBA* gba) { gba->memory.rom = NULL; gba->isPristine = false; + gba->memory.savedata.maskWriteback = false; + GBASavedataUnmask(&gba->memory.savedata); GBASavedataDeinit(&gba->memory.savedata); if (gba->memory.savedata.realVf) { gba->memory.savedata.realVf->close(gba->memory.savedata.realVf); diff --git a/src/gba/memory.c b/src/gba/memory.c index 0ae984eff..384fd81cc 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -99,13 +99,6 @@ void GBAMemoryDeinit(struct GBA* gba) { if (gba->memory.rom) { mappedMemoryFree(gba->memory.rom, gba->memory.romSize); } - gba->memory.savedata.maskWriteback = false; - GBASavedataUnmask(&gba->memory.savedata); - GBASavedataDeinit(&gba->memory.savedata); - if (gba->memory.savedata.realVf) { - gba->memory.savedata.realVf->close(gba->memory.savedata.realVf); - } - if (gba->memory.agbPrintBuffer) { mappedMemoryFree(gba->memory.agbPrintBuffer, SIZE_AGB_PRINT); } diff --git a/src/gba/savedata.c b/src/gba/savedata.c index 1c34100dd..ba702e36b 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -88,7 +88,11 @@ void GBASavedataDeinit(struct GBASavedata* savedata) { void GBASavedataMask(struct GBASavedata* savedata, struct VFile* vf, bool writeback) { enum SavedataType type = savedata->type; + struct VFile* oldVf = savedata->vf; GBASavedataDeinit(savedata); + if (oldVf && oldVf != savedata->realVf) { + oldVf->close(oldVf); + } savedata->vf = vf; savedata->mapMode = MAP_READ; savedata->maskWriteback = writeback; From 64b44efbf15168b03ee5f02ca03f55f519e4824f Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 2 Oct 2018 09:39:27 -0700 Subject: [PATCH 28/60] Qt: State file load/save menu options --- CHANGES | 1 + src/platform/qt/Window.cpp | 28 ++++++++++++++++++++++++++++ src/platform/qt/Window.h | 1 + 3 files changed, 30 insertions(+) diff --git a/CHANGES b/CHANGES index 63ba1d53e..af13230da 100644 --- a/CHANGES +++ b/CHANGES @@ -104,6 +104,7 @@ Features: - Qt: Separate fast forward volume control (fixes mgba.io/i/846, mgba.io/i/1143) - Switch: Rumble support - Switch: Rotation support + - Qt: State file load/save menu options Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index 10254984f..b9dba9374 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -362,6 +362,22 @@ void Window::selectSave(bool temporary) { } } +void Window::selectState(bool load) { + QStringList formats{"*.ss0", "*.ss1", "*.ss2", "*.ss3", "*.ss4", "*.ss5", "*.ss6", "*.ss7", "*.ss8", "*.ss9"}; + QString filter = tr("mGBA savestate files (%1)").arg(formats.join(QChar(' '))); + if (load) { + QString filename = GBAApp::app()->getOpenFileName(this, tr("Select savestate"), filter); + if (!filename.isEmpty()) { + m_controller->loadState(filename); + } + } else { + QString filename = GBAApp::app()->getSaveFileName(this, tr("Select savestate"), filter); + if (!filename.isEmpty()) { + m_controller->saveState(filename); + } + } +} + void Window::multiplayerChanged() { if (!m_controller) { return; @@ -1046,6 +1062,12 @@ void Window::setupMenu(QMenuBar* menubar) { m_nonMpActions.append(loadState); addControlledAction(fileMenu, loadState, "loadState"); + QAction* loadStateFile = new QAction(tr("Load state file..."), fileMenu); + connect(loadStateFile, &QAction::triggered, [this]() { this->selectState(true); }); + m_gameActions.append(loadStateFile); + m_nonMpActions.append(loadStateFile); + addControlledAction(fileMenu, loadStateFile, "loadStateFile"); + QAction* saveState = new QAction(tr("&Save state"), fileMenu); saveState->setShortcut(tr("Shift+F10")); connect(saveState, &QAction::triggered, [this]() { this->openStateWindow(LoadSave::SAVE); }); @@ -1053,6 +1075,12 @@ void Window::setupMenu(QMenuBar* menubar) { m_nonMpActions.append(saveState); addControlledAction(fileMenu, saveState, "saveState"); + QAction* saveStateFile = new QAction(tr("Save state file..."), fileMenu); + connect(saveStateFile, &QAction::triggered, [this]() { this->selectState(false); }); + m_gameActions.append(saveStateFile); + m_nonMpActions.append(saveStateFile); + addControlledAction(fileMenu, saveStateFile, "saveStateFile"); + QMenu* quickLoadMenu = fileMenu->addMenu(tr("Quick load")); QMenu* quickSaveMenu = fileMenu->addMenu(tr("Quick save")); m_shortcutController->addMenu(quickLoadMenu); diff --git a/src/platform/qt/Window.h b/src/platform/qt/Window.h index 44b8e812a..f30e524af 100644 --- a/src/platform/qt/Window.h +++ b/src/platform/qt/Window.h @@ -70,6 +70,7 @@ public slots: void addDirToLibrary(); #endif void selectSave(bool temporary); + void selectState(bool load); void selectPatch(); void enterFullScreen(); void exitFullScreen(); From 18fc2cbdb222d94424044fa3155964f534c4fab4 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 2 Oct 2018 10:00:57 -0700 Subject: [PATCH 29/60] Qt: Fix focus issues with LoadSaveState --- CHANGES | 1 + src/platform/qt/LoadSaveState.cpp | 8 +++++++- src/platform/qt/LoadSaveState.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index af13230da..5abb5d52e 100644 --- a/CHANGES +++ b/CHANGES @@ -116,6 +116,7 @@ Bugfixes: - Qt: Fix jumbled background when paused - Qt: Fix FPS counter on Windows - GB, GBA Savedata: Fix leaks when loading masked save (fixes mgba.io/i/1197) + - Qt: Fix focus issues with load/save state overlay Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types diff --git a/src/platform/qt/LoadSaveState.cpp b/src/platform/qt/LoadSaveState.cpp index d9db6a7d3..93cbfee66 100644 --- a/src/platform/qt/LoadSaveState.cpp +++ b/src/platform/qt/LoadSaveState.cpp @@ -27,8 +27,9 @@ LoadSaveState::LoadSaveState(std::shared_ptr controller, QWidget , m_mode(LoadSave::LOAD) , m_currentFocus(controller->stateSlot() - 1) { - setAttribute(Qt::WA_TranslucentBackground); m_ui.setupUi(this); + m_ui.lsLabel->setFocusProxy(this); + setFocusPolicy(Qt::ClickFocus); m_slots[0] = m_ui.state1; m_slots[1] = m_ui.state2; @@ -56,6 +57,7 @@ LoadSaveState::LoadSaveState(std::shared_ptr controller, QWidget if (m_currentFocus < 0) { m_currentFocus = 0; } + m_slots[m_currentFocus]->setFocus(); QAction* escape = new QAction(this); connect(escape, &QAction::triggered, this, &QWidget::close); @@ -242,6 +244,10 @@ void LoadSaveState::showEvent(QShowEvent* event) { QWidget::showEvent(event); } +void LoadSaveState::focusInEvent(QFocusEvent*) { + m_slots[m_currentFocus]->setFocus(); +} + void LoadSaveState::paintEvent(QPaintEvent*) { QPainter painter(this); QRect full(QPoint(), size()); diff --git a/src/platform/qt/LoadSaveState.h b/src/platform/qt/LoadSaveState.h index b762a00e1..5596c1b10 100644 --- a/src/platform/qt/LoadSaveState.h +++ b/src/platform/qt/LoadSaveState.h @@ -41,6 +41,7 @@ protected: virtual void closeEvent(QCloseEvent*) override; virtual void showEvent(QShowEvent*) override; virtual void paintEvent(QPaintEvent*) override; + virtual void focusInEvent(QFocusEvent*) override; private: void loadState(int slot); From 5e7333e20f63989b81ede8fd456eb522a1db90d6 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 2 Oct 2018 13:03:41 -0700 Subject: [PATCH 30/60] Qt: Don't double-load display driver --- src/platform/qt/Window.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index b9dba9374..be1ebf072 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -81,7 +81,6 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi setAcceptDrops(true); setAttribute(Qt::WA_DeleteOnClose); updateTitle(); - reloadDisplayDriver(); m_logo.setDevicePixelRatio(m_screenWidget->devicePixelRatio()); m_logo = m_logo; // Free memory left over in old pixmap @@ -238,8 +237,10 @@ void Window::reloadConfig() { } m_display->resizeContext(); } - m_display->lockAspectRatio(opts->lockAspectRatio); - m_display->filter(opts->resampleVideo); + if (m_display) { + m_display->lockAspectRatio(opts->lockAspectRatio); + m_display->filter(opts->resampleVideo); + } m_inputController.setScreensaverSuspendable(opts->suspendScreensaver); } @@ -600,9 +601,7 @@ void Window::showEvent(QShowEvent* event) { enterFullScreen(); m_fullscreenOnStart = false; } - if (m_display) { - reloadDisplayDriver(); - } + reloadDisplayDriver(); } void Window::closeEvent(QCloseEvent* event) { @@ -702,6 +701,9 @@ void Window::gameStarted() { if (m_savedScale > 0) { resizeFrame(size * m_savedScale); } + if (!m_display) { + reloadDisplayDriver(); + } attachWidget(m_display.get()); m_display->setMinimumSize(size); @@ -1382,7 +1384,9 @@ void Window::setupMenu(QMenuBar* menubar) { ConfigOption* lockAspectRatio = m_config->addOption("lockAspectRatio"); lockAspectRatio->addBoolean(tr("Lock aspect ratio"), avMenu); lockAspectRatio->connect([this](const QVariant& value) { - m_display->lockAspectRatio(value.toBool()); + if (m_display) { + m_display->lockAspectRatio(value.toBool()); + } if (m_controller) { m_screenWidget->setLockAspectRatio(value.toBool()); } @@ -1392,7 +1396,9 @@ void Window::setupMenu(QMenuBar* menubar) { ConfigOption* lockIntegerScaling = m_config->addOption("lockIntegerScaling"); lockIntegerScaling->addBoolean(tr("Force integer scaling"), avMenu); lockIntegerScaling->connect([this](const QVariant& value) { - m_display->lockIntegerScaling(value.toBool()); + if (m_display) { + m_display->lockIntegerScaling(value.toBool()); + } if (m_controller) { m_screenWidget->setLockIntegerScaling(value.toBool()); } @@ -1402,7 +1408,9 @@ void Window::setupMenu(QMenuBar* menubar) { ConfigOption* resampleVideo = m_config->addOption("resampleVideo"); resampleVideo->addBoolean(tr("Bilinear filtering"), avMenu); resampleVideo->connect([this](const QVariant& value) { - m_display->filter(value.toBool()); + if (m_display) { + m_display->filter(value.toBool()); + } }, this); m_config->updateOption("resampleVideo"); From 50e699037fe72d0c13ac676c7492bc0032dca2ac Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 2 Oct 2018 13:04:15 -0700 Subject: [PATCH 31/60] Qt: Clear display before closing window --- src/platform/qt/Window.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/qt/Window.cpp b/src/platform/qt/Window.cpp index be1ebf072..ea03858f0 100644 --- a/src/platform/qt/Window.cpp +++ b/src/platform/qt/Window.cpp @@ -613,6 +613,7 @@ void Window::closeEvent(QCloseEvent* event) { m_config->setOption("width", VIDEO_HORIZONTAL_PIXELS * m_savedScale); } saveConfig(); + m_display.reset(); QMainWindow::closeEvent(event); } From f52859126bcc3fd8c6f3026bc2209f2678a06c5d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 2 Oct 2018 13:07:26 -0700 Subject: [PATCH 32/60] Qt: End painter thread when destroying GL display --- src/platform/qt/DisplayGL.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 28b191831..223829432 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -40,6 +40,7 @@ DisplayGL::DisplayGL(const QGLFormat& format, QWidget* parent) } DisplayGL::~DisplayGL() { + stopDrawing(); delete m_painter; } From e1b9ace37ca8108932949545f09775c99187679f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20L=C3=B3pez=20Brante?= Date: Tue, 2 Oct 2018 20:44:24 -0300 Subject: [PATCH 33/60] Qt: Updated Spanish translation --- src/platform/qt/ts/mgba-es.ts | 675 ++++++++++++++++++---------------- 1 file changed, 365 insertions(+), 310 deletions(-) diff --git a/src/platform/qt/ts/mgba-es.ts b/src/platform/qt/ts/mgba-es.ts index 662b54668..cae9fd4f7 100644 --- a/src/platform/qt/ts/mgba-es.ts +++ b/src/platform/qt/ts/mgba-es.ts @@ -168,7 +168,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Enter command (try `help` for more info) - Ingresa un comando (intenta `help` para más información) + Ingresa un comando (prueba con `help` para más información) @@ -1249,22 +1249,22 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::CoreController - + Failed to open save file: %1 Error al abrir el archivo de guardado: %1 - + Failed to open game file: %1 Error al abrir el archivo del juego: %1 - + Failed to open snapshot file for reading: %1 Error al leer del archivo de captura: %1 - + Failed to open snapshot file for writing: %1 Error al escribir al archivo de captura: %1 @@ -2764,27 +2764,27 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::LoadSaveState - + Load State Cargar estado - + Save State Guardar estado - + Empty Vacío - + Corrupted Dañado - + Slot %1 Espacio %1 @@ -2832,7 +2832,7 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Map Addr. - Dirección de mapa + Dir de mapa @@ -2899,7 +2899,6 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. - All Todo @@ -2909,32 +2908,32 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Cargar TBL - + Save selected memory Guardar memoria seleccionada - + Failed to open output file: %1 Error al abrir el archivo de salida: %1 - + Load memory Cargar memoria - + Failed to open input file: %1 Error al abrir el archivo de entrada: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3108,59 +3107,59 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (forzar versión 1.x) - + None (Still Image) Nada (imagen estática) - + Keyboard Teclado - + Controllers Controladores - + Shortcuts Atajos de teclado - - + + Shaders Shaders - + Select BIOS Seleccionar BIOS @@ -3219,17 +3218,17 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Error al abrir el archivo de video de salida: %1 - + Native (%0x%1) Native (%0x%1) - + Select output file Seleccionar archivo de salida @@ -3280,54 +3279,65 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. - - + + Select save Seleccionar guardado - + + mGBA savestate files (%1) + Archivos de estado de guardado de mGBA (%1) + + + + + Select savestate + Elegir estado de guardado + + + Select patch Seleccionar parche - + Patches (*.ips *.ups *.bps) Parches (*.ips *.ups *.bps) - + Select image Seleccionar imagen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Archivo de imagen (*.png *.gif *.jpg *.jpeg);;Todos los archivos (*) - - + + GameShark saves (*.sps *.xps) Guardados de GameShark (*.sps *.xps) - + Select video log Seleccionar video-registro - + Video logs (*.mvl) Video-registros (*.mvl) - + Crash Error fatal - + The game has crashed with the following error: %1 @@ -3336,648 +3346,655 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. %1 - + Couldn't Load No se pudo cargar - + Could not load game. Are you sure it's in the correct format? No se pudo cargar el juego. ¿Estás seguro de que está en el formato correcto? - + Unimplemented BIOS call Llamada a BIOS no implementada - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Este juego utiliza una llamada al BIOS que no se ha implementado. Utiliza el BIOS oficial para obtener la mejor experiencia. - + Really make portable? ¿Hacer "portable"? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Esto hará que el emulador cargue su configuración desde el mismo directorio que el ejecutable. ¿Quieres continuar? - + Restart needed Reinicio necesario - + Some changes will not take effect until the emulator is restarted. Algunos cambios no surtirán efecto hasta que se reinicie el emulador. - + - Player %1 of %2 - Jugador %1 de %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 fps) - %4 - + &File &Archivo - + Load &ROM... Cargar &ROM... - + Load ROM in archive... Cargar ROM desde contenedor... - + Add folder to library... Agregar carpeta a la biblioteca... - + Load alternate save... Cargar guardado alternativo... - + Load temporary save... Cargar guardado temporal... - + Load &patch... Cargar &parche... - + Boot BIOS Arrancar BIOS - + Replace ROM... Reemplazar ROM... - + ROM &info... &Información de la ROM... - + Recent Recientes - + Make portable Hacer "portable" - + &Load state Ca&rgar estado - + F10 F10 - + + Load state file... + Cargar archivo de estado... + + + &Save state Guardar e&stado - + Shift+F10 Shift+F10 - + + Save state file... + Guardar archivo de estado... + + + Quick load Cargado rápido - + Quick save Guardado rápido - + Load recent Cargar reciente - + Save recent Guardar reciente - + Undo load state Deshacer cargar estado - + F11 F11 - + Undo save state Deshacer guardar estado - + Shift+F11 Shift+F11 - - + + State &%1 Estado &%1 - + F%1 F%1 - + Shift+F%1 Shift+F%1 - + Load camera image... Cargar imagen para la cámara... - + Import GameShark Save Importar guardado de GameShark - + Export GameShark Save Exportar guardado de GameShark - + New multiplayer window Nueva ventana multijugador - + About Acerca de - + E&xit Salir (&X) - + &Emulation &Emulación - + &Reset &Reinicializar - + Ctrl+R Ctrl+R - + Sh&utdown Apagar (&U) - + Yank game pak Tirar del cartucho - + &Pause &Pausar - + Ctrl+P Ctrl+P - + &Next frame Cuadro siguie&nte - + Ctrl+N Ctrl+N - + Fast forward (held) Avance rápido (mantener) - + &Fast forward &Avance rápido - + Shift+Tab Shift+Tab - + Fast forward speed Velocidad de avance rápido - + Unbounded Sin límite - + %0x %0x - + Rewind (held) Rebobinar (mantener) - + Re&wind Re&bobinar - + ~ ~ - + Step backwards Paso hacia atrás - + Ctrl+B Ctrl+B - + Sync to &video Sincronizar a &video - + Sync to &audio Sincronizar a au&dio - + Solar sensor Sensor solar - + Increase solar level Subir nivel - + Decrease solar level Bajar nivel - + Brightest solar level Más claro - + Darkest solar level Más oscuro - + Brightness %1 Brillo %1 - + Audio/&Video Audio/&video - + Frame size Tamaño del cuadro - + %1x %1x - + Toggle fullscreen Pantalla completa - + Lock aspect ratio Bloquear proporción de aspecto - + Force integer scaling Forzar escala a enteros - + Bilinear filtering Filtro bilineal - + Frame&skip &Salto de cuadros - + Mute Silenciar - + FPS target Objetivo de FPS - + + Native (59.7275) + Nativo (59,7275) + + 15 - 15 + 15 - 30 - 30 + 30 - 45 - 45 + 45 - Native (59.7) - Nativo (59.7) + Nativo (59.7) - 60 - 60 + 60 - 90 - 90 + 90 - 120 - Bilineal120 + Bilineal120 - 240 - 240 + 240 - + Take &screenshot Tomar pan&tallazo - + F12 F12 - + Record output... Grabar salida... - + Record GIF... Grabar GIF... - + Record video log... Grabar video-registro... - + Stop video log Detener video-registro - + Game Boy Printer... Game Boy Printer... - + Video layers Capas de video - + Audio channels Canales de audio - + Adjust layer placement... Ajustar ubicación de capas... - + &Tools Herramien&tas - + View &logs... Ver re&gistros... - + Game &overrides... Ajustes específic&os por juego... - + Game &Pak sensors... Sensores del Game &Pak... - + &Cheats... Tru&cos... - + Settings... Ajustes... - + Open debugger console... Abrir consola de depuración... - + Start &GDB server... Iniciar servidor &GDB... - + View &palette... Ver &paleta... - + View &sprites... Ver &sprites... - + View &tiles... Ver &tiles... - + View &map... Ver &mapa... - + View memory... Ver memoria... - + Search memory... Buscar memoria... - + View &I/O registers... Ver registros &I/O... - + Exit fullscreen Salir de pantalla completa - + GameShark Button (held) Botón GameShark (mantener) - + Autofire Disparo automático - + Autofire A Disparo automático A - + Autofire B Disparo automático B - + Autofire L Disparo automático L - + Autofire R Disparo automático R - + Autofire Start Disparo automático Start - + Autofire Select Disparo automático Select - + Autofire Up Disparo automático Arriba - + Autofire Right Disparo automático Derecha - + Autofire Down Disparo automático Abajo - + Autofire Left Disparo automático Izquierda @@ -4259,382 +4276,387 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. + Mute Silenciar - + + Fast forward volume: + Vol. durante av. rápido: + + + Display driver: Sistema de video: - + Frameskip: Salto de cuadros: - + Skip every Saltar cada - - + + frames cuadros - + FPS target: Objetivo de FPS: - + frames per second cuadros por segundo - + Sync: Sincronizar con: - + Video Video - + Audio Audio - + Lock aspect ratio Bloquear proporción de aspecto - + Bilinear filtering Filtro bilineal - + Force integer scaling - Forzar escala a enteros + Forzar escalado de enteros - + Language Idioma - + English English - + Library: Biblioteca: - + List view Lista - + Tree view Ãrbol - + Show when no game open Mostrar cuando no haya un juego abierto - + Clear cache Limpiar caché - + Allow opposing input directions Permitir direcciones opuestas al mismo tiempo - + Suspend screensaver Suspender protector de pantalla - + Pause when inactive Pausar al no estar activo - + Show FPS in title bar Mostrar FPS en la barra de título - + Automatically save cheats Guardar trucos automáticamente - + Automatically load cheats Cargar trucos automáticamente - + Automatically save state Guardar estado automáticamente - + Automatically load state Cargar estado automáticamente - + Fast forward speed: Velocidad de avance rápido: - + × × - + Unbounded Sin límite - + Enable rewind Habilitar el rebobinar - + Rewind history: Historial de rebobinado: - + Idle loops: Bucles inactivos: - + Run all Ejecutarlos todos - + Remove known Eliminar los conocidos - + Detect and remove Detectar y eliminar - + Savestate extra data: Guardar datos extra con el estado: - - + + Screenshot Pantallazo - - + + Save data Datos de guardado - - + + Cheat codes Trucos - + Load extra data: Cargar datos extra con el estado: - Rewind affects save data - El rebobinar afecta los datos de guardado + El rebobinar afecta los datos de guardado - + Preload entire ROM into memory Cargar ROM completa a la memoria - + Autofire interval: Intervalo de disparo automático: - + GB BIOS file: Archivo BIOS GB: - - - - - - - - - + + + + + + + + + Browse Examinar - + Use BIOS file if found Usar archivo BIOS si fue encontrado - + Skip BIOS intro Saltar animación de entrada del BIOS - + GBA BIOS file: Archivo BIOS GBA: - + GBC BIOS file: Archivo BIOS GBC: - + SGB BIOS file: SGB BIOS file: - + Save games Datos de guardado - - - - - + + + + + Same directory as the ROM Al mismo directorio que la ROM - + Save states Estados de guardado - + Screenshots Pantallazos - + Patches Parches - + Cheats Trucos - + Game Boy model Modelo de Game Boy - - - + + + Autodetect Detección automática - - - + + + Game Boy (DMG) Game Boy (DMG) - - - + + + Super Game Boy (SGB) - - - + + + Game Boy Color (CGB) Game Boy Color (CGB) - - - + + + Game Boy Advance (AGB) Game Boy Advance (AGB) - + Super Game Boy model Modelo de Super Game Boy - + Game Boy Color model Modelo de Game Boy Color - + Default BG colors: Colores de fondo por defecto: - + Super Game Boy borders Bordes de Super Game Boy - + Camera driver: Controlador de cámara: - + Default sprite colors 1: Colores de sprite 1 por defecto: - + Default sprite colors 2: Colores de sprite 2 por defecto: @@ -4751,14 +4773,12 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. Ajustes predefinidos - High Quality - Alta calidad + Alta calidad - YouTube - YouTube + YouTube @@ -4767,29 +4787,24 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. WebM - Lossless - Sin pérdidas + Sin pérdidas - 1080p - 1080p + 1080p - 720p - 720p + 720p - 480p - 480p + 480p - Native - Nativa + Nativa @@ -4815,6 +4830,41 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. PNG PNG + + + High &Quality + Alta &calidad + + + + &YouTube + &YouTube + + + + &Lossless + Sin pér&didas + + + + &1080p + &1080p + + + + &720p + &720p + + + + &480p + &480p + + + + &Native + &NAtivo + h.264 @@ -4837,76 +4887,81 @@ Game Boy Advance es una marca registrada de Nintendo Co., Ltd. + VP9 + VP9 + + + FFV1 FFV1 - + FLAC FLAC - + Opus Opus - + Vorbis Vorbis - + MP3 MP3 - + AAC AAC - + Uncompressed Sin comprimir - + Bitrate (kbps) Tasa de bits (kbps) - + VBR VBR - + ABR ABR - + Dimensions Dimensiones - + : : - + × × - + Lock aspect ratio Bloquear proporción de aspecto - + Show advanced Mostrar ajustes avanzados From b8d29a0ce8d237aa7eac32b1486d31dac869cab0 Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Wed, 3 Oct 2018 22:55:48 +0200 Subject: [PATCH 34/60] Qt: Update German GUI translation --- src/platform/qt/ts/mgba-de.ts | 736 ++++++++++++++++------------------ 1 file changed, 344 insertions(+), 392 deletions(-) diff --git a/src/platform/qt/ts/mgba-de.ts b/src/platform/qt/ts/mgba-de.ts index 6203125fa..ec6ce7f87 100644 --- a/src/platform/qt/ts/mgba-de.ts +++ b/src/platform/qt/ts/mgba-de.ts @@ -1165,40 +1165,6 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.0x%0 (%1) - - QGBA::AudioDevice - - - Can't set format of context-less audio device - - - - - Audio device is missing its core - - - - - Writing data to read-only audio device - - - - - QGBA::AudioProcessorQt - - - Can't start an audio processor without input - - - - - QGBA::AudioProcessorSDL - - - Can't start an audio processor without input - - - QGBA::CheatsModel @@ -1245,22 +1211,22 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::CoreController - + Failed to open save file: %1 Fehler beim Öffnen der Speicherdatei: %1 - + Failed to open game file: %1 Fehler beim Öffnen der Spieldatei: %1 - + Failed to open snapshot file for reading: %1 Konnte Snapshot-Datei %1 nicht zum Lesen öffnen - + Failed to open snapshot file for writing: %1 Konnte Snapshot-Datei %1 nicht zum Schreiben öffnen @@ -2737,27 +2703,27 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::LoadSaveState - + Load State Savestate laden - + Save State Savestate speichern - + Empty Leer - + Corrupted Defekt - + Slot %1 Speicherplatz %1 @@ -2872,7 +2838,6 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. - All Alle @@ -2882,32 +2847,32 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.TBL laden - + Save selected memory Ausgewählten Speicher abspeichern - + Failed to open output file: %1 Fehler beim Öffnen der Ausgabedatei: %1 - + Load memory Lade Speicher - + Failed to open input file: %1 Fehler beim Laden der Eingabedatei: %1 - + TBL TBL - + ISO-8859-1 ISO-8859-1 @@ -3069,59 +3034,59 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::SettingsView - - + + Qt Multimedia Qt Multimedia - + SDL SDL - + Software (Qt) Software (Qt) - + OpenGL OpenGL - + OpenGL (force version 1.x) OpenGL (erzwinge Version 1.x) - + None (Still Image) Keiner (Standbild) - + Keyboard Tastatur - + Controllers Gamepads - + Shortcuts Tastenkürzel - - + + Shaders Shader - + Select BIOS BIOS auswählen @@ -3180,17 +3145,17 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. QGBA::VideoView - + Failed to open output video file: %1 Fehler beim Öffnen der Ausgabe-Videodatei: %1 - + Native (%0x%1) Nativ (%0x%1) - + Select output file Ausgabedatei auswählen @@ -3236,54 +3201,65 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. - - + + Select save Speicherdatei wählen - + + mGBA savestate files (%1) + mGBA Savestate-Dateien (%1) + + + + + Select savestate + Savestate auswählen + + + Select patch Patch wählen - + Patches (*.ips *.ups *.bps) Patches (*.ips *.ups *.bps) - + Select image Bild auswählen - + Image file (*.png *.gif *.jpg *.jpeg);;All files (*) Bild-Datei (*.png *.gif *.jpg *.jpeg);;Alle Dateien (*) - - + + GameShark saves (*.sps *.xps) GameShark-Speicherdaten (*.sps *.xps) - + Select video log Video-Log auswählen - + Video logs (*.mvl) Video-Logs (*.mvl) - + Crash Absturz - + The game has crashed with the following error: %1 @@ -3292,538 +3268,508 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. - + Couldn't Load Konnte nicht geladen werden - + Could not load game. Are you sure it's in the correct format? Konnte das Spiel nicht laden. Sind Sie sicher, dass es im korrekten Format vorliegt? - + Unimplemented BIOS call Nicht implementierter BIOS-Aufruf - + This game uses a BIOS call that is not implemented. Please use the official BIOS for best experience. Dieses Spiel verwendet einen BIOS-Aufruf, der nicht implementiert ist. Bitte verwenden Sie für die beste Spielerfahrung das offizielle BIOS. - + Really make portable? Portablen Modus wirklich aktivieren? - + This will make the emulator load its configuration from the same directory as the executable. Do you want to continue? Diese Einstellung wird den Emulator so konfigurieren, dass er seine Konfiguration aus dem gleichen Verzeichnis wie die Programmdatei lädt. Möchten Sie fortfahren? - + Restart needed Neustart benötigt - + Some changes will not take effect until the emulator is restarted. Einige Änderungen werden erst übernommen, wenn der Emulator neu gestartet wurde. - + - Player %1 of %2 - Spieler %1 von %2 - + %1 - %2 %1 - %2 - + %1 - %2 - %3 %1 - %2 - %3 - + %1 - %2 (%3 fps) - %4 %1 - %2 (%3 Bilder/Sekunde) - %4 - + &File &Datei - + Load &ROM... &ROM laden... - + Load ROM in archive... ROM aus Archiv laden... - + Load alternate save... Alternative Speicherdatei laden... - + Load temporary save... Temporäre Speicherdatei laden... - + Load &patch... &Patch laden... - + Boot BIOS BIOS booten - + Replace ROM... ROM ersetzen... - + ROM &info... ROM-&Informationen... - + Recent Zuletzt verwendet - + Make portable Portablen Modus aktivieren - + &Load state Savestate (aktueller Zustand) &laden - + F10 F10 - + + Load state file... + Ssavestate-Datei laden... + + + &Save state Savestate (aktueller Zustand) &speichern - + Shift+F10 Umschalt+F10 - + + Save state file... + Savestate-Datei speichern... + + + Quick load Schnell laden - + Quick save Schnell speichern - + Load recent Lade zuletzt gespeicherten Savestate - + Save recent Speichere aktuellen Zustand - + Undo load state Laden des Savestate rückgängig machen - + F11 F11 - + Undo save state Speichern des Savestate rückgängig machen - + Shift+F11 Umschalt+F11 - - + + State &%1 Savestate &%1 - + F%1 F%1 - + Shift+F%1 Umschalt+F%1 - + Load camera image... Lade Kamerabild... - + Import GameShark Save Importiere GameShark-Speicherstand - + Export GameShark Save Exportiere GameShark-Speicherstand - + New multiplayer window Neues Multiplayer-Fenster - + About Ãœber - + E&xit &Beenden - + &Emulation &Emulation - + &Reset Zu&rücksetzen - + Ctrl+R Strg+R - + Sh&utdown Schli&eßen - + Yank game pak Spielmodul herausziehen - + &Pause &Pause - + Ctrl+P Strg+P - + &Next frame &Nächstes Bild - + Ctrl+N Strg+N - + Fast forward (held) Schneller Vorlauf (gehalten) - + &Fast forward Schneller &Vorlauf - + Shift+Tab Umschalt+Tab - + Fast forward speed Vorlauf-Geschwindigkeit - + Unbounded Unbegrenzt - + %0x %0x - + Rewind (held) Zurückspulen (gehalten) - + Re&wind Zur&ückspulen - + ~ ~ - + Step backwards Schrittweiser Rücklauf - + Ctrl+B Strg+B - + Sync to &video Mit &Video synchronisieren - + Sync to &audio Mit &Audio synchronisieren - + Solar sensor Solar-Sensor - + Increase solar level Sonnen-Level erhöhen - + Decrease solar level Sonnen-Level verringern - + Brightest solar level Hellster Sonnen-Level - + Darkest solar level Dunkelster Sonnen-Level - + Brightness %1 Helligkeit %1 - + Audio/&Video Audio/&Video - + Frame size Bildgröße - + %1x %1x - + Toggle fullscreen Vollbildmodus umschalten - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Pixelgenaue Skalierung (Integer scaling) - + Frame&skip Frame&skip - + Mute Stummschalten - + FPS target Bildwiederholrate - - 15 - 15 - - - - 30 - 30 - - - - 45 - 45 - - - - Native (59.7) - Nativ (59.7) - - - - 60 - 60 - - - - 90 - 90 - - - - 120 - 120 - - - - 240 - 240 - - - + Take &screenshot &Screenshot erstellen - + F12 F12 - + Record output... Ausgabe aufzeichen... - + Record GIF... GIF aufzeichen... - + Record video log... Video-Log aufzeichnen... - + Stop video log Video-Log beenden - + Game Boy Printer... Game Boy Printer... - + Video layers Video-Ebenen - + Audio channels Audio-Kanäle - + Adjust layer placement... Lage der Bildebenen anpassen... - + &Tools &Werkzeuge - + View &logs... &Logs ansehen... - + Game &overrides... Spiel-&Ãœberschreibungen... - + Game &Pak sensors... Game &Pak-Sensoren... - + &Cheats... &Cheats... - + Open debugger console... Debugger-Konsole öffnen... - + Start &GDB server... &GDB-Server starten... - + Settings... Einstellungen... @@ -3833,112 +3779,117 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd.Ordner auswählen - + Add folder to library... Ordner zur Bibliothek hinzufügen... - + Bilinear filtering Bilineare Filterung - + + Native (59.7275) + Nativ (59.7275) + + + View &palette... &Palette betrachten... - + View &sprites... &Sprites betrachten... - + View &tiles... &Tiles betrachten... - + View &map... &Map betrachten... - + View memory... Speicher betrachten... - + Search memory... Speicher durchsuchen... - + View &I/O registers... &I/O-Register betrachten... - + Exit fullscreen Vollbildmodus beenden - + GameShark Button (held) GameShark-Taste (gehalten) - + Autofire Autofeuer - + Autofire A Autofeuer A - + Autofire B Autofeuer B - + Autofire L Autofeuer L - + Autofire R Autofeuer R - + Autofire Start Autofeuer Start - + Autofire Select Autofeuer Select - + Autofire Up Autofeuer nach oben - + Autofire Right Autofeuer rechts - + Autofire Down Autofeuer nach unten - + Autofire Left Autofeuer links @@ -4215,259 +4166,259 @@ Game Boy Advance ist ein eingetragenes Warenzeichen von Nintendo Co., Ltd. + Mute Stummschalten - + + Fast forward volume: + Vorspul-Lautstärke: + + + Display driver: Anzeige-Treiber: - + Frameskip: Frameskip: - + Skip every Ãœberspringe - - + + frames Bild(er) - + FPS target: Bildwiederholrate: - + frames per second Bilder pro Sekunde - + Sync: Synchronisierung: - + Video Video - + Audio Audio - + Lock aspect ratio Seitenverhältnis korrigieren - + Force integer scaling Erzwinge pixelgenaue Skalierung (Integer scaling) - + Language Sprache - + English Englisch - + List view Listenansicht - + Tree view Baumansicht - + Show FPS in title bar Bildwiederholrate in der Titelleiste anzeigen - + Automatically save cheats Cheats automatisch speichern - + Automatically load cheats Cheats automatisch laden - + Automatically save state Zustand (Savestate) automatisch speichern - + Automatically load state Zustand (Savestate) automatisch laden - + Cheats Cheats - + Game Boy model Game Boy-Modell - - - + + + Autodetect Automatisch erkennen - - - + + + Game Boy (DMG) Game Boy (DMG) - - - + + + Super Game Boy (SGB) Super Game Boy (SGB) - - - + + + Game Boy Color (CGB) Game Boy Color (CGB) - - - + + + Game Boy Advance (AGB) Game Boy Advance (AGB) - + Super Game Boy model Super Game Boy-Modell - + Game Boy Color model Game Boy Color-Modell - + Default BG colors: Standard-Hintergrundfarben: - + Default sprite colors 1: Standard-Sprite-Farben 1: - + Default sprite colors 2: Standard-Sprite-Farben 2: - + Super Game Boy borders Super Game Boy-Rahmen - + Camera driver: Kamera-Treiber: - + Library: Bibliothek: - + Show when no game open Anzeigen, wenn kein Spiel geöffnet ist - + Clear cache Cache leeren - + Fast forward speed: Vorlauf-Geschwindigkeit: - - Rewind affects save data - Rücklauf beeinflusst -Speicherdaten - - - + Preload entire ROM into memory ROM-Datei vollständig in Arbeitsspeicher vorladen - - - - - - - - - + + + + + + + + + Browse Durchsuchen - + Use BIOS file if found BIOS-Datei verwenden, wenn vorhanden - + Skip BIOS intro BIOS-Intro überspringen - + × × - + Unbounded unbegrenzt - + Suspend screensaver Bildschirmschoner deaktivieren @@ -4477,129 +4428,129 @@ wenn vorhanden BIOS - + Pause when inactive Pause, wenn inaktiv - + Run all Alle ausführen - + Remove known Bekannte entfernen - + Detect and remove Erkennen und entfernen - + Allow opposing input directions Gegensätzliche Eingaberichtungen erlauben - - + + Screenshot Screenshot - - + + Save data Speicherdaten - - + + Cheat codes Cheat-Codes - + Enable rewind Rücklauf aktivieren - + Bilinear filtering Bilineare Filterung - + Rewind history: Rücklauf-Verlauf: - + Idle loops: Leerlaufprozesse: - + Savestate extra data: Zusätzliche Savestate-Daten: - + Load extra data: Lade zusätzliche Daten: - + Autofire interval: Autofeuer-Intervall: - + GB BIOS file: Datei mit GB-BIOS: - + GBA BIOS file: Datei mit GBA-BIOS: - + GBC BIOS file: Datei mit GBC-BIOS: - + SGB BIOS file: Datei mit SGB-BIOS: - + Save games Spielstände - - - - - + + + + + Same directory as the ROM Verzeichnis der ROM-Datei - + Save states Savestates - + Screenshots Screenshots - + Patches Patches @@ -4715,47 +4666,12 @@ wenn vorhanden Presets Vorgaben - - - High Quality - Hohe Qualität - - - - YouTube - YouTube - WebM WebM - - - Lossless - Verlustfrei - - - - 1080p - 1080p - - - - 720p - 720p - - - - 480p - 480p - - - - Native - Nativ - Format @@ -4777,8 +4693,39 @@ wenn vorhanden MP4 - PNG - PNG + + High &Quality + Hohe &Qualität + + + + &YouTube + &YouTube + + + + &Lossless + Ver&lustfrei + + + + &1080p + &1080p + + + + &720p + &720p + + + + &480p + &480p + + + + &Native + &Nativ @@ -4802,76 +4749,81 @@ wenn vorhanden + VP9 + VP9 + + + FFV1 FFV1 - + FLAC FLAC - + Opus Opus - + Vorbis Vorbis - + MP3 MP3 - + AAC AAC - + Uncompressed Unkomprimiert - + Bitrate (kbps) Bitrate (kbps) - + VBR VBR - + ABR ABR - + Dimensions Abmessungen - + : : - + × × - + Lock aspect ratio Seitenverhältnis sperren - + Show advanced Erweiterte Optionen anzeigen From df9c5f5f91727068cbe2dc28af8e2d4cceb539e0 Mon Sep 17 00:00:00 2001 From: rootfather Date: Thu, 7 Dec 2017 23:47:38 +0100 Subject: [PATCH 35/60] Win32: Add Inno Setup script --- tools/windows/mgba-setup-win32.iss | 173 +++++++++++++++++++++++++ tools/windows/mgba-setupiconfile.ico | Bin 0 -> 43778 bytes tools/windows/mgba-wizardimagefile.bmp | Bin 0 -> 154542 bytes 3 files changed, 173 insertions(+) create mode 100644 tools/windows/mgba-setup-win32.iss create mode 100644 tools/windows/mgba-setupiconfile.ico create mode 100644 tools/windows/mgba-wizardimagefile.bmp diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss new file mode 100644 index 000000000..7bd12ec99 --- /dev/null +++ b/tools/windows/mgba-setup-win32.iss @@ -0,0 +1,173 @@ +;For automation purposes it is highly recommended to copy the files from +;\tools\windows\ to the directory that contains the win32 distribution files! + +;IsRelease = yes will create a setup file named after the current version of mGBA. +;IsRelease = no will create a setup fille named mGBA-setup-latest-win32.exe. +#define IsRelease = yes + +#define VerMajor +#define VerMinor +#define VerRev +#define VerBuild +#define FullVersion=ParseVersion('mGBA.exe', VerMajor, VerMinor, VerRev, VerBuild) +#define AppVer = Str(VerMajor) + "." + Str(VerMinor) + "." + Str(VerRev) + +[Setup] +SourceDir=.\ +SetupIconFile=mgba-setupiconfile.ico +WizardImageFile=mgba-wizardimagefile.bmp + +AppName=mGBA +AppVersion={#AppVer} +AppPublisher=Jeffrey Pfau +AppPublisherURL=https://mgba.io +AppSupportURL=https://mgba.io +AppUpdatesURL=https://mgba.io +AppReadmeFile=README.html +OutputDir=.\ +DefaultDirName={pf}\mGBA +DefaultGroupName=mGBA +AllowNoIcons=yes +DirExistsWarning=no +ChangesAssociations=True +AppendDefaultDirName=False +UninstallDisplayIcon={app}\mGBA.exe +MinVersion=0,6.0 +AlwaysShowDirOnReadyPage=True +UsePreviousSetupType=True +UsePreviousTasks=True +AlwaysShowGroupOnReadyPage=True +LicenseFile=LICENSE.txt +#if IsRelease==yes; + OutputBaseFilename=mGBA-{#AppVer}-win32 +#elif IsRelease==no; + OutputBaseFilename=mGBA-setup-latest-win32 + #endif +UsePreviousLanguage=False +DisableWelcomePage=False +VersionInfoDescription=mGBA is an open-source Game Boy Advance emulator +VersionInfoCopyright=© 2013–2017 Jeffrey Pfau +VersionInfoProductName=mGBA +VersionInfoVersion={#AppVer} +Compression=lzma2/ultra64 +SolidCompression=True +VersionInfoTextVersion={#AppVer} +VersionInfoProductVersion={#AppVer} +VersionInfoProductTextVersion={#AppVer} + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "german"; MessagesFile: "compiler:Languages\German.isl" +Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" +Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" +Name: "gbfileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy}"; GroupDescription: "{cm:FileAssoc}" +Name: "gbcfileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy Color}"; GroupDescription: "{cm:FileAssoc}" +Name: "gbafileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy Advance}"; GroupDescription: "{cm:FileAssoc}" + +[Files] +Source: "mGBA.exe"; DestDir: "{app}"; Flags: ignoreversion +Source: "CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion +Source: "LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion +Source: "mGBA.exe"; DestDir: "{app}\"; Flags: ignoreversion +Source: "nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion +Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion +Source: "shaders\agb001.shader\agb001.fs"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion +Source: "shaders\agb001.shader\manifest.ini"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion +Source: "shaders\ags001.shader\ags001-light.fs"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion +Source: "shaders\ags001.shader\ags001.fs"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion +Source: "shaders\ags001.shader\manifest.ini"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion +Source: "shaders\fish.shader\fish.fs"; DestDir: "{app}\shaders\fish.shader\"; Flags: ignoreversion +Source: "shaders\fish.shader\manifest.ini"; DestDir: "{app}\shaders\fish.shader\"; Flags: ignoreversion +Source: "shaders\gba-color.shader\gba-color.fs"; DestDir: "{app}\shaders\gba-color.shader\"; Flags: ignoreversion +Source: "shaders\gba-color.shader\manifest.ini"; DestDir: "{app}\shaders\gba-color.shader\"; Flags: ignoreversion +Source: "shaders\lcd.shader\lcd.fs"; DestDir: "{app}\shaders\lcd.shader\"; Flags: ignoreversion +Source: "shaders\lcd.shader\manifest.ini"; DestDir: "{app}\shaders\lcd.shader\"; Flags: ignoreversion +Source: "shaders\motion_blur.shader\manifest.ini"; DestDir: "{app}\shaders\motion_blur.shader\"; Flags: ignoreversion +Source: "shaders\motion_blur.shader\motion_blur.fs"; DestDir: "{app}\shaders\motion_blur.shader\"; Flags: ignoreversion +Source: "shaders\pixelate.shader\manifest.ini"; DestDir: "{app}\shaders\pixelate.shader\"; Flags: ignoreversion +Source: "shaders\scanlines.shader\manifest.ini"; DestDir: "{app}\shaders\scanlines.shader\"; Flags: ignoreversion +Source: "shaders\scanlines.shader\scanlines.fs"; DestDir: "{app}\shaders\scanlines.shader\"; Flags: ignoreversion +Source: "shaders\soften.shader\manifest.ini"; DestDir: "{app}\shaders\soften.shader\"; Flags: ignoreversion +Source: "shaders\soften.shader\soften.fs"; DestDir: "{app}\shaders\soften.shader\"; Flags: ignoreversion +Source: "shaders\vba_pixelate.shader\manifest.ini"; DestDir: "{app}\shaders\vba_pixelate.shader\"; Flags: ignoreversion +Source: "shaders\vba_pixelate.shader\vba_pixelate.fs"; DestDir: "{app}\shaders\vba_pixelate.shader\"; Flags: ignoreversion +Source: "shaders\vignette.shader\manifest.ini"; DestDir: "{app}\shaders\vignette.shader\"; Flags: ignoreversion +Source: "shaders\vignette.shader\vignette.fs"; DestDir: "{app}\shaders\vignette.shader\"; Flags: ignoreversion +Source: "shaders\wiiu.shader\manifest.ini"; DestDir: "{app}\shaders\wiiu.shader\"; Flags: ignoreversion +Source: "shaders\wiiu.shader\wiiu.fs"; DestDir: "{app}\shaders\wiiu.shader\"; Flags: ignoreversion +Source: "shaders\xbr-lv2.shader\manifest.ini"; DestDir: "{app}\shaders\xbr-lv2.shader\"; Flags: ignoreversion +Source: "shaders\xbr-lv2.shader\xbr.fs"; DestDir: "{app}\shaders\xbr-lv2.shader\"; Flags: ignoreversion +Source: "shaders\xbr-lv2.shader\xbr.vs"; DestDir: "{app}\shaders\xbr-lv2.shader\"; Flags: ignoreversion +Source: "shaders\xbr-lv3.shader\manifest.ini"; DestDir: "{app}\shaders\xbr-lv3.shader\"; Flags: ignoreversion +Source: "shaders\xbr-lv3.shader\xbr.fs"; DestDir: "{app}\shaders\xbr-lv3.shader\"; Flags: ignoreversion +Source: "shaders\xbr-lv3.shader\xbr.vs"; DestDir: "{app}\shaders\xbr-lv3.shader\"; Flags: ignoreversion +Source: "third-party\LICENSE.blip-buf"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.ffmpeg"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.imagemagick"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.inih"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.lame"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.libvpx"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.opus"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.qt5"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.sdl2"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.x264"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "third-party\LICENSE.xvid"; DestDir: "{app}\third-party\"; Flags: ignoreversion + +[Icons] +Name: "{commonstartmenu}\mGBA"; Filename: "{app}\mGBA.exe" +Name: "{commondesktop}\mGBA"; Filename: "{app}\mGBA.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\mGBA.exe"; Description: "{cm:LaunchProgram,mGBA}"; Flags: nowait postinstall skipifsilent +Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: english +Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: italian +Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: spanish +Filename: "{app}\README.html"; Description: "README anzeigen"; Flags: nowait postinstall skipifsilent unchecked; Languages: german +Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: english +Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: italian +Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: spanish +Filename: "{app}\CHANGES.txt"; Description: "Changelog anzeigen"; Flags: nowait postinstall skipifsilent unchecked; Languages: german + +[Dirs] +Name: "{app}\shaders\" +Name: "{app}\shaders\agb001.shader\" +Name: "{app}\shaders\ags001.shader\" +Name: "{app}\shaders\fish.shader\" +Name: "{app}\shaders\gba-color.shader\" +Name: "{app}\shaders\lcd.shader\" +Name: "{app}\shaders\motion_blur.shader\" +Name: "{app}\shaders\pixelate.shader\" +Name: "{app}\shaders\scanlines.shader\" +Name: "{app}\shaders\soften.shader\" +Name: "{app}\shaders\vba_pixelate.shader\" +Name: "{app}\shaders\vignette.shader\" +Name: "{app}\shaders\wiiu.shader\" +Name: "{app}\shaders\xbr-lv2.shader\" +Name: "{app}\shaders\xbr-lv3.shader\" +Name: "{app}\third-party\" + +[CustomMessages] +english.FileAssoc=Register file associations +italian.FileAssoc=Register file associations +spanish.FileAssoc=Register file associations +german.FileAssoc=Dateierweiterungen registrieren + +[INI] +Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "en"; Languages: english +Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "de"; Languages: german +Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "es"; Languages: spanish +Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "it"; Languages: italian + +[Registry] +Root: HKCR; Subkey: ".gb"; ValueType: string; ValueName: ""; ValueData: "Game Boy ROM"; Flags: uninsdeletevalue; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gb\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gbc"; ValueType: string; ValueName: ""; ValueData: "Game Boy Color ROM"; Flags: uninsdeletevalue; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gbc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gbc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gba"; ValueType: string; ValueName: ""; ValueData: "Game Boy Advance ROM"; Flags: uninsdeletevalue; Tasks: gbafileassoc +Root: HKCR; Subkey: ".gba\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbafileassoc +Root: HKCR; Subkey: ".gba\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbafileassoc \ No newline at end of file diff --git a/tools/windows/mgba-setupiconfile.ico b/tools/windows/mgba-setupiconfile.ico new file mode 100644 index 0000000000000000000000000000000000000000..7b382e8084a323a9aa58ec1aa776ac03d4e0fb01 GIT binary patch literal 43778 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

8u3hN*4Njm*XxYbMwpnGz;oSgpScx`RBQMt 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 Date: Fri, 8 Dec 2017 20:07:30 +0100 Subject: [PATCH 36/60] Win32: Improve version handling in Inno Setup --- tools/windows/mgba-setup-win32.iss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 7bd12ec99..328fe507b 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -39,8 +39,10 @@ UsePreviousTasks=True AlwaysShowGroupOnReadyPage=True LicenseFile=LICENSE.txt #if IsRelease==yes; + AppVerName=mGBA {#AppVer} OutputBaseFilename=mGBA-{#AppVer}-win32 #elif IsRelease==no; + AppVerName=mGBA (Development build) OutputBaseFilename=mGBA-setup-latest-win32 #endif UsePreviousLanguage=False From 06b999afd5be23e23880c9fbbef4d0ee41374e06 Mon Sep 17 00:00:00 2001 From: rootfather Date: Thu, 14 Dec 2017 20:04:01 +0100 Subject: [PATCH 37/60] Win32: Remove workaround for bug #906 (now fixed) --- tools/windows/mgba-setup-win32.iss | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 328fe507b..34bae2e7b 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -157,12 +157,6 @@ italian.FileAssoc=Register file associations spanish.FileAssoc=Register file associations german.FileAssoc=Dateierweiterungen registrieren -[INI] -Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "en"; Languages: english -Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "de"; Languages: german -Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "es"; Languages: spanish -Filename: "{userappdata}\mGBA\qt.ini"; Section: "General"; Key: "language"; String: "it"; Languages: italian - [Registry] Root: HKCR; Subkey: ".gb"; ValueType: string; ValueName: ""; ValueData: "Game Boy ROM"; Flags: uninsdeletevalue; Tasks: gbfileassoc Root: HKCR; Subkey: ".gb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbfileassoc From c1a7e1aca19d63432a552445b81ac640e9f5571e Mon Sep 17 00:00:00 2001 From: rootfather Date: Tue, 19 Dec 2017 11:16:50 +0100 Subject: [PATCH 38/60] Win32: Add notification message when installing a development build --- tools/windows/mgba-setup-win32.iss | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 34bae2e7b..638955371 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -3,7 +3,7 @@ ;IsRelease = yes will create a setup file named after the current version of mGBA. ;IsRelease = no will create a setup fille named mGBA-setup-latest-win32.exe. -#define IsRelease = yes +#define IsRelease = 'no' #define VerMajor #define VerMinor @@ -38,10 +38,10 @@ UsePreviousSetupType=True UsePreviousTasks=True AlwaysShowGroupOnReadyPage=True LicenseFile=LICENSE.txt -#if IsRelease==yes; +#if IsRelease=='yes'; AppVerName=mGBA {#AppVer} OutputBaseFilename=mGBA-{#AppVer}-win32 -#elif IsRelease==no; +#elif IsRelease=='no'; AppVerName=mGBA (Development build) OutputBaseFilename=mGBA-setup-latest-win32 #endif @@ -165,5 +165,21 @@ Root: HKCR; Subkey: ".gbc"; ValueType: string; ValueName: ""; ValueData: "Game B Root: HKCR; Subkey: ".gbc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbcfileassoc Root: HKCR; Subkey: ".gbc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbcfileassoc Root: HKCR; Subkey: ".gba"; ValueType: string; ValueName: ""; ValueData: "Game Boy Advance ROM"; Flags: uninsdeletevalue; Tasks: gbafileassoc -Root: HKCR; Subkey: ".gba\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbafileassoc -Root: HKCR; Subkey: ".gba\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbafileassoc \ No newline at end of file +Root: HKCR; Subkey: ".gba\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbafileassoc Root: HKCR; Subkey: ".gba\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbafileassoc + +[Code] +var + noReleaseWarning: String; + +procedure InitializeWizard(); + begin + if ExpandConstant('{#IsRelease}') = 'no' then + begin + if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie möchten eine Entwicklerversion von mGBA installieren.' + #13#10#13#10 + 'Entwicklerversionen können bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden können, auf der GitHub-Projektseite.'; + MsgBox(noReleaseWarning, mbInformation, MB_OK); + end; + end; +end. \ No newline at end of file From 8880ed7277165d96ad796b326551850904b051c1 Mon Sep 17 00:00:00 2001 From: rootfather Date: Tue, 19 Dec 2017 11:56:36 +0100 Subject: [PATCH 39/60] Win32: Add version detection to the Inno script Now you don't have to switch between IsRelease = yes and no. Instead, you set the CurrentReleaseVersion variable to the number of the latest stable release and Inno will decide if the setup you are about to build is a stable or a development package, so you have to alter the script only once for each release cycle. This is the highest level of automation I can currently imagine. --- tools/windows/mgba-setup-win32.iss | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 638955371..c00ef0131 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -1,9 +1,8 @@ ;For automation purposes it is highly recommended to copy the files from ;\tools\windows\ to the directory that contains the win32 distribution files! -;IsRelease = yes will create a setup file named after the current version of mGBA. -;IsRelease = no will create a setup fille named mGBA-setup-latest-win32.exe. -#define IsRelease = 'no' +;Set CurrentReleaseVersion to the number of the latest stable mGBA build. +#define CurrentReleaseVersion = '0.6.1' #define VerMajor #define VerMinor @@ -38,10 +37,12 @@ UsePreviousSetupType=True UsePreviousTasks=True AlwaysShowGroupOnReadyPage=True LicenseFile=LICENSE.txt -#if IsRelease=='yes'; +#if CurrentReleaseVersion == AppVer; + #define IsRelease = 'yes' AppVerName=mGBA {#AppVer} OutputBaseFilename=mGBA-{#AppVer}-win32 -#elif IsRelease=='no'; +#elif CurrentReleaseVersion != AppVer; + #define IsRelease = 'no' AppVerName=mGBA (Development build) OutputBaseFilename=mGBA-setup-latest-win32 #endif From ae553bab3498a4d7538aa41fec610daed57f9df8 Mon Sep 17 00:00:00 2001 From: rootfather Date: Tue, 26 Dec 2017 12:34:00 +0100 Subject: [PATCH 40/60] Win32: Add German README file to the installer script --- tools/windows/mgba-setup-win32.iss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index c00ef0131..593dec987 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -76,7 +76,8 @@ Source: "CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion Source: "LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion Source: "mGBA.exe"; DestDir: "{app}\"; Flags: ignoreversion Source: "nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion -Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion +Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion +Source: "README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german Source: "shaders\agb001.shader\agb001.fs"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion Source: "shaders\agb001.shader\manifest.ini"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion Source: "shaders\ags001.shader\ags001-light.fs"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion @@ -128,7 +129,7 @@ Filename: "{app}\mGBA.exe"; Description: "{cm:LaunchProgram,mGBA}"; Flags: nowai Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: english Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: italian Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: spanish -Filename: "{app}\README.html"; Description: "README anzeigen"; Flags: nowait postinstall skipifsilent unchecked; Languages: german +Filename: "{app}\README_DE.html"; Description: "README anzeigen"; Flags: nowait postinstall skipifsilent unchecked; Languages: german Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: english Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: italian Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: spanish From a81259f94b1b6a12b855d13442eb3503ac0920d4 Mon Sep 17 00:00:00 2001 From: rootfather Date: Tue, 26 Dec 2017 12:37:14 +0100 Subject: [PATCH 41/60] Win32: Fix entries for the README/documentation files --- tools/windows/mgba-setup-win32.iss | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 593dec987..ba2fab830 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -72,11 +72,11 @@ Name: "gbafileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy Advance [Files] Source: "mGBA.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion +Source: "CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme Source: "LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion Source: "mGBA.exe"; DestDir: "{app}\"; Flags: ignoreversion Source: "nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion -Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion +Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: english italian spanish Source: "README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german Source: "shaders\agb001.shader\agb001.fs"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion Source: "shaders\agb001.shader\manifest.ini"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion @@ -125,15 +125,7 @@ Name: "{commonstartmenu}\mGBA"; Filename: "{app}\mGBA.exe" Name: "{commondesktop}\mGBA"; Filename: "{app}\mGBA.exe"; Tasks: desktopicon [Run] -Filename: "{app}\mGBA.exe"; Description: "{cm:LaunchProgram,mGBA}"; Flags: nowait postinstall skipifsilent -Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: english -Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: italian -Filename: "{app}\README.html"; Description: "View README"; Flags: nowait postinstall skipifsilent unchecked; Languages: spanish -Filename: "{app}\README_DE.html"; Description: "README anzeigen"; Flags: nowait postinstall skipifsilent unchecked; Languages: german -Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: english -Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: italian -Filename: "{app}\CHANGES.txt"; Description: "View Changelog"; Flags: nowait postinstall skipifsilent unchecked; Languages: spanish -Filename: "{app}\CHANGES.txt"; Description: "Changelog anzeigen"; Flags: nowait postinstall skipifsilent unchecked; Languages: german +Filename: "{app}\mGBA.exe"; Description: "{cm:LaunchProgram,mGBA}"; Flags: nowait postinstall skipifsilent [Dirs] Name: "{app}\shaders\" From 2a60cc9951bfd1373e533dded395a2d17b629449 Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Thu, 26 Apr 2018 08:15:53 +0200 Subject: [PATCH 42/60] Win32: Increase version number for the inno installer to 0.6.3 --- tools/windows/mgba-setup-win32.iss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index ba2fab830..88d9054c3 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -2,7 +2,7 @@ ;\tools\windows\ to the directory that contains the win32 distribution files! ;Set CurrentReleaseVersion to the number of the latest stable mGBA build. -#define CurrentReleaseVersion = '0.6.1' +#define CurrentReleaseVersion = '0.6.3' #define VerMajor #define VerMinor From cf1a2b817e853949c2929d3b601d17f5ac674484 Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Thu, 26 Apr 2018 08:19:47 +0200 Subject: [PATCH 43/60] Win32: Add French as language option in the inno installer --- tools/windows/mgba-setup-win32.iss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 88d9054c3..43d3dbb20 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -60,6 +60,7 @@ VersionInfoProductTextVersion={#AppVer} [Languages] Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "french"; MessagesFile: "compiler:Languages\French.isl" Name: "german"; MessagesFile: "compiler:Languages\German.isl" Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" @@ -147,6 +148,7 @@ Name: "{app}\third-party\" [CustomMessages] english.FileAssoc=Register file associations +french.FileAssoc=Register file associations italian.FileAssoc=Register file associations spanish.FileAssoc=Register file associations german.FileAssoc=Dateierweiterungen registrieren @@ -170,6 +172,7 @@ procedure InitializeWizard(); if ExpandConstant('{#IsRelease}') = 'no' then begin if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'french' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie möchten eine Entwicklerversion von mGBA installieren.' + #13#10#13#10 + 'Entwicklerversionen können bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden können, auf der GitHub-Projektseite.'; From 3e957c7b9183212f9c7690b3f0076de2b2686065 Mon Sep 17 00:00:00 2001 From: Lothar Serra Mari Date: Sat, 1 Sep 2018 13:42:17 +0200 Subject: [PATCH 44/60] Win32: Let Inno setup parse the source directory recursively --- tools/windows/mgba-setup-win32.iss | 69 +++--------------------------- 1 file changed, 7 insertions(+), 62 deletions(-) diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss index 43d3dbb20..902b1efc9 100644 --- a/tools/windows/mgba-setup-win32.iss +++ b/tools/windows/mgba-setup-win32.iss @@ -36,7 +36,7 @@ AlwaysShowDirOnReadyPage=True UsePreviousSetupType=True UsePreviousTasks=True AlwaysShowGroupOnReadyPage=True -LicenseFile=LICENSE.txt +LicenseFile=LICENSE #if CurrentReleaseVersion == AppVer; #define IsRelease = 'yes' AppVerName=mGBA {#AppVer} @@ -49,7 +49,7 @@ LicenseFile=LICENSE.txt UsePreviousLanguage=False DisableWelcomePage=False VersionInfoDescription=mGBA is an open-source Game Boy Advance emulator -VersionInfoCopyright=© 2013–2017 Jeffrey Pfau +VersionInfoCopyright=© 2013–2018 Jeffrey Pfau VersionInfoProductName=mGBA VersionInfoVersion={#AppVer} Compression=lzma2/ultra64 @@ -73,53 +73,13 @@ Name: "gbafileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy Advance [Files] Source: "mGBA.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme -Source: "LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion -Source: "mGBA.exe"; DestDir: "{app}\"; Flags: ignoreversion +Source: "CHANGES"; DestDir: "{app}\"; Flags: ignoreversion isreadme +Source: "LICENSE"; DestDir: "{app}\"; Flags: ignoreversion Source: "nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: english italian spanish Source: "README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german -Source: "shaders\agb001.shader\agb001.fs"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion -Source: "shaders\agb001.shader\manifest.ini"; DestDir: "{app}\shaders\agb001.shader\"; Flags: ignoreversion -Source: "shaders\ags001.shader\ags001-light.fs"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion -Source: "shaders\ags001.shader\ags001.fs"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion -Source: "shaders\ags001.shader\manifest.ini"; DestDir: "{app}\shaders\ags001.shader\"; Flags: ignoreversion -Source: "shaders\fish.shader\fish.fs"; DestDir: "{app}\shaders\fish.shader\"; Flags: ignoreversion -Source: "shaders\fish.shader\manifest.ini"; DestDir: "{app}\shaders\fish.shader\"; Flags: ignoreversion -Source: "shaders\gba-color.shader\gba-color.fs"; DestDir: "{app}\shaders\gba-color.shader\"; Flags: ignoreversion -Source: "shaders\gba-color.shader\manifest.ini"; DestDir: "{app}\shaders\gba-color.shader\"; Flags: ignoreversion -Source: "shaders\lcd.shader\lcd.fs"; DestDir: "{app}\shaders\lcd.shader\"; Flags: ignoreversion -Source: "shaders\lcd.shader\manifest.ini"; DestDir: "{app}\shaders\lcd.shader\"; Flags: ignoreversion -Source: "shaders\motion_blur.shader\manifest.ini"; DestDir: "{app}\shaders\motion_blur.shader\"; Flags: ignoreversion -Source: "shaders\motion_blur.shader\motion_blur.fs"; DestDir: "{app}\shaders\motion_blur.shader\"; Flags: ignoreversion -Source: "shaders\pixelate.shader\manifest.ini"; DestDir: "{app}\shaders\pixelate.shader\"; Flags: ignoreversion -Source: "shaders\scanlines.shader\manifest.ini"; DestDir: "{app}\shaders\scanlines.shader\"; Flags: ignoreversion -Source: "shaders\scanlines.shader\scanlines.fs"; DestDir: "{app}\shaders\scanlines.shader\"; Flags: ignoreversion -Source: "shaders\soften.shader\manifest.ini"; DestDir: "{app}\shaders\soften.shader\"; Flags: ignoreversion -Source: "shaders\soften.shader\soften.fs"; DestDir: "{app}\shaders\soften.shader\"; Flags: ignoreversion -Source: "shaders\vba_pixelate.shader\manifest.ini"; DestDir: "{app}\shaders\vba_pixelate.shader\"; Flags: ignoreversion -Source: "shaders\vba_pixelate.shader\vba_pixelate.fs"; DestDir: "{app}\shaders\vba_pixelate.shader\"; Flags: ignoreversion -Source: "shaders\vignette.shader\manifest.ini"; DestDir: "{app}\shaders\vignette.shader\"; Flags: ignoreversion -Source: "shaders\vignette.shader\vignette.fs"; DestDir: "{app}\shaders\vignette.shader\"; Flags: ignoreversion -Source: "shaders\wiiu.shader\manifest.ini"; DestDir: "{app}\shaders\wiiu.shader\"; Flags: ignoreversion -Source: "shaders\wiiu.shader\wiiu.fs"; DestDir: "{app}\shaders\wiiu.shader\"; Flags: ignoreversion -Source: "shaders\xbr-lv2.shader\manifest.ini"; DestDir: "{app}\shaders\xbr-lv2.shader\"; Flags: ignoreversion -Source: "shaders\xbr-lv2.shader\xbr.fs"; DestDir: "{app}\shaders\xbr-lv2.shader\"; Flags: ignoreversion -Source: "shaders\xbr-lv2.shader\xbr.vs"; DestDir: "{app}\shaders\xbr-lv2.shader\"; Flags: ignoreversion -Source: "shaders\xbr-lv3.shader\manifest.ini"; DestDir: "{app}\shaders\xbr-lv3.shader\"; Flags: ignoreversion -Source: "shaders\xbr-lv3.shader\xbr.fs"; DestDir: "{app}\shaders\xbr-lv3.shader\"; Flags: ignoreversion -Source: "shaders\xbr-lv3.shader\xbr.vs"; DestDir: "{app}\shaders\xbr-lv3.shader\"; Flags: ignoreversion -Source: "third-party\LICENSE.blip-buf"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.ffmpeg"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.imagemagick"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.inih"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.lame"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.libvpx"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.opus"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.qt5"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.sdl2"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.x264"; DestDir: "{app}\third-party\"; Flags: ignoreversion -Source: "third-party\LICENSE.xvid"; DestDir: "{app}\third-party\"; Flags: ignoreversion +Source: "shaders\*"; DestDir: "{app}\shaders\"; Flags: ignoreversion recursesubdirs +Source: "licenses\*"; DestDir: "{app}\licenses\"; Flags: ignoreversion recursesubdirs [Icons] Name: "{commonstartmenu}\mGBA"; Filename: "{app}\mGBA.exe" @@ -129,22 +89,7 @@ Name: "{commondesktop}\mGBA"; Filename: "{app}\mGBA.exe"; Tasks: desktopicon Filename: "{app}\mGBA.exe"; Description: "{cm:LaunchProgram,mGBA}"; Flags: nowait postinstall skipifsilent [Dirs] -Name: "{app}\shaders\" -Name: "{app}\shaders\agb001.shader\" -Name: "{app}\shaders\ags001.shader\" -Name: "{app}\shaders\fish.shader\" -Name: "{app}\shaders\gba-color.shader\" -Name: "{app}\shaders\lcd.shader\" -Name: "{app}\shaders\motion_blur.shader\" -Name: "{app}\shaders\pixelate.shader\" -Name: "{app}\shaders\scanlines.shader\" -Name: "{app}\shaders\soften.shader\" -Name: "{app}\shaders\vba_pixelate.shader\" -Name: "{app}\shaders\vignette.shader\" -Name: "{app}\shaders\wiiu.shader\" -Name: "{app}\shaders\xbr-lv2.shader\" -Name: "{app}\shaders\xbr-lv3.shader\" -Name: "{app}\third-party\" +Name: "{app}" [CustomMessages] english.FileAssoc=Register file associations From c7e615a047e3c9b550ce9032e310379e9136fd30 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 3 Oct 2018 12:50:53 -0700 Subject: [PATCH 45/60] Windows: Add Inno Setup script --- CMakeLists.txt | 52 ++++++- src/platform/qt/CMakeLists.txt | 4 + .../platform/windows/setup/setup.ico | Bin src/platform/windows/setup/setup.iss.in | 140 ++++++++++++++++++ .../platform/windows/setup/wizard-image.bmp | Bin tools/windows/mgba-setup-win32.iss | 127 ---------------- 6 files changed, 191 insertions(+), 132 deletions(-) rename tools/windows/mgba-setupiconfile.ico => src/platform/windows/setup/setup.ico (100%) create mode 100644 src/platform/windows/setup/setup.iss.in rename tools/windows/mgba-wizardimagefile.bmp => src/platform/windows/setup/wizard-image.bmp (100%) delete mode 100644 tools/windows/mgba-setup-win32.iss diff --git a/CMakeLists.txt b/CMakeLists.txt index b2daddb35..82150410f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1003,6 +1003,26 @@ endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/core/flags.h.in ${CMAKE_CURRENT_BINARY_DIR}/flags.h) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/flags.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mgba COMPONENT lib${BINARY_NAME}) +if(WIN32) + set(BIN_DIR ".\\") + string(REGEX REPLACE "[^-A-Za-z0-9_.]" "-" CLEAN_VERSION_STRING "${VERSION_STRING}") + file(RELATIVE_PATH SETUP_DIR_SLASH "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/setup") + file(RELATIVE_PATH RES_DIR_SLASH "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/res") + string(REPLACE "/" "\\" SETUP_DIR "${SETUP_DIR_SLASH}") + string(REPLACE "/" "\\" RES_DIR "${RES_DIR_SLASH}") + if(CMAKE_SYSTEM_PROCESSOR MATCHES ".*64$") + set(WIN_BITS 64) + else() + set(WIN_BITS 32) + endif() + if(GIT_TAG) + set(IS_RELEASE 1) + else() + set(IS_RELEASE 0) + endif() + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/platform/windows/setup/setup.iss.in" ${CMAKE_CURRENT_BINARY_DIR}/setup.iss) +endif() + # Packaging install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/res/licenses DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) if(EXTRA_LICENSES) @@ -1025,6 +1045,25 @@ else() add_custom_target(CHANGES ALL DEPENDS CHANGES.txt) add_custom_target(LICENSE ALL DEPENDS LICENSE.txt) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) + if(DISTBUILD AND WIN32) + set(INSTALLER "${PROJECT_NAME}-setup-${CLEAN_VERSION_STRING}-win${WIN_BITS}.exe") + if(CMAKE_CROSSCOMPILING) + find_program(WINE NAMES wine wine-stable wine-development) + find_file(ISCC ISCC.exe HINTS "$ENV{HOME}/.wine/drive_c/Program Files/") + add_custom_command(OUTPUT ${INSTALLER} + COMMAND "${WINE}" "${ISCC}" setup.iss /Q + DEPENDS ${BINARY_NAME}-qt ${BINARY_NAME}-sdl CHANGES LICENSE) + else() + find_program(ISCC NAMES ISSC ISSC.exe) + add_custom_command(OUTPUT ${INSTALLER} + COMMAND "${ISCC}" setup.iss /Q + DEPENDS ${BINARY_NAME}-qt ${BINARY_NAME}-sdl CHANGES LICENSE) + endif() + if(ISCC) + add_custom_target(installer ALL DEPENDS ${INSTALLER}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${INSTALLER}" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT installer) + endif() + endif() endif() if(MARKDOWN) @@ -1064,11 +1103,11 @@ if(DISTBUILD) install(FILES "$.dSYM" DESTINATION ${LIBDIR} COMPONENT lib${BINARY_NAME}-dbg) endif() endif() - if(WIN32 OR APPLE) + if(APPLE) set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-qt ${BINARY_NAME}-sdl ${BINARY_NAME}-qt-dbg ${BINARY_NAME}-sdl-dbg ${BINARY_NAME}-perf) - if(APPLE) - set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) - endif() + set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE) + elseif(WIN32) + set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-qt ${BINARY_NAME}-sdl ${BINARY_NAME}-qt-dbg ${BINARY_NAME}-sdl-dbg ${BINARY_NAME}-perf installer) elseif(3DS) set(CPACK_COMPONENTS_ALL ${BINARY_NAME} ${BINARY_NAME}-dbg ${BINARY_NAME}-3ds ${BINARY_NAME}-perf) elseif(WII) @@ -1115,7 +1154,7 @@ if(SDL_FOUND) cpack_add_component(${BINARY_NAME}-sdl GROUP sdl) endif() -if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") +if(DISTBUILD) cpack_add_component_group(debug PARENT_GROUP dev) if(BUILD_SHARED AND NOT IS_EMBEDDED) cpack_add_component(lib${BINARY_NAME}-dbg GROUP debug) @@ -1129,6 +1168,9 @@ if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") if(SDL_FOUND) cpack_add_component(${BINARY_NAME}-sdl-dbg GROUP debug) endif() + if(WIN32) + cpack_add_component_group(installer PARENT_GROUP base) + endif() endif() cpack_add_component_group(test PARENT_GROUP dev) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 76e389c4b..33685bcc3 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -347,6 +347,10 @@ elseif(WIN32) find_program(BASH bash) install(CODE "execute_process(COMMAND \"${BASH}\" \"${CMAKE_SOURCE_DIR}/tools/deploy-win.sh\" \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe\" \"\${CMAKE_INSTALL_PREFIX}\" \"\$ENV{PWD}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")" COMPONENT ${BINARY_NAME}-qt) endif() + if(DISTBUILD) + file(WRITE "portable.ini" "") + install(FILES "portable.ini" DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT ${BINARY_NAME}-qt) + endif() endif() if(DISTBUILD AND CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") diff --git a/tools/windows/mgba-setupiconfile.ico b/src/platform/windows/setup/setup.ico similarity index 100% rename from tools/windows/mgba-setupiconfile.ico rename to src/platform/windows/setup/setup.ico diff --git a/src/platform/windows/setup/setup.iss.in b/src/platform/windows/setup/setup.iss.in new file mode 100644 index 000000000..c3771eadb --- /dev/null +++ b/src/platform/windows/setup/setup.iss.in @@ -0,0 +1,140 @@ +#define AppName "${PROJECT_NAME}" +#define AppName2 "${BINARY_NAME}" +#define VerMajor ${LIB_VERSION_MAJOR} +#define VerMinor ${LIB_VERSION_MINOR} +#define VerRev ${LIB_VERSION_PATCH} +#define VerBuild ${GIT_REV} +#define Release ${IS_RELEASE} +#define WinBits "${WIN_BITS}" +#define VersionString "${VERSION_STRING}" +#define CleanVersionString "${CLEAN_VERSION_STRING}" +#define SetupDir "${SETUP_DIR}" +#define BinDir "${BIN_DIR}" +#define ResDir "${RES_DIR}" + +#define FullVersion ParseVersion('{#AppName}.exe', VerMajor, VerMinor, VerRev, VerBuild) +#define AppVer Str(VerMajor) + "." + Str(VerMinor) + "." + Str(VerRev) + +[Setup] +SourceDir={#BinDir} +SetupIconFile={#SetupDir}\setup.ico +WizardImageFile={#SetupDir}\wizard-image.bmp + +AppName={#AppName} +AppVersion={#AppVer} +AppPublisher=Jeffrey Pfau +AppPublisherURL=https://mgba.io +AppSupportURL=https://mgba.io +AppUpdatesURL=https://mgba.io +AppReadmeFile={#BinDir}\README.html +OutputDir=.\ +DefaultDirName={pf}\{#AppName} +DefaultGroupName={#AppName} +AllowNoIcons=yes +DirExistsWarning=no +ChangesAssociations=True +AppendDefaultDirName=False +UninstallDisplayIcon={app}\{#AppName}.exe +MinVersion=0,6.0 +AlwaysShowDirOnReadyPage=True +UsePreviousSetupType=True +UsePreviousTasks=True +AlwaysShowGroupOnReadyPage=True +LicenseFile={#BinDir}\LICENSE.txt +#if Release + #define IsRelease = 'yes' + AppVerName={#AppName} {#AppVer} +#else + #define IsRelease = 'no' + AppVerName={#AppName} {#VersionString} (Development build) +#endif +#if '{#WinBits}' == '64' + ArchitecturesInstallIn64BitMode=x64 + ArchitecturesAllows=x64 +#endif +OutputBaseFilename={#AppName}-setup-{#CleanVersionString}-win{#WinBits} +UsePreviousLanguage=False +DisableWelcomePage=False +VersionInfoDescription={#AppName} is an open-source Game Boy Advance emulator +VersionInfoCopyright=© 2013–2018 Jeffrey Pfau +VersionInfoProductName={#AppName} +VersionInfoVersion={#AppVer} +Compression=lzma2/ultra64 +SolidCompression=True +VersionInfoTextVersion={#AppVer} +VersionInfoProductVersion={#AppVer} +VersionInfoProductTextVersion={#AppVer} + +[Languages] +Name: "english"; MessagesFile: "compiler:Default.isl" +Name: "french"; MessagesFile: "compiler:Languages\French.isl" +Name: "german"; MessagesFile: "compiler:Languages\German.isl" +Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" +Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" + +[Tasks] +Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" +Name: "gbfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Game Boy}"; GroupDescription: "{cm:FileAssoc}" +Name: "gbcfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Game Boy Color}"; GroupDescription: "{cm:FileAssoc}" +Name: "sgbfileassoc"; Description: "{cm:AssocFileExtension,{#AppName},Super Game Boy}"; GroupDescription: "{cm:FileAssoc}" +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}\CHANGES.txt"; DestDir: "{app}\"; Flags: ignoreversion isreadme +Source: "{#BinDir}\LICENSE.txt"; DestDir: "{app}\"; Flags: ignoreversion +Source: "{#ResDir}\nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion +Source: "{#BinDir}\README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: english italian spanish +Source: "{#BinDir}\README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german +Source: "{#ResDir}\shaders\*"; DestDir: "{app}\shaders\"; Flags: ignoreversion recursesubdirs +Source: "{#ResDir}\licenses\*"; DestDir: "{app}\licenses\"; Flags: ignoreversion recursesubdirs + +[Icons] +Name: "{commonstartmenu}\{#AppName}"; Filename: "{app}\{#AppName}.exe" +Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppName}.exe"; Tasks: desktopicon + +[Run] +Filename: "{app}\{#AppName}.exe"; Description: "{cm:LaunchProgram,{#AppName}}"; Flags: nowait postinstall skipifsilent + +[Dirs] +Name: "{app}" + +[CustomMessages] +english.FileAssoc=Register file associations +french.FileAssoc=Register file associations +italian.FileAssoc=Register file associations +spanish.FileAssoc=Register file associations +german.FileAssoc=Dateierweiterungen registrieren + +[Registry] +Root: HKCR; Subkey: ".gb"; ValueType: string; ValueName: ""; ValueData: "Game Boy ROM"; Flags: uninsdeletevalue; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gb\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: gbfileassoc +Root: HKCR; Subkey: ".gbc"; ValueType: string; ValueName: ""; ValueData: "Game Boy Color ROM"; Flags: uninsdeletevalue; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gbc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".gbc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: gbcfileassoc +Root: HKCR; Subkey: ".sgb"; ValueType: string; ValueName: ""; ValueData: "Super Game Boy ROM"; Flags: uninsdeletevalue; Tasks: sgbfileassoc +Root: HKCR; Subkey: ".sgb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: sgbfileassoc +Root: HKCR; Subkey: ".sgb\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: sgbfileassoc +Root: HKCR; Subkey: ".gba"; ValueType: string; ValueName: ""; ValueData: "Game Boy Advance ROM"; Flags: uninsdeletevalue; Tasks: gbafileassoc +Root: HKCR; Subkey: ".gba\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppName}.exe,0"; Tasks: gbafileassoc +Root: HKCR; Subkey: ".gba\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#AppName}.exe"" ""%1"""; Tasks: gbafileassoc + +[Code] +var + noReleaseWarning: String; + +procedure InitializeWizard(); + begin + if ExpandConstant('{#IsRelease}') = 'no' then + begin + if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'french' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of {#AppName}.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; + if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie möchten eine Entwicklerversion von {#AppName} installieren.' + #13#10#13#10 + 'Entwicklerversionen können bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden können, auf der GitHub-Projektseite.'; + MsgBox(noReleaseWarning, mbInformation, MB_OK); + end; + end; +end. diff --git a/tools/windows/mgba-wizardimagefile.bmp b/src/platform/windows/setup/wizard-image.bmp similarity index 100% rename from tools/windows/mgba-wizardimagefile.bmp rename to src/platform/windows/setup/wizard-image.bmp diff --git a/tools/windows/mgba-setup-win32.iss b/tools/windows/mgba-setup-win32.iss deleted file mode 100644 index 902b1efc9..000000000 --- a/tools/windows/mgba-setup-win32.iss +++ /dev/null @@ -1,127 +0,0 @@ -;For automation purposes it is highly recommended to copy the files from -;\tools\windows\ to the directory that contains the win32 distribution files! - -;Set CurrentReleaseVersion to the number of the latest stable mGBA build. -#define CurrentReleaseVersion = '0.6.3' - -#define VerMajor -#define VerMinor -#define VerRev -#define VerBuild -#define FullVersion=ParseVersion('mGBA.exe', VerMajor, VerMinor, VerRev, VerBuild) -#define AppVer = Str(VerMajor) + "." + Str(VerMinor) + "." + Str(VerRev) - -[Setup] -SourceDir=.\ -SetupIconFile=mgba-setupiconfile.ico -WizardImageFile=mgba-wizardimagefile.bmp - -AppName=mGBA -AppVersion={#AppVer} -AppPublisher=Jeffrey Pfau -AppPublisherURL=https://mgba.io -AppSupportURL=https://mgba.io -AppUpdatesURL=https://mgba.io -AppReadmeFile=README.html -OutputDir=.\ -DefaultDirName={pf}\mGBA -DefaultGroupName=mGBA -AllowNoIcons=yes -DirExistsWarning=no -ChangesAssociations=True -AppendDefaultDirName=False -UninstallDisplayIcon={app}\mGBA.exe -MinVersion=0,6.0 -AlwaysShowDirOnReadyPage=True -UsePreviousSetupType=True -UsePreviousTasks=True -AlwaysShowGroupOnReadyPage=True -LicenseFile=LICENSE -#if CurrentReleaseVersion == AppVer; - #define IsRelease = 'yes' - AppVerName=mGBA {#AppVer} - OutputBaseFilename=mGBA-{#AppVer}-win32 -#elif CurrentReleaseVersion != AppVer; - #define IsRelease = 'no' - AppVerName=mGBA (Development build) - OutputBaseFilename=mGBA-setup-latest-win32 - #endif -UsePreviousLanguage=False -DisableWelcomePage=False -VersionInfoDescription=mGBA is an open-source Game Boy Advance emulator -VersionInfoCopyright=© 2013–2018 Jeffrey Pfau -VersionInfoProductName=mGBA -VersionInfoVersion={#AppVer} -Compression=lzma2/ultra64 -SolidCompression=True -VersionInfoTextVersion={#AppVer} -VersionInfoProductVersion={#AppVer} -VersionInfoProductTextVersion={#AppVer} - -[Languages] -Name: "english"; MessagesFile: "compiler:Default.isl" -Name: "french"; MessagesFile: "compiler:Languages\French.isl" -Name: "german"; MessagesFile: "compiler:Languages\German.isl" -Name: "italian"; MessagesFile: "compiler:Languages\Italian.isl" -Name: "spanish"; MessagesFile: "compiler:Languages\Spanish.isl" - -[Tasks] -Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}" -Name: "gbfileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy}"; GroupDescription: "{cm:FileAssoc}" -Name: "gbcfileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy Color}"; GroupDescription: "{cm:FileAssoc}" -Name: "gbafileassoc"; Description: "{cm:AssocFileExtension,mGBA,Game Boy Advance}"; GroupDescription: "{cm:FileAssoc}" - -[Files] -Source: "mGBA.exe"; DestDir: "{app}"; Flags: ignoreversion -Source: "CHANGES"; DestDir: "{app}\"; Flags: ignoreversion isreadme -Source: "LICENSE"; DestDir: "{app}\"; Flags: ignoreversion -Source: "nointro.dat"; DestDir: "{app}\"; Flags: ignoreversion -Source: "README.html"; DestDir: "{app}\"; Flags: ignoreversion isreadme; Languages: english italian spanish -Source: "README_DE.html"; DestDir: "{app}\"; DestName: "LIESMICH.html"; Flags: ignoreversion isreadme; Languages: german -Source: "shaders\*"; DestDir: "{app}\shaders\"; Flags: ignoreversion recursesubdirs -Source: "licenses\*"; DestDir: "{app}\licenses\"; Flags: ignoreversion recursesubdirs - -[Icons] -Name: "{commonstartmenu}\mGBA"; Filename: "{app}\mGBA.exe" -Name: "{commondesktop}\mGBA"; Filename: "{app}\mGBA.exe"; Tasks: desktopicon - -[Run] -Filename: "{app}\mGBA.exe"; Description: "{cm:LaunchProgram,mGBA}"; Flags: nowait postinstall skipifsilent - -[Dirs] -Name: "{app}" - -[CustomMessages] -english.FileAssoc=Register file associations -french.FileAssoc=Register file associations -italian.FileAssoc=Register file associations -spanish.FileAssoc=Register file associations -german.FileAssoc=Dateierweiterungen registrieren - -[Registry] -Root: HKCR; Subkey: ".gb"; ValueType: string; ValueName: ""; ValueData: "Game Boy ROM"; Flags: uninsdeletevalue; Tasks: gbfileassoc -Root: HKCR; Subkey: ".gb\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbfileassoc -Root: HKCR; Subkey: ".gb\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbfileassoc -Root: HKCR; Subkey: ".gbc"; ValueType: string; ValueName: ""; ValueData: "Game Boy Color ROM"; Flags: uninsdeletevalue; Tasks: gbcfileassoc -Root: HKCR; Subkey: ".gbc\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbcfileassoc -Root: HKCR; Subkey: ".gbc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbcfileassoc -Root: HKCR; Subkey: ".gba"; ValueType: string; ValueName: ""; ValueData: "Game Boy Advance ROM"; Flags: uninsdeletevalue; Tasks: gbafileassoc -Root: HKCR; Subkey: ".gba\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\mGBA.exe,0"; Tasks: gbafileassoc Root: HKCR; Subkey: ".gba\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\mGBA.exe"" ""%1"""; Tasks: gbafileassoc - -[Code] -var - noReleaseWarning: String; - -procedure InitializeWizard(); - begin - if ExpandConstant('{#IsRelease}') = 'no' then - begin - if ExpandConstant('{language}') = 'english' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; - if ExpandConstant('{language}') = 'french' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; - if ExpandConstant('{language}') = 'italian' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; - if ExpandConstant('{language}') = 'spanish' then noReleaseWarning := 'You are about to install a development build of mGBA.' + #13#10#13#10 + 'Development builds may contain bugs that are not yet discovered. Please report any issues you can find to the GitHub project page.'; - if ExpandConstant('{language}') = 'german' then noReleaseWarning := 'Sie möchten eine Entwicklerversion von mGBA installieren.' + #13#10#13#10 + 'Entwicklerversionen können bislang noch nicht endeckte Fehler beinhalten. Bitte melden Sie alle Fehler, die Sie finden können, auf der GitHub-Projektseite.'; - MsgBox(noReleaseWarning, mbInformation, MB_OK); - end; - end; -end. \ No newline at end of file From 360890d5dc733520d76680565ac3f63aa088fc2e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 3 Oct 2018 20:53:26 -0700 Subject: [PATCH 46/60] Qt: Fix portable.ini creation --- src/platform/qt/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index 33685bcc3..629f45082 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -348,8 +348,8 @@ elseif(WIN32) install(CODE "execute_process(COMMAND \"${BASH}\" \"${CMAKE_SOURCE_DIR}/tools/deploy-win.sh\" \"${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.exe\" \"\${CMAKE_INSTALL_PREFIX}\" \"\$ENV{PWD}\" WORKING_DIRECTORY \"${CMAKE_BINARY_DIR}\")" COMPONENT ${BINARY_NAME}-qt) endif() if(DISTBUILD) - file(WRITE "portable.ini" "") - install(FILES "portable.ini" DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT ${BINARY_NAME}-qt) + file(WRITE "${CMAKE_BINARY_DIR}/portable.ini" "") + install(FILES "${CMAKE_BINARY_DIR}/portable.ini" DESTINATION "${CMAKE_INSTALL_BINDIR}" COMPONENT ${BINARY_NAME}-qt) endif() endif() From a44621e0d4e15d49864ef751c6f6f048a5df6415 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 3 Oct 2018 23:11:32 -0700 Subject: [PATCH 47/60] CMake: Ubuntu Cosmic fixes --- CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 82150410f..0668c1bee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,9 @@ cmake_minimum_required(VERSION 3.1) if(POLICY CMP0025) cmake_policy(SET CMP0025 NEW) endif() +if(POLICY CMP0072) + cmake_policy(SET CMP0072 NEW) +endif() project(mGBA) set(BINARY_NAME mgba CACHE INTERNAL "Name of output binaries") if(NOT MSVC) @@ -532,7 +535,11 @@ if(USE_FFMPEG) 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}) - math(EXPR LIBSWRESAMPLE_VERSION_DEBIAN "${LIBSWRESAMPLE_VERSION_MAJOR} - 1") + if(${libswresample_VERSION} EQUAL "3.1.100") + set(LIBSWRESAMPLE_VERSION_DEBIAN 3) + else() + math(EXPR LIBSWRESAMPLE_VERSION_DEBIAN "${LIBSWRESAMPLE_VERSION_MAJOR} - 1") + endif() set(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS},libswresample${LIBSWRESAMPLE_VERSION_DEBIAN}|libswresample-ffmpeg${LIBSWRESAMPLE_VERSION_DEBIAN}") else() string(REGEX MATCH "^[0-9]+" LIBAVRESAMPLE_VERSION_MAJOR ${libavresample_VERSION}) @@ -559,6 +566,8 @@ if(USE_MAGICK) string(REGEX MATCH "^[0-9]+" MAGICKWAND_VERSION_MAJOR ${MagickWand_VERSION}) if(${MAGICKWAND_VERSION_PARTIAL} EQUAL "6.7") set(MAGICKWAND_DEB_VERSION "5") + elseif(${MagickWand_VERSION} EQUAL "6.9.10") + set(MAGICKWAND_DEB_VERSION "-6.q16-6") elseif(${MagickWand_VERSION} EQUAL "6.9.7") set(MAGICKWAND_DEB_VERSION "-6.q16-3") else() From 23e60e081ea4e5dc35e28feb3af14b3d94bef329 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 4 Oct 2018 09:26:03 -0700 Subject: [PATCH 48/60] GB: Improved SGB2 support --- CHANGES | 1 + src/gb/audio.c | 2 +- src/gb/core.c | 6 +++--- src/gb/gb.c | 5 +++++ src/gb/io.c | 8 ++++---- src/gb/renderers/software.c | 2 +- src/gb/serialize.c | 4 ++-- src/gb/video.c | 4 ++-- 8 files changed, 19 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 5abb5d52e..3ad8e7a0f 100644 --- a/CHANGES +++ b/CHANGES @@ -124,6 +124,7 @@ Misc: - Wii: Expose stretch configuration in settings - Wii: Stretch now sets pixel-accurate mode size cap - Qt: Ensure camera image is valid + - GB: Improved SGB2 support 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/gb/audio.c b/src/gb/audio.c index 994eaeedb..ee5ec9ed8 100644 --- a/src/gb/audio.c +++ b/src/gb/audio.c @@ -150,7 +150,7 @@ void GBAudioReset(struct GBAudio* audio) { audio->playingCh2 = false; audio->playingCh3 = false; audio->playingCh4 = false; - if (audio->p && audio->p->model != GB_MODEL_SGB) { + if (audio->p && !(audio->p->model & GB_MODEL_SGB)) { audio->playingCh1 = true; audio->enable = true; *audio->nr52 |= 0x01; diff --git a/src/gb/core.c b/src/gb/core.c index a5b29d6a9..92e922d03 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -229,7 +229,7 @@ static void _GBCoreLoadConfig(struct mCore* core, const struct mCoreConfig* conf static void _GBCoreDesiredVideoDimensions(struct mCore* core, unsigned* width, unsigned* height) { struct GB* gb = core->board; - if (gb && (gb->model != GB_MODEL_SGB || !gb->video.sgbBorders)) { + if (gb && (!(gb->model & GB_MODEL_SGB) || !gb->video.sgbBorders)) { *width = GB_VIDEO_HORIZONTAL_PIXELS; *height = GB_VIDEO_VERTICAL_PIXELS; } else { @@ -373,9 +373,9 @@ static void _GBCoreReset(struct mCore* core) { GBDetectModel(gb); if (gb->model == GB_MODEL_DMG && modelGB) { gb->model = GBNameToModel(modelGB); - } else if (gb->model == GB_MODEL_CGB && modelCGB) { + } else if ((gb->model & GB_MODEL_CGB) && modelCGB) { gb->model = GBNameToModel(modelCGB); - } else if (gb->model == GB_MODEL_SGB && modelSGB) { + } else if ((gb->model & GB_MODEL_SGB) && modelSGB) { gb->model = GBNameToModel(modelSGB); } } diff --git a/src/gb/gb.c b/src/gb/gb.c index fa5408107..508483c1b 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -30,6 +30,7 @@ static const uint8_t _knownHeader[4] = { 0xCE, 0xED, 0x66, 0x66}; #define DMG_2_BIOS_CHECKSUM 0x59C8598E #define MGB_BIOS_CHECKSUM 0xE6920754 #define SGB_BIOS_CHECKSUM 0xEC8A83B9 +#define SGB2_BIOS_CHECKSUM 0X53D0DD63 #define CGB_BIOS_CHECKSUM 0x41884E46 mLOG_DEFINE_CATEGORY(GB, "GB", "gb"); @@ -400,6 +401,7 @@ bool GBIsBIOS(struct VFile* vf) { case DMG_2_BIOS_CHECKSUM: case MGB_BIOS_CHECKSUM: case SGB_BIOS_CHECKSUM: + case SGB2_BIOS_CHECKSUM: case CGB_BIOS_CHECKSUM: return true; default: @@ -588,6 +590,9 @@ void GBDetectModel(struct GB* gb) { case SGB_BIOS_CHECKSUM: gb->model = GB_MODEL_SGB; break; + case SGB2_BIOS_CHECKSUM: + gb->model = GB_MODEL_SGB2; + break; case CGB_BIOS_CHECKSUM: gb->model = GB_MODEL_CGB; break; diff --git a/src/gb/io.c b/src/gb/io.c index 2d3efec2f..84b3a35bc 100644 --- a/src/gb/io.c +++ b/src/gb/io.c @@ -199,7 +199,7 @@ void GBIOReset(struct GB* gb) { } GBIOWrite(gb, REG_WY, 0x00); GBIOWrite(gb, REG_WX, 0x00); - if (gb->model >= GB_MODEL_CGB) { + if (gb->model & GB_MODEL_CGB) { GBIOWrite(gb, REG_UNK4C, 0); GBIOWrite(gb, REG_JOYP, 0xFF); GBIOWrite(gb, REG_VBK, 0); @@ -211,7 +211,7 @@ void GBIOReset(struct GB* gb) { GBIOWrite(gb, REG_HDMA3, 0xFF); GBIOWrite(gb, REG_HDMA4, 0xFF); gb->memory.io[REG_HDMA5] = 0xFF; - } else if (gb->model == GB_MODEL_SGB) { + } else if (gb->model & GB_MODEL_SGB) { GBIOWrite(gb, REG_JOYP, 0xFF); } GBIOWrite(gb, REG_IE, 0x00); @@ -404,7 +404,7 @@ void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) { case REG_JOYP: gb->memory.io[REG_JOYP] = value | 0x0F; _readKeys(gb); - if (gb->model == GB_MODEL_SGB) { + if (gb->model & GB_MODEL_SGB) { _writeSGBBits(gb, (value >> 4) & 3); } return; @@ -719,7 +719,7 @@ void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) { gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCX, state->io[REG_SCX]); gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WY, state->io[REG_WY]); gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WX, state->io[REG_WX]); - if (gb->model == GB_MODEL_SGB) { + if (gb->model & GB_MODEL_SGB) { gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_BGP, state->io[REG_BGP]); gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP0, state->io[REG_OBP0]); gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP1, state->io[REG_OBP1]); diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index d2e000422..6447f9c82 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -196,7 +196,7 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS; softwareRenderer->hasWindow = false; softwareRenderer->wx = 0; - softwareRenderer->model = model; + softwareRenderer->model = model & ~GB_MODEL_MGB; softwareRenderer->sgbTransfer = 0; softwareRenderer->sgbCommandHeader = 0; softwareRenderer->sgbBorders = sgbBorders; diff --git a/src/gb/serialize.c b/src/gb/serialize.c index 67046a888..4eef6ae67 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -64,7 +64,7 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) { GBTimerSerialize(&gb->timer, state); GBAudioSerialize(&gb->audio, state); - if (gb->model == GB_MODEL_SGB) { + if (gb->model & GB_MODEL_SGB) { GBSGBSerialize(gb, state); } } @@ -187,7 +187,7 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) { GBTimerDeserialize(&gb->timer, state); GBAudioDeserialize(&gb->audio, state); - if (gb->model == GB_MODEL_SGB && canSgb) { + if (gb->model & GB_MODEL_SGB && canSgb) { GBSGBDeserialize(gb, state); } diff --git a/src/gb/video.c b/src/gb/video.c index f90536ae0..dcb49523c 100644 --- a/src/gb/video.c +++ b/src/gb/video.c @@ -107,7 +107,7 @@ void GBVideoReset(struct GBVideo* video) { video->renderer->oam = &video->oam; memset(&video->palette, 0, sizeof(video->palette)); - if (video->p->model == GB_MODEL_SGB) { + if (video->p->model & GB_MODEL_SGB) { video->renderer->sgbCharRam = anonymousMemoryMap(SGB_SIZE_CHAR_RAM); video->renderer->sgbMapRam = anonymousMemoryMap(SGB_SIZE_MAP_RAM); video->renderer->sgbPalRam = anonymousMemoryMap(SGB_SIZE_PAL_RAM); @@ -491,7 +491,7 @@ void GBVideoWritePalette(struct GBVideo* video, uint16_t address, uint8_t value) video->renderer->writePalette(video->renderer, 9 * 4 + 3, video->palette[9 * 4 + 3]); break; } - } else if (video->p->model == GB_MODEL_SGB) { + } else if (video->p->model & GB_MODEL_SGB) { video->renderer->writeVideoRegister(video->renderer, address, value); } else { switch (address) { From d7f2f5ba06fdf8e3d6feff7d7962323b813a92ad Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 4 Oct 2018 09:45:38 -0700 Subject: [PATCH 49/60] GB Video: SGB border drawing improvements --- CHANGES | 1 + src/gb/renderers/software.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 3ad8e7a0f..116b8df40 100644 --- a/CHANGES +++ b/CHANGES @@ -117,6 +117,7 @@ Bugfixes: - Qt: Fix FPS counter on Windows - GB, GBA Savedata: Fix leaks when loading masked save (fixes mgba.io/i/1197) - Qt: Fix focus issues with load/save state overlay + - GB Video: Fix SGB border hole size Misc: - mGUI: Add SGB border configuration option - mGUI: Add support for different settings types diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index 6447f9c82..e8ef59e99 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -56,7 +56,7 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) { int x, y; for (y = 0; y < 224; ++y) { for (x = 0; x < 256; x += 8) { - if (x >= 48 && x < 208 && y >= 40 && y < 104) { + if (x >= 48 && x < 208 && y >= 40 && y < 184) { continue; } uint16_t mapData; @@ -79,16 +79,13 @@ static void _regenerateSGBBorder(struct GBVideoSoftwareRenderer* renderer) { int paletteBase = SGBBgAttributesGetPalette(mapData) * 0x10; int colorSelector; + int flip = 0; if (SGBBgAttributesIsXFlip(mapData)) { - for (i = 0; i < 8; ++i) { - colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3; - renderer->outputBuffer[base + i] = renderer->palette[paletteBase | colorSelector]; - } - } else { - for (i = 7; i >= 0; --i) { - colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3; - renderer->outputBuffer[base + 7 - i] = renderer->palette[paletteBase | colorSelector]; - } + flip = 7; + } + for (i = 7; i >= 0; --i) { + colorSelector = (tileData[0] >> i & 0x1) << 0 | (tileData[1] >> i & 0x1) << 1 | (tileData[2] >> i & 0x1) << 2 | (tileData[3] >> i & 0x1) << 3; + renderer->outputBuffer[(base + 7 - i) ^ flip] = renderer->palette[paletteBase | colorSelector]; } } } @@ -712,6 +709,9 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; if (softwareRenderer->model == GB_MODEL_SGB) { + if (enable == softwareRenderer->sgbBorders) { + return; + } softwareRenderer->sgbBorders = enable; if (softwareRenderer->sgbBorders && !renderer->sgbRenderMode) { _regenerateSGBBorder(softwareRenderer); From d5548f6da87cd39070d96e69bc4293c9a121ce89 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 4 Oct 2018 10:34:17 -0700 Subject: [PATCH 50/60] GB Video: More SGB fixes --- src/gb/core.c | 1 + src/gb/renderers/software.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/gb/core.c b/src/gb/core.c index 92e922d03..5185e9a69 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -1048,6 +1048,7 @@ static bool _GBVLPLoadState(struct mCore* core, const void* buffer) { gb->cpu->pc = GB_BASE_HRAM; gb->cpu->memory.setActiveRegion(gb->cpu, gb->cpu->pc); + GBVideoReset(&gb->video); GBVideoDeserialize(&gb->video, state); GBIODeserialize(gb, state); GBAudioReset(&gb->audio); diff --git a/src/gb/renderers/software.c b/src/gb/renderers/software.c index e8ef59e99..c5e0d3c7a 100644 --- a/src/gb/renderers/software.c +++ b/src/gb/renderers/software.c @@ -30,7 +30,7 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende static void _clearScreen(struct GBVideoSoftwareRenderer* renderer) { size_t sgbOffset = 0; - if (renderer->model == GB_MODEL_SGB) { + if (renderer->model & GB_MODEL_SGB) { return; } int y; @@ -193,7 +193,7 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G softwareRenderer->lastY = GB_VIDEO_VERTICAL_PIXELS; softwareRenderer->hasWindow = false; softwareRenderer->wx = 0; - softwareRenderer->model = model & ~GB_MODEL_MGB; + softwareRenderer->model = model; softwareRenderer->sgbTransfer = 0; softwareRenderer->sgbCommandHeader = 0; softwareRenderer->sgbBorders = sgbBorders; @@ -429,7 +429,7 @@ static void GBVideoSoftwareRendererWriteSGBPacket(struct GBVideoRenderer* render static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer, int index, uint16_t value) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; color_t color = mColorFrom555(value); - if (softwareRenderer->model == GB_MODEL_SGB) { + if (softwareRenderer->model & GB_MODEL_SGB) { if (index < 0x10 && index && !(index & 3)) { color = softwareRenderer->palette[0]; } else if (index >= 0x40 && !(index & 0xF)) { @@ -460,7 +460,7 @@ static void GBVideoSoftwareRendererWritePalette(struct GBVideoRenderer* renderer } softwareRenderer->palette[index] = color; - if (softwareRenderer->model == GB_MODEL_SGB && !index && GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) { + if (softwareRenderer->model & GB_MODEL_SGB && !index && GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) { renderer->writePalette(renderer, 0x04, value); renderer->writePalette(renderer, 0x08, value); renderer->writePalette(renderer, 0x0C, value); @@ -525,7 +525,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i } size_t sgbOffset = 0; - if (softwareRenderer->model == GB_MODEL_SGB && softwareRenderer->sgbBorders) { + if (softwareRenderer->model & GB_MODEL_SGB && softwareRenderer->sgbBorders) { sgbOffset = softwareRenderer->outputBufferStride * 40 + 48; } color_t* row = &softwareRenderer->outputBuffer[softwareRenderer->outputBufferStride * y + sgbOffset]; @@ -533,7 +533,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i int p = 0; switch (softwareRenderer->d.sgbRenderMode) { case 0: - if (softwareRenderer->model == GB_MODEL_SGB) { + if (softwareRenderer->model & GB_MODEL_SGB) { p = softwareRenderer->d.sgbAttributes[(startX >> 5) + 5 * (y >> 3)]; p >>= 6 - ((x / 4) & 0x6); p &= 3; @@ -543,7 +543,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i row[x] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x] & 0x7F]]; } for (; x + 7 < (endX & ~7); x += 8) { - if (softwareRenderer->model == GB_MODEL_SGB) { + if (softwareRenderer->model & GB_MODEL_SGB) { p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)]; p >>= 6 - ((x / 4) & 0x6); p &= 3; @@ -558,7 +558,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i row[x + 6] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 6] & 0x7F]]; row[x + 7] = softwareRenderer->palette[p | softwareRenderer->lookup[softwareRenderer->row[x + 7] & 0x7F]]; } - if (softwareRenderer->model == GB_MODEL_SGB) { + if (softwareRenderer->model & GB_MODEL_SGB) { p = softwareRenderer->d.sgbAttributes[(x >> 5) + 5 * (y >> 3)]; p >>= 6 - ((x / 4) & 0x6); p &= 3; @@ -675,7 +675,7 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) if (!GBRegisterLCDCIsEnable(softwareRenderer->lcdc)) { _clearScreen(softwareRenderer); } - if (softwareRenderer->model == GB_MODEL_SGB) { + if (softwareRenderer->model & GB_MODEL_SGB) { switch (softwareRenderer->sgbCommandHeader >> 3) { case SGB_PAL_SET: case SGB_ATTR_SET: @@ -708,7 +708,7 @@ static void GBVideoSoftwareRendererFinishFrame(struct GBVideoRenderer* renderer) static void GBVideoSoftwareRendererEnableSGBBorder(struct GBVideoRenderer* renderer, bool enable) { struct GBVideoSoftwareRenderer* softwareRenderer = (struct GBVideoSoftwareRenderer*) renderer; - if (softwareRenderer->model == GB_MODEL_SGB) { + if (softwareRenderer->model & GB_MODEL_SGB) { if (enable == softwareRenderer->sgbBorders) { return; } From eda2669780362bbecd52429088ff6b9512fdb2b3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 4 Oct 2018 12:09:54 -0700 Subject: [PATCH 51/60] CMake: Installer buildscript fixes --- CHANGES | 1 + CMakeLists.txt | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 116b8df40..1853b26e8 100644 --- a/CHANGES +++ b/CHANGES @@ -105,6 +105,7 @@ Features: - Switch: Rumble support - Switch: Rotation support - Qt: State file load/save menu options + - Windows installer Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full diff --git a/CMakeLists.txt b/CMakeLists.txt index 0668c1bee..4d35bc242 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1055,22 +1055,28 @@ else() add_custom_target(LICENSE ALL DEPENDS LICENSE.txt) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) if(DISTBUILD AND WIN32) - set(INSTALLER "${PROJECT_NAME}-setup-${CLEAN_VERSION_STRING}-win${WIN_BITS}.exe") + if(INSTALLER_NAME) + set(INSTALLER_TARGET "${INSTALLER_NAME}.exe") + set(ISCC_FLAGS "/F${INSTALLER_NAME}") + else() + set(INSTALLER_TARGET "${PROJECT_NAME}-setup-${CLEAN_VERSION_STRING}-win${WIN_BITS}.exe") + endif() if(CMAKE_CROSSCOMPILING) find_program(WINE NAMES wine wine-stable wine-development) - find_file(ISCC ISCC.exe HINTS "$ENV{HOME}/.wine/drive_c/Program Files/") - add_custom_command(OUTPUT ${INSTALLER} - COMMAND "${WINE}" "${ISCC}" setup.iss /Q + find_file(ISCC ISCC.exe HINTS "$ENV{HOME}/.wine/drive_c/Program Files/" PATH_SUFFIXES "Inno Setup 5") + message(STATUS "${WINE}" "${ISCC}" setup.iss /Q ${ISCC_FLAGS}) + add_custom_command(OUTPUT ${INSTALLER_TARGET} + COMMAND "${WINE}" "${ISCC}" setup.iss /Q ${ISCC_FLAGS} DEPENDS ${BINARY_NAME}-qt ${BINARY_NAME}-sdl CHANGES LICENSE) else() - find_program(ISCC NAMES ISSC ISSC.exe) - add_custom_command(OUTPUT ${INSTALLER} - COMMAND "${ISCC}" setup.iss /Q + find_program(ISCC NAMES ISCC ISCC.exe PATH_SUFFIXES "Inno Setup 5") + add_custom_command(OUTPUT ${INSTALLER_TARGET} + COMMAND "${ISCC}" setup.iss /Q ${ISCC_FLAGS} DEPENDS ${BINARY_NAME}-qt ${BINARY_NAME}-sdl CHANGES LICENSE) endif() if(ISCC) - add_custom_target(installer ALL DEPENDS ${INSTALLER}) - install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${INSTALLER}" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT installer) + add_custom_target(installer ALL DEPENDS ${INSTALLER_TARGET}) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${INSTALLER_TARGET}" DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT installer) endif() endif() endif() From 1bf29ae36291337545fc79ed7c0745e4d4c0df60 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 4 Oct 2018 12:26:03 -0700 Subject: [PATCH 52/60] CMake: unix2dos, not dos2unix --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d35bc242..0ba995484 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1040,17 +1040,17 @@ endif() file(GLOB READMES ${CMAKE_CURRENT_SOURCE_DIR}/README*.md) -find_program(DOS2UNIX NAMES dos2unix) +find_program(UNIX2DOS NAMES unix2dos) find_program(MARKDOWN NAMES markdown kramdown pandoc) -if(UNIX OR NOT DOS2UNIX) +if(UNIX OR NOT UNIX2DOS) if(UNIX OR NOT MARKDOWN) install(FILES ${READMES} DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) endif() install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES" "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) else() - add_custom_command(OUTPUT CHANGES.txt COMMAND ${DOS2UNIX} -n "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES" "${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt" MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES") - add_custom_command(OUTPUT LICENSE.txt COMMAND ${DOS2UNIX} -n "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt" MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") + add_custom_command(OUTPUT CHANGES.txt COMMAND ${UNIX2DOS} -n "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES" "${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt" MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/CHANGES") + add_custom_command(OUTPUT LICENSE.txt COMMAND ${UNIX2DOS} -n "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE" "${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt" MAIN_DEPENDENCY "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") add_custom_target(CHANGES ALL DEPENDS CHANGES.txt) add_custom_target(LICENSE ALL DEPENDS LICENSE.txt) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CHANGES.txt ${CMAKE_CURRENT_BINARY_DIR}/LICENSE.txt DESTINATION ${CMAKE_INSTALL_DOCDIR} COMPONENT ${BINARY_NAME}) From a8d991e24f12aa1930498af61f16fa2b098cc618 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 5 Oct 2018 08:42:20 -0700 Subject: [PATCH 53/60] Libretro: Reduce rumble callbacks --- CHANGES | 1 + src/platform/libretro/libretro.c | 36 ++++++++++++++++++-------------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 1853b26e8..e4bfe1547 100644 --- a/CHANGES +++ b/CHANGES @@ -127,6 +127,7 @@ Misc: - Wii: Stretch now sets pixel-accurate mode size cap - Qt: Ensure camera image is valid - GB: Improved SGB2 support + - Libretro: Reduce rumble callbacks 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index eafc7fca1..06a9638b1 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -23,7 +23,6 @@ #include #include #endif -#include #include #include @@ -55,8 +54,8 @@ static void* data; static size_t dataSize; static void* savedata; static struct mAVStream stream; -static int rumbleLevel; -static struct CircleBuffer rumbleHistory; +static int rumbleUp; +static int rumbleDown; static struct mRumble rumble; static struct GBALuminanceSource lux; static int luxLevel; @@ -254,7 +253,6 @@ void retro_init(void) { struct retro_rumble_interface rumbleInterface; if (environCallback(RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE, &rumbleInterface)) { rumbleCallback = rumbleInterface.set_rumble_state; - CircleBufferInit(&rumbleHistory, RUMBLE_PWM); rumble.setRumble = _setRumble; } else { rumbleCallback = 0; @@ -347,6 +345,18 @@ void retro_run(void) { unsigned width, height; core->desiredVideoDimensions(core, &width, &height); videoCallback(outputBuffer, width, height, BYTES_PER_PIXEL * 256); + + if (rumbleCallback) { + if (rumbleUp) { + rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleUp * 0xFFFF / (rumbleUp + rumbleDown)); + } else { + rumbleCallback(0, RETRO_RUMBLE_STRONG, 0); + rumbleCallback(0, RETRO_RUMBLE_WEAK, 0); + } + rumbleUp = 0; + rumbleDown = 0; + } } static void _setupMaps(struct mCore* core) { @@ -437,9 +447,8 @@ void retro_reset(void) { core->reset(core); _setupMaps(core); - if (rumbleCallback) { - CircleBufferClear(&rumbleHistory); - } + rumbleUp = 0; + rumbleDown = 0; } bool retro_load_game(const struct retro_game_info* game) { @@ -557,7 +566,6 @@ void retro_unload_game(void) { data = 0; mappedMemoryFree(savedata, SIZE_CART_FLASH1M); savedata = 0; - CircleBufferDeinit(&rumbleHistory); } size_t retro_serialize_size(void) { @@ -754,15 +762,11 @@ static void _setRumble(struct mRumble* rumble, int enable) { if (!rumbleCallback) { return; } - rumbleLevel += enable; - if (CircleBufferSize(&rumbleHistory) == RUMBLE_PWM) { - int8_t oldLevel; - CircleBufferRead8(&rumbleHistory, &oldLevel); - rumbleLevel -= oldLevel; + if (enable) { + ++rumbleUp; + } else { + ++rumbleDown; } - CircleBufferWrite8(&rumbleHistory, enable); - rumbleCallback(0, RETRO_RUMBLE_STRONG, rumbleLevel * 0xFFFF / RUMBLE_PWM); - rumbleCallback(0, RETRO_RUMBLE_WEAK, rumbleLevel * 0xFFFF / RUMBLE_PWM); } static void _updateLux(struct GBALuminanceSource* lux) { From 704642241748e05de8db30a5b4d4751ba31834a0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 5 Oct 2018 13:15:08 -0700 Subject: [PATCH 54/60] Qt: Add width adjustment to tile viewer --- CHANGES | 1 + src/platform/qt/TilePainter.cpp | 6 +- src/platform/qt/TileView.cpp | 15 ++++ src/platform/qt/TileView.ui | 143 +++++++++++++++++++++----------- 4 files changed, 115 insertions(+), 50 deletions(-) diff --git a/CHANGES b/CHANGES index e4bfe1547..1b5863a81 100644 --- a/CHANGES +++ b/CHANGES @@ -106,6 +106,7 @@ Features: - Switch: Rotation support - Qt: State file load/save menu options - Windows installer + - Tile viewer now has adjustable width Bugfixes: - PSP2: Fix audio crackling after fast forward - PSP2: Fix audio crackling when buffer is full diff --git a/src/platform/qt/TilePainter.cpp b/src/platform/qt/TilePainter.cpp index 454530a7c..bbf975ca6 100644 --- a/src/platform/qt/TilePainter.cpp +++ b/src/platform/qt/TilePainter.cpp @@ -59,8 +59,12 @@ void TilePainter::setTileCount(int tiles) { int w = width() / m_size; int h = (tiles + w - 1) * m_size / w; setMinimumSize(m_size, h - (h % m_size)); - resizeEvent(nullptr); + } else { + int w = minimumSize().width() / m_size; + int h = (tiles + w - 1) * m_size / w; + setMinimumSize(minimumSize().width(), h - (h % m_size)); } + resizeEvent(nullptr); } void TilePainter::setTileMagnification(int mag) { diff --git a/src/platform/qt/TileView.cpp b/src/platform/qt/TileView.cpp index 38c2610f7..063caf8d3 100644 --- a/src/platform/qt/TileView.cpp +++ b/src/platform/qt/TileView.cpp @@ -65,6 +65,21 @@ TileView::TileView(std::shared_ptr controller, QWidget* parent) connect(m_ui.magnification, static_cast(&QSpinBox::valueChanged), [this]() { updateTiles(true); }); + + connect(m_ui.tilesPerRow, static_cast(&QSpinBox::valueChanged), [this](int count) { + m_ui.tiles->setMinimumSize(m_ui.magnification->value() * 8 * count, m_ui.tiles->minimumSize().height()); + updateTiles(true); + }); + + connect(m_ui.tileFit, &QAbstractButton::toggled, [this](bool selected) { + if (!selected) { + m_ui.tiles->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_ui.tiles->setMinimumSize(m_ui.magnification->value() * 8 * m_ui.tilesPerRow->value(), m_ui.tiles->minimumSize().height()); + } else { + m_ui.tiles->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + } + updateTiles(true); + }); } #ifdef M_CORE_GBA diff --git a/src/platform/qt/TileView.ui b/src/platform/qt/TileView.ui index 608e1d2d0..02c4c533f 100644 --- a/src/platform/qt/TileView.ui +++ b/src/platform/qt/TileView.ui @@ -6,48 +6,15 @@ 0 0 - 501 - 335 + 693 + 467 Tiles - - - - - - - - - - - 0 - 0 - - - - × - - - 1 - - - 4 - - - - - - - Magnification - - - - - - + + @@ -66,7 +33,7 @@ 0 0 - 256 + 405 768 @@ -112,7 +79,7 @@ - + Qt::Vertical @@ -125,22 +92,84 @@ + + + - - + + 15 - + 256 colors + + + + + 0 + 0 + + + + × + + + 1 + + + 4 + + + + + + + Magnification + + + + + + + false + + + 1 + + + 64 + + + 32 + + + + + + + Tiles per row + + + + + + + Fit to window + + + true + + + @@ -164,6 +193,22 @@ + + tileFit + toggled(bool) + tilesPerRow + setDisabled(bool) + + + 162 + 180 + + + 39 + 133 + + + magnification valueChanged(int) @@ -171,12 +216,12 @@ setTileMagnification(int) - 36 - 83 + 39 + 81 - 339 - 396 + 462 + 391 @@ -187,11 +232,11 @@ setDisabled(bool) - 158 - 29 + 148 + 24 - 44 + 39 29 From cf28e05f1ae15bd915589b038e0f0a7bc6e82d05 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 6 Oct 2018 18:03:23 -0700 Subject: [PATCH 55/60] Debugger: Minor text fixes --- CHANGES | 1 + src/debugger/cli-debugger.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 1b5863a81..90d223a87 100644 --- a/CHANGES +++ b/CHANGES @@ -129,6 +129,7 @@ Misc: - Qt: Ensure camera image is valid - GB: Improved SGB2 support - Libretro: Reduce rumble callbacks + - Debugger: Minor text fixes 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index d0ed6b672..aff3f5ded 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -841,9 +841,9 @@ static void _reportEntry(struct mDebugger* debugger, enum mDebuggerEntryReason r case DEBUGGER_ENTER_WATCHPOINT: if (info) { if (info->type.wp.accessType & WATCHPOINT_WRITE) { - cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (new value = 0x%08x, old value = 0x%08X)\n", info->address, info->type.wp.newValue, info->type.wp.oldValue); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (new value = 0x%08X, old value = 0x%08X)\n", info->address, info->type.wp.newValue, info->type.wp.oldValue); } else { - cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (value = 0x%08x)\n", info->address, info->type.wp.oldValue); + cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint at 0x%08X: (value = 0x%08X)\n", info->address, info->type.wp.oldValue); } } else { cliDebugger->backend->printf(cliDebugger->backend, "Hit watchpoint\n"); From 086a34103d625936af63b729a3d86d0944b971d2 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 6 Oct 2018 18:23:11 -0700 Subject: [PATCH 56/60] Qt: Debugger console history --- CHANGES | 1 + src/platform/qt/DebuggerConsole.cpp | 42 +++++++++++++++++++++++++++++ src/platform/qt/DebuggerConsole.h | 5 ++++ 3 files changed, 48 insertions(+) diff --git a/CHANGES b/CHANGES index 90d223a87..b8c91aba5 100644 --- a/CHANGES +++ b/CHANGES @@ -130,6 +130,7 @@ Misc: - GB: Improved SGB2 support - Libretro: Reduce rumble callbacks - Debugger: Minor text fixes + - Qt: Debugger console history 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/platform/qt/DebuggerConsole.cpp b/src/platform/qt/DebuggerConsole.cpp index a9c505da8..b7ac06323 100644 --- a/src/platform/qt/DebuggerConsole.cpp +++ b/src/platform/qt/DebuggerConsole.cpp @@ -17,6 +17,8 @@ DebuggerConsole::DebuggerConsole(DebuggerConsoleController* controller, QWidget* { m_ui.setupUi(this); + m_ui.prompt->installEventFilter(this); + connect(m_ui.prompt, &QLineEdit::returnPressed, this, &DebuggerConsole::postLine); connect(controller, &DebuggerConsoleController::log, this, &DebuggerConsole::log); connect(m_ui.breakpoint, &QAbstractButton::clicked, controller, &DebuggerController::attach); @@ -36,7 +38,47 @@ void DebuggerConsole::postLine() { if (line.isEmpty()) { m_consoleController->enterLine(QString("\n")); } else { + m_history.append(line); + m_historyOffset = 0; log(QString("> %1\n").arg(line)); m_consoleController->enterLine(line); } } + +bool DebuggerConsole::eventFilter(QObject*, QEvent* event) { + if (event->type() != QEvent::KeyPress) { + return false; + } + if (m_history.isEmpty()) { + return false; + } + QKeyEvent* keyEvent = static_cast(event); + switch (keyEvent->key()) { + case Qt::Key_Down: + if (m_historyOffset <= 0) { + return false; + } + --m_historyOffset; + break; + case Qt::Key_Up: + if (m_historyOffset >= m_history.size()) { + return false; + } + ++m_historyOffset; + break; + case Qt::Key_End: + m_historyOffset = 0; + break; + case Qt::Key_Home: + m_historyOffset = m_history.size(); + break; + default: + return false; + } + if (m_historyOffset == 0) { + m_ui.prompt->clear(); + } else { + m_ui.prompt->setText(m_history[m_history.size() - m_historyOffset]); + } + return true; +} \ No newline at end of file diff --git a/src/platform/qt/DebuggerConsole.h b/src/platform/qt/DebuggerConsole.h index f4bd4cadb..5fe523c24 100644 --- a/src/platform/qt/DebuggerConsole.h +++ b/src/platform/qt/DebuggerConsole.h @@ -21,8 +21,13 @@ private slots: void log(const QString&); void postLine(); +protected: + bool eventFilter(QObject*, QEvent*) override; + private: Ui::DebuggerConsole m_ui; + QStringList m_history; + int m_historyOffset; DebuggerConsoleController* m_consoleController; }; From ab4b730991e53d01737634b225696a2e793f90b1 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 6 Oct 2018 18:24:29 -0700 Subject: [PATCH 57/60] Debugger: More minor text fixes --- src/debugger/cli-debugger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/debugger/cli-debugger.c b/src/debugger/cli-debugger.c index aff3f5ded..e4ff8ab5b 100644 --- a/src/debugger/cli-debugger.c +++ b/src/debugger/cli-debugger.c @@ -66,8 +66,8 @@ static struct CLIDebuggerCommandSummary _debuggerCommands[] = { { "break", _setBreakpoint, "Is", "Set a breakpoint" }, { "c", _continue, "", "Continue execution" }, { "continue", _continue, "", "Continue execution" }, - { "d", _clearBreakpoint, "I", "Delete a breakpoint" }, - { "delete", _clearBreakpoint, "I", "Delete a breakpoint" }, + { "d", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" }, + { "delete", _clearBreakpoint, "I", "Delete a breakpoint or watchpoint" }, { "dis", _disassemble, "Ii", "Disassemble instructions" }, { "disasm", _disassemble, "Ii", "Disassemble instructions" }, { "disassemble", _disassemble, "Ii", "Disassemble instructions" }, From 01d9c106cb4aeeb42f35562168b155a8ba457ef8 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sat, 6 Oct 2018 21:06:52 -0700 Subject: [PATCH 58/60] Qt: Detect presence of GL_ARB_framebuffer_object --- CHANGES | 1 + src/platform/qt/DisplayGL.cpp | 13 ++++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index b8c91aba5..07a213524 100644 --- a/CHANGES +++ b/CHANGES @@ -131,6 +131,7 @@ Misc: - Libretro: Reduce rumble callbacks - Debugger: Minor text fixes - Qt: Debugger console history + - Qt: Detect presence of GL_ARB_framebuffer_object 0.7 beta 1: (2018-09-24) - Initial beta for 0.7 diff --git a/src/platform/qt/DisplayGL.cpp b/src/platform/qt/DisplayGL.cpp index 223829432..a07da6c7f 100644 --- a/src/platform/qt/DisplayGL.cpp +++ b/src/platform/qt/DisplayGL.cpp @@ -193,8 +193,15 @@ PainterGL::PainterGL(int majorVersion, QGLWidget* parent) mGLES2Context* gl2Backend; #endif + m_gl->makeCurrent(); +#if defined(_WIN32) && defined(USE_EPOXY) + epoxy_handle_external_wglMakeCurrent(); +#endif + + QStringList extensions = QString(reinterpret_cast(glGetString(GL_EXTENSIONS))).split(' '); + #if !defined(_WIN32) || defined(USE_EPOXY) - if (majorVersion >= 2) { + if (extensions.contains("GL_ARB_framebuffer_object") && majorVersion >= 2) { gl2Backend = static_cast(malloc(sizeof(mGLES2Context))); mGLES2ContextCreate(gl2Backend); m_backend = &gl2Backend->d; @@ -215,10 +222,6 @@ PainterGL::PainterGL(int majorVersion, QGLWidget* parent) painter->m_gl->swapBuffers(); }; - m_gl->makeCurrent(); -#if defined(_WIN32) && defined(USE_EPOXY) - epoxy_handle_external_wglMakeCurrent(); -#endif m_backend->init(m_backend, reinterpret_cast(m_gl->winId())); #if !defined(_WIN32) || defined(USE_EPOXY) if (m_supportsShaders) { From f6a4a13b60ae30fa74ee33422e2d951b6c0a3348 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 7 Oct 2018 12:51:01 -0700 Subject: [PATCH 59/60] GBA: All IRQs have 7 cycle delay (fixes #539, #1208) --- CHANGES | 4 ++ include/mgba/internal/gba/gba.h | 4 +- include/mgba/internal/gba/serialize.h | 20 ++++++---- include/mgba/internal/gba/timer.h | 2 - src/arm/arm.c | 1 + src/gba/gba.c | 56 +++++++++++++-------------- src/gba/io.c | 20 +++++----- src/gba/serialize.c | 11 +++++- src/gba/timer.c | 54 +------------------------- 9 files changed, 67 insertions(+), 105 deletions(-) diff --git a/CHANGES b/CHANGES index 07a213524..5e922cdf6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,7 @@ +0.8.0: (Future) +Bugfixes: + - GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208) + 0.7.0: (Future) Features: - ELF support diff --git a/include/mgba/internal/gba/gba.h b/include/mgba/internal/gba/gba.h index 8796f113e..4bd899fe6 100644 --- a/include/mgba/internal/gba/gba.h +++ b/include/mgba/internal/gba/gba.h @@ -82,6 +82,8 @@ struct GBA { struct GBATimer timers[4]; int springIRQ; + struct mTimingEvent irqEvent; + uint32_t biosChecksum; int* keySource; struct mRotationSource* rotationSource; @@ -141,8 +143,6 @@ void GBADestroy(struct GBA* gba); void GBAReset(struct ARMCore* cpu); void GBASkipBIOS(struct GBA* gba); -void GBAWriteIE(struct GBA* gba, uint16_t value); -void GBAWriteIME(struct GBA* gba, uint16_t value); void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq); void GBATestIRQ(struct ARMCore* cpu); void GBAHalt(struct GBA* gba); diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 0e2656fa3..b95a07a1f 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -98,28 +98,28 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * | 0x00202 - 0x00203: Old reload value * | 0x00204 - 0x00207: Last event * | 0x00208 - 0x0020B: Next event - * | 0x0020C - 0x0020F: Next IRQ + * | 0x0020C - 0x0020F: Reserved * | 0x00210 - 0x00213: Miscellaneous flags * 0x00214 - 0x00227: Timer 1 * | 0x00214 - 0x00215: Reload value * | 0x00216 - 0x00217: Old reload value * | 0x00218 - 0x0021B: Last event * | 0x0021C - 0x0021F: Next event - * | 0x00220 - 0x00223: Next IRQ + * | 0x00220 - 0x00223: Reserved * | 0x00224 - 0x00227: Miscellaneous flags * 0x00228 - 0x0023B: Timer 2 * | 0x00228 - 0x00229: Reload value * | 0x0022A - 0x0022B: Old reload value * | 0x0022C - 0x0022F: Last event * | 0x00230 - 0x00233: Next event - * | 0x00234 - 0x00237: Next IRQ + * | 0x00234 - 0x00237: Reserved * | 0x00238 - 0x0023B: Miscellaneous flags * 0x0023C - 0x00250: Timer 3 * | 0x0023C - 0x0023D: Reload value * | 0x0023E - 0x0023F: Old reload value * | 0x00240 - 0x00243: Last event * | 0x00244 - 0x00247: Next event - * | 0x00248 - 0x0024B: Next IRQ + * | 0x00248 - 0x0024B: Reserved * | 0x0024C - 0x0024F: Miscellaneous flags * 0x00250 - 0x0025F: DMA 0 * | 0x00250 - 0x00253: DMA next source @@ -196,7 +196,9 @@ mLOG_DECLARE_CATEGORY(GBA_STATE); * 0x0031C - 0x0031F: Miscellaneous flags * | bit 0: Is CPU halted? * | bit 1: POSTFLG - * 0x00320 - 0x003FF: Reserved (leave zero) + * | bit 2: Is IRQ pending? + * 0x00320 - 0x00323: Next IRQ event + * 0x00324 - 0x003FF: Reserved (leave zero) * 0x00400 - 0x007FF: I/O memory * 0x00800 - 0x00BFF: Palette * 0x00C00 - 0x00FFF: OAM @@ -227,6 +229,7 @@ DECL_BIT(GBASerializedSavedataFlags, DustSettling, 5); DECL_BITFIELD(GBASerializedMiscFlags, uint32_t); DECL_BIT(GBASerializedMiscFlags, Halted, 0); DECL_BIT(GBASerializedMiscFlags, POSTFLG, 1); +DECL_BIT(GBASerializedMiscFlags, IrqPending, 2); struct GBASerializedState { uint32_t versionMagic; @@ -267,10 +270,10 @@ struct GBASerializedState { struct { uint16_t reload; - uint16_t reserved; + uint16_t reserved0; uint32_t lastEvent; uint32_t nextEvent; - uint32_t nextIrq; + uint32_t reserved1; GBATimerFlags flags; } timers[4]; @@ -320,8 +323,9 @@ struct GBASerializedState { uint32_t lastPrefetchedPc; GBASerializedMiscFlags miscFlags; + uint32_t nextIrq; - uint32_t reserved[56]; + uint32_t reserved[55]; uint16_t io[SIZE_IO >> 1]; uint16_t pram[SIZE_PALETTE_RAM >> 1]; diff --git a/include/mgba/internal/gba/timer.h b/include/mgba/internal/gba/timer.h index 2a4234123..664842e6b 100644 --- a/include/mgba/internal/gba/timer.h +++ b/include/mgba/internal/gba/timer.h @@ -17,14 +17,12 @@ DECL_BITS(GBATimerFlags, PrescaleBits, 0, 4); DECL_BIT(GBATimerFlags, CountUp, 4); DECL_BIT(GBATimerFlags, DoIrq, 5); DECL_BIT(GBATimerFlags, Enable, 6); -DECL_BIT(GBATimerFlags, IrqPending, 7); struct GBA; struct GBATimer { uint16_t reload; int32_t lastEvent; struct mTimingEvent event; - struct mTimingEvent irq; GBATimerFlags flags; }; diff --git a/src/arm/arm.c b/src/arm/arm.c index 618f34750..d0325dc05 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -167,6 +167,7 @@ void ARMRaiseIRQ(struct ARMCore* cpu) { cpu->spsr = cpsr; cpu->cpsr.i = 1; cpu->cycles += currentCycles; + cpu->halted = 0; } void ARMRaiseSWI(struct ARMCore* cpu) { diff --git a/src/gba/gba.c b/src/gba/gba.c index 057957161..eab779158 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -25,6 +25,8 @@ #include #endif +#define GBA_IRQ_DELAY 7 + mLOG_DEFINE_CATEGORY(GBA, "GBA", "gba"); mLOG_DEFINE_CATEGORY(GBA_DEBUG, "GBA Debug", "gba.debug"); @@ -45,6 +47,8 @@ static void GBAHitStub(struct ARMCore* cpu, uint32_t opcode); static void GBAIllegal(struct ARMCore* cpu, uint32_t opcode); static void GBABreakpoint(struct ARMCore* cpu, int immediate); +static void _triggerIRQ(struct mTiming*, void* user, uint32_t cyclesLate); + #ifdef USE_DEBUGGERS static bool _setSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t* opcode); static bool _clearSoftwareBreakpoint(struct ARMDebugger*, uint32_t address, enum ExecutionMode mode, uint32_t opcode); @@ -86,7 +90,6 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) { GBAHardwareInit(&gba->memory.hw, NULL); - gba->springIRQ = 0; gba->keySource = 0; gba->rotationSource = 0; gba->luminanceSource = 0; @@ -116,6 +119,11 @@ static void GBAInit(void* cpu, struct mCPUComponent* component) { gba->yankedRomSize = 0; mTimingInit(&gba->timing, &gba->cpu->cycles, &gba->cpu->nextEvent); + + gba->irqEvent.name = "GBA IRQ Event"; + gba->irqEvent.callback = _triggerIRQ; + gba->irqEvent.context = gba; + gba->irqEvent.priority = 0; } void GBAUnloadROM(struct GBA* gba) { @@ -247,11 +255,6 @@ static void GBAProcessEvents(struct ARMCore* cpu) { gba->bus |= cpu->prefetch[1] << 16; } - if (gba->springIRQ && !cpu->cpsr.i) { - ARMRaiseIRQ(cpu); - gba->springIRQ = 0; - } - int32_t nextEvent = cpu->nextEvent; while (cpu->cycles >= nextEvent) { cpu->nextEvent = INT_MAX; @@ -474,34 +477,17 @@ void GBAApplyPatch(struct GBA* gba, struct Patch* patch) { gba->romCrc32 = doCrc32(gba->memory.rom, gba->memory.romSize); } -void GBAWriteIE(struct GBA* gba, uint16_t value) { - if (gba->memory.io[REG_IME >> 1] && value & gba->memory.io[REG_IF >> 1]) { - ARMRaiseIRQ(gba->cpu); - } -} - -void GBAWriteIME(struct GBA* gba, uint16_t value) { - if (value && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { - ARMRaiseIRQ(gba->cpu); - } -} - void GBARaiseIRQ(struct GBA* gba, enum GBAIRQ irq) { gba->memory.io[REG_IF >> 1] |= 1 << irq; - - if (gba->memory.io[REG_IE >> 1] & 1 << irq) { - gba->cpu->halted = 0; - if (gba->memory.io[REG_IME >> 1]) { - ARMRaiseIRQ(gba->cpu); - } - } + GBATestIRQ(gba->cpu); } void GBATestIRQ(struct ARMCore* cpu) { struct GBA* gba = (struct GBA*) cpu->master; - if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { - gba->springIRQ = gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]; - gba->cpu->nextEvent = gba->cpu->cycles; + if (gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { + if (!mTimingIsScheduled(&gba->timing, &gba->irqEvent)) { + mTimingSchedule(&gba->timing, &gba->irqEvent, GBA_IRQ_DELAY); + } } } @@ -857,6 +843,20 @@ void GBATestKeypadIRQ(struct GBA* gba) { } } +static void _triggerIRQ(struct mTiming* timing, void* user, uint32_t cyclesLate) { + UNUSED(timing); + UNUSED(cyclesLate); + struct GBA* gba = user; + gba->cpu->halted = 0; + if (!(gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1])) { + return; + } + + if (gba->memory.io[REG_IME >> 1] && !gba->cpu->cpsr.i) { + ARMRaiseIRQ(gba->cpu); + } +} + void GBASetBreakpoint(struct GBA* gba, struct mCPUComponent* component, uint32_t address, enum ExecutionMode mode, uint32_t* opcode) { size_t immediate; for (immediate = 0; immediate < gba->cpu->numComponents; ++immediate) { diff --git a/src/gba/io.c b/src/gba/io.c index 7621c887c..a4dd110f9 100644 --- a/src/gba/io.c +++ b/src/gba/io.c @@ -547,15 +547,18 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) { GBAAdjustWaitstates(gba, value); break; case REG_IE: - GBAWriteIE(gba, value); - break; + gba->memory.io[REG_IE >> 1] = value; + GBATestIRQ(gba->cpu); + return; case REG_IF: - gba->springIRQ &= ~value; value = gba->memory.io[REG_IF >> 1] & ~value; - break; + gba->memory.io[REG_IF >> 1] = value; + GBATestIRQ(gba->cpu); + return; case REG_IME: - GBAWriteIME(gba, value); - break; + gba->memory.io[REG_IME >> 1] = value; + GBATestIRQ(gba->cpu); + return; case REG_MAX: // Some bad interrupt libraries will write to this break; @@ -931,7 +934,6 @@ void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) { STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload); STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent); STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent); - STORE_32(gba->timers[i].irq.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextIrq); STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags); STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource); STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest); @@ -971,10 +973,6 @@ void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) { if (GBATimerFlagsIsEnable(gba->timers[i].flags)) { mTimingSchedule(&gba->timing, &gba->timers[i].event, when); } - LOAD_32(when, 0, &state->timers[i].nextIrq); - if (GBATimerFlagsIsIrqPending(gba->timers[i].flags)) { - mTimingSchedule(&gba->timing, &gba->timers[i].irq, when); - } LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io); LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource); diff --git a/src/gba/serialize.c b/src/gba/serialize.c index 72cdd453f..458ba3d3a 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -15,7 +15,7 @@ #include const uint32_t GBA_SAVESTATE_MAGIC = 0x01000000; -const uint32_t GBA_SAVESTATE_VERSION = 0x00000002; +const uint32_t GBA_SAVESTATE_VERSION = 0x00000003; mLOG_DEFINE_CATEGORY(GBA_STATE, "GBA Savestate", "gba.serialize"); @@ -62,6 +62,10 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) { GBASerializedMiscFlags miscFlags = 0; miscFlags = GBASerializedMiscFlagsSetHalted(miscFlags, gba->cpu->halted); miscFlags = GBASerializedMiscFlagsSetPOSTFLG(miscFlags, gba->memory.io[REG_POSTFLG >> 1] & 1); + if (mTimingIsScheduled(&gba->timing, &gba->irqEvent)) { + miscFlags = GBASerializedMiscFlagsFillIrqPending(miscFlags); + STORE_32(gba->irqEvent.when - mTimingCurrentTime(&gba->timing), 0, &state->nextIrq); + } STORE_32(miscFlags, 0, &state->miscFlags); GBAMemorySerialize(&gba->memory, state); @@ -179,6 +183,11 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { LOAD_32(miscFlags, 0, &state->miscFlags); gba->cpu->halted = GBASerializedMiscFlagsGetHalted(miscFlags); gba->memory.io[REG_POSTFLG >> 1] = GBASerializedMiscFlagsGetPOSTFLG(miscFlags); + if (GBASerializedMiscFlagsIsIrqPending(miscFlags)) { + int32_t when; + LOAD_32(when, 0, &state->nextIrq); + mTimingSchedule(&gba->timing, &gba->irqEvent, when); + } GBAVideoDeserialize(&gba->video, state); GBAMemoryDeserialize(&gba->memory, state); diff --git a/src/gba/timer.c b/src/gba/timer.c index ac17266e9..c0a6fb81d 100644 --- a/src/gba/timer.c +++ b/src/gba/timer.c @@ -8,44 +8,11 @@ #include #include -#define TIMER_IRQ_DELAY 7 #define TIMER_RELOAD_DELAY 0 #define TIMER_STARTUP_DELAY 2 #define REG_TMCNT_LO(X) (REG_TM0CNT_LO + ((X) << 2)) -static void GBATimerIrq(struct GBA* gba, int timerId) { - struct GBATimer* timer = &gba->timers[timerId]; - if (GBATimerFlagsIsIrqPending(timer->flags)) { - timer->flags = GBATimerFlagsClearIrqPending(timer->flags); - GBARaiseIRQ(gba, IRQ_TIMER0 + timerId); - } -} - -static void GBATimerIrq0(struct mTiming* timing, void* context, uint32_t cyclesLate) { - UNUSED(timing); - UNUSED(cyclesLate); - GBATimerIrq(context, 0); -} - -static void GBATimerIrq1(struct mTiming* timing, void* context, uint32_t cyclesLate) { - UNUSED(timing); - UNUSED(cyclesLate); - GBATimerIrq(context, 1); -} - -static void GBATimerIrq2(struct mTiming* timing, void* context, uint32_t cyclesLate) { - UNUSED(timing); - UNUSED(cyclesLate); - GBATimerIrq(context, 2); -} - -static void GBATimerIrq3(struct mTiming* timing, void* context, uint32_t cyclesLate) { - UNUSED(timing); - UNUSED(cyclesLate); - GBATimerIrq(context, 3); -} - static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) { struct GBATimer* timer = &gba->timers[timerId]; if (GBATimerFlagsIsCountUp(timer->flags)) { @@ -55,10 +22,7 @@ static void GBATimerUpdate(struct GBA* gba, int timerId, uint32_t cyclesLate) { } if (GBATimerFlagsIsDoIrq(timer->flags)) { - timer->flags = GBATimerFlagsFillIrqPending(timer->flags); - if (!mTimingIsScheduled(&gba->timing, &timer->irq)) { - mTimingSchedule(&gba->timing, &timer->irq, TIMER_IRQ_DELAY - cyclesLate); - } + GBARaiseIRQ(gba, IRQ_TIMER0 + timerId); } if (gba->audio.enable && timerId < 2) { @@ -120,22 +84,6 @@ void GBATimerInit(struct GBA* gba) { gba->timers[3].event.callback = GBATimerUpdate3; gba->timers[3].event.context = gba; gba->timers[3].event.priority = 0x23; - gba->timers[0].irq.name = "GBA Timer 0 IRQ"; - gba->timers[0].irq.callback = GBATimerIrq0; - gba->timers[0].irq.context = gba; - gba->timers[0].irq.priority = 0x28; - gba->timers[1].irq.name = "GBA Timer 1 IRQ"; - gba->timers[1].irq.callback = GBATimerIrq1; - gba->timers[1].irq.context = gba; - gba->timers[1].irq.priority = 0x29; - gba->timers[2].irq.name = "GBA Timer 2 IRQ"; - gba->timers[2].irq.callback = GBATimerIrq2; - gba->timers[2].irq.context = gba; - gba->timers[2].irq.priority = 0x2A; - gba->timers[3].irq.name = "GBA Timer 3 IRQ"; - gba->timers[3].irq.callback = GBATimerIrq3; - gba->timers[3].irq.context = gba; - gba->timers[3].irq.priority = 0x2B; } void GBATimerUpdateRegister(struct GBA* gba, int timer, int32_t cyclesLate) { From 946ae038cc15cbf5656a396ad59d0bc055eec1aa Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Sun, 7 Oct 2018 14:28:00 -0700 Subject: [PATCH 60/60] CMake: Bump version --- version.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.cmake b/version.cmake index 53120ef5e..de381293f 100644 --- a/version.cmake +++ b/version.cmake @@ -2,9 +2,9 @@ if(NOT PROJECT_NAME) set(PROJECT_NAME "mGBA") endif() set(LIB_VERSION_MAJOR 0) -set(LIB_VERSION_MINOR 7) +set(LIB_VERSION_MINOR 8) set(LIB_VERSION_PATCH 0) -set(LIB_VERSION_ABI 0.7) +set(LIB_VERSION_ABI 0.8) set(LIB_VERSION_STRING ${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}) set(SUMMARY "${PROJECT_NAME} Game Boy Advance Emulator")