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.
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.

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.
Received Exception Code 0xC0000005 @ EIP := 0x001D1C28(=unknown+0x0)
Press "OK" to terminate emulation.
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
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:
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.
Most helpful comment
Found the issue. CrashMonitor function from WndMain.cpp file think it has crashed. Hence the reason cause to "stop" emulation.