VOGONS


First post, by wuerzig

User metadata
Rank Newbie
Rank
Newbie

Hi there,

I have some old turbo pascal code which makes use of the so-called "direct-dac" and mixer control feature of SB cards a lot. It essentially is a mixer (as in windows mixer) application to control the sb16's channels volume (master, voice, midi, cd, line-in), and the cd-audio colume of mscdex. In addition to that, it uses sampling via direct-dac to display the recording volume. It can also control the playing of cd-audio.

The cd-audio code works since dosbox 0.71 (thanks btw 😀) . However, neither the code to control the sb's channels volume (simply does nothing), nor the code to aquire samples from the sound card work (hangs on waiting for input).

I can imagine the emulation simply doesnt go that far and the features havent been added to dosbox yet. Maybe my code just sucks, I was kinda young at the time 🤣

I can supply code samples or the source of the whole app if you need more concrete examples.

Thanks in advance for any replies,

Thomas

Reply 1 of 2, by Qbix

User metadata
Rank DOSBox Author
Rank
DOSBox Author

the mixer should be functional. at least it works in games 😀
You could post some code samples if you want. Preferable samples as the whole source will be a lot to read through.

Water flows down the stream
How to ask questions the smart way!

Reply 2 of 2, by wuerzig

User metadata
Rank Newbie
Rank
Newbie

After a bit of testing the master, voice and midi channels now work (tweaked one line of code), tho not as my old puter handled it. While playing cd or feeding it something via line-in, the master volume controlled the overall volume of sound. I guess dosbox doesnt route the cd-audio through its emulated sound device and thus the control of that volume is impossible.

-- Code samples (Turbo Pascal... $ means Hex like 0x in C, comments in {})

procedure SetMSCDEXVolume(Vol : Byte;cdr:word); assembler;
asm
mov bx,seg Req
mov es,bx
mov bx,offset Req
mov byte ptr es:[bx+2],0Ch
mov cx,cdr {drive letter}
mov byte ptr ioctl,03h {function}
xor al,al {start at channel 0}
mov ah,Vol {volume - user input}
mov word ptr ioctl+1,ax {left}
inc al {next channel}
mov word ptr ioctl+3,ax {right}
inc al {next channel}
mov word ptr ioctl+5,ax {left prime}
inc al {next channel}
mov word ptr ioctl+7,ax {right prime}
mov word ptr es:[bx+0Eh],offset ioctl {transfer offset}
mov word ptr es:[bx+10h],seg ioctl {transfer segment}
mov ax,1510h {mscdex service}
int 2Fh {send device driver request}
end;

function GetMSCDEXVolume(cdr:word) : Byte; assembler;
asm
mov ax,1510h {mscdex service}
mov bx,seg Req
mov es,bx
mov bx,offset Req
mov byte ptr es:[bx+2],03h {command code}
mov cx,cdr {drive letter}
mov byte ptr ioctl,04h {function}
mov word ptr es:[bx+0Eh],offset ioctl {transfer offset}
mov word ptr es:[bx+10h],seg ioctl {transfer segment}
int 2Fh {send device driver request}
mov al,byte ptr ioctl+2 {result - left chn's volume}
end;

And for direct-dac:

      RESETPORT=$226;
READPORT=$22A;
WRITEPORT=$22C;
STATUSPORT=$22C; { its odd that these two have the same value, but the code worked on a real machine}
DATADAPORT=$22E;


function resetDSP:boolean;
var maxv:byte;
drw:byte;
begin
maxv:=100;
drw:=0;
while (drw<>$AA) and (maxv<>0) do begin
port[RESETPORT]:=1;
delay(10); { waits 10 milliseconds }
port[RESETPORT]:=0;
drw:=readfromDSP;
dec(maxv); { maxv-- }
end;
if maxv=0 then resetDSP:=FALSE
else resetDSP:=TRUE;
end;

procedure write2DSP(command:byte);
begin
while ((port[STATUSPORT] and $80)<>0) do ;
port[WRITEPORT]:=command;
end;

function readfromDSP:byte;
begin
while ((port[DATADAPORT]and $80)<>$80) do ;{<-- hangs here <-- }
readfromDSP:=port[READPORT];
end;

{ samples can then be aquired this way: }
if not resetDSP then fail;
while weWantSamples do begin
write2DSP($20);
sample:=readfromDSP;
end;