VOGONS


Reply 100 of 406, by Baron von Riedesel

User metadata
Rank Member
Rank
Member
crazii wrote on 2023-02-06, 03:05:

That's cool! is it possible detect & switch to the module at runtime (support QEMM & the module both)? I was thinking about support different EMMs but not yet starting that. Sine this module almost have the same API like QEMM so I guess only tiny portion need to be adjusted, like detection/entry point and such.

Yes, it's dynamic. The adaption ( in qemm.c, function QEMM_GetVersion() ) is a bit hackish, though, because a real INT 2F has to be executed, not a simulated one. This can surely be improved by someone better aquainted with DJGPP peculiarities

    unsigned int result = _dos_open("QEMM386$", O_RDONLY, &fd);
// if(result != 0)
// return 0;
uint32_t entryfar = 0;
//ioctl - read from character device control channel
DPMI_REG r = {0};
if ( result == 0 ) {
int count = ioctl(fd, DOS_RCVDATA, 4, &entryfar);
_dos_close(fd);
if(count != 4)
return 0;
r.w.cs = entryfar>>16;
r.w.ip = entryfar&0xFFFF;
} else {
/* getting the entry point of QPIEMU is non-trivial in protected-mode, since
* the int 2Fh must be executed as interrupt ( not just "simulated" ). Here
* a small ( 3 bytes ) helper proc is constructed on the fly, at 0040:00D0,
* which is the INT 2Fh, followed by an RETF.
*/
asm(
"push ds \n\t"
"push $0x40 \n\t"
"pop ds \n\t"
"mov $0xd0, bx \n\t"
"mov $0xcb2fcd, (bx) \n\t"
"pop ds \n\t"
);
r.w.ax = 0x1684;
r.w.bx = 0x4354;
r.w.sp = 0; r.w.ss = 0;
r.w.cs = 0x40;
r.w.ip = 0xd0;
if( DPMI_CallRealModeRETF( &r) != 0 || (r.w.ax & 0xff))
return 0;
r.w.ip = r.w.di;
r.w.cs = r.w.es;
}
r.h.ah = 0x03;
QEMM_EntryIP = r.w.ip;
QEMM_EntryCS = r.w.cs;

Reply 101 of 406, by Baron von Riedesel

User metadata
Rank Member
Rank
Member

Made a preliminary Jemm release that has full support for QPIEMU:

https://github.com/Baron-von-Riedesel/Jemm/re … s/tag/v5.84pre1

There's also SBEMU.zip, that contains the slightly modified sbemu.exe, which is aware of QPIEMU.
SBEMU.EXE should work with current versions of Jemm, but for full support the new v5.84 is necessary. You'll hear the difference in Wolfenstein 3D.

Be aware that this is only for "real-mode" games!

Reply 102 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Bondi wrote on 2023-02-06, 18:51:

I also faced that some games don't run on tihs newer laptop no matter if the sbemu is loaded or not, due to other incompatibilities.
For instance setup.exe of Abuse won't run at all. I poked in setup.cfg and got digtal sound, but no music.
Overall my impression is that protected mode games are more compatible with sbemu+fast CPU setup.

Yes it's possible some games refuse to run in modern hardware, CPU speed / memory size might be the reason. Were you running those with HDPMI or not? I think you can try without HDPMI because the version of HDPMI that SBEMU used is hacked, LBA won't run but will with the original HDPMI, I'm afraid some game might be the same.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 103 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
digger wrote on 2023-02-06, 22:05:

By the way, @crazii, may I compliment you on the amazing work you've been doing on this? Legacy DOS sound card emulation has been something that I've been wanting to work on in my spare time for years. And except for taking a few beginners' steps into retro DOS sound and emulation programming, I never really got very far. And here you are, finally solving the notorious and persistent problem of getting sound card emulators to work with protected mode DOS games on modern hardware! 🦸🏻 Kudos.

Nahh, look at the beginning of the thread, I have no clue how to implement such emulation, its you guys that helped me sorted out. and the source code of VSB confirmed me that it's absolutely doable.
BTW I found info about ymfm, https://86box.readthedocs.io/en/latest/settings/sound.html it states that ymfm is moderate on performance & accuarcy. It might worth a try.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 104 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
digger wrote on 2023-02-06, 22:26:

