Cxbx-reloaded: Multi-Xbe Launch bug

Created on 17 May 2018  路  15Comments  路  Source: Cxbx-Reloaded/Cxbx-Reloaded

Sometimes it work as intended, sometimes it doesn't.

For example, Crimson Skies is using same xbe file as reboot. After several reboots, it can cause "Emulating title" state back to "Loaded title" as if there's a problem with launching another xbe. However, the gameplay had not changed.

Cxbx-Reloaded's GUI has a bug for multi-xbe launch. It needs investigation to find source of regression.

bug help wanted regression

Most helpful comment

Found the issue. CrashMonitor function from WndMain.cpp file think it has crashed. Hence the reason cause to "stop" emulation.

All 15 comments

It has to do with the handle of the child process - once an emulating process launches another emulating process, the host GUI process isn't notified (sufficiently?), so the GUI doesn't know the new emulation process ID thus can't query the child process state anymore. Perhaps this could be solved by writing the most recent process ID into EmuShared

From the pop up when running NFL Fever 2003:
WARN: Popup : Fatal error. Generic MS dashboard issue (dashboard not installed?). This error screen will persist indefinitely. Stop the emulation to close it.

dashboard issue

The emulation does stop but the image is still shown. If I start emulation again without shutting Cxbx first or reloading the game, it will start but the stop button is greyed out, and the start emulation option is available still. Error pops up after a few seconds, hitting ok gets you back to the xbox requires service screen like above.


Cxbx-Reloaded

Received Exception Code 0xC0000005 @ EIP := 0x001D1C28(=unknown+0x0)

Press "OK" to terminate emulation.

Press "Cancel" to debug.

OK Cancel

KrnlDebug2.txt

I can confirm that this (the OP's) issue happens on my end as well.

Shogun

I has been working on the fix. While fixing it, I noticed there is no SendMessage(CxbxKrnl_hEmuParent, WM_PARENTNOTIFY, WM_CREATE, 0); anywhere in the project even in kernel mode. I'm not entirely sure where it is obtaining new child's process id. Yet, I think I know where it could be at.
Actually WM_PARENTNOTIFY message was sent by kernel process' graphic window creation.

Currently working on using g_EmuShared's GetIsReady and SetIsReady function methods. This will prevent race condition between parent and child process causing problem for multi-xbe.

Found the issue. CrashMonitor function from WndMain.cpp file think it has crashed. Hence the reason cause to "stop" emulation.

I did a quick test: I added the following code to intentionally cause a crash upon a quick reboot and tested with Tenchu. On reboot and after closing the crash window that appears, the LED and FPS are not cleared, which means that CrashMonitor is still not catching this crash. I also discovered that the kernel quick reboot flag persists more than it should: after the crash, you will indefinitely get a quick reboot in the VMManager because the flag is still set. Clearing in CrashMonitor should fix this
capture
capture2

Waiting for CrashMonitor to close:
https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/feaea08ccd6c44197bdfffadd7553ad5a0ca5a2a/src/CxbxKrnl/CxbxKrnl.cpp#L942-L948

CrashMonitor handling:
https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/feaea08ccd6c44197bdfffadd7553ad5a0ca5a2a/src/Cxbx/WndMain.cpp#L2474-L2489

The only difference are m_bMultiXbeFlag is a boolean while m_BootFlags is integer. Is there a real reason for separate variables? It might be best to merge into m_BootFlags with enum flags.

If you believe it is an issue, please do re-open the issue.

This problem will arise if a title hard crashes (Windows app crash not cxbx crash) after it performed a quick reboot since the flag in this case is not cleared so that needs fixing. m_bMultiXbeFlag and m_BootFlags can be merged together since they both signal a reboot. However, when I tried it (when I wrote the VMManager) I was having issues (but now I don't remember which they were) so it's necessary to experiment with them

This problem will arise if a title hard crashes (Windows app crash not cxbx crash) after it performed a quick reboot since the flag in this case is not cleared so that needs fixing.

Okay, then at start of emulation. It needs a force default value. I do not see a default set in StartEmulation function for both m_bMultiXbeFlag and m_BootFlags.
https://github.com/Cxbx-Reloaded/Cxbx-Reloaded/blob/feaea08ccd6c44197bdfffadd7553ad5a0ca5a2a/src/Cxbx/WndMain.cpp#L2336
Since shared memory does not reset to default every time it start emulation.

And CrashMonitor thread doesn't start until openGL or DirectX create a window. It might be possible to start CrashMonitor earlier if we pass down the child's process id to ID_KRNL_IS_READY message. Which is before VManager initialize.

EDIT: I think we should have a reset function for EmuShared to set default (aka zero'd) for certain variables for start of emulating and within kernel process.

Here's a good solution to start CrashMonitor earlier:

case WM_USER: {
    switch(HIWORD(wParam)) {
        case ID_KRNL_IS_READY: {
            m_childProcID = (DWORD)lParam;
            ... // Including start CrashMonitor thread too.
        }
    }
}

Agree?

Adding the clearing to StartEmulation won't help with this, because that function is only called when a title is first launched, but the reboots are performed with HalReturnToFirmware. To fix this it's necessary to put the clearing in the CrashMonitor function and only when it has detected that a hard crash has occurred

Huh? When kernel process made a hard crash. CrashManager thread trigger a "stop" emulation which clear the status. Then the next start of emulation by user is still trigger by StartEmulation function.

Plus we shouldn't be relying on GUI to clear things for us on every reboots. The kernel process should be able to handle it.

Basically should be doing this method:

  • (GUI) Start Emulation

    1. (GUI) Reset certain shared variables to default value (normally zero'd)



      • Since shared variables doesn't reset to default after used in kernel process by shutdown, crash, or forced closed.



    2. (GUI / KRNL) Launch kernel process.



      • (KRNL) Send message to GUI (optional)





        • (KRNL) Wait for GUI is ready (temporary solution)



        • (GUI) Create CrashManager thread with given process id



        • (GUI) Response back with is ready (temporary solution)





      • (KRNL) Read and save EmuShared data locally


      • (KRNL) Reset certain shared variables to default value (normally zero'd)


      • (KRNL) Perform special tasks if certain variables aren't default.


      • HINT: This is where VMManager perform initialize task.


      • (KRNL) Start xbe emulation


      • (KRNL) Request ...





        • (KRNL) Reboot (repeat step 2 except launched from kernel side.)



        • (KRNL) Shutdown



        • (KRNL) Crash






NOTICE: Currently, CrashManager thread is created inside "Start xbe emulation". After VMManager initalized.

Realistically, if no GUI is used on launch. Then it should be able to load the settings from ini file AND be able to handle itself without GUI. Which is a separate issue.

Experimental branch to resolve this issue: repo's branch had been removed

More work will occur later on.

This was solved again by @RadWolfie in #1317.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Margen67 picture Margen67  路  3Comments

PatrickvL picture PatrickvL  路  3Comments

Kumoashi picture Kumoashi  路  3Comments

LukeUsher picture LukeUsher  路  3Comments

LukeUsher picture LukeUsher  路  4Comments