System: Support changing BIOS path

This commit is contained in:
Connor McLaughlin 2019-11-11 18:19:57 +10:00
parent 7b6a2f1aaf
commit 6f4cf7d5e3
21 changed files with 93 additions and 77 deletions

View File

@ -1,6 +1,7 @@
#include "bus.h" #include "bus.h"
#include "YBaseLib/ByteStream.h" #include "YBaseLib/ByteStream.h"
#include "YBaseLib/Log.h" #include "YBaseLib/Log.h"
#include "YBaseLib/MD5Digest.h"
#include "YBaseLib/String.h" #include "YBaseLib/String.h"
#include "cdrom.h" #include "cdrom.h"
#include "common/state_wrapper.h" #include "common/state_wrapper.h"
@ -31,12 +32,9 @@ Bus::Bus() = default;
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) Pad* pad, Timers* timers, SPU* spu, MDEC* mdec)
{ {
if (!LoadBIOS())
return false;
m_cpu = cpu; m_cpu = cpu;
m_dma = dma; m_dma = dma;
m_interrupt_controller = interrupt_controller; m_interrupt_controller = interrupt_controller;
@ -46,7 +44,6 @@ bool Bus::Initialize(CPU::Core* cpu, DMA* dma, InterruptController* interrupt_co
m_timers = timers; m_timers = timers;
m_spu = spu; m_spu = spu;
m_mdec = mdec; m_mdec = mdec;
return true;
} }
void Bus::Reset() 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()); old_disasm.GetCharArray(), new_value, new_disasm.GetCharArray());
} }
void Bus::GetBIOSHash(u8 hash[16])
{
MD5Digest digest;
digest.Update(m_bios.data(), static_cast<u32>(m_bios.size()));
digest.Final(hash);
}
void Bus::SetExpansionROM(std::vector<u8> data) void Bus::SetExpansionROM(std::vector<u8> data)
{ {
m_exp1_rom = std::move(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) if (!fp)
{
Log_ErrorPrintf("Failed to open BIOS image '%s'", filename);
return false; return false;
}
std::fseek(fp, 0, SEEK_END); std::fseek(fp, 0, SEEK_END);
const u32 size = static_cast<u32>(std::ftell(fp)); const u32 size = static_cast<u32>(std::ftell(fp));
@ -217,13 +224,6 @@ bool Bus::LoadBIOS()
} }
std::fclose(fp); std::fclose(fp);
#if 1
// Patch to enable TTY.
PatchBIOS(BIOS_BASE + 0x6F0C, 0x24010001);
PatchBIOS(BIOS_BASE + 0x6F14, 0xAF81A9C0);
#endif
return true; return true;
} }

View File

@ -27,11 +27,15 @@ public:
Bus(); Bus();
~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); Timers* timers, SPU* spu, MDEC* mdec);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); 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 ReadByte(PhysicalMemoryAddress address, u8* value);
bool ReadHalfWord(PhysicalMemoryAddress address, u16* value); bool ReadHalfWord(PhysicalMemoryAddress address, u16* value);
bool ReadWord(PhysicalMemoryAddress address, u32* value); bool ReadWord(PhysicalMemoryAddress address, u32* value);
@ -46,7 +50,6 @@ public:
TickCount ReadWords(PhysicalMemoryAddress address, u32* words, u32 word_count); TickCount ReadWords(PhysicalMemoryAddress address, u32* words, u32 word_count);
TickCount WriteWords(PhysicalMemoryAddress address, const 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<u8> data); void SetExpansionROM(std::vector<u8> data);
// changing interfaces // changing interfaces
@ -154,8 +157,6 @@ private:
}; };
}; };
bool LoadBIOS();
static std::tuple<TickCount, TickCount, TickCount> CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay); static std::tuple<TickCount, TickCount, TickCount> CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay);
void RecalculateMemoryTimings(); void RecalculateMemoryTimings();

View File

@ -16,13 +16,12 @@ CDROM::CDROM()
CDROM::~CDROM() = default; 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_system = system;
m_dma = dma; m_dma = dma;
m_interrupt_controller = interrupt_controller; m_interrupt_controller = interrupt_controller;
m_spu = spu; m_spu = spu;
return true;
} }
void CDROM::Reset() void CDROM::Reset()

View File

@ -22,7 +22,7 @@ public:
CDROM(); CDROM();
~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(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -38,7 +38,7 @@ Core::Core() = default;
Core::~Core() = default; Core::~Core() = default;
bool Core::Initialize(Bus* bus) void Core::Initialize(Bus* bus)
{ {
m_bus = bus; m_bus = bus;
@ -46,8 +46,6 @@ bool Core::Initialize(Bus* bus)
m_cop0_regs.PRID = UINT32_C(0x00000002); m_cop0_regs.PRID = UINT32_C(0x00000002);
m_cop2.Initialize(); m_cop2.Initialize();
return true;
} }
void Core::Reset() void Core::Reset()

View File

@ -24,7 +24,7 @@ public:
Core(); Core();
~Core(); ~Core();
bool Initialize(Bus* bus); void Initialize(Bus* bus);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -14,7 +14,7 @@ DMA::DMA() = default;
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) SPU* spu, MDEC* mdec)
{ {
m_system = system; m_system = system;
@ -25,7 +25,6 @@ bool DMA::Initialize(System* system, Bus* bus, InterruptController* interrupt_co
m_spu = spu; m_spu = spu;
m_mdec = mdec; m_mdec = mdec;
m_transfer_buffer.resize(32); m_transfer_buffer.resize(32);
return true;
} }
void DMA::Reset() void DMA::Reset()

View File

@ -35,7 +35,7 @@ public:
DMA(); DMA();
~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); MDEC* mdec);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -8,10 +8,9 @@ InterruptController::InterruptController() = default;
InterruptController::~InterruptController() = default; InterruptController::~InterruptController() = default;
bool InterruptController::Initialize(CPU::Core* cpu) void InterruptController::Initialize(CPU::Core* cpu)
{ {
m_cpu = cpu; m_cpu = cpu;
return true;
} }
void InterruptController::Reset() void InterruptController::Reset()