It makes one wonder why not all new hardware interface standards are memory-mapped these days. Especially since port-mapped I/O isn't even supported in most non-x86 architectures. Or am I confusing things here?

I don't know much about NVMe, It seems first started at 2011, and HDA started at 2004 (by wiki pages). Since all PCI devices have PCI configuration space registers those are all port mapped. if including the PCI configuration registers, PIO is mandatory for HDA too, especially for device detection & initialization, It's just some little portion of the registers are optional: the immediate commands.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 105 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
georgel wrote on 2023-02-06, 23:56:

FYI MAME has more accurate Sound Blaster emulation than dosbox. They even run the actual creative's 8051 firmware (as far as I remember V4.13) on an emulated 8051 MCU.

Good to know that! For now only OPL3 emulation are used from third party codes. The Sound blaster part for SBEMU started from scratch and is very simple, it just records the DSP commands states (transfer bits/channels/sample rates) so that the the interrupt routine of the real sound card can read them and decide how to process the DMA buffer. Most of those DSP commands are well documented in the "Sound Blaster Series Hardware Programming Guide".
Also when I encounter unrecognized/undocumented DSP commands, I could found it in DOSBox source code, that will add MAME as a good source too. 😁

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 106 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Baron von Riedesel wrote on 2023-02-07, 04:36:
Yes, it's dynamic. The adaption ( in qemm.c, function QEMM_GetVersion() ) is a bit hackish, though, because a real INT 2F has to […]
Show full quote
crazii wrote on 2023-02-06, 03:05:

That's cool! is it possible detect & switch to the module at runtime (support QEMM & the module both)? I was thinking about support different EMMs but not yet starting that. Sine this module almost have the same API like QEMM so I guess only tiny portion need to be adjusted, like detection/entry point and such.

Yes, it's dynamic. The adaption ( in qemm.c, function QEMM_GetVersion() ) is a bit hackish, though, because a real INT 2F has to be executed, not a simulated one. This can surely be improved by someone better aquainted with DJGPP peculiarities

    unsigned int result = _dos_open("QEMM386$", O_RDONLY, &fd);
// if(result != 0)
// return 0;
uint32_t entryfar = 0;
//ioctl - read from character device control channel
DPMI_REG r = {0};
if ( result == 0 ) {
int count = ioctl(fd, DOS_RCVDATA, 4, &entryfar);
_dos_close(fd);
if(count != 4)
return 0;
r.w.cs = entryfar>>16;
r.w.ip = entryfar&0xFFFF;
} else {
/* getting the entry point of QPIEMU is non-trivial in protected-mode, since
* the int 2Fh must be executed as interrupt ( not just "simulated" ). Here
* a small ( 3 bytes ) helper proc is constructed on the fly, at 0040:00D0,
* which is the INT 2Fh, followed by an RETF.
*/
asm(
"push ds \n\t"
"push $0x40 \n\t"
"pop ds \n\t"
"mov $0xd0, bx \n\t"
"mov $0xcb2fcd, (bx) \n\t"
"pop ds \n\t"
);
r.w.ax = 0x1684;
r.w.bx = 0x4354;
r.w.sp = 0; r.w.ss = 0;
r.w.cs = 0x40;
r.w.ip = 0xd0;
if( DPMI_CallRealModeRETF( &r) != 0 || (r.w.ax & 0xff))
return 0;
r.w.ip = r.w.di;
r.w.cs = r.w.es;
}
r.h.ah = 0x03;
QEMM_EntryIP = r.w.ip;
QEMM_EntryCS = r.w.cs;

Cool! I think I'll include Jemm in the next publish. May I directly use your code in my repo, or I want start a Pull Request?

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 107 of 406, by Baron von Riedesel

User metadata
Rank Member
Rank
Member
crazii wrote on 2023-02-07, 07:25:

Cool! I think I'll include Jemm in the next publish. May I directly use your code in my repo, or I want start a Pull Request?

Please use it directly!

Reply 108 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Baron von Riedesel wrote on 2023-02-07, 14:30:
crazii wrote on 2023-02-07, 07:25:

Cool! I think I'll include Jemm in the next publish. May I directly use your code in my repo, or I want start a Pull Request?

Please use it directly!

