Skip to content

Commit

Permalink
Korean MSX SMS 8000 (Zemina) mapper support. #81
Browse files Browse the repository at this point in the history
  • Loading branch information
drhelius committed Dec 22, 2024
1 parent a815dee commit 5b6e275
Show file tree
Hide file tree
Showing 11 changed files with 252 additions and 14 deletions.
1 change: 1 addition & 0 deletions platforms/desktop-shared/Makefile.sources
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ SOURCES_CXX := \
$(SRC_DIR)/GearsystemCore.cpp \
$(SRC_DIR)/Input.cpp \
$(SRC_DIR)/KoreanMemoryRule.cpp \
$(SRC_DIR)/KoreanMSXSMS8000MemoryRule.cpp \
$(SRC_DIR)/Memory.cpp \
$(SRC_DIR)/MemoryRule.cpp \
$(SRC_DIR)/MSXMemoryRule.cpp \
Expand Down
2 changes: 2 additions & 0 deletions platforms/windows/Gearsystem.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<ClCompile Include="..\..\src\Input.cpp" />
<ClCompile Include="..\..\src\JanggunMemoryRule.cpp" />
<ClCompile Include="..\..\src\KoreanMemoryRule.cpp" />
<ClCompile Include="..\..\src\KoreanMSXSMS8000MemoryRule.cpp" />
<ClCompile Include="..\..\src\Memory.cpp" />
<ClCompile Include="..\..\src\MemoryRule.cpp" />
<ClCompile Include="..\..\src\MSXMemoryRule.cpp" />
Expand Down Expand Up @@ -92,6 +93,7 @@
<ClInclude Include="..\..\src\IOPorts.h" />
<ClInclude Include="..\..\src\JanggunMemoryRule.h" />
<ClInclude Include="..\..\src\KoreanMemoryRule.h" />
<ClInclude Include="..\..\src\KoreanMSXSMS8000MemoryRule.h" />
<ClInclude Include="..\..\src\Memory.h" />
<ClInclude Include="..\..\src\MemoryRule.h" />
<ClInclude Include="..\..\src\Memory_inline.h" />
Expand Down
6 changes: 6 additions & 0 deletions platforms/windows/Gearsystem.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
<ClCompile Include="..\..\src\KoreanMemoryRule.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\KoreanMSXSMS8000MemoryRule.cpp">
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Memory.cpp">
<Filter>core</Filter>
</ClCompile>
Expand Down Expand Up @@ -272,6 +275,9 @@
<ClInclude Include="..\..\src\KoreanMemoryRule.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\KoreanMSXSMS8000MemoryRule.h">
<Filter>core</Filter>
</ClInclude>
<ClInclude Include="..\..\src\Memory.h">
<Filter>core</Filter>
</ClInclude>
Expand Down
7 changes: 0 additions & 7 deletions platforms/windows/Makefile

This file was deleted.

30 changes: 25 additions & 5 deletions src/Cartridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ Cartridge::Cartridge()
m_bReady = false;
m_szFilePath[0] = 0;
m_szFileName[0] = 0;
m_iROMBankCount = 0;
m_iROMBankCount16k = 0;
m_iROMBankCount8k = 0;
m_bGameGear = false;
m_bSG1000 = false;
m_bPAL = false;
Expand Down Expand Up @@ -63,7 +64,8 @@ void Cartridge::Reset()
m_bReady = false;
m_szFilePath[0] = 0;
m_szFileName[0] = 0;
m_iROMBankCount = 0;
m_iROMBankCount16k = 0;
m_iROMBankCount8k = 0;
m_bGameGear = false;
m_bSG1000 = false;
m_bPAL = false;
Expand Down Expand Up @@ -178,6 +180,10 @@ void Cartridge::ForceConfig(Cartridge::ForceConfiguration config)
m_Type = config.type;
Log("Forcing Mapper: Korean");
break;
case Cartridge::CartridgeKoreanMSXSMS8000Mapper:
m_Type = config.type;
Log("Forcing Mapper: Korean MSX SMS 8000");
break;
case Cartridge::CartridgeMSXMapper:
m_Type = config.type;
Log("Forcing Mapper: MSX");
Expand Down Expand Up @@ -224,7 +230,12 @@ int Cartridge::GetROMSize() const

