System: Support loading expansion ROMs

This commit is contained in:
Connor McLaughlin 2019-09-23 01:28:00 +10:00
parent 5d1c12c9ad
commit 20f14688ca
8 changed files with 138 additions and 10 deletions

View file

@ -42,6 +42,7 @@ static int Run(int argc, char* argv[])
// parameters // parameters
const char* filename = nullptr; const char* filename = nullptr;
const char* exp1_filename = nullptr;
TinyString state_filename; TinyString state_filename;
for (int i = 1; i < argc; i++) for (int i = 1; i < argc; i++)
{ {
@ -50,6 +51,8 @@ static int Run(int argc, char* argv[])
if (CHECK_ARG_PARAM("-state")) if (CHECK_ARG_PARAM("-state"))
state_filename = SDLInterface::GetSaveStateFilename(std::strtoul(argv[++i], nullptr, 10)); state_filename = SDLInterface::GetSaveStateFilename(std::strtoul(argv[++i], nullptr, 10));
else if (CHECK_ARG_PARAM("-exp1"))
exp1_filename = argv[++i];
else else
filename = argv[i]; filename = argv[i];
@ -58,7 +61,7 @@ static int Run(int argc, char* argv[])
} }
// create system // create system
if (!host_interface->InitializeSystem(filename, state_filename.IsEmpty() ? nullptr : state_filename.GetCharArray())) if (!host_interface->InitializeSystem(filename, exp1_filename, state_filename.IsEmpty() ? nullptr : state_filename.GetCharArray()))
{ {
host_interface.reset(); host_interface.reset();
SDL_Quit(); SDL_Quit();

View file

@ -112,6 +112,11 @@ void Bus::PatchBIOS(u32 address, u32 value, u32 mask /*= UINT32_C(0xFFFFFFFF)*/)
old_disasm.GetCharArray(), new_value, new_disasm.GetCharArray()); old_disasm.GetCharArray(), new_value, new_disasm.GetCharArray());
} }
void Bus::SetExpansionROM(std::vector<u8> data)
{
m_exp1_rom = std::move(data);
}
bool Bus::LoadBIOS() bool Bus::LoadBIOS()
{ {
std::FILE* fp = std::fopen("SCPH1001.BIN", "rb"); std::FILE* fp = std::fopen("SCPH1001.BIN", "rb");
@ -175,7 +180,49 @@ bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, Physical
return true; return true;
} }
bool Bus::ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value) bool Bus::DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value)
{
if (m_exp1_rom.empty())
return DoInvalidAccess(MemoryAccessType::Read, size, EXP1_BASE | offset, EXP1_BASE | offset, value);
if (offset == 0x20018)
{
// Bit 0 - Action Replay On/Off
return UINT32_C(1);
}
const u32 transfer_size = u32(1) << static_cast<u32>(size);
if ((offset + transfer_size) > m_exp1_rom.size())
{
value = UINT32_C(0);
return true;
}
if (size == MemoryAccessSize::Byte)
{
value = ZeroExtend32(m_exp1_rom[offset]);
}
else if (size == MemoryAccessSize::HalfWord)
{
u16 halfword;
std::memcpy(&halfword, &m_exp1_rom[offset], sizeof(halfword));
value = ZeroExtend32(halfword);
}
else
{
std::memcpy(&value, &m_exp1_rom[offset], sizeof(value));
}
// Log_DevPrintf("EXP1 read: 0x%08X -> 0x%08X", EXP1_BASE | offset, value);
return true;
}
bool Bus::DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value)
{
return DoInvalidAccess(MemoryAccessType::Write, size, EXP1_BASE | offset, EXP1_BASE | offset, value);
}
bool Bus::DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value)
{ {
offset &= EXP2_MASK; offset &= EXP2_MASK;
@ -189,7 +236,7 @@ bool Bus::ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value)
return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, EXP2_BASE | offset, value); return DoInvalidAccess(MemoryAccessType::Read, size, EXP2_BASE | offset, EXP2_BASE | offset, value);
} }
bool Bus::WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value) bool Bus::DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value)
{ {
offset &= EXP2_MASK; offset &= EXP2_MASK;
@ -233,6 +280,22 @@ bool Bus::DoWritePad(MemoryAccessSize size, u32 offset, u32 value)
return true; return true;
} }
bool Bus::DoReadSIO(MemoryAccessSize size, u32 offset, u32& value)
{
Log_ErrorPrintf("SIO Read 0x%08X", offset);
value = 0;
if (offset == 0x04)
value = 0x5;
return true;
}
bool Bus::DoWriteSIO(MemoryAccessSize size, u32 offset, u32 value)
{
Log_ErrorPrintf("SIO Write 0x%08X <- 0x%08X", offset, value);
return true;
}
bool Bus::DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value) bool Bus::DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value)
{ {
// TODO: Splitting of half/word reads. // TODO: Splitting of half/word reads.

View file

@ -40,11 +40,18 @@ public:
bool DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value); bool DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value);
void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF));
void SetExpansionROM(std::vector<u8> data);
private: private:
static constexpr u32 EXP1_BASE = 0x1F000000;
static constexpr u32 EXP1_SIZE = 0x800000;
static constexpr u32 EXP1_MASK = EXP1_SIZE - 1;
static constexpr u32 PAD_BASE = 0x1F801040; static constexpr u32 PAD_BASE = 0x1F801040;
static constexpr u32 PAD_SIZE = 0x10; static constexpr u32 PAD_SIZE = 0x10;
static constexpr u32 PAD_MASK = PAD_SIZE - 1; static constexpr u32 PAD_MASK = PAD_SIZE - 1;
static constexpr u32 SIO_BASE = 0x1F801050;
static constexpr u32 SIO_SIZE = 0x10;
static constexpr u32 SIO_MASK = SIO_SIZE - 1;
static constexpr u32 INTERRUPT_CONTROLLER_BASE = 0x1F801070; static constexpr u32 INTERRUPT_CONTROLLER_BASE = 0x1F801070;
static constexpr u32 INTERRUPT_CONTROLLER_SIZE = 0x08; static constexpr u32 INTERRUPT_CONTROLLER_SIZE = 0x08;
static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1; static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1;
@ -80,12 +87,18 @@ private:
bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address, bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address,
PhysicalMemoryAddress bus_address, u32& value); PhysicalMemoryAddress bus_address, u32& value);
bool ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value); bool DoReadEXP1(MemoryAccessSize size, u32 offset, u32& value);
bool WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value); bool DoWriteEXP1(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadEXP2(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadPad(MemoryAccessSize size, u32 offset, u32& value); bool DoReadPad(MemoryAccessSize size, u32 offset, u32& value);
bool DoWritePad(MemoryAccessSize size, u32 offset, u32 value); bool DoWritePad(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadSIO(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteSIO(MemoryAccessSize size, u32 offset, u32 value);
bool DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value); bool DoReadCDROM(MemoryAccessSize size, u32 offset, u32& value);
bool DoWriteCDROM(MemoryAccessSize size, u32 offset, u32 value); bool DoWriteCDROM(MemoryAccessSize size, u32 offset, u32 value);
@ -114,6 +127,7 @@ private:
std::array<u8, 2097152> m_ram{}; // 2MB RAM std::array<u8, 2097152> m_ram{}; // 2MB RAM
std::array<u8, 524288> m_bios{}; // 512K BIOS ROM std::array<u8, 524288> m_bios{}; // 512K BIOS ROM
std::vector<u8> m_exp1_rom;
String m_tty_line_buffer; String m_tty_line_buffer;
}; };

View file

@ -80,6 +80,15 @@ bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddres
{ {
return DoRAMAccess<type, size>(bus_address, value); return DoRAMAccess<type, size>(bus_address, value);
} }
else if (bus_address < EXP1_BASE)
{
return DoInvalidAccess(type, size, cpu_address, bus_address, value);
}
else if (bus_address < (EXP1_BASE + EXP1_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadEXP1(size, bus_address & EXP1_MASK, value) :
DoWriteEXP1(size, bus_address & EXP1_MASK, value);
}
else if (bus_address < PAD_BASE) else if (bus_address < PAD_BASE)
{ {
return DoInvalidAccess(type, size, cpu_address, bus_address, value); return DoInvalidAccess(type, size, cpu_address, bus_address, value);
@ -89,6 +98,11 @@ bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddres
return (type == MemoryAccessType::Read) ? DoReadPad(size, bus_address & PAD_MASK, value) : return (type == MemoryAccessType::Read) ? DoReadPad(size, bus_address & PAD_MASK, value) :
DoWritePad(size, bus_address & PAD_MASK, value); DoWritePad(size, bus_address & PAD_MASK, value);
} }
else if (bus_address < (SIO_BASE + SIO_SIZE))
{
return (type == MemoryAccessType::Read) ? DoReadSIO(size, bus_address & SIO_MASK, value) :
DoWriteSIO(size, bus_address & SIO_MASK, value);
}
else if (bus_address < INTERRUPT_CONTROLLER_BASE) else if (bus_address < INTERRUPT_CONTROLLER_BASE)
{ {
return DoInvalidAccess(type, size, cpu_address, bus_address, value); return DoInvalidAccess(type, size, cpu_address, bus_address, value);
@ -150,8 +164,8 @@ bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddres
} }
else if (bus_address < (EXP2_BASE + EXP2_SIZE)) else if (bus_address < (EXP2_BASE + EXP2_SIZE))
{ {
return (type == MemoryAccessType::Read) ? ReadExpansionRegion2(size, bus_address & EXP2_MASK, value) : return (type == MemoryAccessType::Read) ? DoReadEXP2(size, bus_address & EXP2_MASK, value) :
WriteExpansionRegion2(size, bus_address & EXP2_MASK, value); DoWriteEXP2(size, bus_address & EXP2_MASK, value);
} }
else if (bus_address < BIOS_BASE) else if (bus_address < BIOS_BASE)
{ {

View file

@ -8,7 +8,7 @@ HostInterface::HostInterface() = default;
HostInterface::~HostInterface() = default; HostInterface::~HostInterface() = default;
bool HostInterface::InitializeSystem(const char* filename, const char* save_state_filename) bool HostInterface::InitializeSystem(const char* filename, const char* exp1_filename, const char* save_state_filename)
{ {
m_system = std::make_unique<System>(this); m_system = std::make_unique<System>(this);
if (!m_system->Initialize()) if (!m_system->Initialize())
@ -42,6 +42,9 @@ bool HostInterface::InitializeSystem(const char* filename, const char* save_stat
} }
} }
if (exp1_filename)
m_system->SetExpansionROM(exp1_filename);
if (save_state_filename) if (save_state_filename)
LoadState(save_state_filename); LoadState(save_state_filename);

View file

@ -14,7 +14,7 @@ public:
HostInterface(); HostInterface();
virtual ~HostInterface(); virtual ~HostInterface();
bool InitializeSystem(const char* filename, const char* save_state_filename); bool InitializeSystem(const char* filename, const char* exp1_filename, const char* save_state_filename);
virtual void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height) = 0; virtual void SetDisplayTexture(GL::Texture* texture, u32 offset_x, u32 offset_y, u32 width, u32 height) = 0;
virtual void ReportMessage(const char* message) = 0; virtual void ReportMessage(const char* message) = 0;

View file

@ -1,5 +1,5 @@
#include "system.h" #include "system.h"
#include "YBaseLib/ByteStream.h" #include "YBaseLib/Log.h"
#include "bus.h" #include "bus.h"
#include "cdrom.h" #include "cdrom.h"
#include "common/state_wrapper.h" #include "common/state_wrapper.h"
@ -10,6 +10,8 @@
#include "pad.h" #include "pad.h"
#include "pad_device.h" #include "pad_device.h"
#include "timers.h" #include "timers.h"
#include <cstdio>
Log_SetChannel(System);
System::System(HostInterface* host_interface) : m_host_interface(host_interface) System::System(HostInterface* host_interface) : m_host_interface(host_interface)
{ {
@ -209,6 +211,34 @@ bool System::LoadEXE(const char* filename)
return true; return true;
} }
bool System::SetExpansionROM(const char* filename)
{
std::FILE* fp = std::fopen(filename, "rb");
if (!fp)
{
Log_ErrorPrintf("Failed to open '%s'", filename);
return false;
}
std::fseek(fp, 0, SEEK_END);
const u32 size = static_cast<u32>(std::ftell(fp));
std::fseek(fp, 0, SEEK_SET);
std::vector<u8> data(size);
if (std::fread(data.data(), size, 1, fp) != 1)
{
Log_ErrorPrintf("Failed to read ROM data from '%s'", filename);
std::fclose(fp);
return false;
}
std::fclose(fp);
Log_InfoPrintf("Loaded expansion ROM from '%s': %u bytes", filename, size);
m_bus->SetExpansionROM(std::move(data));
return true;
}
void System::Synchronize() void System::Synchronize()
{ {
m_cpu->ResetDowncount(); m_cpu->ResetDowncount();

View file

@ -41,6 +41,7 @@ public:
void RunFrame(); void RunFrame();
bool LoadEXE(const char* filename); bool LoadEXE(const char* filename);
bool SetExpansionROM(const char* filename);
void SetDowncount(TickCount downcount); void SetDowncount(TickCount downcount);
void Synchronize(); void Synchronize();