sarah-walker-pcem / pcem

PCem
http://pcem-emulator.co.uk
GNU General Public License v2.0
1.55k stars 216 forks source link

SB DSP reset not properly implemented, rendering detection not working #249

Open sgoehler opened 8 months ago

sgoehler commented 8 months ago

Describe the bug Basically resetting the DSP should return 0AAh from the DSP when working properly. However, independent of the time waiting for the reset to be done, the value 0AAh is not returned, but 004h.

I've written SoundLib, and its reset procedure cannot detect the SB due to this routine not working properly. Note that I've tested this on real hardware, with a multitude of original SB and clone cards, and they all work the same way, returning 0AAh upon reset. https://crossfire-designs.de/index.php?lang=de&what=sourcecode&name=sl2.htm

By the development manual from gamedev.net: http://archive.gamedev.net/archive/reference/articles/article443.html

02x06h DSP - Reset Write SB

 DESCRIPTION
  Performs complete reset of DSP, terminating all pending operations.

 PROCEDURE
   a) Write 001h
   b) Wait 3.3жs minimum
   c) Write 000h
   d) Wait 100жs maximum for DSP Data Available (02x0Eh) 
   e) Read 0AAh from DSP Read Data (02x0Ah) <<<<<

 NOTES
  ю Reset of DSP disables speaker (see DSP command 0D3h).

To Reproduce Here's the Pascal code to reproduce it:


procedure outp(port : word;value : byte);assembler; asm mov dx,port mov al,value out dx,al end;

function inp(port : word) : byte;assembler; asm mov dx,port in al,dx end;

function writeDSPToAddress(address : word; v : byte) : boolean;assembler; asm mov dx,address add dx,0Ch xor cx,cx @lp: in al,dx dec cx jz @err test al,$80 jnz @lp jmp @noerr @err: mov al,0 jmp @end @noerr: mov al,v out dx,al mov al,1 @end: end;

function readDSPFromAddress(address : word) : byte;assembler; asm mov dx,address add dx,0Eh xor cx,cx @lp: in al,dx dec cx jz @err test al,$80 jz @lp jmp @noerr @err: mov al,0 jmp @end @noerr:

mov dx,address add dx,0Ah in al,dx @end: end;

function currenttime : longint;assembler; asm mov ax,0 int 1Ah mov ax,dx mov dx,cx end;

function resetBlasterAtAddress(address : word) : boolean; var b : byte; endtime : longint;

begin outp(address + $6,1); endtime := currenttime + 2; while (endtime > currenttime) do; outp(address + $6, 0); b := readDSPFromAddress(address); endtime := currenttime + 3; repeat b := inp(address + $E); b := inp(address + $A); until (b = $AA) or (currenttime >= endtime); resetBlasterAtAddress := b = $AA; end;

begin writeln(resetBlasterAtAddress($220)); end.


NOTE: b is 04h every time on PCem, instead of being 0AAh, so resetting always fails.

Expected behavior As described, 0AAh should be returned from the DSP.

Emulator configuration

Additional context Add any other context about the problem here.