int Cartridge::GetROMBankCount() const
{
return m_iROMBankCount;
return m_iROMBankCount16k;
}

int Cartridge::GetROMBankCount8k() const
{
return m_iROMBankCount8k;
}

const char* Cartridge::GetFilePath() const
Expand Down Expand Up @@ -521,10 +532,12 @@ bool Cartridge::GatherMetadata(u32 crc)
}
}

m_iROMBankCount = std::max(Pow2Ceil(m_iROMSize / 0x4000), 1u);
m_iROMBankCount16k = std::max(Pow2Ceil(m_iROMSize / 0x4000), 1u);
m_iROMBankCount8k = std::max(Pow2Ceil(m_iROMSize / 0x2000), 1u);

Log("ROM Size: %d KB", m_iROMSize / 1024);
Log("ROM Bank Count: %d", m_iROMBankCount);
Log("ROM Bank Count (16KB): %d", m_iROMBankCount16k);
Log("ROM Bank Count (8KB): %d", m_iROMBankCount8k);

if (m_iROMSize <= 0xC000)
{
Expand Down Expand Up @@ -555,6 +568,9 @@ bool Cartridge::GatherMetadata(u32 crc)
case Cartridge::CartridgeKoreanMapper:
Log("Korean mapper found");
break;
case Cartridge::CartridgeKoreanMSXSMS8000Mapper:
Log("Korean MSX SMS 8000 mapper found");
break;
case Cartridge::CartridgeMSXMapper:
Log("MSX mapper found");
break;
Expand Down Expand Up @@ -608,6 +624,10 @@ void Cartridge::GetInfoFromDB(u32 crc)
{
m_Type = Cartridge::CartridgeKoreanMapper;
}
else if (kGameDatabase[i].mapper == GS_DB_KOREAN_MSX_SMS_8000_MAPPER)
{
m_Type = Cartridge::CartridgeKoreanMSXSMS8000Mapper;
}
else if (kGameDatabase[i].mapper == GS_DB_MSX_MAPPER)
{
m_Type = Cartridge::CartridgeMSXMapper;
Expand Down
7 changes: 5 additions & 2 deletions src/Cartridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ class Cartridge
{
CartridgeRomOnlyMapper,
CartridgeSegaMapper,
CartridgeCodemastersMapper,
CartridgeCodemastersMapper,
CartridgeSG1000Mapper,
CartridgeKoreanMapper,
CartridgeKoreanMSXSMS8000Mapper,
CartridgeMSXMapper,
CartridgeJanggunMapper,
CartridgeNotSupported
Expand Down Expand Up @@ -88,6 +89,7 @@ class Cartridge
void ForceConfig(ForceConfiguration config);
int GetROMSize() const;
int GetROMBankCount() const;
int GetROMBankCount8k() const;
const char* GetFilePath() const;
const char* GetFileName() const;
u8* GetROM() const;
Expand All @@ -112,7 +114,8 @@ class Cartridge
bool m_bReady;
char m_szFilePath[512];
char m_szFileName[512];
int m_iROMBankCount;
int m_iROMBankCount16k;
int m_iROMBankCount8k;
bool m_bGameGear;
bool m_bSG1000;
bool m_bPAL;
Expand Down
8 changes: 8 additions & 0 deletions src/GearsystemCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "CodemastersMemoryRule.h"
#include "RomOnlyMemoryRule.h"
#include "KoreanMemoryRule.h"
#include "KoreanMSXSMS8000MemoryRule.h"
#include "MSXMemoryRule.h"
#include "JanggunMemoryRule.h"
#include "SG1000MemoryRule.h"
Expand All @@ -49,6 +50,7 @@ GearsystemCore::GearsystemCore()
InitPointer(m_pSG1000MemoryRule);
InitPointer(m_pRomOnlyMemoryRule);
InitPointer(m_pKoreanMemoryRule);
InitPointer(m_pKoreanMSXSMS8000MemoryRule);
InitPointer(m_pMSXMemoryRule);
InitPointer(m_pJanggunMemoryRule);
InitPointer(m_pSmsIOPorts);
Expand All @@ -69,6 +71,7 @@ GearsystemCore::~GearsystemCore()
SafeDelete(m_pSG1000MemoryRule);
SafeDelete(m_pSegaMemoryRule);
SafeDelete(m_pKoreanMemoryRule);
SafeDelete(m_pKoreanMSXSMS8000MemoryRule);
SafeDelete(m_pMSXMemoryRule);
SafeDelete(m_pJanggunMemoryRule);
SafeDelete(m_pCartridge);
Expand Down Expand Up @@ -845,6 +848,7 @@ void GearsystemCore::InitMemoryRules()
m_pSegaMemoryRule = new SegaMemoryRule(m_pMemory, m_pCartridge, m_pInput);
m_pRomOnlyMemoryRule = new RomOnlyMemoryRule(m_pMemory, m_pCartridge, m_pInput);
m_pKoreanMemoryRule = new KoreanMemoryRule(m_pMemory, m_pCartridge, m_pInput);
m_pKoreanMSXSMS8000MemoryRule = new KoreanMSXSMS8000MemoryRule(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_pBootromMemoryRule = new BootromMemoryRule(m_pMemory, m_pCartridge, m_pInput);
Expand Down Expand Up @@ -877,6 +881,9 @@ bool GearsystemCore::AddMemoryRules()
case Cartridge::CartridgeKoreanMapper:
m_pMemory->SetCurrentRule(m_pKoreanMemoryRule);
break;
case Cartridge::CartridgeKoreanMSXSMS8000Mapper:
m_pMemory->SetCurrentRule(m_pKoreanMSXSMS8000MemoryRule);
break;
case Cartridge::CartridgeMSXMapper:
m_pMemory->SetCurrentRule(m_pMSXMemoryRule);
break;
Expand Down Expand Up @@ -916,6 +923,7 @@ void GearsystemCore::Reset()
m_pSG1000MemoryRule->Reset();
m_pRomOnlyMemoryRule->Reset();
m_pKoreanMemoryRule->Reset();
m_pKoreanMSXSMS8000MemoryRule->Reset();
m_pMSXMemoryRule->Reset();
m_pJanggunMemoryRule->Reset();
m_pBootromMemoryRule->Reset();
Expand Down
2 changes: 2 additions & 0 deletions src/GearsystemCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class CodemastersMemoryRule;
class RomOnlyMemoryRule;
class SG1000MemoryRule;
class KoreanMemoryRule;
class KoreanMSXSMS8000MemoryRule;
class MSXMemoryRule;
class JanggunMemoryRule;
class MemoryRule;
Expand Down Expand Up @@ -107,6 +108,7 @@ class GearsystemCore
SG1000MemoryRule* m_pSG1000MemoryRule;
RomOnlyMemoryRule* m_pRomOnlyMemoryRule;
KoreanMemoryRule* m_pKoreanMemoryRule;
KoreanMSXSMS8000MemoryRule* m_pKoreanMSXSMS8000MemoryRule;
MSXMemoryRule* m_pMSXMemoryRule;
JanggunMemoryRule* m_pJanggunMemoryRule;
SmsIOPorts* m_pSmsIOPorts;
Expand Down
154 changes: 154 additions & 0 deletions src/KoreanMSXSMS8000MemoryRule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* 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 "KoreanMSXSMS8000MemoryRule.h"
#include "Memory.h"
#include "Cartridge.h"

KoreanMSXSMS8000MemoryRule::KoreanMSXSMS8000MemoryRule(Memory* pMemory, Cartridge* pCartridge, Input* pInput) : MemoryRule(pMemory, pCartridge, pInput)
{
Reset();
}

KoreanMSXSMS8000MemoryRule::~KoreanMSXSMS8000MemoryRule()
{
}

u8 KoreanMSXSMS8000MemoryRule::PerformRead(u16 address)
{
if (address < 0xC000)
{
int page = (address >> 13) & 0x03;
if (page > 5)
{
Debug("--> ** Invalid page %d", page);
return 0xFF;
}
return m_pCartridge->GetROM()[m_iPageAddress[page] + (address & 0x1FFF)];
}
else
{
// RAM + RAM mirror
return m_pMemory->Retrieve(address);
}
}

void KoreanMSXSMS8000MemoryRule::PerformWrite(u16 address, u8 value)
{
if (address < 0xC000)
{
if (address == 0x8000)
{
Debug("--> ** Writing to register $%X %X", address, value);

if (m_Register == 0xFF)
value ^= 0x22;

m_Register = value;

if (value & 0x80)
{
m_iPageAddress[0] = 0x2000 * ((value ^ 0x03) & (m_pCartridge->GetROMBankCount8k() - 1));
m_iPageAddress[1] = 0x2000 * ((value ^ 0x02) & (m_pCartridge->GetROMBankCount8k() - 1));
}
else
{
m_iPageAddress[0] = 0x2000 * (0x3C & (m_pCartridge->GetROMBankCount8k() - 1));
m_iPageAddress[1] = 0x2000 * (0x3C & (m_pCartridge->GetROMBankCount8k() - 1));
}

m_iPageAddress[2] = 0x2000 * ((value ^ 0x01) & (m_pCartridge->GetROMBankCount8k() - 1));
m_iPageAddress[3] = 0x2000 * ((value ^ 0x00) & (m_pCartridge->GetROMBankCount8k() - 1));
m_iPageAddress[4] = 0x2000 * ((value ^ 0x03) & (m_pCartridge->GetROMBankCount8k() - 1));
m_iPageAddress[5] = 0x2000 * ((value ^ 0x02) & (m_pCartridge->GetROMBankCount8k() - 1));
}
else
{
Debug("--> ** Attempting to write on ROM address $%X %X", address, value);
}
}
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 KoreanMSXSMS8000MemoryRule::Reset()
{
m_Register = 0;
m_iPageAddress[0] = 0x2000 * (0x3C);
m_iPageAddress[1] = 0x2000 * (0x3C);
m_iPageAddress[2] = 0x2000 * (m_Register ^ 0x01);
m_iPageAddress[3] = 0x2000 * (m_Register ^ 0x00);
m_iPageAddress[4] = 0x2000 * (m_Register ^ 0x03);
m_iPageAddress[5] = 0x2000 * (m_Register ^ 0x02);
}

u8* KoreanMSXSMS8000MemoryRule::GetPage(int index)
{
return 0;
// switch (index)
// {
// case 0:
// case 1:
// return m_pCartridge->GetROM() + (index * 0x4000);
// case 2:
// return m_pCartridge->GetROM() + m_iMapperSlot2Address;
// default:
// return NULL;
// }
}

int KoreanMSXSMS8000MemoryRule::GetBank(int index)
{
return 0;

// switch (index)
// {
// case 0:
// case 1:
// return index;
// case 2:
// return m_iMapperSlot2;
// default:
// return 0;
// }
}

void KoreanMSXSMS8000MemoryRule::SaveState(std::ostream& stream)
{
stream.write(reinterpret_cast<const char*> (m_iPageAddress), sizeof(m_iPageAddress));
stream.write(reinterpret_cast<const char*> (&m_Register), sizeof(m_Register));
}

void KoreanMSXSMS8000MemoryRule::LoadState(std::istream& stream)
{
using namespace std;

stream.read(reinterpret_cast<char*> (m_iPageAddress), sizeof(m_iPageAddress));
stream.read(reinterpret_cast<char*> (&m_Register), sizeof(m_Register));
}
Loading

0 comments on commit 5b6e275

Please sign in to comment.