"sound off" does not turn all sounds off
"sound off" does not turn all sounds off
If I start PoP1 1.0 or 1.3 with digital sound (not pc speaker) in DOSBox, Ctrl-S seems to turn off only the music (MIDI). Is this a bug?
In version 1.4 Ctrl-S works as it should.
In version 1.4 Ctrl-S works as it should.
Re: "sound off" does not turn all sounds off
I can reproduce with PoP1 1.4 too with SB Pro selected in DOSBox (it's the only audio option besides PC Speaker). Does seem to be a bug.
Edit: Speaking of which, while testing this I came across another very funny bug! First run PoP1 1.4's Setup.exe and select PC Speaker for both options:
Next run Prince.exe (I used the uncracked/original file) with prince improved 7. In my DOSBox the Prince turns into a mouse after dying, and when I press any key to restart the level he even falls in a crouching position and then again turns into a mouse!
As you can see by the version text at the end, clearly there's some memory corruption. Perhaps it is not a game but a DOSBox bug?

Can someone confirm?
Edit: Speaking of which, while testing this I came across another very funny bug! First run PoP1 1.4's Setup.exe and select PC Speaker for both options:
Next run Prince.exe (I used the uncracked/original file) with prince improved 7. In my DOSBox the Prince turns into a mouse after dying, and when I press any key to restart the level he even falls in a crouching position and then again turns into a mouse!


Can someone confirm?
- Attachments
-
- Prince turns into Mouse.rar
- DOSBox video recording
- (211.31 KiB) Downloaded 346 times
Re: "sound off" does not turn all sounds off
I tried with DOSBox 0.73, 0.74, 0.60, plus some unofficial versions from http://ykhwong.x-y.net/safe.php (20110705 and 20130124) but I could not reproduce this.
Which version of DOSBox were you using?
I can't extract the RAR you attached. I suppose it would show the same thing as the GIF, right?
However, I found something else: In joystick mode (*), PoP1 v1.4 fills the screen with debug messages, which scrolls the screen up, messing up the room:
This can be redirected into a file (or NUL), though.
(*) You don't need to have an actual joystick, just set joysticktype=2axis in dosbox.conf.
Which version of DOSBox were you using?
It seems that every fourth byte was increased by one:Andrew wrote:As you can see by the version text at the end, clearly there's some memory corruption.
Code: Select all
PRINCE OF PERSIA V1.4
QRINDE OG PESSIA! V1/4
! ! ! ! ! !
However, I found something else: In joystick mode (*), PoP1 v1.4 fills the screen with debug messages, which scrolls the screen up, messing up the room:
This can be redirected into a file (or NUL), though.
(*) You don't need to have an actual joystick, just set joysticktype=2axis in dosbox.conf.
- Attachments
-
- joystick-debug.png (2.88 KiB) Viewed 9494 times
Re: "sound off" does not turn all sounds off
0.74 official.David wrote:I tried with DOSBox 0.73, 0.74, 0.60, plus some unofficial versions from http://ykhwong.x-y.net/safe.php (20110705 and 20130124) but I could not reproduce this.
Which version of DOSBox were you using?
Not always, the corruption is random.David wrote:It seems that every fourth byte was increased by one:Code: Select all
PRINCE OF PERSIA V1.4 QRINDE OG PESSIA! V1/4 ! ! ! ! ! !
Yes, it contains the DOSBox AVI. The archive uses the latest RAR5 format.David wrote:I can't extract the RAR you attached. I suppose it would show the same thing as the GIF, right?
I've attached my DOSBox conf with this post. It might help you reproduce the bug. If not, perhaps it's a DOSBox bug triggered by something on my system. I'll check on my other systems and see if I can reproduce.
- Attachments
-
- dosbox-0.74.rar
- (3.51 KiB) Downloaded 366 times
Re: "sound off" does not turn all sounds off
Now I could reproduce it!
Try to grab the ledge!
Also, the bug works on all levels. Just wait. The kid won't turn into a mouse, but lean forward and become uncontrollable. After that the game will show the frames of the jumping but *very* slowly.
And: there is a repeating high pitch beep but only when there are no other sounds playing.
Perhaps the sound player has a bug?
This works only if I configure the game to pc speaker, using the stdsnd command line parameter is not enough.
The problem seems to be caused by the SET statements in the [autoexec] section.
They don't have to be there, the same thing happens if I enter a SET directly in the command line.
Even a small "set a=b" will cause this.
But there are some environment variables already set by default!
The changed characters are always 4 bytes apart.
If you hold ctrl-V, you'll see how the characters become corrupted one by one.
The other texts are also corrupted.
If I use DOSBox 0.73, the game will constantly pause itself.
If I use the unofficial version of DOSBox that has a debugger, I first have to delete the GLIDE and PROMPT variables that are not present in the official version, and then use set a=b.
Now I am going to debug the game. This may take a while so I submit this post now.
Try to grab the ledge!
Also, the bug works on all levels. Just wait. The kid won't turn into a mouse, but lean forward and become uncontrollable. After that the game will show the frames of the jumping but *very* slowly.
And: there is a repeating high pitch beep but only when there are no other sounds playing.
Perhaps the sound player has a bug?
This works only if I configure the game to pc speaker, using the stdsnd command line parameter is not enough.
The problem seems to be caused by the SET statements in the [autoexec] section.
They don't have to be there, the same thing happens if I enter a SET directly in the command line.
Even a small "set a=b" will cause this.
But there are some environment variables already set by default!
I have seen these:Andrew wrote:Not always, the corruption is random.
Code: Select all
QRINDE OG PESSIA! V1/4
PRJNCE!OF QERSJA W1.4
PRINCE OF QERSJA W1.4
If you hold ctrl-V, you'll see how the characters become corrupted one by one.
The other texts are also corrupted.
If I use DOSBox 0.73, the game will constantly pause itself.
If I use the unofficial version of DOSBox that has a debugger, I first have to delete the GLIDE and PROMPT variables that are not present in the official version, and then use set a=b.
Now I am going to debug the game. This may take a while so I submit this post now.
Re: "sound off" does not turn all sounds off
Ha! Yes, I can confirm.David wrote:Now I could reproduce it!
Try to grab the ledge!
Also, the bug works on all levels. Just wait. The kid won't turn into a mouse, but lean forward and become uncontrollable. After that the game will show the frames of the jumping but *very* slowly.
And: there is a repeating high pitch beep but only when there are no other sounds playing.
It's quite possible, but 1.4 in PC speaker mode must also be doing something different because 1.0 (no setup, PC speaker by default), 1.1 (no setup, SB by default?) and 1.3 (has setup) aren't affected. Need not necessarily be a game bug, just some difference in behavior that's triggering a DOSBox bug.David wrote: Perhaps the sound player has a bug?
Yep, that's why I specifically provided the setup screenshot.David wrote: This works only if I configure the game to pc speaker, using the stdsnd command line parameter is not enough.
Good catch! Also, the bug's not manifested if I run 1.4 from a DOS window in 32-bit Win7, but of course sound doesn't work properly there anyway. It would be nice if someone can confirm in actual real mode DOS.David wrote: The problem seems to be caused by the SET statements in the [autoexec] section.
They don't have to be there, the same thing happens if I enter a SET directly in the command line.
Even a small "set a=b" will cause this.
But there are some environment variables already set by default!
Ok, so the predictability points to a DOSBox bug, right?David wrote: I have seen these:The changed characters are always 4 bytes apart.Code: Select all
QRINDE OG PESSIA! V1/4 PRJNCE!OF QERSJA W1.4 PRINCE OF QERSJA W1.4
If you hold ctrl-V, you'll see how the characters become corrupted one by one.
The other texts are also corrupted.
I look forward eagerly to the results of your investigation.David wrote: If I use the unofficial version of DOSBox that has a debugger, I first have to delete the GLIDE and PROMPT variables that are not present in the official version, and then use set a=b.
Now I am going to debug the game. This may take a while so I submit this post now.

This makes me wonder, just how many 'bugs' that we find, document here and attribute to the game are actually DOSBox bugs instead? For example, is the joystick bug you mentioned above 1.4 or DOSBox's fault? I regret now that my old DOS machine for game playing is no longer available. I need to replace it anyway, since no emulator can perfectly emulate all the hardware features and even bugs that program authors sometimes creatively used.David wrote:However, I found something else: In joystick mode (*), PoP1 v1.4 fills the screen with debug messages, which scrolls the screen up, messing up the room:
This can be redirected into a file (or NUL), though.
(*) You don't need to have an actual joystick, just set joysticktype=2axis in dosbox.conf.
P.S. Speaking of bugs, did you manage to reproduce the original bug you started this thread with in 1.4 too? I may have found a hint in the PoP1 manual:
The game setup allows you to select different sound and music devices. As you can see, in the Apple version there's an extra key combo i.e. Ctrl-N to turn off the music. This is similar to PoP2 which has Alt-S and Alt-M. In the DOS version of PoP1 Ctrl-N isn't implemented and Ctrl+S seems to actually turn off the music (there's no title or level loading music). So the description in the manual for Ctrl-S for the DOS version seems to be incorrect since it acts like Ctrl-N on Macs. There seems to be no way to turn off all sounds in PoP1.
Re: "sound off" does not turn all sounds off
Unless you're using the PC speaker.Andrew wrote:There seems to be no way to turn off all sounds in PoP1.
There is a "JoyX: %2d JoyY: %2d Btn: %2d" string in PRINCE.EXE. And the code in fact refers to that string.Andrew wrote:For example, is the joystick bug you mentioned above 1.4 or DOSBox's fault?
Here it is: (very long!)Andrew wrote:I look forward eagerly to the results of your investigation.
First I added memory-change breakpoints on the version string (BPLM 00019502 and BPLM 00019500).
The breakpoint was triggered by this code:
Code: Select all
01A3:140B 5E pop si
01A3:140C 0000 add [bx+si],al ; <-- overwritten!
01A3:140E 3E2843A7 sub ds:[bp+di-59],al
01A3:1412 7407 je 0000141B ($+7)
Code: Select all
.0000140B:5E pop si
.0000140C:CB retf ; <-- original!
.0000140D:803E2843A7 cmp [+4328],A7
.00001412:7407 je .0000141B
The debugger stopped here:
Code: Select all
0E17:208A 55 push bp
0E17:208B 8BEC mov bp,sp
0E17:208D 1E push ds
0E17:208E B84219 mov ax,1942
0E17:2091 8ED8 mov ds,ax
0E17:2093 33C0 xor ax,ax
0E17:2095 A3342E mov [2E34],ax
0E17:2098 A3362E mov [2E36],ax
0E17:209B A33E2E mov [2E3E],ax
0E17:209E A3402E mov [2E40],ax
0E17:20A1 C55606 lds dx,[bp+06]
0E17:20A4 B8003D mov ax,3D00
0E17:20A7 CD21 int 21
0E17:20A9 A33C2E mov [2E3C],ax ; <-- this
0E17:20AC 7308 jnc 000020B6 ($+8)
Code: Select all
EAX=00000002 ESI=0000008D DS=0000 ES=0000 FS=0000 GS=0000 SS=1942 Real
EBX=000077FC EDI=00007555 CS=0E17 EIP=000020AC C1 Z1 S0 O0 A0 P1 D0 I1 T0
ECX=00000000 EBP=00007490 IOPL3 CPL0
EDX=00000000 ESP=0000748E 182627883
It was the LDS instruction!
Let's look at the stack: (BP+6=7496)
Code: Select all
1942:7490 AE 74 50 1F 17 0E 00 00 00 00 42 19 55 75 AE 74
Who called this procedure?
The answer is:
Code: Select all
0E17:1F32 833E242E00 cmp word [2E24],0000
0E17:1F37 740D je 00001F46 ($+d)
0E17:1F39 B8FC2D mov ax,2DFC
0E17:1F3C 8946F0 mov [bp-10],ax
0E17:1F3F 8C5EF2 mov [bp-0E],ds
0E17:1F42 8CDA mov dx,ds
0E17:1F44 EB03 jmp short 00001F49 ($+3)
0E17:1F46 2BC0 sub ax,ax ; <- ax=0
0E17:1F48 99 cwd ; <- dx=0
0E17:1F49 52 push dx
0E17:1F4A 50 push ax
0E17:1F4B 90 nop
0E17:1F4C 0E push cs
0E17:1F4D E83A01 call 0000208A ($+13a) ; <-- this
0E17:1F50 83C404 add sp,0004
Code: Select all
seg009:1F32 cmp word_1A814, 0
seg009:1F37 jz loc_E686
seg009:1F39 mov ax, offset aDigi_drv ; "DIGI.DRV"
seg009:1F3C mov word ptr [bp+var_10], ax
seg009:1F3F mov word ptr [bp+var_10+2], ds
seg009:1F42 mov dx, ds
seg009:1F44 jmp short loc_E689
seg009:1F46 ; ───────────────────────────────────────────────────────────────────────────
seg009:1F46
seg009:1F46 loc_E686: ; CODE XREF: load_drivers+31j
seg009:1F46 sub ax, ax ; NULL
seg009:1F48 cwd
seg009:1F49
seg009:1F49 loc_E689: ; CODE XREF: load_drivers+3Ej
seg009:1F49 push dx
seg009:1F4A push ax ; filename
seg009:1F4B nop
seg009:1F4C push cs
seg009:1F4D call near ptr load_driver
seg009:1F50 add sp, 4
Code: Select all
seg009:208A load_driver proc far ; CODE XREF: load_drivers+47p
seg009:208A ; load_drivers+6Fp
seg009:208A
seg009:208A filename = dword ptr 6
seg009:208A
seg009:208A push bp
seg009:208B mov bp, sp
seg009:208D push ds
seg009:208E mov ax, seg seg016
seg009:2091 mov ds, ax
seg009:2093 xor ax, ax
seg009:2095 mov word ptr driver_code_ptr, ax
seg009:2098 mov word ptr driver_code_ptr+2, ax
seg009:209B mov word ptr driver_header_ptr, ax
seg009:209E mov word ptr driver_header_ptr+2, ax
seg009:20A1 lds dx, [bp+filename] ; ahem...
seg009:20A4 mov ax, 3D00h
seg009:20A7 int 21h ; DOS - 2+ - OPEN DISK FILE WITH HANDLE
seg009:20A7 ; DS:DX -> ASCIZ filename
seg009:20A7 ; AL = access mode
seg009:20A7 ; 0 - read
seg009:20A9 mov driv_pres_handle, ax
seg009:20AC jnb loc_E7F6
seg009:20AE xor ax, ax
seg009:20B0 mov driv_pres_handle, ax
seg009:20B3 jmp loc_E8C7
The procedure that calls load_driver passes either "DIGI.DRV" or NULL. In the latter case, load_driver should not be called at all. Or if it is called with NULL, it should check if this is the case.
Or it should always use "DIGI.DRV", and silently fail if that file doesn't exist.
(DIGI.DRV and MIDI.DRV are copied by SETUP.EXE from the SNDDRVRS folder if you choose Sound Blaster Pro, and they are deleted if you choose PC Speaker.)
Now, how do the SET statements come into play?
The EXE is loaded immediately after the area that stores the SET variables.
That is, if there are more or longer variables, the EXE is loaded at a different place.
But the rogue write always overwrites the same address, 0000:2E3C.
Various codes may end up at this address, depending on the size of the SET area.
Under real DOS (and in the DOS emulator built into Windows), some part of DOS (ntio.sys) is here, so this bug may end up breaking the system (or the DOS emulation)!
And which procedure is overwritten?
This:
Code: Select all
seg000:1400 call play_sound_from_buffer
seg000:1405
seg000:1405 loc_1405: ; CODE XREF: play_current_sound+6j
seg000:1405 ; play_current_sound+1Ej ...
seg000:1405 mov current_sound, 0FFFFh
seg000:140B pop si
seg000:140C retf ; <-- this becomes add [bx+si],al
seg000:140C play_current_sound endp
seg000:140D
seg000:140D ; int __pascal far check_sword_vs_sword()
seg000:140D check_sword_vs_sword proc far ; CODE XREF: sub_994+35p
seg000:140D cmp byte_1BD18, 0A7h ; 'ž' ; <-- this becomes sub ds:[bp+di-59],al
seg000:1412 jz loc_141B
seg000:1414 cmp byte_1BC98, 0A7h ; 'ž'
seg000:1419 jnz locret_1423
seg000:141B
seg000:141B loc_141B: ; CODE XREF: check_sword_vs_sword+5j
seg000:141B mov ax, 0Ah
seg000:141E push ax ; sound_id
seg000:141F push cs
seg000:1420 call near ptr play_sound
seg000:1423
seg000:1423 locret_1423: ; CODE XREF: check_sword_vs_sword+Cj
seg000:1423 retf
seg000:1423 check_sword_vs_sword endp ; sp = 2
Perhaps that repeating beep is the sword vs. sword sound?
According to the debugger, that JZ does jump every second time, which causes that sound to be played.
SI and DI are always 4 bigger than last time.
(Debugging corrupted code is hard, because it follows no logic, so the following may be unclear.)
check_sword_vs_sword and play_current_sound are called in an alternating way.
I also found out what increases SI and DI: when check_sword_vs_sword is actually called, this code gets executed: (this is the overwritten code)
Code: Select all
01A3:140D 003E2843 add [4328],bh
01A3:1411 A7 cmpsw
01A3:1412 7407 je 0000141B ($+7)
When play_current_sound is called, it does reach the add and sub, and at every second call (when AL=0, and the pointed byte is 0 and remains 0), the sound is played. At the other calls, AL is 1, so the pointed byte is changed.
Whew! That was long!
To sum up things:
0000:2E3C is always overwritten with zero. What it does depends on what is loaded there.
In your case it overwrites the boundary between a procedure that is called for every sound (play_current_sound), and a procedure that plays a certain sound effect (check_sword_vs_sword).
It is overwritten because DS is loaded from a far NULL pointer, but DS is not restored before the next access to a (global) variable.
Re: "sound off" does not turn all sounds off
Well yes, but I guess if we use the PC speaker for sound with another device for music or vice versa, we're likely to have the same problem (I haven't tested this though).David wrote:Unless you're using the PC speaker.Andrew wrote:There seems to be no way to turn off all sounds in PoP1.
Yep, I've seen that in the EXE, but surely the effect in 1.4 has to be a bug, either of the game or DOSBox? Ideally that string should be displayed in the status bar where other strings such as game version appear, and be updated in place when the joystick is moved and its buttons pressed. Also, ideally it should be a debug parameter (or perhaps be displayed only when cheats are enabled) and not show up every time you turn on joystick mode!David wrote:There is a "JoyX: %2d JoyY: %2d Btn: %2d" string in PRINCE.EXE. And the code in fact refers to that string.
Wow, that was some effort David and it'll take me time to digest that disassembled code properly. You seem to suggest that this is purely a game bug and not DOSBox's fault at all, but I guess one really needs to confirm by using a debugger in real mode DOS. I'm not entirely convinced that the emulator is totally blameless here, and that 1.4 has the potential to break even actual DOS when PC speaker is selected (a bug I've never encountered in all my years of playing in DOS so far, but which is a major issue in DOSBox).David wrote:Now, how do the SET statements come into play?
The EXE is loaded immediately after the area that stores the SET variables.
That is, if there are more or longer variables, the EXE is loaded at a different place.
But the rogue write always overwrites the same address, 0000:2E3C.
Various codes may end up at this address, depending on the size of the SET area.
Under real DOS (and in the DOS emulator built into Windows), some part of DOS (ntio.sys) is here, so this bug may end up breaking the system (or the DOS emulation)!
...
To sum up things:
0000:2E3C is always overwritten with zero. What it does depends on what is loaded there.
In your case it overwrites the boundary between a procedure that is called for every sound (play_current_sound), and a procedure that plays a certain sound effect (check_sword_vs_sword).
It is overwritten because DS is loaded from a far NULL pointer, but DS is not restored before the next access to a (global) variable.
P.S. Is it just me or do PoP1 1.3 and 1.4 sound quite different (not the music but sounds like gate opening/closing, tile falling etc.) in DOSBox even with both configured to use SB?