diff --git a/src/core/bios.cpp b/src/core/bios.cpp index 193592ffc..4844b155a 100644 --- a/src/core/bios.cpp +++ b/src/core/bios.cpp @@ -96,7 +96,7 @@ static constexpr const BIOS::ImageInfo s_openbios_info = {"OpenBIOS", ConsoleReg static constexpr const char s_openbios_signature[] = {'O', 'p', 'e', 'n', 'B', 'I', 'O', 'S'}; static constexpr u32 s_openbios_signature_offset = 0x78; -static BIOS::Hash GetHash(const BIOS::Image& image) +BIOS::Hash BIOS::GetImageHash(const BIOS::Image& image) { BIOS::Hash hash; MD5Digest digest; @@ -132,17 +132,21 @@ std::optional BIOS::LoadImageFromFile(const char* filename) return std::nullopt; } - Log_DevPrint(fmt::format("Hash for BIOS '{}': {}", FileSystem::GetDisplayNameFromPath(filename), GetHash(ret).ToString()).c_str()); + Log_DevPrint(fmt::format("Hash for BIOS '{}': {}", FileSystem::GetDisplayNameFromPath(filename), GetImageHash(ret).ToString()).c_str()); return ret; } const BIOS::ImageInfo* BIOS::GetInfoForImage(const Image& image) { - const Hash hash(GetHash(image)); + const Hash hash(GetImageHash(image)); + return GetInfoForImage(image, hash); +} +const BIOS::ImageInfo* BIOS::GetInfoForImage(const Image& image, const Hash& hash) +{ // check for openbios if (image.size() >= (s_openbios_signature_offset + std::size(s_openbios_signature)) && - std::memcmp(&image[s_openbios_signature_offset], s_openbios_signature, std::size(s_openbios_signature)) == 0) + std::memcmp(&image[s_openbios_signature_offset], s_openbios_signature, std::size(s_openbios_signature)) == 0) { return &s_openbios_info; } diff --git a/src/core/bios.h b/src/core/bios.h index cf79af725..caa4d026b 100644 --- a/src/core/bios.h +++ b/src/core/bios.h @@ -59,8 +59,10 @@ static_assert(sizeof(PSEXEHeader) == 0x800); #pragma pack(pop) std::optional LoadImageFromFile(const char* filename); +Hash GetImageHash(const Image& image); const ImageInfo* GetInfoForImage(const Image& image); +const ImageInfo* GetInfoForImage(const Image& image, const Hash& hash); bool IsValidBIOSForRegion(ConsoleRegion console_region, ConsoleRegion bios_region); void PatchBIOS(u8* image, u32 image_size, u32 address, u32 value, u32 mask = UINT32_C(0xFFFFFFFF)); diff --git a/src/core/bus.cpp b/src/core/bus.cpp index 52a9a1079..ec5e85d2b 100644 --- a/src/core/bus.cpp +++ b/src/core/bus.cpp @@ -223,17 +223,6 @@ void SetExpansionROM(std::vector data) m_exp1_rom = std::move(data); } -void SetBIOS(const std::vector& image) -{ - if (image.size() != static_cast(BIOS_SIZE)) - { - Panic("Incorrect BIOS image size"); - return; - } - - std::memcpy(g_bios, image.data(), BIOS_SIZE); -} - std::tuple CalculateMemoryTiming(MEMDELAY mem_delay, COMDELAY common_delay) { // from nocash spec diff --git a/src/core/bus.h b/src/core/bus.h index aa55922e5..09469b48b 100644 --- a/src/core/bus.h +++ b/src/core/bus.h @@ -114,7 +114,6 @@ void UpdateFastmemViews(CPUFastmemMode mode); bool CanUseFastmemForAddress(VirtualMemoryAddress address); void SetExpansionROM(std::vector data); -void SetBIOS(const std::vector& image); extern std::bitset m_ram_code_bits; extern u8* g_ram; // 2MB-8MB RAM diff --git a/src/core/cpu_recompiler_code_generator_x64.cpp b/src/core/cpu_recompiler_code_generator_x64.cpp index a591d2294..439d754a1 100644 --- a/src/core/cpu_recompiler_code_generator_x64.cpp +++ b/src/core/cpu_recompiler_code_generator_x64.cpp @@ -2081,6 +2081,7 @@ void CodeGenerator::EmitStoreGuestMemoryFastmem(const CodeBlockInstruction& cbi, bpi.address_host_reg = HostReg_Invalid; bpi.value_host_reg = value.host_reg; bpi.guest_pc = m_current_instruction->pc; + bpi.fault_count = 0; if (g_settings.cpu_fastmem_mode == CPUFastmemMode::MMap) { diff --git a/src/core/system.cpp b/src/core/system.cpp index cf2adef70..c05ae33e6 100644 --- a/src/core/system.cpp +++ b/src/core/system.cpp @@ -96,6 +96,7 @@ static bool ReadExecutableFromImage(ISOReader& iso, std::string* out_executable_ static void StallCPU(TickCount ticks); +static bool LoadBIOS(); static void InternalReset(); static void ClearRunningGame(); static void DestroySystem(); @@ -139,6 +140,8 @@ TickCount System::g_ticks_per_second = System::MASTER_CLOCK; static TickCount s_max_slice_ticks = System::MASTER_CLOCK / 10; static u32 s_frame_number = 1; static u32 s_internal_frame_number = 1; +static const BIOS::ImageInfo* s_bios_image_info = nullptr; +static BIOS::Hash s_bios_hash = {}; static std::string s_running_game_path; static std::string s_running_game_serial; @@ -330,6 +333,16 @@ bool System::IsRunningBIOS() return s_running_bios; } +const BIOS::ImageInfo* System::GetBIOSImageInfo() +{ + return s_bios_image_info; +} + +const BIOS::Hash& System::GetBIOSHash() +{ + return s_bios_hash; +} + float System::GetFPS() { return s_fps; @@ -1217,11 +1230,8 @@ bool System::BootSystem(SystemBootParameters parameters) #endif // Load BIOS image. - std::optional bios_image(BIOS::GetBIOSImage(s_region)); - if (!bios_image) + if (!LoadBIOS()) { - Host::ReportFormattedErrorAsync("Error", Host::TranslateString("System", "Failed to load %s BIOS."), - Settings::GetConsoleRegionName(s_region)); s_state = State::Shutdown; ClearRunningGame(); Host::OnSystemDestroyed(); @@ -1240,17 +1250,15 @@ bool System::BootSystem(SystemBootParameters parameters) // Allow controller analog mode for EXEs and PSFs. s_running_bios = s_running_game_path.empty() && exe_boot.empty() && psf_boot.empty(); - Bus::SetBIOS(bios_image.value()); UpdateControllers(); UpdateMemoryCardTypes(); UpdateMultitaps(); InternalReset(); // Enable tty by patching bios. - const BIOS::ImageInfo* bios_info = BIOS::GetInfoForImage(bios_image.value()); if (g_settings.bios_patch_tty_enable) { - if (bios_info && bios_info->patch_compatible) + if (s_bios_image_info && s_bios_image_info->patch_compatible) BIOS::PatchBIOSEnableTTY(Bus::g_bios, Bus::BIOS_SIZE); else Log_ErrorPrintf("Not patching TTY enable, as BIOS is not patch compatible."); @@ -1276,7 +1284,7 @@ bool System::BootSystem(SystemBootParameters parameters) if (CDROM::HasMedia() && (parameters.override_fast_boot.has_value() ? parameters.override_fast_boot.value() : g_settings.bios_patch_fast_boot)) { - if (bios_info && bios_info->patch_compatible) + if (s_bios_image_info && s_bios_image_info->patch_compatible) BIOS::PatchBIOSFastBoot(Bus::g_bios, Bus::BIOS_SIZE); else Log_ErrorPrintf("Not patching fast boot, as BIOS is not patch compatible."); @@ -1497,6 +1505,9 @@ void System::DestroySystem() Host::ReleaseHostDisplay(); } + s_bios_hash = {}; + s_bios_image_info = nullptr; + Host::OnSystemDestroyed(); } @@ -1755,6 +1766,33 @@ bool System::DoState(StateWrapper& sw, GPUTexture** host_texture, bool update_di return !sw.HasError(); } +bool System::LoadBIOS() +{ + std::optional bios_image(BIOS::GetBIOSImage(s_region)); + if (!bios_image.has_value()) + { + Host::ReportFormattedErrorAsync("Error", Host::TranslateString("System", "Failed to load %s BIOS."), + Settings::GetConsoleRegionName(s_region)); + return false; + } + + if (bios_image->size() != static_cast(Bus::BIOS_SIZE)) + { + Host::ReportFormattedErrorAsync("Error", Host::TranslateString("System", "Incorrect BIOS image size")); + return false; + } + + s_bios_hash = BIOS::GetImageHash(bios_image.value()); + s_bios_image_info = BIOS::GetInfoForImage(bios_image.value(), s_bios_hash); + if (s_bios_image_info) + Log_InfoPrintf("Using BIOS: %s", s_bios_image_info->description); + else + Log_WarningPrintf("Using an unknown BIOS: %s", s_bios_image_info->hash.ToString().c_str()); + + std::memcpy(Bus::g_bios, bios_image->data(), Bus::BIOS_SIZE); + return true; +} + void System::InternalReset() { if (IsShutdown()) diff --git a/src/core/system.h b/src/core/system.h index 73004cef0..7dfd22902 100644 --- a/src/core/system.h +++ b/src/core/system.h @@ -19,6 +19,12 @@ class Controller; struct CheatCode; class CheatList; +namespace BIOS +{ +struct ImageInfo; +struct Hash; +} + struct SystemBootParameters { SystemBootParameters(); @@ -174,7 +180,10 @@ void IncrementInternalFrameNumber(); const std::string& GetRunningPath(); const std::string& GetRunningSerial(); const std::string& GetRunningTitle(); + bool IsRunningBIOS(); +const BIOS::ImageInfo* GetBIOSImageInfo(); +const BIOS::Hash& GetBIOSHash(); // TODO: Move to PerformanceMetrics static constexpr u32 NUM_FRAME_TIME_SAMPLES = 150;