{sb device}
const blocksize=512;
bsdiv2=blocksize div 2;
bsdiv4=blocksize div 4;
playspeed:word=22222; {5000-45454, voi vaihtaa ennen inittiƤ}
base:word=$220;
irq:byte=5;
dma:byte=1;
type channelinforec=
record
playing:boolean;
position:longint;
fixed:word;
faddl:word;
faddh:word;
sample:byte;
freq:longint;
volume:integer; {0-64!!!!!!!!!!}
end;
const charecsize=sizeof(channelinforec);
samrecsize=sizeof(samrec);
var interrupts:longint;
airq,pic,pageport:byte;
istam,istom,dstam,dstom:byte;
koee:byte;
dsp_reset:word;
dsp_read_data:word;
dsp_write_data:word;
dsp_write_status:word;
dsp_data_avail:word;
tmp:array[0..bsdiv2] of integer;
mix:array[0..blocksize*2] of byte;
mixalku:word;
imultable:array[0..64] of array[-128..127] of shortint;
vuoro:word;
oldclk:pointer;
channel:array[1..32] of channelinforec;
rekisterit:array[0..24] of byte;
{$i sndblst.pas}
{$S-}
procedure saver; assembler;
asm
db $66; mov [rekisterit].word[0],ax
db $66; mov [rekisterit].word[4],bx
db $66; mov [rekisterit].word[8],cx
db $66; mov [rekisterit].word[12],dx
db $66; mov [rekisterit].word[16],si
db $66; mov [rekisterit].word[20],di
end;
{$S-}
procedure restr; assembler;
asm
db $66; mov ax,[rekisterit].word[0]
db $66; mov bx,[rekisterit].word[4]
db $66; mov cx,[rekisterit].word[8]
db $66; mov dx,[rekisterit].word[12]
db $66; mov si,[rekisterit].word[16]
db $66; mov di,[rekisterit].word[20]
end;
{$S-}
procedure clip; near; assembler;
asm
mov di,[vuoro];
add di,offset mix;
add di,[mixalku];
mov si,offset tmp;
mov cx,bsdiv2
mov dx,$FF00;
@looppi:;
mov ax,[si];
cmp ax,127;
jg @liikaa;
add ax,128;
jl @liianvahan;
mov [di],al;
add si,2;
inc di
dec cx;
jnz @looppi;
jmp @loppu;
@liikaa:
mov [di],dh;
add si,2;
inc di
dec cx;
jnz @looppi;
jmp @loppu;
@liianvahan:
mov [di],dl;
add si,2;
inc di
dec cx;
jnz @looppi;
@loppu:
end;
{$S-}
procedure tyhjennatmp; near; assembler;
asm
db $66; push ax;
mov dx,seg tmp;
db $66; xor ax,ax;
mov es,dx;
mov cx,bsdiv4;
mov di,offset tmp;
cld;
db $66; rep stosw;
db $66; pop ax;
end;
{mixerille}
var mi,ma:word;
sam:byte;
oerror:byte;
offs,page:word;
offseti:longint;
bytes:longint;
bytez:longint;
vol:integer;
alku:word;
{$S-}
procedure map_page2(handle:word; phys_page:byte; log_page:word); near;
assembler; asm
mov ah,$44;
mov al,[phys_page];
mov bx,[log_page];
mov dx,[handle];
cli;
int $67;
mov [error],ah
end;
{$F+}
{$S-}
procedure mixer; interrupt;
begin
asm
cli; cli;
end;
saver;
koee:=port[base+$E];
tyhjennatmp;
oerror:=omaems.error;
omaems.save_ems(ems.handle);
if omaems.error>0 then mwrite('ERROR 1',0,0,15);
ems.page:=65535;
for mi:=1 to 32 do if channel[mi].playing then with channel[mi] do begin
ma:=0;
sam:=sample;
{ vol:=byte(word(word(volume)*word(master)) div 64);}
repeat
offseti:=samples[sam].data+position;
page:=word(longint(offseti) shr 14);
offs:=word(offseti) and $3FFF;
if page<>ems.page then begin
ems.page:=page;
map_page2(ems.handle,0,ems.page);
end;
bytes:=16384-offs;
bytez:=samples[sam].length-position;
if (bytez<bytes) then bytes:=bytez;
bytez:=samples[sam].loop.endi-position;
if (samples[sam].loop.endi>0) and (bytez<bytes) then bytes:=bytez;
inc(bytes,offs);
alku:=offs;
asm
mov ax,[ems+emsrec.addr];
mov es,ax;
mov cx,[mi];
mov ax,charecsize;
mul cx;
mov di,ax;
sub di,charecsize;
push bp;
mov si,[ma];
mov dx,[bytes].word;
mov bp,[offs];
mov cx,[channel+channelinforec.faddl+di];
mov bh,[channel+channelinforec.volume+di].byte;
mov al,[master];
mul bh;
shr ax,6;
mov bh,al;
@looppi:
mov bl,es:[bp];
mov al,[imultable+bx].byte;
cbw;
add [tmp+si].word,ax;
add [channel+channelinforec.fixed+di],cx;
adc bp,[channel+channelinforec.faddh+di];
add si,2;
cmp bp,dx
jae @loppu;
cmp si,bsdiv2*2;
jb @looppi;
@loppu:
mov bx,bp;
pop bp;
mov [ma],si;
mov [offs],bx;
db $66; xor ax,ax;
mov ax,[offs];
sub ax,[alku];
db $66; mov cx,[channel+channelinforec.position+di].word[0];
db $66; add cx,ax;
db $66; mov [channel+channelinforec.position+di].word[0],cx;
end;
if position>=samples[sam].loop.endi then
dec(position,samples[sam].loop.length);
if position>=samples[sam].length then playing:=false;
until (ma>=blocksize) or (playing=false);
end;
clip;
omaems.rest_ems(ems.handle);
if error>0 then mwrite('ERROR 2',0,1,15);
omaems.error:=oerror;
if vuoro=0 then vuoro:=bsdiv2 else vuoro:=0;
inc(interrupts,1);
port[$20]:=$20;
if irq>7 then port[$A0]:=$20;
restr;
end;
{$F-}
{$S-}
procedure init; far;
var c:byte;
l,i,t:integer;
cha:char;
begin
if ((longint(seg(mix))*16+longint(ofs(mix))) and $FFFF)+
longint(blocksize) > $0000FFFF then mixalku:=blocksize else
mixalku:=0;
if ((longint(seg(mix))*16+longint(ofs(mix)+mixalku)) and $FFFF)+
longint(blocksize) > $0000FFFF then begin
writeln('error locating DMA-buffer. press any key.');
cha:=readkey;
end;
for i:=0 to 64 do
for l:=-128 to 127 do begin
t:=i*l div 64;
if t<-128 then t:=-128 else
if t>127 then t:=127;
imultable[i][byte(l)-128]:=shortint(t);
end;
for c:=1 to 32 do fillchar(channel[c],sizeof(channel[c]),0);
if resetdsp((base-$200) div $10,10) then;
if resetdsp((base-$200) div $10,10) then;
if irq<=7 then airq:=irq+$08 else airq:=$70+irq-$08;
if irq<=7 then pic:=$21 else pic:=$A1;
istom:=1 shl (irq mod 8);
istam:=not(istom);
dstam:=dma;
dstom:=dstam or $04;
case dma of
0:pageport:=$87;
1:pageport:=$83;
2:pageport:=$81;
3:pageport:=$82;
end;
vuoro:=0;
interrupts:=0;
asm cli; cli; end;
port[pic]:=port[pic] or istom;
oldclk:=getintvek(airq);
setintvek(airq,@mixer);
koee:=port[base+$E];
port[$20]:=$20;
if irq>7 then port[$A0]:=$20;
port[pic]:=port[pic] and istam;
asm sti; sti; end;
speakeroff;
dmastop;
speakeron;
playspeed:=setfreq(playspeed);
fillchar(mix,sizeof(mix),0);
playback(ptr(seg(mix),ofs(mix)),blocksize,dstam,dstom,pageport);
end;
procedure deinit; far;
begin
asm cli; cli; end;
if resetdsp((base-$200) div $10,10) then;
if resetdsp((base-$200) div $10,10) then;
port[pic]:=port[pic] or istom;
setintvek(airq,oldclk);
koee:=port[base+$E];
dmastop;
speakeroff;
port[$0A]:=dstom;
asm sti; sti; end;
end;
{$S-}
procedure playvoice(samplenro:byte; offset:longint; channa:byte);
begin
asm pushf; cli; end;
channel[channa].playing:=false;
channel[channa].sample:=samplenro;
channel[channa].fixed:=0;
channel[channa].position:=offset;
channel[channa].playing:=true;
asm popf; end;
end;
{$S-}
procedure setplayfreq(c:byte; freq:longint);
begin
asm pushf; cli; end;
channel[c].freq:=freq;
channel[c].faddh:=freq div longint(playspeed);
channel[c].faddl:=word(longint(longint(longint(freq) mod longint(playspeed)) shl 16) div longint(playspeed));
asm popf; end;
end;
{$S-}
procedure setamigafreq(chan:byte; period:word);
begin
if period>0 then
setplayfreq(chan,longint(14317056) div longint(period));
end;
{$S-}
procedure stopvoice(channa:byte);
begin
asm pushf; cli; end;
channel[channa].playing:=false;
asm popf; end;
end;
{$S-}
procedure setvolume(chan:byte; volume:byte);
begin
asm pushf; cli; end;
channel[chan].volume:=volume;
asm popf; end;
end;