VOGONS


First post, by Oerg866

User metadata
Rank Member
Rank
Member

Hello everyone,

I wanted to mess around with Windows NT 3.1 to port some software of mine, and I came across an annoying problem in that the official SoundBlaster 16 driver for Windows NT 3.1 driver doesn't load on VirtualBox (it does work on 86Box and real hardware though). It does so with a curiously unspecific error message:

unknown.png

The SoundBlaster 1.x driver which is very similar in functionality loads properly as well.

The user mode DLL which shows the dialog box here and starts the kernel driver when you click OK uses the "DSP Version" registry key as an error indicator and checks it for various values and then picks a string from the compiled string resources to display in the error dialog.

  StopDriverServiceIfRunning(&RegistryHandle);
StartDriverServiceMAYBE(&RegistryHandle);
dspQueryResult = getDSPVersionFromRegistry();
if ( IsServiceRunningMAYBE(&RegistryHandle) )
{
if ( installInitiated )
{
dspVersion = dspQueryResult >> 16;
if ( (unsigned __int16)dspVersion < 0x400u || (unsigned __int16)dspVersion > 0x499u )
DisplayErrorString(hDlg, string_errCardNotASB16);
installInitiated = 0;
}
result = EndDialog(hDlg, 2);
}
else
{
dspQueryErrorFlags = dspQueryResult >> 16;
if ( dspQueryErrorFlags & 0x4000 )
{
errorStringToDisplay = string_errCardNotFoundWithThisPortNumber;
}
else if ( dspQueryErrorFlags & 0x2000 )
{
errorStringToDisplay = string_errNotRespondingOnThisInterrupt;
}
else
{
errorStringToDisplay = (dspQueryErrorFlags & 0x1000) < 1 ? string_errConfigOrHardwareProblemOccured : string_errInterruptInUse;
}
result = DisplayErrorString(hDlg, errorStringToDisplay);
}
return result;
}

Well, that makes sense, except after closer inspection it appeared that the registry key was not written to, I verified this by writing an arbitrary value to it and it stayed the same after erroring out even though the initialization routines of the kernel driver were clearly triggered.

It turns out that the SB16 driver never writes *any* of these values into the registry. It either succeeds and writes the DSP version into it, or it does nothing at all.

But upon even more close inspection, the sB1.x driver *does* write these codes. So I guess they decided "nah, whatever".

I disassembled & decompiled a few things inside the kernel mode driver to figure out why its initialization failed and determined that the driver does something with a seemingly undocumented mixer register (0x83) as well as to another mystery IO port. Due to the lack of a debugger (and my limited intellect) I couldn't figure out what that port is and what the register does. All I know is it attempts to read the port for 10 times and if it doesn't match a certain value, the function returns with an error, and the driver fails to load. This happens a few times in the initialization (this code has been added since the 1.x driver). It seems to serve no other useful purpose.

I guess it's something to lock out clone cards maybe?

unknown.png
unknown.png
unknown.png

I'm not a professional reverse engineer btw, take everything with a grain of salt. I'm also mildly curious why 86Box doesn't trip over this.

Anyway, I NOPed all those checks out and the driver loads in VirtualBox now. So if anyone is interested, here it is.

Tested on VirutalBox 6.1 with Windows host.

Best
Eric

Attachments

  • Filename
    sb16nt31_vbox.zip
    File size
    149.63 KiB
    Downloads
    166 downloads
    File comment
    drivers with patched SB16SND.SYS
    File license
    Fair use/fair dealing exception
  • Filename
    SB16NT31VBOX_Disk_Image.zip
    File size
    130.45 KiB
    Downloads
    170 downloads
    File comment
    Disk image with the drivers
    File license
    Fair use/fair dealing exception