mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-03-31 09:42:06 +00:00
When the interpreter calls MSRUpdated, we should update the membase variable. Not because the interpreter itself needs it, but because the JIT needs it if it's falling back to the interpreter for an instruction that sets the MSR. Additionally, the JIT's FallBackToInterpreter needs to read back the new membase value afterwards. This fixes games crashing on JitArm64 if mtmsr is set to fall back to interpreter. I was unable to reproduce the issue on Jit64, presumably due to a fortunate series of coincidences (instructions that set MSR are always followed by an exception exit, and PowerPCManager::CheckExternalExceptions was always calling JitInterface::UpdateMembase, and Jit64::WriteExceptionExit was always calling Jit64::EmitUpdateMembase.)
110 lines
3.4 KiB
C++
110 lines
3.4 KiB
C++
// Copyright 2017 Dolphin Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include "Core/IOS/MIOS.h"
|
|
|
|
#include <cstring>
|
|
#include <utility>
|
|
|
|
#include "Common/Assert.h"
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/FileUtil.h"
|
|
#include "Common/Logging/Log.h"
|
|
#include "Common/MsgHandler.h"
|
|
#include "Common/Swap.h"
|
|
|
|
#include "Core/Config/MainSettings.h"
|
|
#include "Core/ConfigManager.h"
|
|
#include "Core/Core.h"
|
|
#include "Core/DSPEmulator.h"
|
|
#include "Core/HLE/HLE.h"
|
|
#include "Core/HW/DSP.h"
|
|
#include "Core/HW/DVD/DVDInterface.h"
|
|
#include "Core/HW/Memmap.h"
|
|
#include "Core/HW/SystemTimers.h"
|
|
#include "Core/HW/Wiimote.h"
|
|
#include "Core/Host.h"
|
|
#include "Core/PowerPC/PPCSymbolDB.h"
|
|
#include "Core/PowerPC/PowerPC.h"
|
|
#include "Core/System.h"
|
|
|
|
namespace IOS::HLE::MIOS
|
|
{
|
|
static void ReinitHardware(Core::System& system)
|
|
{
|
|
system.SetIsWii(false);
|
|
|
|
// IOS clears mem2 and overwrites it with pseudo-random data (for security).
|
|
auto& memory = system.GetMemory();
|
|
std::memset(memory.GetEXRAM(), 0, memory.GetExRamSizeReal());
|
|
// MIOS appears to only reset the DI and the PPC.
|
|
// HACK However, resetting DI will reset the DTK config, which is set by the system menu
|
|
// (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually
|
|
// reset DI fully, in such a way that the DTK config isn't cleared?
|
|
// system.GetDVDInterface().ResetDrive(true);
|
|
system.GetPowerPC().Reset();
|
|
Wiimote::ResetAllWiimotes();
|
|
// Note: this is specific to Dolphin and is required because we initialised it in Wii mode.
|
|
auto& dsp = system.GetDSP();
|
|
dsp.Reinit(Config::Get(Config::MAIN_DSP_HLE));
|
|
dsp.GetDSPEmulator()->Initialize(system.IsWii(), Config::Get(Config::MAIN_DSP_THREAD));
|
|
|
|
system.GetSystemTimers().ChangePPCClock(SystemTimers::Mode::GC);
|
|
}
|
|
|
|
constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8;
|
|
|
|
bool Load(Core::System& system)
|
|
{
|
|
auto& memory = system.GetMemory();
|
|
|
|
ASSERT(Core::IsCPUThread());
|
|
Core::CPUThreadGuard guard(system);
|
|
|
|
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
|
|
memory.Write_U32(0x09142001, 0x3180);
|
|
|
|
ReinitHardware(system);
|
|
NOTICE_LOG_FMT(IOS, "Reinitialised hardware.");
|
|
|
|
auto& power_pc = system.GetPowerPC();
|
|
auto& ppc_symbol_db = power_pc.GetSymbolDB();
|
|
|
|
// Load symbols for the IPL if they exist.
|
|
bool symbols_changed = ppc_symbol_db.Clear();
|
|
|
|
if (ppc_symbol_db.LoadMap(guard, File::GetUserPath(D_MAPS_IDX) + "mios-ipl.map"))
|
|
{
|
|
::HLE::Clear();
|
|
::HLE::PatchFunctions(system);
|
|
symbols_changed = true;
|
|
}
|
|
|
|
if (symbols_changed)
|
|
Host_PPCSymbolsChanged();
|
|
|
|
const PowerPC::CoreMode core_mode = power_pc.GetMode();
|
|
power_pc.SetMode(PowerPC::CoreMode::Interpreter);
|
|
|
|
PowerPC::PowerPCState& ppc_state = power_pc.GetPPCState();
|
|
ppc_state.msr.Hex = 0;
|
|
ppc_state.pc = 0x3400;
|
|
power_pc.MSRUpdated();
|
|
|
|
NOTICE_LOG_FMT(IOS, "Loaded MIOS and bootstrapped PPC.");
|
|
|
|
// IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes
|
|
// 0xdeadbeef there, then waits for it to be cleared by IOS before continuing.
|
|
while (memory.Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
|
|
power_pc.SingleStep();
|
|
power_pc.SetMode(core_mode);
|
|
|
|
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
|
|
NOTICE_LOG_FMT(IOS, "IPL ready.");
|
|
system.SetIsMIOS(true);
|
|
system.GetDVDInterface().UpdateRunningGameMetadata();
|
|
SConfig::OnTitleDirectlyBooted(guard);
|
|
return true;
|
|
}
|
|
} // namespace IOS::HLE::MIOS
|