From 6e01765ed2e9f6101aee54d9113cc42b320de305 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 26 Aug 2020 03:39:34 -0700 Subject: [PATCH 01/10] Qt: Add another static dependency on Windows --- src/platform/qt/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index cba2de1d7..a57a1c316 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -300,7 +300,7 @@ if(QT_STATIC) if(CMAKE_CROSSCOMPILING) set(QWINDOWS_DEPS Qt5EventDispatcherSupport Qt5FontDatabaseSupport Qt5ThemeSupport Qt5WindowsUIAutomationSupport) endif() - list(APPEND QT_LIBRARIES Qt5::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} dwmapi uxtheme imm32 -static-libgcc -static-libstdc++) + list(APPEND QT_LIBRARIES Qt5::QWindowsIntegrationPlugin ${QWINDOWS_DEPS} amstrmid dwmapi uxtheme imm32 -static-libgcc -static-libstdc++) set_target_properties(Qt5::Core PROPERTIES INTERFACE_LINK_LIBRARIES "${QTPCRE};version;winmm;ssl;crypto;ws2_32;iphlpapi;crypt32;userenv;netapi32;wtsapi32") set_target_properties(Qt5::Gui PROPERTIES INTERFACE_LINK_LIBRARIES ${OPENGL_LIBRARY} ${OPENGLES2_LIBRARY}) elseif(APPLE) From 65fb61d7e2f5848aac38a12d4042419bb4e537c9 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 27 Aug 2020 04:27:13 -0700 Subject: [PATCH 02/10] GBA Memory: Improve robustness of Matrix memory support --- CHANGES | 1 + include/mgba/internal/gba/matrix.h | 9 +++- include/mgba/internal/gba/serialize.h | 11 ++++- src/gba/matrix.c | 71 ++++++++++++++++++++++++--- src/gba/serialize.c | 8 +++ 5 files changed, 90 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 43f7883ec..bfb5e1e2b 100644 --- a/CHANGES +++ b/CHANGES @@ -33,6 +33,7 @@ Emulation fixes: - GBA Hardware: Fix GB Player detection on big endian platforms - GBA Memory: Improve gamepak prefetch timing - GBA Memory: Stall on VRAM access in mode 2 (fixes mgba.io/i/190) + - GBA Memory: Improve robustness of Matrix memory support - GBA SIO: Fix copying Normal mode transfer values - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA SIO: Fix deseralizing SIO registers diff --git a/include/mgba/internal/gba/matrix.h b/include/mgba/internal/gba/matrix.h index cc4191c8b..27e32a75c 100644 --- a/include/mgba/internal/gba/matrix.h +++ b/include/mgba/internal/gba/matrix.h @@ -10,19 +10,26 @@ CXX_GUARD_START +#define GBA_MATRIX_MAPPINGS_MAX 16 + struct GBAMatrix { uint32_t cmd; uint32_t paddr; uint32_t vaddr; uint32_t size; + + uint32_t mappings[GBA_MATRIX_MAPPINGS_MAX]; }; struct GBA; -struct GBAMemory; void GBAMatrixReset(struct GBA*); void GBAMatrixWrite(struct GBA*, uint32_t address, uint32_t value); void GBAMatrixWrite16(struct GBA*, uint32_t address, uint16_t value); +struct GBASerializedState; +void GBAMatrixSerialize(const struct GBA* memory, struct GBASerializedState* state); +void GBAMatrixDeserialize(struct GBA* memory, const struct GBASerializedState* state); + CXX_GUARD_END #endif diff --git a/include/mgba/internal/gba/serialize.h b/include/mgba/internal/gba/serialize.h index 2b372e51d..cc46c47af 100644 --- a/include/mgba/internal/gba/serialize.h +++ b/include/mgba/internal/gba/serialize.h @@ -331,7 +331,12 @@ struct GBASerializedState { uint32_t dmaTransferRegister; uint32_t dmaBlockPC; - uint32_t reservedHardware[4]; + struct { + uint32_t cmd; + uint32_t paddr; + uint32_t vaddr; + uint32_t size; + } matrix; struct { uint8_t type; @@ -356,7 +361,9 @@ struct GBASerializedState { uint32_t nextIrq; int32_t biosStall; - uint32_t reserved[54]; + uint32_t matrixMappings[16]; + + uint32_t reserved[38]; uint16_t io[SIZE_IO >> 1]; uint16_t pram[SIZE_PALETTE_RAM >> 1]; diff --git a/src/gba/matrix.c b/src/gba/matrix.c index 5c8fef48a..c9c12ff9a 100644 --- a/src/gba/matrix.c +++ b/src/gba/matrix.c @@ -8,25 +8,42 @@ #include #include #include +#include #include static void _remapMatrix(struct GBA* gba) { + if (gba->memory.matrix.vaddr & 0xFFFFE1FF) { + mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping: %08X", gba->memory.matrix.vaddr); + return; + } + if (gba->memory.matrix.size & 0xFFFFE1FF) { + mLOG(GBA_MEM, ERROR, "Invalid Matrix size: %08X", gba->memory.matrix.size); + return; + } + if ((gba->memory.matrix.vaddr + gba->memory.matrix.size - 1) & 0xFFFFE000) { + mLOG(GBA_MEM, ERROR, "Invalid Matrix mapping end: %08X", gba->memory.matrix.vaddr + gba->memory.matrix.size); + return; + } + int start = (gba->memory.matrix.vaddr >> 9) & 0x1F; + int size = (gba->memory.matrix.size >> 9) & 0x1F; + int i; + for (i = 0; i < size; ++i) { + gba->memory.matrix.mappings[start + i] = gba->memory.matrix.paddr + (i << 9); + } + gba->romVf->seek(gba->romVf, gba->memory.matrix.paddr, SEEK_SET); gba->romVf->read(gba->romVf, &gba->memory.rom[gba->memory.matrix.vaddr >> 2], gba->memory.matrix.size); } void GBAMatrixReset(struct GBA* gba) { - gba->memory.matrix.paddr = 0x200; + memset(gba->memory.matrix.mappings, 0, sizeof(gba->memory.matrix.mappings)); gba->memory.matrix.size = 0x1000; - gba->memory.matrix.vaddr = 0; - _remapMatrix(gba); - gba->memory.matrix.vaddr = 0x1000; - _remapMatrix(gba); - gba->memory.matrix.paddr = 0; gba->memory.matrix.vaddr = 0; - gba->memory.matrix.size = 0x100; + _remapMatrix(gba); + gba->memory.matrix.paddr = 0x200; + gba->memory.matrix.vaddr = 0x1000; _remapMatrix(gba); } @@ -51,6 +68,10 @@ void GBAMatrixWrite(struct GBA* gba, uint32_t address, uint32_t value) { gba->memory.matrix.vaddr = value & 0x007FFFFF; return; case 0xC: + if (value == 0) { + mLOG(GBA_MEM, ERROR, "Rejecting Matrix write for size 0"); + return; + } gba->memory.matrix.size = value << 9; return; } @@ -73,3 +94,39 @@ void GBAMatrixWrite16(struct GBA* gba, uint32_t address, uint16_t value) { break; } } + +void GBAMatrixSerialize(const struct GBA* gba, struct GBASerializedState* state) { + STORE_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd); + STORE_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr); + STORE_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr); + STORE_32(gba->memory.matrix.size, 0, &state->matrix.size); + + if (GBA_MATRIX_MAPPINGS_MAX != 16) { + mLOG(GBA_MEM, ERROR, "Matrix memory serialization is broken!"); + } + + int i; + for (i = 0; i < 16; ++i) { + STORE_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings); + } +} + +void GBAMatrixDeserialize(struct GBA* gba, const struct GBASerializedState* state) { + if (GBA_MATRIX_MAPPINGS_MAX != 16) { + mLOG(GBA_MEM, ERROR, "Matrix memory deserialization is broken!"); + } + gba->memory.matrix.size = 0x200; + + int i; + for (i = 0; i < 16; ++i) { + LOAD_32(gba->memory.matrix.mappings[i], i << 2, state->matrixMappings); + gba->memory.matrix.paddr = gba->memory.matrix.mappings[i]; + gba->memory.matrix.vaddr = i << 9; + _remapMatrix(gba); + } + + LOAD_32(gba->memory.matrix.cmd, 0, &state->matrix.cmd); + LOAD_32(gba->memory.matrix.paddr, 0, &state->matrix.paddr); + LOAD_32(gba->memory.matrix.vaddr, 0, &state->matrix.vaddr); + LOAD_32(gba->memory.matrix.size, 0, &state->matrix.size); +} diff --git a/src/gba/serialize.c b/src/gba/serialize.c index fe4e15bef..0e3c43f8c 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -76,6 +76,10 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) { GBAVideoSerialize(&gba->video, state); GBAAudioSerialize(&gba->audio, state); GBASavedataSerialize(&gba->memory.savedata, state); + + if (gba->memory.matrix.size) { + GBAMatrixSerialize(gba, state); + } } bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { @@ -196,6 +200,10 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { GBAAudioDeserialize(&gba->audio, state); GBASavedataDeserialize(&gba->memory.savedata, state); + if (gba->memory.matrix.size) { + GBAMatrixDeserialize(gba, state); + } + gba->timing.reroot = gba->timing.root; gba->timing.root = NULL; From f5a1ceb0252ca4c92f19c000b0039bb82f4e62d3 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Aug 2020 00:53:40 -0700 Subject: [PATCH 03/10] Core: Add savedataUpdated callback --- include/mgba/core/interface.h | 1 + src/gb/gb.c | 8 ++++++++ src/gba/gba.c | 4 ++++ src/gba/savedata.c | 6 ++---- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/include/mgba/core/interface.h b/include/mgba/core/interface.h index c20816dbd..1d19c6e79 100644 --- a/include/mgba/core/interface.h +++ b/include/mgba/core/interface.h @@ -91,6 +91,7 @@ struct mCoreCallbacks { void (*coreCrashed)(void* context); void (*sleep)(void* context); void (*keysRead)(void* context); + void (*savedataUpdated)(void* context); }; DECLARE_VECTOR(mCoreCallbacksList, struct mCoreCallbacks); diff --git a/src/gb/gb.c b/src/gb/gb.c index 7aea9eaad..4cd61eca7 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -247,6 +247,14 @@ void GBSramClean(struct GB* gb, uint32_t frameCount) { } else { mLOG(GB_MEM, INFO, "Savedata failed to sync!"); } + + size_t c; + for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) { + struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c); + if (callbacks->savedataUpdated) { + callbacks->savedataUpdated(callbacks->context); + } + } } } diff --git a/src/gba/gba.c b/src/gba/gba.c index 18ae17222..693a583b5 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -816,6 +816,7 @@ void GBAFrameStarted(struct GBA* gba) { } void GBAFrameEnded(struct GBA* gba) { + int wasDirty = gba->memory.savedata.dirty; GBASavedataClean(&gba->memory.savedata, gba->video.frameCounter); if (gba->cpu->components && gba->cpu->components[CPU_COMPONENT_CHEAT_DEVICE]) { @@ -846,6 +847,9 @@ void GBAFrameEnded(struct GBA* gba) { if (callbacks->videoFrameEnded) { callbacks->videoFrameEnded(callbacks->context); } + if (callbacks->savedataUpdated && wasDirty && !gba->memory.savedata.dirty) { + callbacks->savedataUpdated(callbacks->context); + } } } diff --git a/src/gba/savedata.c b/src/gba/savedata.c index 39a805725..1ae924a9f 100644 --- a/src/gba/savedata.c +++ b/src/gba/savedata.c @@ -534,16 +534,14 @@ void GBASavedataClean(struct GBASavedata* savedata, uint32_t frameCount) { if (savedata->dirty & SAVEDATA_DIRT_NEW) { savedata->dirtAge = frameCount; savedata->dirty &= ~SAVEDATA_DIRT_NEW; - if (!(savedata->dirty & SAVEDATA_DIRT_SEEN)) { - savedata->dirty |= SAVEDATA_DIRT_SEEN; - } + savedata->dirty |= SAVEDATA_DIRT_SEEN; } else if ((savedata->dirty & SAVEDATA_DIRT_SEEN) && frameCount - savedata->dirtAge > CLEANUP_THRESHOLD) { if (savedata->maskWriteback) { GBASavedataUnmask(savedata); } + savedata->dirty = 0; if (savedata->mapMode & MAP_WRITE) { size_t size = GBASavedataSize(savedata); - savedata->dirty = 0; if (savedata->data && savedata->vf->sync(savedata->vf, savedata->data, size)) { mLOG(GBA_SAVE, INFO, "Savedata synced"); } else { From ddc913c13adc507bd78098ffd669332f29d13a64 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Aug 2020 01:49:07 -0700 Subject: [PATCH 04/10] Qt: Refactor GB names and lists into namespace --- src/platform/qt/CMakeLists.txt | 3 +- src/platform/qt/GameBoy.cpp | 94 ++++++++++++++++++++++++++ src/platform/qt/GameBoy.h | 25 +++++++ src/platform/qt/OverrideView.cpp | 78 ++++++++++------------ src/platform/qt/OverrideView.h | 3 - src/platform/qt/OverrideView.ui | 110 ------------------------------- src/platform/qt/SettingsView.cpp | 47 +++++++------ src/platform/qt/SettingsView.h | 1 - src/platform/qt/SettingsView.ui | 60 ----------------- 9 files changed, 183 insertions(+), 238 deletions(-) create mode 100644 src/platform/qt/GameBoy.cpp create mode 100644 src/platform/qt/GameBoy.h diff --git a/src/platform/qt/CMakeLists.txt b/src/platform/qt/CMakeLists.txt index a57a1c316..aacd13a50 100644 --- a/src/platform/qt/CMakeLists.txt +++ b/src/platform/qt/CMakeLists.txt @@ -16,7 +16,7 @@ if(BUILD_SDL) endif() if(POLICY CMP0071) - cmake_policy(SET CMP0071 OLD) + cmake_policy(SET CMP0071 NEW) endif() set(CMAKE_AUTOMOC ON) @@ -154,6 +154,7 @@ set(GBA_SRC GBAOverride.cpp) set(GB_SRC + GameBoy.cpp GBOverride.cpp PrinterView.cpp) diff --git a/src/platform/qt/GameBoy.cpp b/src/platform/qt/GameBoy.cpp new file mode 100644 index 000000000..63f26f1c1 --- /dev/null +++ b/src/platform/qt/GameBoy.cpp @@ -0,0 +1,94 @@ +/* Copyright (c) 2013-2020 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "GameBoy.h" + +#include +#include + +using namespace QGBA; + +static const QList s_gbModelList{ + GB_MODEL_DMG, + GB_MODEL_SGB, + GB_MODEL_CGB, + GB_MODEL_AGB, +}; + +static const QList s_mbcList{ + GB_MBC_NONE, + GB_MBC1, + GB_MBC2, + GB_MBC3, + GB_MBC3_RTC, + GB_MBC5, + GB_MBC5_RUMBLE, + GB_MBC6, + GB_MBC7, + GB_MMM01, + GB_POCKETCAM, + GB_TAMA5, + GB_HuC1, + GB_HuC3, + GB_UNL_WISDOM_TREE, + GB_UNL_BBD, + GB_UNL_HITEK, + GB_UNL_PKJD, +}; + +static QMap s_gbModelNames; +static QMap s_mbcNames; + +static QString tr(const char* str) { + return QCoreApplication::translate("Game Boy", str); +} + +QList GameBoy::modelList() { + return s_gbModelList; +} + +QString GameBoy::modelName(GBModel model) { + if (s_gbModelNames.isEmpty()) { + s_gbModelNames[GB_MODEL_AUTODETECT] = tr("Autodetect"); + s_gbModelNames[GB_MODEL_DMG] = tr("Game Boy (DMG)"); + s_gbModelNames[GB_MODEL_MGB] = tr("Game Boy Pocket (MGB)"); + s_gbModelNames[GB_MODEL_SGB] = tr("Super Game Boy (SGB)"); + s_gbModelNames[GB_MODEL_SGB2] = tr("Super Game Boy 2 (SGB)"); + s_gbModelNames[GB_MODEL_CGB] = tr("Game Boy Color (CGB)"); + s_gbModelNames[GB_MODEL_AGB] = tr("Game Boy Advance (AGB)"); + } + + return s_gbModelNames[model]; +} + +QList GameBoy::mbcList() { + return s_mbcList; +} + +QString GameBoy::mbcName(GBMemoryBankControllerType mbc) { + if (s_mbcNames.isEmpty()) { + s_mbcNames[GB_MBC_AUTODETECT] = tr("Autodetect"); + s_mbcNames[GB_MBC_NONE] = tr("ROM Only"); + s_mbcNames[GB_MBC1] = tr("MBC1"); + s_mbcNames[GB_MBC2] = tr("MBC2"); + s_mbcNames[GB_MBC3] = tr("MBC3"); + s_mbcNames[GB_MBC3_RTC] = tr("MBC3 + RTC"); + s_mbcNames[GB_MBC5] = tr("MBC5"); + s_mbcNames[GB_MBC5_RUMBLE] = tr("MBC5 + Rumble"); + s_mbcNames[GB_MBC6] = tr("MBC6"); + s_mbcNames[GB_MBC7] = tr("MBC7 (Tilt)"); + s_mbcNames[GB_MMM01] = tr("MMM01"); + s_mbcNames[GB_HuC1] = tr("HuC-1"); + s_mbcNames[GB_HuC3] = tr("HuC-3"); + s_mbcNames[GB_POCKETCAM] = tr("Pocket Cam"); + s_mbcNames[GB_TAMA5] = tr("TAMA5"); + s_mbcNames[GB_UNL_WISDOM_TREE] = tr("Wisdom Tree"); + s_mbcNames[GB_UNL_PKJD] = tr("Pokémon Jade/Diamond"); + s_mbcNames[GB_UNL_BBD] = tr("BBD"); + s_mbcNames[GB_UNL_HITEK] = tr("Hitek"); + } + + return s_mbcNames[mbc]; +} diff --git a/src/platform/qt/GameBoy.h b/src/platform/qt/GameBoy.h new file mode 100644 index 000000000..bdb31533f --- /dev/null +++ b/src/platform/qt/GameBoy.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2013-2020 Jeffrey Pfau + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#pragma once + +#include +#include + +#ifdef M_CORE_GB +#include + +namespace QGBA { + +namespace GameBoy { + QList modelList(); + QString modelName(GBModel); + + QList mbcList(); + QString mbcName(GBMemoryBankControllerType); +} + +} +#endif diff --git a/src/platform/qt/OverrideView.cpp b/src/platform/qt/OverrideView.cpp index b045caecb..d3c5b7654 100644 --- a/src/platform/qt/OverrideView.cpp +++ b/src/platform/qt/OverrideView.cpp @@ -6,6 +6,7 @@ #include "OverrideView.h" #include +#include #include "ConfigController.h" #include "CoreController.h" @@ -16,53 +17,17 @@ #endif #ifdef M_CORE_GB +#include "GameBoy.h" #include "GBOverride.h" #include #endif using namespace QGBA; -#ifdef M_CORE_GB -QList OverrideView::s_gbModelList; -QList OverrideView::s_mbcList; -#endif - OverrideView::OverrideView(ConfigController* config, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) , m_config(config) { -#ifdef M_CORE_GB - if (s_mbcList.isEmpty()) { - // NB: Keep in sync with OverrideView.ui - s_mbcList.append(GB_MBC_AUTODETECT); - s_mbcList.append(GB_MBC_NONE); - s_mbcList.append(GB_MBC1); - s_mbcList.append(GB_MBC2); - s_mbcList.append(GB_MBC3); - s_mbcList.append(GB_MBC3_RTC); - s_mbcList.append(GB_MBC5); - s_mbcList.append(GB_MBC5_RUMBLE); - s_mbcList.append(GB_MBC6); - s_mbcList.append(GB_MBC7); - s_mbcList.append(GB_MMM01); - s_mbcList.append(GB_POCKETCAM); - s_mbcList.append(GB_TAMA5); - s_mbcList.append(GB_HuC1); - s_mbcList.append(GB_HuC3); - s_mbcList.append(GB_UNL_WISDOM_TREE); - s_mbcList.append(GB_UNL_BBD); - s_mbcList.append(GB_UNL_HITEK); - s_mbcList.append(GB_UNL_PKJD); - } - if (s_gbModelList.isEmpty()) { - // NB: Keep in sync with OverrideView.ui - s_gbModelList.append(GB_MODEL_AUTODETECT); - s_gbModelList.append(GB_MODEL_DMG); - s_gbModelList.append(GB_MODEL_SGB); - s_gbModelList.append(GB_MODEL_CGB); - s_gbModelList.append(GB_MODEL_AGB); - } -#endif m_ui.setupUi(this); connect(m_ui.hwAutodetect, &QAbstractButton::toggled, [this] (bool enabled) { @@ -74,6 +39,33 @@ OverrideView::OverrideView(ConfigController* config, QWidget* parent) }); #ifdef M_CORE_GB + m_ui.gbModel->setItemData(0, GB_MODEL_AUTODETECT); + m_ui.mbc->setItemData(0, GB_MBC_AUTODETECT); + + for (auto model : GameBoy::modelList()) { + m_ui.gbModel->addItem(GameBoy::modelName(model), model); + } + + QStandardItemModel* model = static_cast(m_ui.mbc->model()); + int bitsSeen = 0; + for (auto mbc : GameBoy::mbcList()) { + int mbcValue = static_cast(mbc); + if ((mbcValue & ~bitsSeen) & 0x001) { + m_ui.mbc->addItem(tr("Official MBCs"), -2); + model->item(m_ui.mbc->count() - 1)->setFlags(Qt::NoItemFlags); + } + if ((mbcValue & ~bitsSeen) & 0x010) { + m_ui.mbc->addItem(tr("Licensed MBCs"), -3); + model->item(m_ui.mbc->count() - 1)->setFlags(Qt::NoItemFlags); + } + if ((mbcValue & ~bitsSeen) & 0x200) { + m_ui.mbc->addItem(tr("Unlicensed MBCs"), -4); + model->item(m_ui.mbc->count() - 1)->setFlags(Qt::NoItemFlags); + } + bitsSeen |= mbcValue; + m_ui.mbc->addItem(GameBoy::mbcName(mbc), mbc); + } + m_colorPickers[0] = ColorPicker(m_ui.color0, QColor(0xF8, 0xF8, 0xF8)); m_colorPickers[1] = ColorPicker(m_ui.color1, QColor(0xA8, 0xA8, 0xA8)); m_colorPickers[2] = ColorPicker(m_ui.color2, QColor(0x50, 0x50, 0x50)); @@ -190,8 +182,8 @@ void OverrideView::updateOverrides() { #ifdef M_CORE_GB if (m_ui.tabWidget->currentWidget() == m_ui.tabGB) { std::unique_ptr gb(new GBOverride); - gb->override.mbc = s_mbcList[m_ui.mbc->currentIndex()]; - gb->override.model = s_gbModelList[m_ui.gbModel->currentIndex()]; + gb->override.mbc = static_cast(m_ui.mbc->currentData().toInt()); + gb->override.model = static_cast(m_ui.gbModel->currentData().toInt()); bool hasColor = false; for (int i = 0; i < 12; ++i) { gb->override.gbColors[i] = m_gbColors[i]; @@ -240,13 +232,13 @@ void OverrideView::gameStarted() { case PLATFORM_GB: { m_ui.tabWidget->setCurrentWidget(m_ui.tabGB); GB* gb = static_cast(thread->core->board); - int mbc = s_mbcList.indexOf(gb->memory.mbcType); - if (mbc >= 0) { - m_ui.mbc->setCurrentIndex(mbc); + int index = m_ui.mbc->findData(gb->memory.mbcType); + if (index >= 0) { + m_ui.mbc->setCurrentIndex(index); } else { m_ui.mbc->setCurrentIndex(0); } - int model = s_gbModelList.indexOf(gb->model); + int model = m_ui.gbModel->findData(gb->model); if (model >= 0) { m_ui.gbModel->setCurrentIndex(model); } else { diff --git a/src/platform/qt/OverrideView.h b/src/platform/qt/OverrideView.h index cbface71c..880bc99bd 100644 --- a/src/platform/qt/OverrideView.h +++ b/src/platform/qt/OverrideView.h @@ -55,9 +55,6 @@ private: #ifdef M_CORE_GB uint32_t m_gbColors[12]{}; ColorPicker m_colorPickers[12]; - - static QList s_gbModelList; - static QList s_mbcList; #endif }; diff --git a/src/platform/qt/OverrideView.ui b/src/platform/qt/OverrideView.ui index 28fb357e2..12bd873f3 100644 --- a/src/platform/qt/OverrideView.ui +++ b/src/platform/qt/OverrideView.ui @@ -248,26 +248,6 @@ Autodetect - - - Game Boy (DMG) - - - - - Super Game Boy (SGB) - - - - - Game Boy Color (CGB) - - - - - Game Boy Advance (AGB) - - @@ -284,96 +264,6 @@ Autodetect - - - None - - - - - MBC1 - - - - - MBC2 - - - - - MBC3 - - - - - MBC3 + RTC - - - - - MBC5 - - - - - MBC5 + Rumble - - - - - MBC6 - - - - - MBC7 - - - - - MMM01 - - - - - Pocket Cam - - - - - TAMA5 - - - - - HuC-1 - - - - - HuC-3 - - - - - Wisdom Tree (Unlicensed) - - - - - BBD (Unlicensed) - - - - - Hitek (Unlicensed) - - - - - Pokémon Jade/Diamond (Unlicensed) - - diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index b0416133a..f6d47b165 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -15,16 +15,16 @@ #include "ShaderSelector.h" #include "ShortcutView.h" +#ifdef M_CORE_GB +#include "GameBoy.h" +#endif + #include #include #include using namespace QGBA; -#ifdef M_CORE_GB -QList SettingsView::s_gbModelList; -#endif - SettingsView::SettingsView(ConfigController* controller, InputController* inputController, ShortcutController* shortcutController, LogController* logController, QWidget* parent) : QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint) , m_controller(controller) @@ -33,13 +33,14 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC m_ui.setupUi(this); #ifdef M_CORE_GB - if (s_gbModelList.isEmpty()) { - // NB: Keep in sync with SettingsView.ui - s_gbModelList.append(GB_MODEL_AUTODETECT); - s_gbModelList.append(GB_MODEL_DMG); - s_gbModelList.append(GB_MODEL_SGB); - s_gbModelList.append(GB_MODEL_CGB); - s_gbModelList.append(GB_MODEL_AGB); + m_ui.gbModel->setItemData(0, GB_MODEL_AUTODETECT); + m_ui.sgbModel->setItemData(0, GB_MODEL_AUTODETECT); + m_ui.cgbModel->setItemData(0, GB_MODEL_AUTODETECT); + + for (auto model : GameBoy::modelList()) { + m_ui.gbModel->addItem(GameBoy::modelName(model), model); + m_ui.sgbModel->addItem(GameBoy::modelName(model), model); + m_ui.cgbModel->addItem(GameBoy::modelName(model), model); } #endif @@ -511,14 +512,20 @@ void SettingsView::updateConfig() { m_logModel.logger()->logToStdout(m_ui.logToStdout->isChecked()); #ifdef M_CORE_GB - GBModel modelGB = s_gbModelList[m_ui.gbModel->currentIndex()]; - m_controller->setOption("gb.model", GBModelToName(modelGB)); + QVariant modelGB = m_ui.gbModel->currentData(); + if (modelGB.isValid()) { + m_controller->setOption("gb.model", GBModelToName(static_cast(modelGB.toInt()))); + } - GBModel modelSGB = s_gbModelList[m_ui.sgbModel->currentIndex()]; - m_controller->setOption("sgb.model", GBModelToName(modelSGB)); + QVariant modelSGB = m_ui.sgbModel->currentData(); + if (modelSGB.isValid()) { + m_controller->setOption("sgb.model", GBModelToName(static_cast(modelSGB.toInt()))); + } - GBModel modelCGB = s_gbModelList[m_ui.cgbModel->currentIndex()]; - m_controller->setOption("cgb.model", GBModelToName(modelCGB)); + QVariant modelCGB = m_ui.cgbModel->currentData(); + if (modelCGB.isValid()) { + m_controller->setOption("cgb.model", GBModelToName(static_cast(modelCGB.toInt()))); + } for (int colorId = 0; colorId < 12; ++colorId) { if (!(m_gbColors[colorId] & 0xFF000000)) { @@ -641,21 +648,21 @@ void SettingsView::reloadConfig() { QString modelGB = m_controller->getOption("gb.model"); if (!modelGB.isNull()) { GBModel model = GBNameToModel(modelGB.toUtf8().constData()); - int index = s_gbModelList.indexOf(model); + int index = m_ui.gbModel->findData(model); m_ui.gbModel->setCurrentIndex(index >= 0 ? index : 0); } QString modelSGB = m_controller->getOption("sgb.model"); if (!modelSGB.isNull()) { GBModel model = GBNameToModel(modelSGB.toUtf8().constData()); - int index = s_gbModelList.indexOf(model); + int index = m_ui.sgbModel->findData(model); m_ui.sgbModel->setCurrentIndex(index >= 0 ? index : 0); } QString modelCGB = m_controller->getOption("cgb.model"); if (!modelCGB.isNull()) { GBModel model = GBNameToModel(modelCGB.toUtf8().constData()); - int index = s_gbModelList.indexOf(model); + int index = m_ui.cgbModel->findData(model); m_ui.cgbModel->setCurrentIndex(index >= 0 ? index : 0); } #endif diff --git a/src/platform/qt/SettingsView.h b/src/platform/qt/SettingsView.h index 23a8c18ff..5d43b9e1e 100644 --- a/src/platform/qt/SettingsView.h +++ b/src/platform/qt/SettingsView.h @@ -61,7 +61,6 @@ private: #ifdef M_CORE_GB uint32_t m_gbColors[12]{}; ColorPicker m_colorPickers[12]; - static QList s_gbModelList; #endif void saveSetting(const char* key, const QAbstractButton*); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 0dfb884d2..54519f346 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -1476,26 +1476,6 @@ Autodetect - - - Game Boy (DMG) - - - - - Super Game Boy (SGB) - - - - - Game Boy Color (CGB) - - - - - Game Boy Advance (AGB) - - @@ -1512,26 +1492,6 @@ Autodetect - - - Game Boy (DMG) - - - - - Super Game Boy (SGB) - - - - - Game Boy Color (CGB) - - - - - Game Boy Advance (AGB) - - @@ -1548,26 +1508,6 @@ Autodetect - - - Game Boy (DMG) - - - - - Super Game Boy (SGB) - - - - - Game Boy Color (CGB) - - - - - Game Boy Advance (AGB) - - From 3e91c50f2dbfc9875a60e8be427639d23fd0e369 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Aug 2020 01:52:20 -0700 Subject: [PATCH 05/10] Qt: Fix language code for Korean --- src/platform/qt/ts/mgba-ko.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/qt/ts/mgba-ko.ts b/src/platform/qt/ts/mgba-ko.ts index b8ce6b12c..695ed75b6 100644 --- a/src/platform/qt/ts/mgba-ko.ts +++ b/src/platform/qt/ts/mgba-ko.ts @@ -1,6 +1,6 @@ - + AboutScreen From 9dc6dc7e658be648d875d31098a577b58ad73c3a Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Aug 2020 18:19:13 -0700 Subject: [PATCH 06/10] GB: Add separate overrides for GBC games that can also run on SGB or regular GB --- CHANGES | 7 +- include/mgba/gb/interface.h | 2 + src/gb/core.c | 49 +++++++--- src/gb/gb.c | 16 ++++ src/platform/qt/SettingsView.cpp | 36 +++++++- src/platform/qt/SettingsView.ui | 150 ++++++++++++++++--------------- 6 files changed, 167 insertions(+), 93 deletions(-) diff --git a/CHANGES b/CHANGES index bfb5e1e2b..a52464063 100644 --- a/CHANGES +++ b/CHANGES @@ -1,9 +1,10 @@ 0.9.0: (Future) Features: - e-Reader card scanning - - Add WebP and APNG recording - - Add mute option in homebrew ports - - Add status indicators for fast-forward and mute in homebrew ports + - WebP and APNG recording + - Separate overrides for GBC games that can also run on SGB or regular GB + - Mute option in homebrew ports + - Status indicators for fast-forward and mute in homebrew ports - Support for unlicensed Pokemon Jade/Diamond Game Boy mapper - Support for unlicensed BBD Game Boy mapper - Support for unlicensed Hitek Game Boy mapper diff --git a/include/mgba/gb/interface.h b/include/mgba/gb/interface.h index c834f5d78..390e9e8cb 100644 --- a/include/mgba/gb/interface.h +++ b/include/mgba/gb/interface.h @@ -59,6 +59,8 @@ bool GBIsBIOS(struct VFile* vf); enum GBModel GBNameToModel(const char*); const char* GBModelToName(enum GBModel); +int GBValidModels(const uint8_t* bank0); + CXX_GUARD_END #endif diff --git a/src/gb/core.c b/src/gb/core.c index 6cb84cf95..61cedc774 100644 --- a/src/gb/core.c +++ b/src/gb/core.c @@ -221,6 +221,8 @@ 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, "cgb.hybridModel"); + mCoreConfigCopyValue(&core->config, config, "cgb.sgbModel"); mCoreConfigCopyValue(&core->config, config, "useCgbColors"); mCoreConfigCopyValue(&core->config, config, "allowOpposingDirections"); @@ -437,19 +439,42 @@ static void _GBCoreReset(struct mCore* core) { if (GBOverrideFind(gbcore->overrides, &override) || (doColorOverride && GBOverrideColorFind(&override))) { GBOverrideApply(gb, &override); } - } - const char* modelGB = mCoreConfigGetValue(&core->config, "gb.model"); - const char* modelCGB = mCoreConfigGetValue(&core->config, "cgb.model"); - const char* modelSGB = mCoreConfigGetValue(&core->config, "sgb.model"); - if (modelGB || modelCGB || modelSGB) { - GBDetectModel(gb); - if (gb->model == GB_MODEL_DMG && modelGB) { - gb->model = GBNameToModel(modelGB); - } else if ((gb->model & GB_MODEL_CGB) && modelCGB) { - gb->model = GBNameToModel(modelCGB); - } else if ((gb->model & GB_MODEL_SGB) && modelSGB) { - gb->model = GBNameToModel(modelSGB); + const char* modelGB = mCoreConfigGetValue(&core->config, "gb.model"); + const char* modelSGB = mCoreConfigGetValue(&core->config, "sgb.model"); + const char* modelCGB = mCoreConfigGetValue(&core->config, "cgb.model"); + const char* modelCGBHybrid = mCoreConfigGetValue(&core->config, "cgb.hybridModel"); + const char* modelCGBSGB = mCoreConfigGetValue(&core->config, "cgb.sgbModel"); + if (modelGB || modelCGB || modelSGB || modelCGBHybrid || modelCGBSGB) { + int models = GBValidModels(gb->memory.rom); + switch (models) { + case GB_MODEL_SGB | GB_MODEL_MGB: + if (modelSGB) { + gb->model = GBNameToModel(modelSGB); + } + break; + case GB_MODEL_MGB: + if (modelGB) { + gb->model = GBNameToModel(modelGB); + } + break; + case GB_MODEL_MGB | GB_MODEL_CGB: + if (modelCGBHybrid) { + gb->model = GBNameToModel(modelCGBHybrid); + } + break; + case GB_MODEL_SGB | GB_MODEL_CGB: // TODO: Do these even exist? + case GB_MODEL_MGB | GB_MODEL_SGB | GB_MODEL_CGB: + if (modelCGBSGB) { + gb->model = GBNameToModel(modelCGBSGB); + } + break; + case GB_MODEL_CGB: + if (modelCGB) { + gb->model = GBNameToModel(modelCGB); + } + break; + } } } diff --git a/src/gb/gb.c b/src/gb/gb.c index 4cd61eca7..fb407425e 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -656,6 +656,22 @@ void GBDetectModel(struct GB* gb) { } } +int GBValidModels(const uint8_t* bank0) { + const struct GBCartridge* cart = (const struct GBCartridge*) &bank0[0x100]; + int models; + if (cart->cgb == 0x80) { + models = GB_MODEL_CGB | GB_MODEL_MGB; + } else if (cart->cgb == 0xC0) { + models = GB_MODEL_CGB; + } else { + models = GB_MODEL_MGB; + } + if (cart->sgb == 0x03 && cart->oldLicensee == 0x33) { + models |= GB_MODEL_SGB; + } + return models; +} + void GBUpdateIRQs(struct GB* gb) { int irqs = gb->memory.ie & gb->memory.io[REG_IF] & 0x1F; if (!irqs) { diff --git a/src/platform/qt/SettingsView.cpp b/src/platform/qt/SettingsView.cpp index f6d47b165..13bd7042c 100644 --- a/src/platform/qt/SettingsView.cpp +++ b/src/platform/qt/SettingsView.cpp @@ -33,15 +33,19 @@ SettingsView::SettingsView(ConfigController* controller, InputController* inputC m_ui.setupUi(this); #ifdef M_CORE_GB - m_ui.gbModel->setItemData(0, GB_MODEL_AUTODETECT); - m_ui.sgbModel->setItemData(0, GB_MODEL_AUTODETECT); - m_ui.cgbModel->setItemData(0, GB_MODEL_AUTODETECT); - for (auto model : GameBoy::modelList()) { m_ui.gbModel->addItem(GameBoy::modelName(model), model); m_ui.sgbModel->addItem(GameBoy::modelName(model), model); m_ui.cgbModel->addItem(GameBoy::modelName(model), model); + m_ui.cgbHybridModel->addItem(GameBoy::modelName(model), model); + m_ui.cgbSgbModel->addItem(GameBoy::modelName(model), model); } + + m_ui.gbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_DMG)); + m_ui.sgbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_SGB)); + m_ui.cgbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_CGB)); + m_ui.cgbHybridModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_CGB)); + m_ui.cgbSgbModel->setCurrentIndex(m_ui.gbModel->findData(GB_MODEL_CGB)); #endif reloadConfig(); @@ -527,6 +531,16 @@ void SettingsView::updateConfig() { m_controller->setOption("cgb.model", GBModelToName(static_cast(modelCGB.toInt()))); } + QVariant modelCGBHybrid = m_ui.cgbHybridModel->currentData(); + if (modelCGBHybrid.isValid()) { + m_controller->setOption("cgb.hybridModel", GBModelToName(static_cast(modelCGBHybrid.toInt()))); + } + + QVariant modelCGBSGB = m_ui.cgbSgbModel->currentData(); + if (modelCGBSGB.isValid()) { + m_controller->setOption("cgb.sgbModel", GBModelToName(static_cast(modelCGBSGB.toInt()))); + } + for (int colorId = 0; colorId < 12; ++colorId) { if (!(m_gbColors[colorId] & 0xFF000000)) { continue; @@ -665,6 +679,20 @@ void SettingsView::reloadConfig() { int index = m_ui.cgbModel->findData(model); m_ui.cgbModel->setCurrentIndex(index >= 0 ? index : 0); } + + QString modelCGBHybrid = m_controller->getOption("cgb.hybridModel"); + if (!modelCGBHybrid.isNull()) { + GBModel model = GBNameToModel(modelCGBHybrid.toUtf8().constData()); + int index = m_ui.cgbHybridModel->findData(model); + m_ui.cgbHybridModel->setCurrentIndex(index >= 0 ? index : 0); + } + + QString modelCGBSGB = m_controller->getOption("cgb.sgbModel"); + if (!modelCGBSGB.isNull()) { + GBModel model = GBNameToModel(modelCGBSGB.toUtf8().constData()); + int index = m_ui.cgbSgbModel->findData(model); + m_ui.cgbSgbModel->setCurrentIndex(index >= 0 ? index : 0); + } #endif int hwaccelVideo = m_controller->getOption("hwaccelVideo", 0).toInt(); diff --git a/src/platform/qt/SettingsView.ui b/src/platform/qt/SettingsView.ui index 54519f346..166810adc 100644 --- a/src/platform/qt/SettingsView.ui +++ b/src/platform/qt/SettingsView.ui @@ -1465,18 +1465,12 @@ - Game Boy model: + Game Boy-only model: - - - - Autodetect - - - + @@ -1486,45 +1480,40 @@ - - - - Autodetect - - - + - Game Boy Color model: + Game Boy Color-only model: - - - - Autodetect - - + + + + + + Game Boy/Game Boy Color model: + - + Qt::Horizontal - + Default BG colors: - + @@ -1604,7 +1593,14 @@ - + + + + Default sprite colors 1: + + + + @@ -1684,38 +1680,14 @@ + + + + Default sprite colors 2: + + + - - - Super Game Boy borders - - - - - - - Qt::Horizontal - - - - - - - Camera driver: - - - - - - - - 0 - 0 - - - - - @@ -1795,35 +1767,52 @@ - - - - Default sprite colors 1: - - - - - - - Default sprite colors 2: - - - - + Use GBC colors in GB games - + + + + Super Game Boy borders + + + + + + + Qt::Horizontal + + + + + + + Camera driver: + + + + + + + + 0 + 0 + + + + + Camera: - + false @@ -1836,6 +1825,19 @@ + + + + + + + Super Game Boy/Game Boy Color model: + + + + + + From 6a04f022518e31d4cf641b3b3a3ae5ac76dc2fa7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 28 Aug 2020 18:33:31 -0700 Subject: [PATCH 07/10] Libretro: Build fixes for non-GB and coe cleanup --- src/platform/libretro/libretro.c | 35 +++++++++++++------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index b73b2039c..75ce1de1f 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -78,6 +78,7 @@ static void _reloadSettings(void) { }; struct retro_variable var; +#ifdef M_CORE_GB enum GBModel model; const char* modelName; @@ -101,6 +102,7 @@ static void _reloadSettings(void) { mCoreConfigSetDefaultValue(&core->config, "sgb.model", modelName); mCoreConfigSetDefaultValue(&core->config, "cgb.model", modelName); } +#endif var.key = "mgba_use_bios"; var.value = 0; @@ -114,21 +116,18 @@ static void _reloadSettings(void) { opts.skipBios = strcmp(var.value, "ON") == 0; } +#ifdef M_CORE_GB var.key = "mgba_sgb_borders"; var.value = 0; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - if (strcmp(var.value, "ON") == 0) { - mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", true); - } else { - mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", false); - } + mCoreConfigSetDefaultIntValue(&core->config, "sgb.borders", strcmp(var.value, "ON") == 0); } +#endif var.key = "mgba_frameskip"; var.value = 0; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { opts.frameskip = strtol(var.value, NULL, 10); - } var.key = "mgba_idle_optimization"; @@ -179,7 +178,11 @@ void retro_set_input_state(retro_input_state_t input) { void retro_get_system_info(struct retro_system_info* info) { info->need_fullpath = false; - info->valid_extensions = "gba|gb|gbc"; +#ifdef M_CORE_GB + info->valid_extensions = "gba|gb|gbc|sgb"; +#else + info->valid_extensions = "gba"; +#endif info->library_version = projectVersion; info->library_name = projectName; info->block_extract = false; @@ -287,25 +290,15 @@ void retro_run(void) { .value = 0 }; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - struct GBA* gba = core->board; - struct GB* gb = core->board; - switch (core->platform(core)) { - case PLATFORM_GBA: - gba->allowOpposingDirections = strcmp(var.value, "yes") == 0; - break; - case PLATFORM_GB: - gb->allowOpposingDirections = strcmp(var.value, "yes") == 0; - break; - default: - break; - } + mCoreConfigSetIntValue(&core->config, "allowOpposingDirections", strcmp(var.value, "yes") == 0); + core->reloadConfigOption(core, "allowOpposingDirections", NULL); } var.key = "mgba_frameskip"; var.value = 0; if (environCallback(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { - mCoreConfigSetUIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10)); - mCoreLoadConfig(core); + mCoreConfigSetIntValue(&core->config, "frameskip", strtol(var.value, NULL, 10)); + core->reloadConfigOption(core, "frameskip", NULL); } } From 0019cb69d8bb7588f7e9e50344e3d4bd2eca2aeb Mon Sep 17 00:00:00 2001 From: RufoH Date: Sun, 2 Feb 2020 22:38:37 -0800 Subject: [PATCH 08/10] Libretro: Add Italian core options translation --- src/platform/libretro/libretro_core_options.h | 2 +- .../libretro/libretro_core_options_intl.h | 129 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) diff --git a/src/platform/libretro/libretro_core_options.h b/src/platform/libretro/libretro_core_options.h index 930e13239..93e3ab3bd 100644 --- a/src/platform/libretro/libretro_core_options.h +++ b/src/platform/libretro/libretro_core_options.h @@ -190,7 +190,7 @@ struct retro_core_option_definition *option_defs_intl[RETRO_LANGUAGE_LAST] = { NULL, /* RETRO_LANGUAGE_FRENCH */ NULL, /* RETRO_LANGUAGE_SPANISH */ NULL, /* RETRO_LANGUAGE_GERMAN */ - NULL, /* RETRO_LANGUAGE_ITALIAN */ + option_defs_it, /* RETRO_LANGUAGE_ITALIAN */ NULL, /* RETRO_LANGUAGE_DUTCH */ NULL, /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ NULL, /* RETRO_LANGUAGE_PORTUGUESE_PORTUGAL */ diff --git a/src/platform/libretro/libretro_core_options_intl.h b/src/platform/libretro/libretro_core_options_intl.h index 42fc012b3..c19dd40f2 100644 --- a/src/platform/libretro/libretro_core_options_intl.h +++ b/src/platform/libretro/libretro_core_options_intl.h @@ -47,6 +47,135 @@ extern "C" { /* RETRO_LANGUAGE_ITALIAN */ +struct retro_core_option_definition option_defs_it[] = { + { + "mgba_solar_sensor_level", + "Livello Sensore Solare", + "Imposta l'intensità solare dell'ambiente. Può essere usato dai giochi che includono un sensore solare nelle loro cartucce, es.: la serie Boktai.", + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { "9", NULL }, + { "10", NULL }, + { NULL, NULL }, + }, + "0" + }, + { + "mgba_allow_opposing_directions", + "Permetti Input Direzionali Opposti", + "Attivando questa funzionalità ti permette di premere / alternare velocemente / tenere premuti entrambe le direzioni destra e sinistra (oppure su e giù) allo stesso momento. Potrebbe causare dei glitch di movimento.", + { + { "no", "Disabilitato" }, + { "yes", "Abilitato" }, + { NULL, NULL }, + }, + "no" + }, + { + "mgba_gb_model", + "Modello Game Boy (richiede riavvio)", + "Esegue il contenuto caricato con un modello specifico di Game Boy. 'Rivela Automaticamente' selezionerà il modello più appropriato per il gioco attuale.", + { + { "Autodetect", "Rivela Automaticamente" }, + { "Game Boy", NULL }, + { "Super Game Boy", NULL }, + { "Game Boy Color", NULL }, + { "Game Boy Advance", NULL }, + { NULL, NULL }, + }, + "Autodetect" + }, + { + "mgba_use_bios", + "Usa il File BIOS se Presente (richiede riavvio)", + "Usa il BIOS/bootloader ufficiale per hardware emulato, se presente nella cartella di sistema di RetroArch.", + { + { "ON", NULL }, + { "OFF", NULL }, + { NULL, NULL }, + }, + "ON" + }, + { + "mgba_skip_bios", + "Salta Intro BIOS (richiede riavvio)", + "Salta il filmato del logo di avvio se si usa un BIOS/bootloader ufficiale. Questa impostazione è ignorata se 'Usa il file BIOS se presente' è disabilitato.", + { + { "OFF", NULL }, + { "ON", NULL }, + { NULL, NULL }, + }, + "OFF" + }, + { + "mgba_sgb_borders", + "Utilizza i Bordi Super Game Boy (richiede riavvio)", + "Visualizza i bordi del Super Game Boy quando apri un gioco potenziato dal Super Game Boy.", + { + { "ON", NULL }, + { "OFF", NULL }, + { NULL, NULL }, + }, + "ON" + }, + { + "mgba_idle_optimization", + "Rimozione Idle Loop", + "Riduce il carico del sistema ottimizzando gli 'idle-loops' - sezione del codice dove non accade nulla, ma la CPU lavora a velocità massima. Migliora le prestazioni, è consigliato abilitarlo su hardware di bassa fascia.", + { + { "Remove Known", "Rimuovi Conosciuti" }, + { "Detect and Remove", "Rileva e Rimuovi" }, + { "Don't Remove", "Non Rimuovere" }, + { NULL, NULL }, + }, + "Remove Known" + }, + { + "mgba_frameskip", + "Salta Frame", + "Salta dei frame per migliorare le prestazioni a costo della fluidità dell'immagine. Il valore impostato qui è il numero dei frame rimosso dopo che un frame sia stato renderizzato - ovvero '0' = 60fps, '1' = 30fps, '2' = 15fps, ecc.", + { + { "0", NULL }, + { "1", NULL }, + { "2", NULL }, + { "3", NULL }, + { "4", NULL }, + { "5", NULL }, + { "6", NULL }, + { "7", NULL }, + { "8", NULL }, + { "9", NULL }, + { "10", NULL }, + { NULL, NULL }, + }, + "0" + }, +#if defined(COLOR_16_BIT) && defined(COLOR_5_6_5) + { + "mgba_color_correction", + "Correzione Colore", + "Regola i colori per corrispondere lo schermo di GBA/GBC reali.", + { + { "OFF", NULL }, + { "GBA", "Game Boy Advance" }, + { "GBC", "Game Boy Color" }, + { "Auto", NULL }, + { NULL, NULL }, + }, + "OFF" + }, +#endif + { NULL, NULL, NULL, {{0}}, NULL }, +}; + /* RETRO_LANGUAGE_DUTCH */ /* RETRO_LANGUAGE_PORTUGUESE_BRAZIL */ From 274a97a5f0908a68a4e072f918b80b3f66aae382 Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Wed, 22 Apr 2020 15:57:07 +0800 Subject: [PATCH 09/10] Libretro: Add cheevos support for GB/GBC Working implementation: https://github.com/libretro/mgba/issues/182#issuecomment-617561652 --- src/platform/libretro/libretro.c | 96 ++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 75ce1de1f..3e50f423b 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -435,6 +435,102 @@ static void _setupMaps(struct mCore* core) { environCallback(RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, &yes); } #endif +#ifdef M_CORE_GB + if (core->platform(core) == PLATFORM_GB) { + struct GB* gb = core->board; + struct retro_memory_descriptor descs[11]; + struct retro_memory_map mmaps; + + memset(descs, 0, sizeof(descs)); + size_t savedataSize = retro_get_memory_size(RETRO_MEMORY_SAVE_RAM); + + unsigned i = 0; + + /* Map ROM */ + descs[i].ptr = gb->memory.rom; + descs[i].start = GB_BASE_CART_BANK0; + descs[i].len = GB_SIZE_CART_BANK0; + descs[i].flags = RETRO_MEMDESC_CONST; + i++; + + descs[i].ptr = gb->memory.rom; + descs[i].offset = GB_SIZE_CART_BANK0; + descs[i].start = GB_BASE_CART_BANK1; + descs[i].len = GB_SIZE_CART_BANK0; + descs[i].flags = RETRO_MEMDESC_CONST; + i++; + + /* Map VRAM */ + descs[i].ptr = gb->video.vram; + descs[i].start = GB_BASE_VRAM; + descs[i].len = GB_SIZE_VRAM; + i++; + + /* Map working RAM */ + descs[i].ptr = gb->memory.wram; + descs[i].start = GB_BASE_WORKING_RAM_BANK0; + descs[i].len = GB_SIZE_WORKING_RAM_BANK0; + i++; + + descs[i].ptr = gb->memory.wram; + descs[i].offset = GB_SIZE_WORKING_RAM_BANK0; + descs[i].start = GB_BASE_WORKING_RAM_BANK1; + descs[i].len = GB_SIZE_WORKING_RAM_BANK0; + i++; + + /* Map OAM */ + descs[i].ptr = &gb->video.oam; /* video.oam is a structure */ + descs[i].start = GB_BASE_OAM; + descs[i].len = GB_SIZE_OAM; + descs[i].select = 0xFFFFFF60; + i++; + + /* Map mmapped I/O */ + descs[i].ptr = gb->memory.io; + descs[i].start = GB_BASE_IO; + descs[i].len = GB_SIZE_IO; + i++; + + /* Map High RAM */ + descs[i].ptr = gb->memory.hram; + descs[i].start = GB_BASE_HRAM; + descs[i].len = GB_SIZE_HRAM; + descs[i].select = 0xFFFFFF80; + i++; + + /* Map IE Register */ + descs[i].ptr = &gb->memory.ie; + descs[i].start = GB_BASE_IE; + descs[i].len = 1; + i++; + + /* Map External RAM */ + if (savedataSize) { + descs[i].ptr = savedata; + descs[i].start = GB_BASE_EXTERNAL_RAM; + descs[i].len = savedataSize; + i++; + } + + if (gb->model >= GB_MODEL_CGB) { + /* Map working RAM */ + /* banks 2-7 of wram mapped in virtual address so it can be + * accessed without bank switching, GBC only */ + descs[i].ptr = gb->memory.wram + 0x2000; + descs[i].start = 0x10000; + descs[i].len = GB_SIZE_WORKING_RAM - 0x2000; + descs[i].select = 0xFFFFA000; + i++; + } + + mmaps.descriptors = descs; + mmaps.num_descriptors = i; + + bool yes = true; + environCallback(RETRO_ENVIRONMENT_SET_MEMORY_MAPS, &mmaps); + environCallback(RETRO_ENVIRONMENT_SET_SUPPORT_ACHIEVEMENTS, &yes); + } +#endif } void retro_reset(void) { From f6523e2c0111710fa79823331eff360f73f5641e Mon Sep 17 00:00:00 2001 From: negativeExponent Date: Sun, 10 May 2020 19:03:04 +0800 Subject: [PATCH 10/10] libretro: Fix cheevos memory map for GB games using external RAM --- src/platform/libretro/libretro.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/platform/libretro/libretro.c b/src/platform/libretro/libretro.c index 3e50f423b..0d2d0e60b 100644 --- a/src/platform/libretro/libretro.c +++ b/src/platform/libretro/libretro.c @@ -463,7 +463,7 @@ static void _setupMaps(struct mCore* core) { /* Map VRAM */ descs[i].ptr = gb->video.vram; descs[i].start = GB_BASE_VRAM; - descs[i].len = GB_SIZE_VRAM; + descs[i].len = GB_SIZE_VRAM_BANK0; i++; /* Map working RAM */ @@ -505,8 +505,8 @@ static void _setupMaps(struct mCore* core) { i++; /* Map External RAM */ - if (savedataSize) { - descs[i].ptr = savedata; + if (gb->memory.sram) { + descs[i].ptr = gb->memory.sram; descs[i].start = GB_BASE_EXTERNAL_RAM; descs[i].len = savedataSize; i++;