IOS: Hang PPC when reloading IOS for a PPC title launch

The PPC is supposed to be held in reset when another version of IOS is
in the process of being launched for a PPC title launch.

Probably doesn't matter in practice, though the inaccuracy was
definitely observable from the PPC.
This commit is contained in:
Léo Lam 2021-02-26 17:11:47 +01:00
parent 19667cb801
commit 93f0d122c0
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
4 changed files with 23 additions and 13 deletions

View File

@ -127,7 +127,7 @@ void ESDevice::FinishInit()
if (s_title_to_launch != 0) if (s_title_to_launch != 0)
{ {
NOTICE_LOG_FMT(IOS, "Re-launching title after IOS reload."); NOTICE_LOG_FMT(IOS, "Re-launching title after IOS reload.");
LaunchTitle(s_title_to_launch, true); LaunchTitle(s_title_to_launch, HangPPC::No, true);
s_title_to_launch = 0; s_title_to_launch = 0;
} }
} }
@ -270,7 +270,7 @@ IPCReply ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
return IPCReply(IPC_SUCCESS); return IPCReply(IPC_SUCCESS);
} }
bool ESDevice::LaunchTitle(u64 title_id, bool skip_reload) bool ESDevice::LaunchTitle(u64 title_id, HangPPC hang_ppc, bool skip_reload)
{ {
m_title_context.Clear(); m_title_context.Clear();
INFO_LOG_FMT(IOS_ES, "ES_Launch: Title context changed: (none)"); INFO_LOG_FMT(IOS_ES, "ES_Launch: Title context changed: (none)");
@ -290,15 +290,15 @@ bool ESDevice::LaunchTitle(u64 title_id, bool skip_reload)
// likely make the system menu crash. Doing this is okay as anyone who has the shop // likely make the system menu crash. Doing this is okay as anyone who has the shop
// also has the system menu installed, and this behaviour is consistent with what // also has the system menu installed, and this behaviour is consistent with what
// ES does when its DRM system refuses the use of a particular title. // ES does when its DRM system refuses the use of a particular title.
return LaunchTitle(Titles::SYSTEM_MENU); return LaunchTitle(Titles::SYSTEM_MENU, hang_ppc);
} }
if (IsTitleType(title_id, ES::TitleType::System) && title_id != Titles::SYSTEM_MENU) if (IsTitleType(title_id, ES::TitleType::System) && title_id != Titles::SYSTEM_MENU)
return LaunchIOS(title_id); return LaunchIOS(title_id, hang_ppc);
return LaunchPPCTitle(title_id, skip_reload); return LaunchPPCTitle(title_id, skip_reload);
} }
bool ESDevice::LaunchIOS(u64 ios_title_id) bool ESDevice::LaunchIOS(u64 ios_title_id, HangPPC hang_ppc)
{ {
// A real Wii goes through several steps before getting to MIOS. // A real Wii goes through several steps before getting to MIOS.
// //
@ -311,7 +311,7 @@ bool ESDevice::LaunchIOS(u64 ios_title_id)
if (ios_title_id == Titles::BC) if (ios_title_id == Titles::BC)
{ {
NOTICE_LOG_FMT(IOS, "BC: Launching MIOS..."); NOTICE_LOG_FMT(IOS, "BC: Launching MIOS...");
return LaunchIOS(Titles::MIOS); return LaunchIOS(Titles::MIOS, hang_ppc);
} }
// IOS checks whether the system title is installed and returns an error if it isn't. // IOS checks whether the system title is installed and returns an error if it isn't.
@ -323,7 +323,7 @@ bool ESDevice::LaunchIOS(u64 ios_title_id)
const ES::TicketReader ticket = FindSignedTicket(ios_title_id); const ES::TicketReader ticket = FindSignedTicket(ios_title_id);
ES::Content content; ES::Content content;
if (!tmd.IsValid() || !ticket.IsValid() || !tmd.GetContent(tmd.GetBootIndex(), &content) || if (!tmd.IsValid() || !ticket.IsValid() || !tmd.GetContent(tmd.GetBootIndex(), &content) ||
!m_ios.BootIOS(ios_title_id, GetContentPath(ios_title_id, content))) !m_ios.BootIOS(ios_title_id, hang_ppc, GetContentPath(ios_title_id, content)))
{ {
PanicAlertFmtT("Could not launch IOS {0:016x} because it is missing from the NAND.\n" PanicAlertFmtT("Could not launch IOS {0:016x} because it is missing from the NAND.\n"
"The emulated software will likely hang now.", "The emulated software will likely hang now.",
@ -333,7 +333,7 @@ bool ESDevice::LaunchIOS(u64 ios_title_id)
return true; return true;
} }
return m_ios.BootIOS(ios_title_id); return m_ios.BootIOS(ios_title_id, hang_ppc);
} }
bool ESDevice::LaunchPPCTitle(u64 title_id, bool skip_reload) bool ESDevice::LaunchPPCTitle(u64 title_id, bool skip_reload)
@ -364,7 +364,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id, bool skip_reload)
{ {
s_title_to_launch = title_id; s_title_to_launch = title_id;
const u64 required_ios = tmd.GetIOSId(); const u64 required_ios = tmd.GetIOSId();
return LaunchTitle(required_ios); return LaunchTitle(required_ios, HangPPC::Yes);
} }
m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiWAD); m_title_context.Update(tmd, ticket, DiscIO::Platform::WiiWAD);

