diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 5b5b95c6e..2bcb8362a 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -1,6 +1,7 @@ #include "bus.h" #include "YBaseLib/ByteStream.h" #include "YBaseLib/Log.h" +#include "YBaseLib/MD5Digest.h" #include "YBaseLib/String.h" #include "cdrom.h" #include "common/state_wrapper.h" @@ -31,12 +32,9 @@ Bus::Bus() = default; Bus::~Bus() = default; -bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, +void Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, Pad* pad, Timers* timers, SPU* spu, MDEC* mdec) { - if (!LoadBIOS()) - return false; - m_cpu = cpu; m_dma = dma; m_interrupt_controller = interrupt_controller; @@ -46,7 +44,6 @@ bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_co m_timers = timers; m_spu = spu; m_mdec = mdec; - return true; } void Bus::Reset() @@ -187,16 +184,26 @@ void Bus::PatchBIOS(u32 address, u32 value, u32 mask /*= UINT32_C(0xFFFFFFFF)*/) old_disasm.GetCharArray(), new_value, new_disasm.GetCharArray()); } +void Bus::GetBIOSHash(u8 hash[16]) +{ + MD5Digest digest; + digest.Update(m_bios.data(), static_cast(m_bios.size())); + digest.Final(hash); +} + void Bus::SetExpansionROM(std::vector data) { m_exp1_rom = std::move(data); } -bool Bus::LoadBIOS() +bool Bus::LoadBIOS(const char* filename) { - std::FILE* fp = std::fopen("SCPH1001.BIN", "rb"); + std::FILE* fp = std::fopen(filename, "rb"); if (!fp) + { + Log_ErrorPrintf("Failed to open BIOS image '%s'", filename); return false; + } std::fseek(fp, 0, SEEK_END); const u32 size = static_cast(std::ftell(fp)); @@ -217,13 +224,6 @@ bool Bus::LoadBIOS() } std::fclose(fp); - -#if 1 - // Patch to enable TTY. - PatchBIOS(BIOS_BASE + 0x6F0C, 0x24010001); - PatchBIOS(BIOS_BASE + 0x6F14, 0xAF81A9C0); -#endif - return true; } diff --git a/src/core/bus.h b/src/core/bus.h index 9d4a28123..75138b69f 100644 --- a/src/core/bus.h +++ b/src/core/bus.h @@ -27,11 +27,15 @@ public: Bus(); ~Bus(); - bool Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, Pad* pad, + void Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, Pad* pad, Timers* timers, SPU* spu, MDEC* mdec); void Reset(); bool DoState(StateWrapper& sw); + bool LoadBIOS(const char* filename); + void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); + void GetBIOSHash(u8 hash[16]); + bool ReadByte(PhysicalMemoryAddress address, u8* value); bool ReadHalfWord(PhysicalMemoryAddress address, u16* value); bool ReadWord(PhysicalMemoryAddress address, u32* value); @@ -46,7 +50,6 @@ public: TickCount ReadWords(PhysicalMemoryAddress address, u32* words, u32 word_count); TickCount WriteWords(PhysicalMemoryAddress address, const u32* words, u32 word_count); - void PatchBIOS(u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); void SetExpansionROM(std::vector data); // changing interfaces @@ -154,8 +157,6 @@ private: }; }; - bool LoadBIOS(); - static std::tuple CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay); void RecalculateMemoryTimings(); diff --git a/src/core/cdrom.cpp b/src/core/cdrom.cpp index e2cae166d..b836a1667 100644 --- a/src/core/cdrom.cpp +++ b/src/core/cdrom.cpp @@ -16,13 +16,12 @@ CDROM::CDROM() CDROM::~CDROM() = default; -bool CDROM::Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, SPU* spu) +void CDROM::Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, SPU* spu) { m_system = system; m_dma = dma; m_interrupt_controller = interrupt_controller; m_spu = spu; - return true; } void CDROM::Reset() diff --git a/src/core/cdrom.h b/src/core/cdrom.h index 492da5f59..92caf21a9 100644 --- a/src/core/cdrom.h +++ b/src/core/cdrom.h @@ -22,7 +22,7 @@ public: CDROM(); ~CDROM(); - bool Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, SPU* spu); + void Initialize(System* system, DMA* dma, InterruptController* interrupt_controller, SPU* spu); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/cpu_core.cpp b/src/core/cpu_core.cpp index 20ed2e900..ad4d8e2a3 100644 --- a/src/core/cpu_core.cpp +++ b/src/core/cpu_core.cpp @@ -38,7 +38,7 @@ Core::Core() = default; Core::~Core() = default; -bool Core::Initialize(Bus* bus) +void Core::Initialize(Bus* bus) { m_bus = bus; @@ -46,8 +46,6 @@ bool Core::Initialize(Bus* bus) m_cop0_regs.PRID = UINT32_C(0x00000002); m_cop2.Initialize(); - - return true; } void Core::Reset() diff --git a/src/core/cpu_core.h b/src/core/cpu_core.h index 924d46bf3..cc8080419 100644 --- a/src/core/cpu_core.h +++ b/src/core/cpu_core.h @@ -24,7 +24,7 @@ public: Core(); ~Core(); - bool Initialize(Bus* bus); + void Initialize(Bus* bus); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/dma.cpp b/src/core/dma.cpp index 8a2d7fb56..bcec2ccff 100644 --- a/src/core/dma.cpp +++ b/src/core/dma.cpp @@ -14,7 +14,7 @@ DMA::DMA() = default; DMA::~DMA() = default; -bool DMA::Initialize(System* system, Bus* bus, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, +void DMA::Initialize(System* system, Bus* bus, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, SPU* spu, MDEC* mdec) { m_system = system; @@ -25,7 +25,6 @@ bool DMA::Initialize(System* system, Bus* bus, InterruptController* interrupt_co m_spu = spu; m_mdec = mdec; m_transfer_buffer.resize(32); - return true; } void DMA::Reset() diff --git a/src/core/dma.h b/src/core/dma.h index 6fa735bfe..310cec044 100644 --- a/src/core/dma.h +++ b/src/core/dma.h @@ -35,7 +35,7 @@ public: DMA(); ~DMA(); - bool Initialize(System* system, Bus* bus, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, SPU* spu, + void Initialize(System* system, Bus* bus, InterruptController* interrupt_controller, GPU* gpu, CDROM* cdrom, SPU* spu, MDEC* mdec); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/interrupt_controller.cpp b/src/core/interrupt_controller.cpp index 4b5bc47d9..7b14753c1 100644 --- a/src/core/interrupt_controller.cpp +++ b/src/core/interrupt_controller.cpp @@ -8,10 +8,9 @@ InterruptController::InterruptController() = default; InterruptController::~InterruptController() = default; -bool InterruptController::Initialize(CPU::Core* cpu) +void InterruptController::Initialize(CPU::Core* cpu) { m_cpu = cpu; - return true; } void InterruptController::Reset() diff --git a/src/core/interrupt_controller.h b/src/core/interrupt_controller.h index d6a4ec6c8..ab6cbd4d3 100644 --- a/src/core/interrupt_controller.h +++ b/src/core/interrupt_controller.h @@ -32,7 +32,7 @@ public: InterruptController(); ~InterruptController(); - bool Initialize(CPU::Core* cpu); + void Initialize(CPU::Core* cpu); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/mdec.cpp b/src/core/mdec.cpp index 15d16ed8b..81c641879 100644 --- a/src/core/mdec.cpp +++ b/src/core/mdec.cpp @@ -11,11 +11,10 @@ MDEC::MDEC() = default; MDEC::~MDEC() = default; -bool MDEC::Initialize(System* system, DMA* dma) +void MDEC::Initialize(System* system, DMA* dma) { m_system = system; m_dma = dma; - return true; } void MDEC::Reset() diff --git a/src/core/mdec.h b/src/core/mdec.h index c01510b40..c6cb73e68 100644 --- a/src/core/mdec.h +++ b/src/core/mdec.h @@ -15,7 +15,7 @@ public: MDEC(); ~MDEC(); - bool Initialize(System* system, DMA* dma); + void Initialize(System* system, DMA* dma); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/pad.cpp b/src/core/pad.cpp index eac92a26f..2149610fb 100644 --- a/src/core/pad.cpp +++ b/src/core/pad.cpp @@ -12,11 +12,10 @@ Pad::Pad() = default; Pad::~Pad() = default; -bool Pad::Initialize(System* system, InterruptController* interrupt_controller) +void Pad::Initialize(System* system, InterruptController* interrupt_controller) { m_system = system; m_interrupt_controller = interrupt_controller; - return true; } void Pad::Reset() diff --git a/src/core/pad.h b/src/core/pad.h index 36cc0050b..1b75e7925 100644 --- a/src/core/pad.h +++ b/src/core/pad.h @@ -18,7 +18,7 @@ public: Pad(); ~Pad(); - bool Initialize(System* system, InterruptController* interrupt_controller); + void Initialize(System* system, InterruptController* interrupt_controller); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/spu.cpp b/src/core/spu.cpp index cb79fa411..5437cc994 100644 --- a/src/core/spu.cpp +++ b/src/core/spu.cpp @@ -19,13 +19,12 @@ SPU::SPU() = default; SPU::~SPU() = default; -bool SPU::Initialize(System* system, DMA* dma, InterruptController* interrupt_controller) +void SPU::Initialize(System* system, DMA* dma, InterruptController* interrupt_controller) { m_audio_stream = system->GetHostInterface()->GetAudioStream(); m_system = system; m_dma = dma; m_interrupt_controller = interrupt_controller; - return true; } void SPU::Reset() diff --git a/src/core/spu.h b/src/core/spu.h index bfe22b42e..d8e4f96db 100644 --- a/src/core/spu.h +++ b/src/core/spu.h @@ -17,7 +17,7 @@ public: SPU(); ~SPU(); - bool Initialize(System* system, DMA* dma, InterruptController* interrupt_controller); + void Initialize(System* system, DMA* dma, InterruptController* interrupt_controller); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/core/system.cpp b/src/core/system.cpp index 73ae85ca0..1ba481f4f 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -19,8 +19,16 @@ #include Log_SetChannel(System); -System::System(HostInterface* host_interface) - : m_host_interface(host_interface) +namespace BIOSHashes { +static constexpr char SCPH_1000[] = "239665b1a3dade1b5a52c06338011044"; +static constexpr char SCPH_1001[] = "924e392ed05558ffdb115408c263dccf"; +static constexpr char SCPH_1002[] = "54847e693405ffeb0359c6287434cbef"; +static constexpr char SCPH_5500[] = "8dd7d5296a650fac7319bce665a6a53c"; +static constexpr char SCPH_5501[] = "490f666e1afb15b7362b406ed1cea246"; +static constexpr char SCPH_5502[] = "32736f17079d0b2b7024407c39bd3050"; +} // namespace BIOSHashes + +System::System(HostInterface* host_interface) : m_host_interface(host_interface) { m_cpu = std::make_unique(); m_bus = std::make_unique(); @@ -64,44 +72,28 @@ bool System::RecreateGPU() bool System::Initialize() { - if (!m_cpu->Initialize(m_bus.get())) - return false; + m_cpu->Initialize(m_bus.get()); + m_bus->Initialize(m_cpu.get(), m_dma.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), m_pad.get(), + m_timers.get(), m_spu.get(), m_mdec.get()); - if (!m_bus->Initialize(m_cpu.get(), m_dma.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), - m_pad.get(), m_timers.get(), m_spu.get(), m_mdec.get())) - { - return false; - } + m_dma->Initialize(this, m_bus.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), m_spu.get(), + m_mdec.get()); - if (!m_dma->Initialize(this, m_bus.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), m_spu.get(), - m_mdec.get())) - { - return false; - } + m_interrupt_controller->Initialize(m_cpu.get()); - if (!m_interrupt_controller->Initialize(m_cpu.get())) - return false; + m_cdrom->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_spu.get()); + m_pad->Initialize(this, m_interrupt_controller.get()); + m_timers->Initialize(this, m_interrupt_controller.get()); + m_spu->Initialize(this, m_dma.get(), m_interrupt_controller.get()); + m_mdec->Initialize(this, m_dma.get()); if (!CreateGPU()) return false; - if (!m_cdrom->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_spu.get())) - return false; - - if (!m_pad->Initialize(this, m_interrupt_controller.get())) - return false; - - if (!m_timers->Initialize(this, m_interrupt_controller.get())) - return false; - - if (!m_spu->Initialize(this, m_dma.get(), m_interrupt_controller.get())) - return false; - - if (!m_mdec->Initialize(this, m_dma.get())) + if (!LoadBIOS()) return false; UpdateMemoryCards(); - return true; } @@ -144,6 +136,38 @@ bool System::CreateGPU() return true; } +bool System::LoadBIOS() +{ + if (!m_bus->LoadBIOS(GetSettings().bios_path.c_str())) + return false; + + // apply patches + u8 bios_hash[16]; + m_bus->GetBIOSHash(bios_hash); + SmallString bios_hash_string; + bios_hash_string.Format("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", bios_hash[0], + bios_hash[1], bios_hash[2], bios_hash[3], bios_hash[4], bios_hash[5], bios_hash[6], + bios_hash[7], bios_hash[8], bios_hash[9], bios_hash[10], bios_hash[11], bios_hash[12], + bios_hash[13], bios_hash[14], bios_hash[15]); + Log_InfoPrintf("BIOS hash: %s", bios_hash_string.GetCharArray()); + + if (bios_hash_string == BIOSHashes::SCPH_1000 || bios_hash_string == BIOSHashes::SCPH_1001 || + bios_hash_string == BIOSHashes::SCPH_1002 || bios_hash_string == BIOSHashes::SCPH_5500 || + bios_hash_string == BIOSHashes::SCPH_5501 || bios_hash_string == BIOSHashes::SCPH_5502) + { + // Patch to enable TTY. + Log_InfoPrintf("Patching BIOS to enable TTY/printf"); + m_bus->PatchBIOS(0x1FC06F0C, 0x24010001); + m_bus->PatchBIOS(0x1FC06F14, 0xAF81A9C0); + } + else + { + Log_WarningPrintf("Unknown BIOS version, not patching TTY/printf"); + } + + return true; +} + bool System::DoState(StateWrapper& sw) { if (!sw.DoMarker("System")) diff --git a/src/core/system.h b/src/core/system.h index 760bc7573..e1cd33277 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -78,6 +78,7 @@ public: private: bool DoState(StateWrapper& sw); bool CreateGPU(); + bool LoadBIOS(); HostInterface* m_host_interface; std::unique_ptr m_cpu; diff --git a/src/core/timers.cpp b/src/core/timers.cpp index 30ab6cfbf..8dfde9f19 100644 --- a/src/core/timers.cpp +++ b/src/core/timers.cpp @@ -10,11 +10,10 @@ Timers::Timers() = default; Timers::~Timers() = default; -bool Timers::Initialize(System* system, InterruptController* interrupt_controller) +void Timers::Initialize(System* system, InterruptController* interrupt_controller) { m_system = system; m_interrupt_controller = interrupt_controller; - return true; } void Timers::Reset() diff --git a/src/core/timers.h b/src/core/timers.h index df6fb1543..1d55c6778 100644 --- a/src/core/timers.h +++ b/src/core/timers.h @@ -14,7 +14,7 @@ public: Timers(); ~Timers(); - bool Initialize(System* system, InterruptController* interrupt_controller); + void Initialize(System* system, InterruptController* interrupt_controller); void Reset(); bool DoState(StateWrapper& sw); diff --git a/src/duckstation/sdl_host_interface.cpp b/src/duckstation/sdl_host_interface.cpp index 1a521a2b1..ee2b57401 100644 --- a/src/duckstation/sdl_host_interface.cpp +++ b/src/duckstation/sdl_host_interface.cpp @@ -903,7 +903,7 @@ void SDLHostInterface::DrawSettingsWindow() ImGui::Text("BIOS Path:"); ImGui::SameLine(indent); - DrawFileChooser("##bios_path", &m_settings.bios_path); + settings_changed |= DrawFileChooser("##bios_path", &m_settings.bios_path); ImGui::Checkbox("Enable Speed Limiter", &m_settings.speed_limiter_enabled); @@ -1029,9 +1029,8 @@ void SDLHostInterface::DrawSettingsWindow() ImGui::End(); if (settings_changed) - { - // TODO: Save to file - } + SaveSettings(); + if (gpu_settings_changed && m_system) m_system->GetGPU()->UpdateSettings(); }