View File

@ -32,7 +32,7 @@ public:
InterruptController(); InterruptController();
~InterruptController(); ~InterruptController();
bool Initialize(CPU::Core* cpu); void Initialize(CPU::Core* cpu);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -11,11 +11,10 @@ MDEC::MDEC() = default;
MDEC::~MDEC() = default; MDEC::~MDEC() = default;
bool MDEC::Initialize(System* system, DMA* dma) void MDEC::Initialize(System* system, DMA* dma)
{ {
m_system = system; m_system = system;
m_dma = dma; m_dma = dma;
return true;
} }
void MDEC::Reset() void MDEC::Reset()

View File

@ -15,7 +15,7 @@ public:
MDEC(); MDEC();
~MDEC(); ~MDEC();
bool Initialize(System* system, DMA* dma); void Initialize(System* system, DMA* dma);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -12,11 +12,10 @@ Pad::Pad() = default;
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_system = system;
m_interrupt_controller = interrupt_controller; m_interrupt_controller = interrupt_controller;
return true;
} }
void Pad::Reset() void Pad::Reset()

View File

@ -18,7 +18,7 @@ public:
Pad(); Pad();
~Pad(); ~Pad();
bool Initialize(System* system, InterruptController* interrupt_controller); void Initialize(System* system, InterruptController* interrupt_controller);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -19,13 +19,12 @@ SPU::SPU() = default;
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_audio_stream = system->GetHostInterface()->GetAudioStream();
m_system = system; m_system = system;
m_dma = dma; m_dma = dma;
m_interrupt_controller = interrupt_controller; m_interrupt_controller = interrupt_controller;
return true;
} }
void SPU::Reset() void SPU::Reset()

View File

@ -17,7 +17,7 @@ public:
SPU(); SPU();
~SPU(); ~SPU();
bool Initialize(System* system, DMA* dma, InterruptController* interrupt_controller); void Initialize(System* system, DMA* dma, InterruptController* interrupt_controller);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -19,8 +19,16 @@
#include <imgui.h> #include <imgui.h>
Log_SetChannel(System); Log_SetChannel(System);
System::System(HostInterface* host_interface) namespace BIOSHashes {
: m_host_interface(host_interface) 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<CPU::Core>(); m_cpu = std::make_unique<CPU::Core>();
m_bus = std::make_unique<Bus>(); m_bus = std::make_unique<Bus>();
@ -64,44 +72,28 @@ bool System::RecreateGPU()
bool System::Initialize() bool System::Initialize()
{ {
if (!m_cpu->Initialize(m_bus.get())) m_cpu->Initialize(m_bus.get());
return false; 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_dma->Initialize(this, m_bus.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), m_spu.get(),
m_pad.get(), m_timers.get(), m_spu.get(), m_mdec.get())) m_mdec.get());
{
return false;
}
if (!m_dma->Initialize(this, m_bus.get(), m_interrupt_controller.get(), m_gpu.get(), m_cdrom.get(), m_spu.get(), m_interrupt_controller->Initialize(m_cpu.get());
m_mdec.get()))
{
return false;
}
if (!m_interrupt_controller->Initialize(m_cpu.get())) m_cdrom->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_spu.get());
return false; 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()) if (!CreateGPU())
return false; return false;
if (!m_cdrom->Initialize(this, m_dma.get(), m_interrupt_controller.get(), m_spu.get())) if (!LoadBIOS())
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()))
return false; return false;
UpdateMemoryCards(); UpdateMemoryCards();
return true; return true;
} }
@ -144,6 +136,38 @@ bool System::CreateGPU()
return true; 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) bool System::DoState(StateWrapper& sw)
{ {
if (!sw.DoMarker("System")) if (!sw.DoMarker("System"))

View File

@ -78,6 +78,7 @@ public:
private: private:
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);
bool CreateGPU(); bool CreateGPU();
bool LoadBIOS();
HostInterface* m_host_interface; HostInterface* m_host_interface;
std::unique_ptr<CPU::Core> m_cpu; std::unique_ptr<CPU::Core> m_cpu;

View File

@ -10,11 +10,10 @@ Timers::Timers() = default;
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_system = system;
m_interrupt_controller = interrupt_controller; m_interrupt_controller = interrupt_controller;
return true;
} }
void Timers::Reset() void Timers::Reset()

View File

@ -14,7 +14,7 @@ public:
Timers(); Timers();
~Timers(); ~Timers();
bool Initialize(System* system, InterruptController* interrupt_controller); void Initialize(System* system, InterruptController* interrupt_controller);
void Reset(); void Reset();
bool DoState(StateWrapper& sw); bool DoState(StateWrapper& sw);

View File

@ -903,7 +903,7 @@ void SDLHostInterface::DrawSettingsWindow()
ImGui::Text("BIOS Path:"); ImGui::Text("BIOS Path:");
ImGui::SameLine(indent); 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); ImGui::Checkbox("Enable Speed Limiter", &m_settings.speed_limiter_enabled);
@ -1029,9 +1029,8 @@ void SDLHostInterface::DrawSettingsWindow()
ImGui::End(); ImGui::End();
if (settings_changed) if (settings_changed)
{ SaveSettings();
// TODO: Save to file
}
if (gpu_settings_changed && m_system) if (gpu_settings_changed && m_system)
m_system->GetGPU()->UpdateSettings(); m_system->GetGPU()->UpdateSettings();
} }