VOGONS


VOPL3 - Virtual OPL3 FM for Windows 98/ME

Topic actions

First post, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

Edit:
Latest release https://github.com/sdz-mods/VOPL3/releases/tag/A03

It does exactly what the title says, Virtual OPL3 FM for Windows 98/ME.

How it works:
VOPL3.VXD (ring-0 port trap -> ring buffer) -> VOPLSRV.EXE (drains the buffer, Nuked OPL3 -> waveOut -> KMIXER). It works alongside Microsoft's SBEMUL.SYS.

Installation:
run INSTALL.BAT. It does the following:
-makes a backup of SBEMUL.SYS, patches SBEMUL.SYS to stop binding to 388-38B ports and bind to 2A0-2A3 instead (hopefully these are unused). This is needed because SBEMUL only grabs those ports to fake AdLib detection, without doing any sort of FM emulation. If those ports are claimed before SBEMUL, it breaks digital audio as well.
-copies VOPL3.VXD to C:\WINDOWS\SYSTEM
-copies VOPLSRV.EXE to C:\VOPL3
-registers the VOPL3.VXD and VOPLSRV.EXE to they're loaded/start automatically at boot/login.

How to use:
After installation, set the game to use AdLib for music and Sound Blaster for sound effects. You will get OPL3 music via VOPL3 and digital sound effects via SBEMUL.

Github:
https://github.com/sdz-mods/VOPL3

Credits:
-nukeykt's Nuked-OPL3 https://github.com/nukeykt/Nuked-OPL3 - the actual OPL3 emulator inside VOPLSRV.EXE
-JHRobotics's vdmdisp9x https://github.com/JHRobotics/vmdisp9x - VxD glue (vmm.h io32.h code32.h) and for figuring out how to build an actually working VxD
-onethirdxcubed's WDMHDA https://github.com/andrew-hoffman/WDMHDA/releases -without which this project wouldn’t have made sense to me
-agovtman's Nuked-OPL3-fast fork https://github.com/tgies/Nuked-OPL3-fast
-Anthropic's Fable 5 - helped a lot

https://youtu.be/nyR7Ddocxrk

This is very much an alpha release, so any testing is appreciated.

Currently tested on:
Dell Precision M4800 with coreboot/SeaBIOS, running Windows 98 SE with WDMHDA
VirtualBox VM running Windows 98 SE with WDMHDA

So far, it has only been tested with HDA + WDMHDA, but it is not intended to be limited to that setup.

Last edited by sdz on 2026-07-12, 09:55. Edited 2 times in total.

Reply 1 of 24, by stanwebber

User metadata
Rank Member
Rank
Member

this patch rendered my win98se system un-bootable. i installed it on a compaq armada e500 laptop (p3 850mhz 440bx) with an ess maestro 2e soundcard. i switched from vxd to wdm drivers and everything checked out prior to the install. afterwards the system would boot to the desktop and play the windows startup sound, but then i would get an endless hourglass cursor and not be able to click on anything so my only recourse was a hard power-off.

i booted into a dos prompt and restored the original sbemul.sys, but this wasn't sufficient to render the system bootable. (i would recommend explicitly indicating the sbemul.sys path in your readme as you do for everything else. i think it's a hidden file so it was frustrating trying to locate it with a dos prompt unaided.) ultimately, i had to manually delete the vopl3.vxd to get back into windows and then run the uninstall.reg to clean things up.

the lockup in windows occurs suspiciously at the point when my wpa2 supplicant client (odyssey) would normally start--i never see the odyssey splash screen; however, i have no real evidence that any of this is connected. in any case, let me know if there's anything i can do to help track it down for you.

Reply 2 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

@stanwebber thanks for testing and sorry for the bad experience!

Yes, good idea about mentioning explicitly where the backup is located, I'll update that. Didn't do that because there is also an uninstall.bat, that unregisters and removes both VOPLSRV.EXE and VOPL3.VXD, and restores the original SBEMUL.SYS from the backup.
If the system does not boot into Windows, that uninstall.bat can still be run from DOS. It will remove VOPL3.VXD and VOPLSRV.EXE, restore SBEMUL.sys but fail at unregistering the two. Not a huge issue, during boot, windows will complain that it cannot find the VXD, you can press enter on that and it will boot normally. Then, either run again UNINSTALL.BAT from Windows or run only UNINSTALL.REG.

If you're willing to test some more, can you install it normally and before rebooting just remove (or better yet, rename) C:\VOPL3\VOPLSRV.EXE ?
If that works and it boots into Windows, please try to manually run the renamed VOPLSRV.EXE and see what happens.

Last edited by sdz on 2026-07-10, 17:38. Edited 2 times in total.

Reply 3 of 24, by stanwebber

User metadata
Rank Member
Rank
Member

renaming voplsrv.exe allows me to finish booting normally, but as soon as i rename and execute voplsrv.exe from within windows i get an endless hourglass cursor and have to hard power-off.

Reply 4 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

-when you get that hourglass cursor, is the mouse cursor still moving?
-does pressing Ctrl+Alt+Del do anything?