OK, cool. I'm still struggling with the POPF problem of doom, if this problem can be solved, I will publish the binary with JEMM in another thread, but it seems not that easy.
I tried enable PVI but the cr4 seems never changes, always 0. I used the @mov_cr4_eax @mov_eax_cr4 macro.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 109 of 406, by Baron von Riedesel

User metadata
Rank Member
Rank
Member
crazii wrote on 2023-02-07, 14:51:

I tried enable PVI but the cr4 seems never changes, always 0. I used the @mov_cr4_eax @mov_eax_cr4 macro.

Perhaps Qemm does reset that bit?

I could also investigate this "POPF" problem, if you don't mind. Would need a kernel debugger aware version of your hdpmi32i. exe ( copy the ?WDEB386=1 switch in hdpmi32.mak to hdpmi32i.mak ), then make a clean build of the binary.

Reply 110 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Baron von Riedesel wrote on 2023-02-07, 19:41:
crazii wrote on 2023-02-07, 14:51:

I tried enable PVI but the cr4 seems never changes, always 0. I used the @mov_cr4_eax @mov_eax_cr4 macro.

Perhaps Qemm does reset that bit?

I could also investigate this "POPF" problem, if you don't mind. Would need a kernel debugger aware version of your hdpmi32i. exe ( copy the ?WDEB386=1 switch in hdpmi32.mak to hdpmi32i.mak ), then make a clean build of the binary.

Yes I removed QEMM earlier and cr4 works, now I'm testing skipping IRQ0 in intr08 to see what happens. Just wait a few minutes and I'll build a kernel debugger aware version. 😁

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 111 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie

Here is the HDPMI32i with -D?WDEB386=1 defined:

Filename
HDPMI32i.zip
File size
23.02 KiB
Downloads
47 downloads
File license
CC-BY-4.0

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 112 of 406, by Baron von Riedesel

User metadata
Rank Member
Rank
Member
crazii wrote on 2023-02-08, 06:21:

Here is the HDPMI32i with -D?WDEB386=1 defined:

Thanks! I played a bit with that yesterday. Some preliminary results:

1. there are at least 5 locations in doom.exe that have that CLI/POPF problem.
2. patching the one location that causes the freeze results in doom terminating with "transfer stack overflow"
3. the "transfer stack overflow" is actually an overflow of the DPMI "locked protected-mode stack", a result of
IRQs being handled while the previous IRQ isn't "finished" yet.
4. Your hdpmi32i.exe calls IO trap handlers with IOPL3. That's not really a good idea - for "untrapped" IO there's a special API function
5. The IO trap handlers are called with interrupt flag cleared (good!), but trace flag must also be cleared!

Generally, I think the DOS4GW freeze fix should be a bit postphoned until the protected-mode emulation runs stable.
Actually, I'd prefer to first adapt the sbemu source to the current "standard" hdpmi32i.

Reply 113 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Baron von Riedesel wrote on 2023-02-09, 06:45:
Thanks! I played a bit with that yesterday. Some preliminary results: […]
Show full quote
crazii wrote on 2023-02-08, 06:21:

Here is the HDPMI32i with -D?WDEB386=1 defined:

Thanks! I played a bit with that yesterday. Some preliminary results:

1. there are at least 5 locations in doom.exe that have that CLI/POPF problem.
2. patching the one location that causes the freeze results in doom terminating with "transfer stack overflow"
3. the "transfer stack overflow" is actually an overflow of the DPMI "locked protected-mode stack", a result of
IRQs being handled while the previous IRQ isn't "finished" yet.
4. Your hdpmi32i.exe calls IO trap handlers with IOPL3. That's not really a good idea - for "untrapped" IO there's a special API function
5. The IO trap handlers are called with interrupt flag cleared (good!), but trace flag must also be cleared!

Generally, I think the DOS4GW freeze fix should be a bit postphoned until the protected-mode emulation runs stable.
Actually, I'd prefer to first adapt the sbemu source to the current "standard" hdpmi32i.

Cool, thanks! when IOPL3 was used, the untrapped implementation was not added yet, it was added recently so I can change the code a little bit.

BTW I tested JEMM with QPIEMU and it works, except prince of persia 2 may suddenly have not digital sounds, I'll check this again.
and I've added a timeout to check if the VIF was cleared for too long, this fixed DOOM & Duke3D 's freeze when without SBEMU, but when SBEMU used, duke3d still works but doom still freeze or get a internal stack overflow.

