Reply 1140 of 2419, by Dominus
- Rank
- DOSBox Moderator
You don't need a base Dosbox.
You don't need a base Dosbox.
Had to set the core to "normal". It even says to do so in the config file.
wrote:TheGreatCodeholio has not been here since last Sept. This branch is probably headed to extinction if no one else is willing to pick it up.
Sorry about that. Development on DOSBox-X has still been active on Github, don't worry.
wrote:I'm trying to test out DoxBox-X but I'm not sure if I have the latest x86 binary and I'm not sure what base system I should be using it with. (0.74? Daum?)
No matter what I do, I can't boot into Windows 98 SE. I've tried preexisting image installations and installing it myself. After the 98 logo, DosBox-X closes.
Can someone spin up a Win32 binary for me? I no longer make Win32 binaries. I do all development on Linux and I leave the Win32 code as-is in the codebase.
wrote:Does anyone know why the device manager in Windows 98 SE would give an error code 10 for the Soundblaster?
The latest versions of DOSBox-X allow you to enable/disable CSP/ASP SB16 emulation. Windows 98 apparently requires it to be enabled, or else it will ignore it.
I also want to add that the latest code fixes problems with the APM (Advanced Power Management) interface that was responsible for a lot of crashing in Windows 95 through ME. Perhaps that might have been the issue. In the latest code on my machine, I am able to run Windows 95 through ME without crashing at all in DOSBox-X using the normal core.
The latest advances and features in dosbox-x have made it very compatible with a Windows guest OS. Particularly interesting is the page fault code in the normal loop and cpu core. Tested 32-bit protected mode games with and without this code's "try..catch" block in normal_loop(). Even without the occurrence of exceptions, there is a small cost to the strategy. Is it possible to move the try..catch test outside the normal loop? The other try..catch blocks in the normal core had little effect on performance.
Also, is it true that compiler optimizations are disabled inside try..catch blocks? I tested this, too, and the performance difference was very minimal, so any disabled optimizations had little effect.
It might be possible, but, would require reorganizing the code quite a bit. It's little to no performance drop on Linux because of the way GCC handles try catch vs. the way Microsoft does it. It still has to disable the non-recursive mode to avoid jumping out of a callback routine since some (like INT 10h) require calling back into the OS if I/O ports are trapped.
Tested builds from different versions of gcc (v344, 462 and 464) with dwarf2 exception handling. These reportedly handle try..catch at no cost given no exceptions occur. However, tests show a small cost that is compounded inside an inner loop. Measured a 10% penalty at low frame rates with core=normal, but the emulation work flow is also affected.
wrote:Tested builds from different versions of gcc (v344, 462 and 464) with dwarf2 exception handling. These reportedly handle try..catch at no cost given no exceptions occur. However, tests show a small cost that is compounded inside an inner loop. Measured a 10% penalty at low frame rates with core=normal, but the emulation work flow is also affected.
Would it help any if the try ... catch were moved up so that the normal loop sets up the exception frame, then executes the while(1) / if (PIC_RunQueue() loop. A guest page fault would then break out of the loop and set up a CPU exception stack, then return out of the normal loop with return value 0 so that it eventually comes back to resume execution. As far as I understand the code.
That's a brilliant idea. It also makes sense to ensure the exception stack once the event occurs.
wrote:That's a brilliant idea. It also makes sense to ensure the exception stack once the event occurs.
Done. So far, doesn't seem to cause any issues with Win9x/ME or Windows 3.1 386 enhanced mode.
Thank you for the modified implementation of the exception handling! In testing, this had some effect on performance. But any small cost in performance is weighed against having Windows guest compatibility.
Do you think it is worthwhile in having a configure option to disable the page fault handling code? This would be for DOS use only.
wrote:Thank you for the modified implementation of the exception handling! In testing, this had some effect on performance. But any small cost in performance is weighed against having Windows guest compatibility.
Do you think it is worthwhile in having a configure option to disable the page fault handling code? This would be for DOS use only.
I haven't touched it in years, but the "non-recursive page fault" option is still there under the "cpu" section. Switch it off to reenable the old recursive fault model.
I ran DOSBox-X with Windows 3.0 through ME to stress test page fault handling, didn't see any issues.
Wonderful!
Also, I recall that there is code that enables "non-recursive page faults" wherever core=normal. I'll verify whether cpu.cpp has this code.
Edit:
if (cpudecoder == &CPU_Core_Normal_Run || cpudecoder == &CPU_Core_Prefetch_Run) {
if (!dosbox_enable_nonrecursive_page_fault) {
dosbox_enable_nonrecursive_page_fault = true;
_LOG(LOG_CPU,LOG_NORMAL)("normal/prefetch core requires nonrecursive page fault handling, turning it on");
}
}
wrote:Wonderful! […]
Wonderful!
Also, I recall that there is code that enables "non-recursive page faults" wherever core=normal. I'll verify whether cpu.cpp has this code.
Edit:
if (cpudecoder == &CPU_Core_Normal_Run || cpudecoder == &CPU_Core_Prefetch_Run) {
if (!dosbox_enable_nonrecursive_page_fault) {
dosbox_enable_nonrecursive_page_fault = true;
_LOG(LOG_CPU,LOG_NORMAL)("normal/prefetch core requires nonrecursive page fault handling, turning it on");
}
}
There's also code to temporarily turn off non-recursive page faults in cases where throwing an exception back out to the normal loop wouldn't work, such as when running callback instructions. It wouldn't work very well to have INT 10 emulation jump out in the middle of modesetting just because Windows 95 called it from vm86 mode.
Is there a way to detect booting of a guest OS and then require the non-recursive page faults? If possible, this would allow DOS games to run with the old model (presumably a performance benefit).
wrote:Is there a way to detect booting of a guest OS and then require the non-recursive page faults? If possible, this would allow DOS games to run with the old model (presumably a performance benefit).
Why detection code? The emulator is fully aware of what it's doing when it transitions from the DOS kernel to a guest OS. It happens in the SDL main loop when an int() exception is thrown to signal booting a guest OS. So if you'd like the non-recursive page fault option to change when booting a guest OS, that's the place to do it in the code.
Then this code block could be moved to that section in the SDL main loop?
if (!dosbox_enable_nonrecursive_page_fault) {
dosbox_enable_nonrecursive_page_fault = true;
_LOG(LOG_CPU,LOG_NORMAL)("normal/prefetch core requires nonrecursive page fault handling, turning it on");
}
Edit to here?
} catch (int x) {
if (x == 2) { /* booting a guest OS. "boot" has already done the work to load the image and setup CPU registers */
LOG(LOG_MISC,LOG_DEBUG)("Emulation threw a signal to boot guest OS");
run_machine = true; /* make note. don't run the whole shebang from an exception handler! */
dos_kernel_shutdown = !dos_kernel_disabled; /* only if DOS kernel enabled */
}
else if (x == 3) { /* reboot the system */
LOG(LOG_MISC,LOG_DEBUG)("Emulation threw a signal to reboot the system");
reboot_machine = true;
dos_kernel_shutdown = !dos_kernel_disabled; /* only if DOS kernel enabled */
wrote:Then this code block could be moved to that section in the SDL main loop? […]
Then this code block could be moved to that section in the SDL main loop?
if (!dosbox_enable_nonrecursive_page_fault) {
dosbox_enable_nonrecursive_page_fault = true;
_LOG(LOG_CPU,LOG_NORMAL)("normal/prefetch core requires nonrecursive page fault handling, turning it on");
}
Edit to here?
} catch (int x) {
if (x == 2) { /* booting a guest OS. "boot" has already done the work to load the image and setup CPU registers */
LOG(LOG_MISC,LOG_DEBUG)("Emulation threw a signal to boot guest OS");
run_machine = true; /* make note. don't run the whole shebang from an exception handler! */
dos_kernel_shutdown = !dos_kernel_disabled; /* only if DOS kernel enabled */
}
else if (x == 3) { /* reboot the system */
LOG(LOG_MISC,LOG_DEBUG)("Emulation threw a signal to reboot the system");
reboot_machine = true;
dos_kernel_shutdown = !dos_kernel_disabled; /* only if DOS kernel enabled */
Exactly! That part of the code is the part you want to edit if you want to implement anything during the DOS to guest OS transition.
Don't forget that in the latest code, the normal core no longer re-execs DOSBox-X on reboot, but throws another exception to make the SDL main loop come back around to starting up the DOS kernel again. So you'll also need to add code to undo your work if the guest OS reboots.