A few tests to run, all without the VOPLSRV.EXE binary (remove it or rename it), VXD must be installed, as well as your ESS WDM driver.
-with Media Player, play the attached .wav file and report if it works.

Attached archive that contains a couple of tests. Run them from an MS-DOS Command Prompt. Report if it freezes, and if there's any output in the console. If a specific test freezes, please reboot. If it does not, kill it with Ctrl+Alt+Del before proceeding to the next test (or reboot the system).

-test2, this is the VOPLSRV with normal priority, debug output and logging
-test3, this is the VOPLSRV with realtime priority, debug output and logging
-test4, VXD test, without registering the audio path, will exit after 30 seconds if it doesn't freeze the system
-test5 audio path test, 48Khz, without involving the VXD, will exit after 30 seconds if it doesn't freeze the system
-test6 audio path test, 44.1Khz, without involving the VXD, will exit after 30 seconds if it doesn't freeze the system

At the end, please attach C:\Srvtest*.log files, if any.

Reply 5 of 24, by stanwebber

User metadata
Rank Member
Rank
Member

the wav file played successfully and none of the tests locked up the system. test 2 & 3 just kept running so after awhile i hit ctrl-c to end the tests.

when voplsrv.exe locks up the system the mouse is still moveable, but nothing responds to clicks. the keyboard is unable to display the start menu, but ctrl-alt-del still brings up the task manager and it is possible to regain control of the system by ending task on voplsrv.exe using the keyboard only.

Reply 6 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

That is weird. Because test3, is the exact VOPLSRV.EXE that froze your system, just with some console debug output and logging.
Can you run test3, leave it running, and then run a game/application that makes use of FM synth?

Edit: can you try with the attached voplsrv.exe, and let it load automatically at startup?

Reply 7 of 24, by stanwebber

User metadata
Rank Member
Rank
Member

test3 runs realtime and brings the system to its knees. just switching window focus takes like 30sec.

same thing happens with the replacement voplsrv.exe.

Reply 8 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

Attached archive with new VOPLSRV.EXE versions, try the one from the NUKED folder, then the one from the FAST folder. You can manually start them after Windows starts.

Reply 9 of 24, by stanwebber

User metadata
Rank Member
Rank
Member

they both worked! what changed and what does the designation fast signify? btw, what are the system requirements for the nuked-opl3 emulator? also, i notice the volume levels for nuked-opl3 are noticibly lower than sbemul. i found this to be the exact same situation with the ess vxd drivers which also used emulated opl3. i wonder what the cause is.

Reply 10 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

The original binary was compiled with no compiler optimization flags. On my I7-4800MQ@2.7GHz test machine, CPU usage with VOPLSRV.EXE running was around 1-2%, so I assumed it would be fine on your PIII@850MHz. Apparently not, it kept your CPU pegged at 100% and due to the VOPLSRV using REALTIME_PRIORITY_CLASS and THREAD_PRIORITY_TIME_CRITICAL (which are needed, even on a ~3GHz CPU, otherwise sound would be choppy when running a DOS game inside Windows) everything else slowed down to a crawl or got wedged during startup.
To answer your question:
NUKED folder: original ish VOPLSRV.EXE (has another unrelated bugfix) plus optimization flags
FAST folder: VOPLSRV.EXE based on agovtman's Nuked-OPL3-fast : Re: Nuked-OPL3-fast: a performance-optimized fork of Nuked-OPL3 , with the same optimization flags

As for the volume level difference, I'm already investigating that.

Reply 11 of 24, by onethirdxcubed

User metadata
Rank Member
Rank
Member

Thanks for building this!

Seems like the OPL emulation is running all the time even when there is no DOS window open, and I see occasional hangs on startup and shutdown with this enabled (both on VMWare and real hardware). VOPLSRV should probably stop the audio stream and stop running Nuked OPL when it is not needed.

I don't think there are any Win32 games that try to use the OPL directly instead of sending MIDI but I could be wrong.

Reply 12 of 24, by stanwebber

User metadata
Rank Member
Rank
Member
onethirdxcubed wrote on Yesterday, 14:38:

Seems like the OPL emulation is running all the time even when there is no DOS window open, and I see occasional hangs on startup and shutdown with this enabled (both on VMWare and real hardware.

i noticed this as well. it's not an insignificant drain on a p3 850mhz so i just ctrl-alt-del and end task on voplsrv.exe when the system is lagging.

Reply 13 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

@onethirdxcubed yes, it's currently running the OPL emulation at all time (it really didn't bother me on the i7). I will add an idle state, if X consecutive buffers are all zeroes and the OPL engine output is zero (so we don't cut during sustained chord/decay/whatever) -> pause the OPL engine. As for stopping the audio stream entirely, I don't think it would make that big of a difference in terms of CPU usage (KMIXER mixing the silent stream), at least when compared to the OPL engine. But that is also doable.

Reply 14 of 24, by onethirdxcubed

User metadata
Rank Member
Rank
Member

Since the System VM will never run anything that uses the OPL (except if you add MIDI synth support, but there's already another project that does that) you could start a VOPLSRV process when another VM is started by VMM. There are hooks for this, VMM broadcasts a message to all drivers I think. VDMSound calls from the ring 0 driver into a user mode DLL.

The reasons to stop the audio stream when it's not being used are mostly for power consumption but I also think it might cause a deadlock on shutdown in some cases if the audio driver is unloaded while still playing a buffer. I think I might need to handle that case a little better in my own code.

Also could the sample rate and volume be set from a little cfg file or some registry keys? The OPL is a lot quieter than the PCM sound effects coming from SBEMUL. Sound blaster PCM is usually at 11025 or 22050 hz so it would resample to 44100 with less artifacts.

By the way, the same problem with channels fading out quickly also happens with VGM versions of songs and the SBVGM player. Using that player you do have to force it to use an OPL3 at 388h so maybe some games that are silent are detecting a Sound Blaster and using ports 228h and 229h.

Reply 15 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

"Since the System VM will never run anything that uses the OPL (except if you add MIDI synth support, but there's already another project that does that) you could start a VOPLSRV process when another VM is started by VMM. There are hooks for this, VMM broadcasts a message to all drivers I think. VDMSound calls from the ring 0 driver into a user mode DLL." Interesting, I'll have to read about that, thanks!
There is a risk doing this with VOPLSRV though, as it might lose some initial writes done by the game/application. I think just stopping the OPL engine is reasonable and shouldn't break anything.
Also, one could make a win32 application that makes use of the FM emulation.

"The reasons to stop the audio stream when it's not being used are mostly for power consumption but I also think it might cause a deadlock on shutdown in some cases if the audio driver is unloaded while still playing a buffer." I think the renderer should be dead well before the audio driver is unloaded. There was a crash I had at shutdown/reboot, but it's already fixed. The only wasted power remaining is during OPL engine idle, the KMIXER will mix the silent audio stream. Worth adding to the todo list, though I don't think it adds a significant CPU load .

""Also could the sample rate and volume be set from a little cfg file or some registry keys? The OPL is a lot quieter than the PCM sound effects coming from SBEMUL. Sound blaster PCM is usually at 11025 or 22050 hz so it would resample to 44100 with less artifacts."
Regarding OPL vs PCM through SBEMUL volume level, I don't think there is a reasonable way to turn SBEMUL down (either patch it for every volume change or add a mechanism for an external lever).
OPL can be raised up though.
Not sure what you mean about SBEMUL PCM sample rate, VOPLSRV doesn't have anything to do with that. SBEMUL goes through KMIXER, as well as VOPLSRV. But we can add a sample rate knob to VOPLSRV.

"By the way, the same problem with channels fading out quickly also happens with VGM versions of songs and the SBVGM player. Using that player you do have to force it to use an OPL3 at 388h so maybe some games that are silent are detecting a Sound Blaster and using ports 228h and 229h."
I'll take a look at this soon. At the moment I have no idea why that happens.

New build here:
https://github.com/sdz-mods/VOPL3/releases/tag/A02

Changelog:
-fixed BSOD at reboot/shutdown due to VOPLSRV not exiting cleanly
-compiler optimization flags, added Nuked-OPL3-fast as a selectable backend (from the INSTALL.BAT, one can select between vanilla Nuked-OPL3 and Nuked-OPL3-fast)
-user-adjustable FM volume from VOPL3.INI (same folder as VOPLSRV.EXE). Currently set to 200% (adjust as needed, might lead to clipping if it's set too high. I'll check at some point on a regular SoundBlaster how loud FM is compared to PCM, and update the .INI accordingly).
-OPL engine paused in idle

Reply 16 of 24, by keenmaster486

User metadata
Rank l33t
Rank
l33t

Thank you for creating this. I have been hoping someone would do this for a long time.

Unfortunately, it doesn't work on my system: Thinkpad T41, Win98SE. AD1981B AC97 audio.

Tried latest release (A02).

Result: desktop loaded but the system tray icons did not. Had to kill Explorer, systray, sbmx, and voplsrv to get the system stable again. Was then able to run the uninstall batch file and successfully restore the system to a working state.

World's foremost 486 enjoyer.

Reply 17 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

@keenmaster486 thanks for testing!

Can you run install.bat again, don't reboot, go to C:\VOPL3 and rename VOPLSRV.EXE to TEST.EXE, reboot, then open an MS-DOS Prompt and run TEST.EXE?

Reply 18 of 24, by onethirdxcubed

User metadata
Rank Member
Rank
Member

I looked into the envelope problems and I think that what's happening is the player is sending a Key On and a Key Off command for a note in the same millisecond, but because register writes are batched into 1ms buffers and all the writes in a buffer are applied at once, the Key On never applies and the note never starts at all. This would explain why many songs fade away except for little blips.

To fix this properly, the kernel driver needs to save timestamps for every register write and then tick the OPL core the correct amount in between the writes. To fix it without changing the kernel driver, you could assume equal spacing between writes and if you have 10 register updates in the buffer for instance, tick the OPL core 1/10 ms in between each write.

Reply 19 of 24, by sdz

User metadata
Rank Oldbie
Rank
Oldbie

Currently doing exactly that (added timestamps), and it didn't really change the behaviour. Either I'm doing it wrong or there is something else.