joncampbell123 / dosbox-x

DOSBox-X fork of the DOSBox project
GNU General Public License v2.0
2.83k stars 383 forks source link

Reset virtual machine / Reboot guest system do not fully unload AdLib sound driver #4520

Open MX9000 opened 1 year ago

MX9000 commented 1 year ago

Describe the bug

The game Rick Dangerous 2 needs to load the AdLib driver SOUND.COM before starting.

rick2_start driver_load mem_after_load

But once loaded the only way to remove it from the emulator is a full restart of DOSBox-X instance: with "Reset virtual machine" or "Reboot guest system" functions, the SOUND.COM program is no longer detected by MEM /C /P command and the conventional memory returns to 608K free again, but it is impossible to reload the driver until the entire emulator is rebooted.

mem_after_reboot driver_error

Attached a copy of the game folder with AdLib driver from eXoDOS: RICK2.zip

Steps to reproduce the behaviour

  1. Load SOUND.COM
  2. Try to reset the emulator with "Reset virtual machine" or "Reboot guest" functions
  3. Try to reload SOUND.COM again

Expected behavior

It should be possible to reload the driver after a reset

What operating system(s) this bug have occurred on?

Windows 10 Pro 22H2

What version(s) of DOSBox-X have this bug?

DOSBox-X 2023.10.06 VSbuild & MinGW 32 & 64 bit

Used configuration

Standard

Output log

No response

Additional information

No response

Have you checked that no similar bug report(s) exist?

Code of Conduct & Contributing Guidelines

maxpat78 commented 1 year ago

@joncampbell123 I've noticed that, after resetting DOSBox-X, in the "reserved for user software interrupts" area, the interrupt vector table element 0x65 (address 0x194) contains the bytes EF 02 26 08 instead of original null sequence 00 00 00 00.

Perhaps that is why SOUND.COM can't get reloaded?

joncampbell123 commented 1 year ago

@joncampbell123 I've noticed that, after resetting DOSBox-X, in the "reserved for user software interrupts" area, the interrupt vector table element 0x65 (address 0x194) contains the bytes EF 02 26 08 instead of original null sequence 00 00 00 00.

Perhaps that is why SOUND.COM can't get reloaded?

Int 65h must be NULL for it to load? That isn't the wisest design for a TSR... DOSBox-X does not fully zero the partition table on BIOS POST.

maxpat78 commented 1 year ago

Boh? Wise or not, it checks int vector presence:

00000298  06                push es
00000299  56                push si
0000029A  57                push di
0000029B  B065              mov al,0x65
0000029D  B435              mov ah,0x35             ; GET INTERRUPT VECTOR
0000029F  CD21              int 0x21

And, if you reset that vector with the following simple COM program (NASM-compiled), SOUND.COM can get re-installed as many times as you wish:

org 100h

push ds
xor dx, dx
push dx
pop ds
mov ax, 2565h
int 21h
pop ds

mov ax, 4c00h
int 21h

I've not tested the reset/CTRL+ALT+CANC behavior with a real machine, nor with another emulator (86box?), yet.

MX9000 commented 1 year ago

@maxpat78 I guess you got it right: http://mirror.cs.msu.ru/oldlinux.org/Linux.old/docs/interrupts/int-html/rb-7269.htm

maxpat78 commented 1 year ago

@MX9000 @joncampbell123 Running another simple DOS program confirms that SOUND.COM does not check for the signature block, but only for INT 65H in the interrupts table:

#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
    char far* far* int65h = (char far* far*)0x00000194;

    if (*int65h) {
        puts("INT 65 SET");
        if (! _fmemcmp(*int65h-22, "SOUND-DRIVER-AD-LIB", 19)) puts("ADLIB INSTALLED");
    } else puts("INT 65 NOT SET");
    return 0;
}

image

joncampbell123 commented 1 year ago

@MX9000 @joncampbell123 Running another simple DOS program confirms that SOUND.COM does not check for the signature block, but only for INT 65H in the interrupts table:

#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
    char far* far* int65h = (char far* far*)0x00000194;

    if (*int65h) {
        puts("INT 65 SET");
        if (! _fmemcmp(*int65h-22, "SOUND-DRIVER-AD-LIB", 19)) puts("ADLIB INSTALLED");
    } else puts("INT 65 NOT SET");
    return 0;
}

image

That reminds me of a demoscene test case that refused to run in DOSBox no matter what because it didn't like EMM386, but it's method of detecting it was whether or not thst interrupt vector was NULL. DOSBox always set the vector to something even if ems=false so it always refused to run.

maxpat78 commented 1 year ago

@joncampbell123 I've just tested on a real machine (old 2006 HP Pavilion laptop), performing cold & warm reboot programmatically and CTRL+ALT+DEL also. Original Phoenix BIOS does always reset the INT 65H vector ("INT 65 NOT SET"), so SOUND.COM TSR installs successfully every time.

joncampbell123 commented 1 year ago

@joncampbell123 I've just tested on a real machine (old 2006 HP Pavilion laptop), performing cold & warm reboot programmatically and CTRL+ALT+DEL also. Original Phoenix BIOS does always reset the INT 65H vector ("INT 65 NOT SET"), so SOUND.COM TSR installs successfully every time.

Alright, lets zero it. For IBM PC mode though, PC-98 seems to set more vectors

Allofich commented 2 months ago

@joncampbell123 I've just tested on a real machine (old 2006 HP Pavilion laptop), performing cold & warm reboot programmatically and CTRL+ALT+DEL also. Original Phoenix BIOS does always reset the INT 65H vector ("INT 65 NOT SET"), so SOUND.COM TSR installs successfully every time.

Alright, lets zero it. For IBM PC mode though, PC-98 seems to set more vectors

Has the zeroing been implemented?