From e0763fbbfd09f48a4aa007eb98e7363b2746f12d Mon Sep 17 00:00:00 2001 From: Ignacio Sanchez Gines <863613+drhelius@users.noreply.github.com> Date: Sun, 5 Jan 2025 14:11:37 +0100 Subject: [PATCH] Add 4 Pak All Action mapper. Fix #115 --- platforms/desktop-shared/Makefile.sources | 1 + platforms/libretro/Makefile.common | 1 + platforms/windows/Gearsystem.vcxproj | 2 + src/Cartridge.cpp | 10 ++ src/Cartridge.h | 1 + src/GearsystemCore.cpp | 8 ++ src/GearsystemCore.h | 4 +- src/Multi4PAKAllActionMemoryRule.cpp | 131 ++++++++++++++++++++++ src/Multi4PAKAllActionMemoryRule.h | 43 +++++++ src/game_db.h | 3 + 10 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 src/Multi4PAKAllActionMemoryRule.cpp create mode 100644 src/Multi4PAKAllActionMemoryRule.h diff --git a/platforms/desktop-shared/Makefile.sources b/platforms/desktop-shared/Makefile.sources index 6994f602..6c5e6b6d 100644 --- a/platforms/desktop-shared/Makefile.sources +++ b/platforms/desktop-shared/Makefile.sources @@ -41,6 +41,7 @@ SOURCES_CXX := \ $(SRC_DIR)/KoreanBFFCMemoryRule.cpp \ $(SRC_DIR)/KoreanFFF3FFFCMemoryRule.cpp \ $(SRC_DIR)/KoreanMDFFF5MemoryRule.cpp \ + $(SRC_DIR)/Multi4PAKAllActionMemoryRule.cpp \ $(SRC_DIR)/Memory.cpp \ $(SRC_DIR)/MemoryRule.cpp \ $(SRC_DIR)/MSXMemoryRule.cpp \ diff --git a/platforms/libretro/Makefile.common b/platforms/libretro/Makefile.common index 200a24a4..2904131e 100644 --- a/platforms/libretro/Makefile.common +++ b/platforms/libretro/Makefile.common @@ -20,6 +20,7 @@ SOURCES_CXX := $(CORE_DIR)/libretro.cpp \ $(SOURCE_DIR)/KoreanBFFCMemoryRule.cpp \ $(SOURCE_DIR)/KoreanFFF3FFFCMemoryRule.cpp \ $(SOURCE_DIR)/KoreanMDFFF5MemoryRule.cpp \ + $(SOURCE_DIR)/Multi4PAKAllActionMemoryRule.cpp \ $(SOURCE_DIR)/Memory.cpp \ $(SOURCE_DIR)/MemoryRule.cpp \ $(SOURCE_DIR)/MSXMemoryRule.cpp \ diff --git a/platforms/windows/Gearsystem.vcxproj b/platforms/windows/Gearsystem.vcxproj index e8be8958..973a0acf 100644 --- a/platforms/windows/Gearsystem.vcxproj +++ b/platforms/windows/Gearsystem.vcxproj @@ -76,6 +76,7 @@ + @@ -158,6 +159,7 @@ + diff --git a/src/Cartridge.cpp b/src/Cartridge.cpp index 5d80143d..d754c1c2 100644 --- a/src/Cartridge.cpp +++ b/src/Cartridge.cpp @@ -240,6 +240,10 @@ void Cartridge::ForceConfig(Cartridge::ForceConfiguration config) m_Type = config.type; Log("Forcing Mapper: Janggun"); break; + case Cartridge::CartridgeMulti4PAKAllActionMapper: + m_Type = config.type; + Log("Forcing Mapper: Multi 4PAK All Action"); + break; default: Log("Not forcing Mapper: Auto"); break; @@ -651,6 +655,9 @@ bool Cartridge::GatherMetadata(u32 crc) case Cartridge::CartridgeJanggunMapper: Log("Janggun mapper found"); break; + case Cartridge::CartridgeMulti4PAKAllActionMapper: + Log("Multi 4PAK All Action mapper found"); + break; case Cartridge::CartridgeNotSupported: Log("Cartridge not supported!!"); break; @@ -740,6 +747,9 @@ void Cartridge::GetInfoFromDB(u32 crc) case GS_DB_JANGGUN_MAPPER: m_Type = Cartridge::CartridgeJanggunMapper; break; + case GS_DB_MULTI_4PAK_ALL_ACTION_MAPPER: + m_Type = Cartridge::CartridgeMulti4PAKAllActionMapper; + break; } if (kGameDatabase[i].features & GS_DB_FEATURE_SMS_MODE) diff --git a/src/Cartridge.h b/src/Cartridge.h index dc89b5fe..54ff30b8 100644 --- a/src/Cartridge.h +++ b/src/Cartridge.h @@ -47,6 +47,7 @@ class Cartridge CartridgeKoreanMDFFF5Mapper, CartridgeMSXMapper, CartridgeJanggunMapper, + CartridgeMulti4PAKAllActionMapper, CartridgeNotSupported }; diff --git a/src/GearsystemCore.cpp b/src/GearsystemCore.cpp index 3984cdf2..bfcb282b 100644 --- a/src/GearsystemCore.cpp +++ b/src/GearsystemCore.cpp @@ -42,6 +42,7 @@ #include "KoreanMDFFF5MemoryRule.h" #include "MSXMemoryRule.h" #include "JanggunMemoryRule.h" +#include "Multi4PAKAllActionMemoryRule.h" #include "SG1000MemoryRule.h" #include "SmsIOPorts.h" #include "GameGearIOPorts.h" @@ -73,6 +74,7 @@ GearsystemCore::GearsystemCore() InitPointer(m_pKoreanMDFFF5MemoryRule); InitPointer(m_pMSXMemoryRule); InitPointer(m_pJanggunMemoryRule); + InitPointer(m_pMulti4PAKAllActionMemoryRule); InitPointer(m_pSmsIOPorts); InitPointer(m_pGameGearIOPorts); InitPointer(m_pBootromMemoryRule); @@ -104,6 +106,7 @@ GearsystemCore::~GearsystemCore() SafeDelete(m_pKoreanMDFFF5MemoryRule); SafeDelete(m_pMSXMemoryRule); SafeDelete(m_pJanggunMemoryRule); + SafeDelete(m_pMulti4PAKAllActionMemoryRule); SafeDelete(m_pCartridge); SafeDelete(m_pInput); SafeDelete(m_pVideo); @@ -928,6 +931,7 @@ void GearsystemCore::InitMemoryRules() m_pKoreanMDFFF5MemoryRule = new KoreanMDFFF5MemoryRule(m_pMemory, m_pCartridge, m_pInput); m_pMSXMemoryRule = new MSXMemoryRule(m_pMemory, m_pCartridge, m_pInput); m_pJanggunMemoryRule = new JanggunMemoryRule(m_pMemory, m_pCartridge, m_pInput); + m_pMulti4PAKAllActionMemoryRule = new Multi4PAKAllActionMemoryRule(m_pMemory, m_pCartridge, m_pInput); m_pBootromMemoryRule = new BootromMemoryRule(m_pMemory, m_pCartridge, m_pInput); m_pMemory->SetCurrentRule(m_pRomOnlyMemoryRule); m_pMemory->SetBootromRule(m_pBootromMemoryRule); @@ -996,6 +1000,9 @@ bool GearsystemCore::AddMemoryRules() case Cartridge::CartridgeJanggunMapper: m_pMemory->SetCurrentRule(m_pJanggunMemoryRule); break; + case Cartridge::CartridgeMulti4PAKAllActionMapper: + m_pMemory->SetCurrentRule(m_pMulti4PAKAllActionMemoryRule); + break; case Cartridge::CartridgeNotSupported: notSupported = true; break; @@ -1042,6 +1049,7 @@ void GearsystemCore::Reset() m_pKoreanMDFFF5MemoryRule->Reset(); m_pMSXMemoryRule->Reset(); m_pJanggunMemoryRule->Reset(); + m_pMulti4PAKAllActionMemoryRule->Reset(); m_pBootromMemoryRule->Reset(); m_pGameGearIOPorts->Reset(); m_pSmsIOPorts->Reset(); diff --git a/src/GearsystemCore.h b/src/GearsystemCore.h index 1a3e7dff..bcad5a5e 100644 --- a/src/GearsystemCore.h +++ b/src/GearsystemCore.h @@ -18,7 +18,7 @@ */ #ifndef CORE_H -#define CORE_H +#define CORE_H #include "definitions.h" #include "Cartridge.h" @@ -46,6 +46,7 @@ class KoreanFFF3FFFCMemoryRule; class KoreanMDFFF5MemoryRule; class MSXMemoryRule; class JanggunMemoryRule; +class Multi4PAKAllActionMemoryRule; class MemoryRule; class SmsIOPorts; class GameGearIOPorts; @@ -135,6 +136,7 @@ class GearsystemCore KoreanMDFFF5MemoryRule* m_pKoreanMDFFF5MemoryRule; MSXMemoryRule* m_pMSXMemoryRule; JanggunMemoryRule* m_pJanggunMemoryRule; + Multi4PAKAllActionMemoryRule* m_pMulti4PAKAllActionMemoryRule; SmsIOPorts* m_pSmsIOPorts; GameGearIOPorts* m_pGameGearIOPorts; BootromMemoryRule* m_pBootromMemoryRule; diff --git a/src/Multi4PAKAllActionMemoryRule.cpp b/src/Multi4PAKAllActionMemoryRule.cpp new file mode 100644 index 00000000..213c3fa7 --- /dev/null +++ b/src/Multi4PAKAllActionMemoryRule.cpp @@ -0,0 +1,131 @@ +/* + * Gearsystem - Sega Master System / Game Gear Emulator + * Copyright (C) 2013 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#include "Multi4PAKAllActionMemoryRule.h" +#include "Memory.h" +#include "Cartridge.h" + +Multi4PAKAllActionMemoryRule::Multi4PAKAllActionMemoryRule(Memory* pMemory, Cartridge* pCartridge, Input* pInput) : MemoryRule(pMemory, pCartridge, pInput) +{ + Reset(); +} + +Multi4PAKAllActionMemoryRule::~Multi4PAKAllActionMemoryRule() +{ +} + +u8 Multi4PAKAllActionMemoryRule::PerformRead(u16 address) +{ + if (address < 0xC000) + { + int slot = (address >> 14) & 0x03; + if (slot > 3) + { + Debug("--> ** Invalid slot %d", slot); + return 0xFF; + } + return m_pCartridge->GetROM()[m_iMapperSlotAddress[slot] + (address & 0x3FFF)]; + } + else + { + // RAM + RAM mirror + return m_pMemory->Retrieve(address); + } +} + +void Multi4PAKAllActionMemoryRule::PerformWrite(u16 address, u8 value) +{ + if (address < 0xC000) + { + switch (address) + { + case 0x3FFE: + Debug("--> ** Writing to register $%X %X", address, value); + m_iMapperSlot[0] = value; + m_iMapperSlotAddress[0] = 0x4000 * (m_iMapperSlot[0] & (m_pCartridge->GetROMBankCount() - 1)); + return; + case 0x7FFF: + Debug("--> ** Writing to register $%X %X", address, value); + m_iMapperSlot[1] = value; + m_iMapperSlotAddress[1] = 0x4000 * (m_iMapperSlot[1] & (m_pCartridge->GetROMBankCount() - 1)); + return; + case 0xBFFF: + Debug("--> ** Writing to register $%X %X", address, value); + m_iMapperSlot[2] = value; + m_iMapperSlotAddress[2] = 0x4000 * (((m_iMapperSlot[0] & 0x30) + value) & (m_pCartridge->GetROMBankCount() - 1)); + return; + default: + Debug("--> ** Attempting to write on ROM address $%X %X", address, value); + return; + } + } + else if (address < 0xE000) + { + // RAM + m_pMemory->Load(address, value); + m_pMemory->Load(address + 0x2000, value); + } + else + { + // RAM (mirror) + m_pMemory->Load(address, value); + m_pMemory->Load(address - 0x2000, value); + } +} + +void Multi4PAKAllActionMemoryRule::Reset() +{ + m_iMapperSlot[0] = 0; + m_iMapperSlot[1] = 1; + m_iMapperSlot[2] = 2; + + m_iMapperSlotAddress[0] = 0x0000; + m_iMapperSlotAddress[1] = 0x4000; + m_iMapperSlotAddress[2] = 0x8000; +} + +u8* Multi4PAKAllActionMemoryRule::GetPage(int index) +{ + if (index < 0 || index > 2) + return m_pCartridge->GetROM(); + + return m_pCartridge->GetROM() + (m_iMapperSlot[index] * 0x4000); +} + +int Multi4PAKAllActionMemoryRule::GetBank(int index) +{ + if (index < 0 || index > 2) + return 0; + + return m_iMapperSlot[index]; +} + +void Multi4PAKAllActionMemoryRule::SaveState(std::ostream& stream) +{ + stream.write(reinterpret_cast (m_iMapperSlotAddress), sizeof(m_iMapperSlotAddress)); + stream.write(reinterpret_cast (m_iMapperSlot), sizeof(m_iMapperSlot)); +} + +void Multi4PAKAllActionMemoryRule::LoadState(std::istream& stream) +{ + using namespace std; + + stream.read(reinterpret_cast (m_iMapperSlotAddress), sizeof(m_iMapperSlotAddress)); + stream.read(reinterpret_cast (m_iMapperSlot), sizeof(m_iMapperSlot)); +} diff --git a/src/Multi4PAKAllActionMemoryRule.h b/src/Multi4PAKAllActionMemoryRule.h new file mode 100644 index 00000000..3df4a6f8 --- /dev/null +++ b/src/Multi4PAKAllActionMemoryRule.h @@ -0,0 +1,43 @@ +/* + * Gearsystem - Sega Master System / Game Gear Emulator + * Copyright (C) 2013 Ignacio Sanchez + + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/ + * + */ + +#ifndef MULTI4PAKALLACTIONMEMORYRULE_H +#define MULTI4PAKALLACTIONMEMORYRULE_H + +#include "MemoryRule.h" + +class Multi4PAKAllActionMemoryRule : public MemoryRule +{ +public: + Multi4PAKAllActionMemoryRule(Memory* pMemory, Cartridge* pCartridge, Input* pInput); + virtual ~Multi4PAKAllActionMemoryRule(); + virtual u8 PerformRead(u16 address); + virtual void PerformWrite(u16 address, u8 value); + virtual void Reset(); + virtual u8* GetPage(int index); + virtual int GetBank(int index); + virtual void SaveState(std::ostream& stream); + virtual void LoadState(std::istream& stream); + +private: + int m_iMapperSlot[3]; + int m_iMapperSlotAddress[3]; +}; + +#endif /* MULTI4PAKALLACTIONMEMORYRULE_H */ diff --git a/src/game_db.h b/src/game_db.h index 5602b68e..1c0502d4 100644 --- a/src/game_db.h +++ b/src/game_db.h @@ -39,6 +39,7 @@ #define GS_DB_KOREAN_BFFC_MAPPER 14 #define GS_DB_KOREAN_FFF3_FFFC_MAPPER 15 #define GS_DB_KOREAN_MD_FFF5_MAPPER 16 +#define GS_DB_MULTI_4PAK_ALL_ACTION_MAPPER 17 #define GS_DB_FEATURE_NONE 0x00 #define GS_DB_FEATURE_PAL 0x01 @@ -407,6 +408,8 @@ const GS_GameDBEntry kGameDatabase[] = {0x7F667485, GS_DB_KOREAN_MD_FFF5_MAPPER, GS_DB_FEATURE_NONE, "Mega Mode Super Game 138"}, {0xC0AC6956, GS_DB_KOREAN_MD_FFF5_MAPPER, GS_DB_FEATURE_NONE, "Pigu-Wang 7 Hap - Jaemiiss-neun Game Mo-eumjip"}, + {0xA67F2A5C, GS_DB_MULTI_4PAK_ALL_ACTION_MAPPER, GS_DB_FEATURE_NONE, "4 PAK All Action"}, + // Requires vint flag on boot {0xD9096263, GS_DB_DEFAULT_MAPPER, GS_DB_FEATURE_INITIAL_VINT, "Sonic's Edusoft [Proto]"},