View File

@ -47,7 +47,7 @@ public:
static void FinalizeEmulationState(); static void FinalizeEmulationState();
ReturnCode DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket); ReturnCode DIVerify(const ES::TMDReader& tmd, const ES::TicketReader& ticket);
bool LaunchTitle(u64 title_id, bool skip_reload = false); bool LaunchTitle(u64 title_id, HangPPC hang_ppc = HangPPC::No, bool skip_reload = false);
void DoState(PointerWrap& p) override; void DoState(PointerWrap& p) override;
@ -346,7 +346,7 @@ private:
ContextArray::iterator FindActiveContext(s32 fd); ContextArray::iterator FindActiveContext(s32 fd);
ContextArray::iterator FindInactiveContext(); ContextArray::iterator FindInactiveContext();
bool LaunchIOS(u64 ios_title_id); bool LaunchIOS(u64 ios_title_id, HangPPC hang_ppc);
bool LaunchPPCTitle(u64 title_id, bool skip_reload); bool LaunchPPCTitle(u64 title_id, bool skip_reload);
bool IsActiveTitlePermittedByTicket(const u8* ticket_view) const; bool IsActiveTitlePermittedByTicket(const u8* ticket_view) const;

View File

@ -433,7 +433,7 @@ static constexpr SystemTimers::TimeBaseTick GetIOSBootTicks(u32 version)
// Passing a boot content path is optional because we do not require IOSes // Passing a boot content path is optional because we do not require IOSes
// to be installed at the moment. If one is passed, the boot binary must exist // to be installed at the moment. If one is passed, the boot binary must exist
// on the NAND, or the call will fail like on a Wii. // on the NAND, or the call will fail like on a Wii.
bool Kernel::BootIOS(const u64 ios_title_id, const std::string& boot_content_path) bool Kernel::BootIOS(const u64 ios_title_id, HangPPC hang_ppc, const std::string& boot_content_path)
{ {
// IOS suspends regular PPC<->ARM IPC before loading a new IOS. // IOS suspends regular PPC<->ARM IPC before loading a new IOS.
// IPC is not resumed if the boot fails for any reason. // IPC is not resumed if the boot fails for any reason.
@ -453,6 +453,9 @@ bool Kernel::BootIOS(const u64 ios_title_id, const std::string& boot_content_pat
return false; return false;
} }
if (hang_ppc == HangPPC::Yes)
ResetAndPausePPC();
if (Core::IsRunningAndStarted()) if (Core::IsRunningAndStarted())
CoreTiming::ScheduleEvent(GetIOSBootTicks(GetVersion()), s_event_finish_ios_boot, ios_title_id); CoreTiming::ScheduleEvent(GetIOSBootTicks(GetVersion()), s_event_finish_ios_boot, ios_title_id);
else else

View File

@ -97,6 +97,12 @@ enum class MemorySetupType
Full, Full,
}; };
enum class HangPPC : bool
{
No = false,
Yes = true,
};
void RAMOverrideForIOSMemoryValues(MemorySetupType setup_type); void RAMOverrideForIOSMemoryValues(MemorySetupType setup_type);
void WriteReturnValue(s32 value, u32 address); void WriteReturnValue(s32 value, u32 address);
@ -132,7 +138,8 @@ public:
u16 GetGidForPPC() const; u16 GetGidForPPC() const;
bool BootstrapPPC(const std::string& boot_content_path); bool BootstrapPPC(const std::string& boot_content_path);
bool BootIOS(u64 ios_title_id, const std::string& boot_content_path = ""); bool BootIOS(u64 ios_title_id, HangPPC hang_ppc = HangPPC::No,
const std::string& boot_content_path = {});
void InitIPC(); void InitIPC();
u32 GetVersion() const; u32 GetVersion() const;