diff --git a/src/pse-sdl/main.cpp b/src/pse-sdl/main.cpp index d1316a756..d68b3a8c4 100644 --- a/src/pse-sdl/main.cpp +++ b/src/pse-sdl/main.cpp @@ -42,6 +42,7 @@ static int Run(int argc, char* argv[]) // parameters const char* filename = nullptr; + const char* exp1_filename = nullptr; TinyString state_filename; for (int i = 1; i < argc; i++) { @@ -50,6 +51,8 @@ static int Run(int argc, char* argv[]) if (CHECK_ARG_PARAM("-state")) state_filename = SDLInterface::GetSaveStateFilename(std::strtoul(argv[++i], nullptr, 10)); + else if (CHECK_ARG_PARAM("-exp1")) + exp1_filename = argv[++i]; else filename = argv[i]; @@ -58,7 +61,7 @@ static int Run(int argc, char* argv[]) } // 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(); SDL_Quit(); diff --git a/src/pse/bus.cpp b/src/pse/bus.cpp index a68d2d19f..681bec821 100644 --- a/src/pse/bus.cpp +++ b/src/pse/bus.cpp @@ -112,6 +112,11 @@ void Bus::PatchBIOS(u32 address, u32 value, u32 mask /*= UINT32_C(0xFFFFFFFF)*/) old_disasm.GetCharArray(), new_value, new_disasm.GetCharArray()); } +void Bus::SetExpansionROM(std::vector data) +{ + m_exp1_rom = std::move(data); +} + bool Bus::LoadBIOS() { std::FILE* fp = std::fopen("SCPH1001.BIN", "rb"); @@ -175,7 +180,49 @@ bool Bus::DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, Physical 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(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; @@ -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); } -bool Bus::WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value) +bool Bus::DoWriteEXP2(MemoryAccessSize size, u32 offset, u32 value) { offset &= EXP2_MASK; @@ -233,6 +280,22 @@ bool Bus::DoWritePad(MemoryAccessSize size, u32 offset, u32 value) 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) { // TODO: Splitting of half/word reads. diff --git a/src/pse/bus.h b/src/pse/bus.h index 81d576406..1a27e1eb0 100644 --- a/src/pse/bus.h +++ b/src/pse/bus.h @@ -40,11 +40,18 @@ public: bool DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value); void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); + void SetExpansionROM(std::vector data); 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_SIZE = 0x10; 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_SIZE = 0x08; static constexpr u32 INTERRUPT_CONTROLLER_MASK = INTERRUPT_CONTROLLER_SIZE - 1; @@ -80,12 +87,18 @@ private: bool DoInvalidAccess(MemoryAccessType type, MemoryAccessSize size, PhysicalMemoryAddress cpu_address, PhysicalMemoryAddress bus_address, u32& value); - bool ReadExpansionRegion2(MemoryAccessSize size, u32 offset, u32& value); - bool WriteExpansionRegion2(MemoryAccessSize size, u32 offset, u32 value); + bool DoReadEXP1(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 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 DoWriteCDROM(MemoryAccessSize size, u32 offset, u32 value); @@ -114,6 +127,7 @@ private: std::array m_ram{}; // 2MB RAM std::array m_bios{}; // 512K BIOS ROM + std::vector m_exp1_rom; String m_tty_line_buffer; }; diff --git a/src/pse/bus.inl b/src/pse/bus.inl index 9fd682009..46470c2a5 100644 --- a/src/pse/bus.inl +++ b/src/pse/bus.inl @@ -80,6 +80,15 @@ bool Bus::DispatchAccess(PhysicalMemoryAddress cpu_address, PhysicalMemoryAddres { return DoRAMAccess(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) { 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) : 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) { 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)) { - return (type == MemoryAccessType::Read) ? ReadExpansionRegion2(size, bus_address & EXP2_MASK, value) : - WriteExpansionRegion2(size, bus_address & EXP2_MASK, value); + return (type == MemoryAccessType::Read) ? DoReadEXP2(size, bus_address & EXP2_MASK, value) : + DoWriteEXP2(size, bus_address & EXP2_MASK, value); } else if (bus_address < BIOS_BASE) { diff --git a/src/pse/host_interface.cpp b/src/pse/host_interface.cpp index 9791a8b31..f7aeee13f 100644 --- a/src/pse/host_interface.cpp +++ b/src/pse/host_interface.cpp @@ -8,7 +8,7 @@ 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(this); 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) LoadState(save_state_filename); diff --git a/src/pse/host_interface.h b/src/pse/host_interface.h index 28c78fa9d..4127335b1 100644 --- a/src/pse/host_interface.h +++ b/src/pse/host_interface.h @@ -14,7 +14,7 @@ public: 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 ReportMessage(const char* message) = 0; diff --git a/src/pse/system.cpp b/src/pse/system.cpp index 18bbccad4..36323e071 100644 --- a/src/pse/system.cpp +++ b/src/pse/system.cpp @@ -1,5 +1,5 @@ #include "system.h" -#include "YBaseLib/ByteStream.h" +#include "YBaseLib/Log.h" #include "bus.h" #include "cdrom.h" #include "common/state_wrapper.h" @@ -10,6 +10,8 @@ #include "pad.h" #include "pad_device.h" #include "timers.h" +#include +Log_SetChannel(System); System::System(HostInterface* host_interface) : m_host_interface(host_interface) { @@ -209,6 +211,34 @@ bool System::LoadEXE(const char* filename) 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(std::ftell(fp)); + std::fseek(fp, 0, SEEK_SET); + + std::vector 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() { m_cpu->ResetDowncount(); diff --git a/src/pse/system.h b/src/pse/system.h index caca74a54..b073c3315 100644 --- a/src/pse/system.h +++ b/src/pse/system.h @@ -41,6 +41,7 @@ public: void RunFrame(); bool LoadEXE(const char* filename); + bool SetExpansionROM(const char* filename); void SetDowncount(TickCount downcount); void Synchronize();