Why there's a IRQs being handled while the previous IRQ isn't "finished"? I think the IF should be always cleared when handling IRQs.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 114 of 406, by georgel

User metadata
Rank Member
Rank
Member
crazii wrote on 2023-02-09, 08:55:

[Why there's a IRQs being handled while the previous IRQ isn't "finished"? I think the IF should be always cleared when handling IRQs.

Your interrupt handler may be calling other code that may unexpectedly to you reenable interrupts. If you are using a high-level language for your interrupt hanler you can't be sure your compiler hasn't reenabled interrupts in the compiled code. Another possibility is that NMI may be occurring.

Reply 115 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
georgel wrote on 2023-02-09, 09:49:
crazii wrote on 2023-02-09, 08:55:

[Why there's a IRQs being handled while the previous IRQ isn't "finished"? I think the IF should be always cleared when handling IRQs.

Your interrupt handler may be calling other code that may unexpectedly to you reenable interrupts. If you are using a high-level language for your interrupt hanler you can't be sure your compiler hasn't reenabled interrupts in the compiled code. Another possibility is that NMI may be occurring.

C/C++ Compilers usually doesn't do such things as enable interrupts, excepts for some special keywords such as 'interrupt'.
My IRQ handler may call IRQ5/7, that's the possible reason when IRQ5/7 uses STI at the end of its routine. I think. I've masked the all interrupts. but may need a CLI before unmask PIC.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 116 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie

Also found a weird thing: when EMM & HDPMI both exist, I preferred EMM's port trapping over HDPMI, but if HDPMI's port trap is preferred, this is a exception for some DOS/4GW games, I double checked the port trap code of HDPMI and found thing.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 117 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Baron von Riedesel wrote on 2023-02-09, 06:45:
Thanks! I played a bit with that yesterday. Some preliminary results: […]
Show full quote
crazii wrote on 2023-02-08, 06:21:

Here is the HDPMI32i with -D?WDEB386=1 defined:

Thanks! I played a bit with that yesterday. Some preliminary results:

1. there are at least 5 locations in doom.exe that have that CLI/POPF problem.
2. patching the one location that causes the freeze results in doom terminating with "transfer stack overflow"
3. the "transfer stack overflow" is actually an overflow of the DPMI "locked protected-mode stack", a result of
IRQs being handled while the previous IRQ isn't "finished" yet.
4. Your hdpmi32i.exe calls IO trap handlers with IOPL3. That's not really a good idea - for "untrapped" IO there's a special API function
5. The IO trap handlers are called with interrupt flag cleared (good!), but trace flag must also be cleared!

Generally, I think the DOS4GW freeze fix should be a bit postphoned until the protected-mode emulation runs stable.
Actually, I'd prefer to first adapt the sbemu source to the current "standard" hdpmi32i.

I've updated the HDPMI & SBEMU code following your advice, now IOPL0 is used and TF is also cleared.

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD

Reply 118 of 406, by Baron von Riedesel

User metadata
Rank Member
Rank
Member
crazii wrote on 2023-02-09, 13:22:

I've updated the HDPMI & SBEMU code following your advice, now IOPL0 is used and TF is also cleared.

Just for the record: the trace flag being cleared is preferable if one does single-step over an IN/OUT instruction. If TF is NOT cleared, the debugger stops inside the IO trap handler then.

Reply 119 of 406, by crazii

User metadata
Rank Oldbie
Rank
Oldbie
Baron von Riedesel wrote on 2023-02-09, 15:49:
crazii wrote on 2023-02-09, 13:22:

I've updated the HDPMI & SBEMU code following your advice, now IOPL0 is used and TF is also cleared.

Just for the record: the trace flag being cleared is preferable if one does single-step over an IN/OUT instruction. If TF is NOT cleared, the debugger stops inside the IO trap handler then.

Sure, I understand that. 😁

Toshiba Satellite Pro 4300 - YMF744, Savage IX
Toshiba Satellite 2805-S501 - YMF754, GeForce 2Go
IBM Thinkpad A21p - CS4624, Mobility Radeon 128
main: Intel NUC11PHKi7C Phantom Canyon: i7-1165G7 RTX2060 64G 2T760PSDD