mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-18 06:25:37 +00:00
System: Support changing BIOS path
This commit is contained in:
parent
7b6a2f1aaf
commit
6f4cf7d5e3
|
@ -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<u32>(m_bios.size()));
|
||||
digest.Final(hash);
|
||||
}
|
||||
|
||||
void Bus::SetExpansionROM(std::vector<u8> 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<u32>(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<u8> data);
|
||||
|
||||
// changing interfaces
|
||||
|
@ -154,8 +157,6 @@ private:
|
|||
};
|
||||
};
|
||||
|
||||
bool LoadBIOS();
|
||||
|
||||
static std::tuple<TickCount, TickCount, TickCount> CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay);
|
||||
void RecalculateMemoryTimings();
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -24,7 +24,7 @@ public:
|
|||
Core();
|
||||
~Core();
|
||||
|
||||
bool Initialize(Bus* bus);
|
||||
void Initialize(Bus* bus);
|
||||
void Reset();
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -32,7 +32,7 @@ public:
|
|||
InterruptController();
|
||||
~InterruptController();
|
||||
|
||||
bool Initialize(CPU::Core* cpu);
|
||||
void Initialize(CPU::Core* cpu);
|
||||
void Reset();
|
||||
bool DoState(StateWrapper& sw);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -19,8 +19,16 @@
|
|||
#include <imgui.h>
|
||||
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<CPU::Core>();
|
||||
m_bus = std::make_unique<Bus>();
|
||||
|
@ -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"))
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
private:
|
||||
bool DoState(StateWrapper& sw);
|
||||
bool CreateGPU();
|
||||
bool LoadBIOS();
|
||||
|
||||
HostInterface* m_host_interface;
|
||||
std::unique_ptr<CPU::Core> m_cpu;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue