Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOS::HLE::Kernel::InitIPC: Replace s_ios check with Core::IsRunning #11186

Merged
merged 1 commit into from Oct 21, 2022

Conversation

GaryOderNichts
Copy link
Contributor

This avoids issues with devices relying on s_ios, which would be a nullptr while still in the constructor.
For example the ES device will call InitIPC which makes sure s_ios is not nullptr, which it always is while still in the constructor.

@leoetlino
Copy link
Member

leoetlino commented Oct 21, 2022

What problem does this solve? ES.cpp calls InitIPC by using its member variable m_ios, not the global emulation instance. And InitIPC is supposed to be a no-op when emulation is not running (hence the check for s_ios != nullptr - maybe it'd be clearer to replace that check with Core::IsRunningAndStarted(), though)

On the other hand, changing initialisation into a two-step process makes it possible to accidentally forget to call Init().

@GaryOderNichts
Copy link
Contributor Author

GaryOderNichts commented Oct 21, 2022

With the current way InitIPC will always be a no-op once ES calls it on creation, even if emulation is running.
Changing the nullptr check to Core::IsRunningAndStarted() would also work, I guess.

Edit: Core::IsRunningAndStarted() does not work as it returns false at the time IOS::HLE::Init is called.

@leoetlino
Copy link
Member

if (Core::IsRunningAndStarted())
{
CoreTiming::RemoveEvent(s_finish_init_event);
CoreTiming::ScheduleEvent(GetESBootTicks(m_ios.GetVersion()), s_finish_init_event);
}
else
{
FinishInit();
}

If emulation is running, then InitIPC() doesn't get called while the ESDevice is being constructed (from the FinishInit() in the else branch). Instead, it's invoked from a CoreTiming event callback. When that happens, both s_ios != nullptr and Core::IsRunningAndStarted() are true so InitIPC() does have an effect during emulation.

(It would be very obvious if InitIPC() never did anything, as people would have noticed ES launches being broken and emulated software hanging forever.)

One corner case: InitIPC is a no-op on the very first IOS launch (during boot / right before emulation is running). This is not a problem in practice because nothing is running on the PPC at that point and hence nothing will be expecting or even acknowledging the IPC ack. But it might be worthwhile to fix this anyway.

Edit: Core::IsRunningAndStarted() does not work as it returns false at the time IOS::HLE::Init is called.

To fix that particular case, we would probably want to use Core::IsRunning() instead.

@GaryOderNichts
Copy link
Contributor Author

My bad, I should've properly explained the issue I was having.
I'm currently working on getting Ancast images to work in dolphin (to launch the vWii System Menu, which comes as an ancast image).
I got the menu successfully loaded, but it got stuck in an endless loop, waiting for the Y2 bit of HW_IPC_PPCCTRL to become 1.
After some testing I noticed that InitIPC will never be called, due to the corner case you mentioned below:

One corner case: InitIPC is a no-op on the very first IOS launch (during boot / right before emulation is running). This is not a problem in practice because nothing is running on the PPC at that point and hence nothing will be expecting or even acknowledging the IPC ack. But it might be worthwhile to fix this anyway.

To fix that particular case, we would probably want to use Core::IsRunning() instead.

That does fix it as well. Should I change the PR to replace the s_ios check with Core::IsRunning()?

@leoetlino
Copy link
Member

Ah, that's a very interesting edge case :-) yeah I think we should avoid two-step initialisation and just fix the check in InitIPC.

Just curious, what launches the vWii system menu and Wii IOS on Wii U? I'm surprised the vWii system menu checks for the ack -- does it relaunch IOS?

@GaryOderNichts
Copy link
Contributor Author

GaryOderNichts commented Oct 21, 2022

Just curious, what launches the vWii system menu and Wii IOS on Wii U? I'm surprised the vWii system menu checks for the ack -- does it relaunch IOS?

This is actually a somewhat complicated process, since the Wii U doesn't go through boot0 - boot2 when entering vWii.
The process roughly looks like this:

  • While still in Wii U mode, IOSU (Wii U version of IOS) loads the IOS + System Menu into memory and launches cafe2wii (also a binary running on the Starlet (called Starbuck on the Wii U)).
  • cafe2wii sets up the vWii mode by lowering clockspeeds + disabling cores, setting up the limited memory mode, and disabling Wii U specific features. It then jumps to the IOS in memory.
  • The IOS boots up the PPC which starts the PPC bootROM. This bootrom now verifies the signed Ancast image and decrypts it.
  • The bootROM jumps to the decrypted Ancast body, which in this case is directly the System Menu (which contains it's own bootstub).

I'm not exactly sure what happens on the IOS side, as I haven't spent much time REing that yet.

@GaryOderNichts GaryOderNichts changed the title IOS::HLE::EmulationKernel: Move device construction out of constructor IOS::HLE::Kernel::InitIPC: Replace s_ios check with Core::IsRunning Oct 21, 2022
@leoetlino leoetlino merged commit 79e09c3 into dolphin-emu:master Oct 21, 2022
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
2 participants