David wrote:- Why does this change sound to PCspeaker?
It seems to depend on the cpu cycles (in DosBox) when the game starts.
I tried starting the game with fixed cycles, and anything above 16000 seems to cause the game to use the PCspeaker.
However it's not consistent: sometimes I get digital sounds with 20000, sometimes I get PCspeaker sounds with 15000.
(If you want to try it yourself without editing dosbox.conf, you can use the
config cpu cycles=14000 statement with different numbers.)
So it's better to say that faster emulation increases the chances of switching to PCspeaker.
But why?
(
Warning: everything below is technical!)
I've read that detecting certain types of sound cards works by starting a timer on a sound card, and waiting for the timer to expire.
Indeed,
http://bochs.sourceforge.net/techspec/adlib_sb.txt (scroll to "Detecting a Sound Card") says just this.
Code: Select all
| Detecting a Sound Card
|
| According to the AdLib manual, the 'official' method of checking for a
| sound card is as follows:
|
| 1) Reset both timers by writing 60h to register 4.
| 2) Enable the interrupts by writing 80h to register 4. NOTE: this
| must be a separate step from number 1.
| 3) Read the status register (port 388h). Store the result.
| 4) Write FFh to register 2 (Timer 1).
| 5) Start timer 1 by writing 21h to register 4.
| 6) Delay for at least 80 microseconds.
| 7) Read the status register (port 388h). Store the result.
| 8) Reset both timers and interrupts (see steps 1 and 2).
| 9) Test the stored results of steps 3 and 7 by ANDing them
| with E0h. The result of step 3 should be 00h, and the
| result of step 7 should be C0h. If both are correct, an
| AdLib-compatible board is installed in the computer.
Perhaps PoP uses an empty loop for waiting?
Faster emulation would cause it to end too early.
I'll check this in the disassembly.
I think I found it:
Code: Select all
seg009:6F39 mov dx, 388h
seg009:6F3C mov ax, 1
seg009:6F3F call out_word
seg009:6F42 mov ax, 6004h
seg009:6F45 call out_word
seg009:6F48 mov ax, 8004h
seg009:6F4B call out_word
seg009:6F4E in al, dx
seg009:6F4F mov bh, al
seg009:6F51 call wait100
seg009:6F54 mov ax, 0FF02h
seg009:6F57 call out_word
seg009:6F5A mov ax, 2104h
seg009:6F5D call out_word
seg009:6F60 call wait100
seg009:6F63 call wait100
seg009:6F66 in al, dx
seg009:6F67 mov bl, al
seg009:6F69 call wait100
seg009:6F6C mov ax, 6004h
seg009:6F6F call out_word
seg009:6F72 mov ax, 8004h
seg009:6F75 call out_word
seg009:6F78 and bx, 0E0E0h
seg009:6F7C cmp bx, 0C0h ; 'À'
seg009:6F86 out_word proc near ; CODE XREF: sub_1360E+C1p
seg009:6F86 ; sub_1360E+C7p ...
seg009:6F86 call out_byte
seg009:6F89 xchg al, ah
seg009:6F8B inc dx
seg009:6F8C call out_byte
seg009:6F8F dec dx
seg009:6F90 xchg al, ah
seg009:6F92 retn
seg009:6F92 out_word endp
seg009:6F93 out_byte proc near ; CODE XREF: out_wordp
seg009:6F93 ; out_word+6p
seg009:6F93 out dx, al
seg009:6F93 out_byte endp
and wait100 is:
Code: Select all
seg009:6F94 wait100 proc near ; CODE XREF: sub_1360E+D3p
seg009:6F94 ; sub_1360E+E2p ...
seg009:6F94 mov cx, 100h
seg009:6F97
seg009:6F97 loc_13727: ; CODE XREF: wait100+3j
seg009:6F97 loop loc_13727
seg009:6F99 retn
seg009:6F99 wait100 endp
Here is the empty loop!