gates_of_skeldal/libs/zvuka.asm
2025-01-25 13:08:41 +01:00

1247 lines
38 KiB
NASM

.model small
.386P
DGROUP group _DATA
tchannel struct
PLAYPOS DD ?
STARTLOOP DD ?
ENDLOOP DD ?
SPEEDMAJ DD ?
SPEEDMIN DW ?
MINORPOS DW ?
SMPTYPE DW ?;0 - DISABLED, 1 - 8 BIT, 2 - 16 BIT
VOLUMELEFT DW ?
VOLUMERIGHT DW ?
tchannel ends
rm_playdata struct
XLAT_TAB DB 256 DUP(?)
SCANOFS DW ?
SCANSEG DW ?
PORT DW ?
rm_playdata ends
extrn _chaninfo:dword
extrn _mixbuffer:dword
extrn _backsnd:dword ;ukazatel na buffer s hudbou na pozadi (64Kb)
extrn _backstep:dword ;krok o kolik se meni _backsnd
extrn _backfine:dword ;citac udavajici kdy se zmeni _backsnd
extrn _backsndbuff:dword ;buffer hudby na pozadi
extrn _call_back_data:dword ;data_call_back_procedury
extrn _call_back_sel:word ;data_call_back_procedury
extrn _jumptable:dword[3] ;[0] - skip, [1] - mix8, [2] - mix16
extrn _getdma:dword
extrn _ido:dword
extrn _predstih:word
extrn _lastdma:dword
extrn _lastmix:dword
extrn _surpos:dword
extrn _mixpos:dword
extrn _mixsize:dword
extrn _samplerate:dword
extrn _dmaposadr:dword
extrn _dmasizadr:dword
extrn _dmanum:byte
extrn _dpmiselector:word
extrn _idt_map:dword
extrn _test_counter:dword
extrn _mixer_zavora:byte
extrn _timer_test_port:word
extrn _oldvect:dword
extrn _devport:dword
extrn _devirq:dword
extrn _gus_dma_type:byte
extrn _gus_last_buff:byte
_TEXT segment byte public 'CODE' use32
assume CS:_TEXT
assume DS:DGROUP
gus_out equ 0
gus_irqs equ 6
gus_timer_c equ 8
gus_timer_d equ 9
gus_irq_dma equ 0bh
gus_voice equ 102h
gus_reg equ 103h
gus_reg_data equ 104h
gus_pio equ 107h
gus_block equ 2000h
PUBLIC MIXER_
MIXER_: ;THIS IS MAIN MIXING PROCEDURE.
;BEFORE USING, YOU MUST SET UP ALL VARIBLES TO THE CORRECT VALUES.
;_MIXBUFFER MUST START ON PAGE OF MEMORY (EX. 0x10000 0x20000 0x30000)
;PROCEDURE MUST BE CALLED EACH 55ms OR LITTLE.
;IF YOU USING INTERRUPT, REMEBER, THAT YOU MUST STORE ALL REGISTERS
;BEFORE USE.
cmp _mixer_zavora,0
jnz mixend
inc _mixer_zavora
CALL calcsize ;VYPOCET DELKY MIXOVANI
mov edi,_mixpos ;Nejprve se vymaze mixovaci pamet
mov ecx,_mixsize
shr ecx,2
jz MIXALL
MIXOK: xor eax,eax
MIXCLR: mov [edi],ax
add di,2
mov [edi],ax
add di,2
dec ecx
jnz MIXCLR
lea ebx,_chaninfo ;TED SE ZACNE MIXOVAT
MIXING: xor eax,eax
mov ax,smptype[ebx]
call _jumptable[eax*4]
add ebx,sizeof(tchannel)
cmp ebx,(32*sizeof(tchannel))+offset _chaninfo
jnz MIXING
call _ido
mov ecx,_mixsize
add word ptr _mixpos,cx
MIXALL: mov _mixer_zavora,0
MIXEND: ret
CALCSIZE:call _getdma ;eax - pozice v mixovaci pameti
mov ecx,eax ;ecx - pozice dma
sub cx,word ptr _mixpos ;odecti mixpos (dma-mix_pos<0)
js CALCOK
shr cx,2
;add _predstih,cx
;add _predstih,64
CALCOK: mov ebx,_lastdma
mov _lastdma,eax
sub ax,bx
add ax,_predstih
add ax,word ptr _lastdma
mov bx,word ptr _mixpos
sub ax,bx
js CALCEND
and ax,not 3
add ax,4
and eax,0ffffh
mov _mixsize,eax
ret
CALCEND:mov _mixsize,0
ret
ADDC macro REG1,REG2,CLIP
local addc1
add REG1,REG2
jno addc1
shl REG2,1
Mov REG2,CLIP
adc REG2,0
mov REG1,REG2
addc1:
endm
MIXS_ :;primixuje sampl do bufferu (8-bit stereo)
;musi platit vsechny promenne a ebx je adresa kanalu
mov edi,_mixpos
mov ecx,_mixsize
mov esi,[ebx]
push ebp
mov bp,minorpos[ebx]
mixslp: mov dl,[esi]
mov dh,dl
mov al,byte ptr volumeleft[ebx+1]
imul dl
shl eax,1
mov dl,ah
mov al,byte ptr volumeright[ebx+1]
imul dh
shl eax,1
mov dh,ah
mov ax,[edi]
addc al,dl,7fh
addc ah,dh,7fh
mov [edi],ax ;je smixovano
add di,2 ;dalsi pozice
add bp,speedmin[ebx]
adc esi,speedmaj[ebx]
cmp esi,endloop[ebx]
jc mixsskp
mov esi,startloop[ebx]
cmp esi,endloop[ebx]
jnz mixsskp
mov smptype[ebx],0
jmp mixsend
mixsskp:dec ecx
dec ecx
jnz mixslp
mixsend:mov minorpos[ebx],bp
mov playpos[ebx],esi
pop ebp
ret
mixskip:ret
mixs2 :;primixuje sampl do bufferu (16-bit stereo)
;musi platit vsechny promenne a ebx je adresa kanalu
mov edi,_mixpos ;vem mixovaci pozici
mov ecx,_mixsize ;vem pocet potrebnych bajtu
mov esi,[ebx] ;vyzvedni ukazatel na sample
push ebp ;zachovej bp
mov bp,minorpos[ebx] ;bp pro tuto chvili predstavuje minorpozici
mix2slp:mov dl,[esi+1] ;vem sample, ale jen vyssi bajt
mov dh,dl ;zkopiruj levy kanal do praveho
mov al,byte ptr volumeleft[ebx+1];vyzvedni hlasitost leveho kanalu
imul dl ;nasob vzorek hlasitosti
shl eax,1 ;vysledek je v ah vydelen 256x
mov dl,ah ;schovej vysledek do dl
mov al,byte ptr volumeright[ebx+1];to same pro pravy kanal
imul dh
shl eax,1
mov dh,ah
mov ax,[edi] ;ted precti aktualni stav samplu v bufferu
addc al,dl,7fh ;pricti levy kanal s clippingem
addc ah,dh,7fh ;pricti pravy kanal s clippingem
mov [edi],ax ;je smixovano
add di,2 ;dalsi pozice
add bp,speedmin[ebx] ;skok po minor hodnotach
lahf ;uchovej priznaky v ah (hlavne cf)
adc esi,speedmaj[ebx] ;skok po major hodnotach
sahf ;obnov cf
adc esi,speedmaj[ebx] ;a jeste jednou celkem o 2xvic nez je rychlost
cmp esi,endloop[ebx] ;test na konec samplu
jc mix2sskp ;pokud jsme prekrocili konec mohou nastat dva
mov esi,startloop[ebx];pripady:
cmp esi,endloop[ebx] ; bud ma sampl opakovani pak zacina na adrese
jnz mix2sskp ; startloop nebo nema
mov smptype[ebx],0 ; pak je vypnut
jmp mix2send ;skoc na konec
mix2sskp:dec ecx ;pokracujeme v prehravani
dec ecx ;byly naplneny 2 bajty, citac o 2 dolu
jnz mix2slp ;opakuj cele mixovani dokud neni citac nule
mix2send:mov minorpos[ebx],bp ;uloz minorpozici
mov playpos[ebx],esi ;uloz majorpozici
pop ebp ;obnov BP
ret ;konec
m8sido: mov esi,_mixpos ;vem mixovaci pozici
sub si,2 ;o jeden sampl dozadu
and esi,not 1
mov edi,_backfine ;finepozice
mov ebx,_backsnd ;pozice v bufferu
mov ecx,_mixsize ;pocet bajtu
sub ecx,2
shl ecx,16 ;uloz do horni poloviny ecx
mov ax,[esi] ;vezmi sample
xor eax,8080h ;neznaminkova korekce
m8sido1:add si,2 ;dalsi sample
mov dx,[esi] ;nacti do dx sample
xor edx,8080h ;neznaminkova korekce
add al,dl ;secti leve kanaly
rcr al,1 ;nasleduje deleni 2x prumer
add ah,dh ;totez pro prave kanaly
rcr ah,1
xor eax,8080h ;neznaminkova korekce
mov cl,byte ptr _backsndbuff[1+ebx*4] ;nacti back sound pro levej kanal
mov ch,byte ptr _backsndbuff[3+ebx*4];nactu back sound pro pravej kanal
addc al,cl,7fh ;secti s clippingem levy kanal
addc ah,ch,7fh ;secti s clippingem pravy kanal
add di,word ptr _backstep ;pricti fine pozici
adc bx,word ptr [_backstep+2];preteceni jde do bx plus step
; and ebx,03ffffh ;celkem 16384*4 samplu
xor eax,8080h ;neznaminkova korekce
sub si,2 ;uloz na zdrojovou pozici
mov [esi],ax
add si,2
mov eax,edx ;pouzity sampl pro prumerovani se
sub ecx,20000h ;do ax a odecti dva takty pro citac
jnc m8sido1 ;a opakuj dokud neni konec
mov _backsnd,ebx
mov _backfine,edi
ret ;navrat
sbdma: mov edx,_dmaposadr
out 0ch,al
out 0d8h,al
xor eax,eax
in al,dx
xchg al,ah
in al,dx
xchg al,ah
cmp _dmanum,4
jc sbdma1
shl eax,1
sbdma1: add eax,_mixbuffer
ret
PUBLIC setsbpro_
setsbpro_:
lea edi,_jumptable
mov eax,offset mixskip
stosd
mov eax,offset mixs_
stosd
mov eax,offset mixs2
stosd
mov _getdma,offset sbdma
mov _ido,offset m8sido
ret
MIXM_ :;primixuje sampl do bufferu (8-bit mono)
;musi platit vsechny promenne a ebx je adresa kanalu
mov edi,_mixpos ;vezmi mixovaci pozici
mov ecx,_mixsize ;vezmi delku mixovani
mov esi,[ebx] ;nacti ukazatel na aktualni pozici v samplu
push ebp ;uchovej docasne BP
mov bp,minorpos[ebx] ;bp ma novou ulohu, drzi minor pozici
mov al,byte ptr volumeleft[ebx+1] ;vypocti hlasitost
mov ah,byte ptr volumeright[ebx+1]
add al,ah
rcr al,1 ;jak prumer leve a prave hlasitosti
mov dh,al
mixmlp: mov al,[esi] ;vezmi sample
imul dh ;vynasob s hlasitosti
shl eax,1 ;vydel /256x (ah je vysledek)
mov al,[edi] ;vezmi momentalni obsah bufferu
addc al,ah,7fh ;secti s clippingem
mov [edi],al ;je smixovano
inc di ;dalsi pozice
add bp,speedmin[ebx]
adc esi,speedmaj[ebx]
cmp esi,endloop[ebx]
jc mixmskp
mov esi,startloop[ebx]
cmp esi,endloop[ebx]
jnz mixmskp
mov smptype[ebx],0
jmp mixmend
mixmskp:dec ecx
jnz mixmlp
mixmend:mov minorpos[ebx],bp
mov playpos[ebx],esi
pop ebp
ret
MIXM2 :;primixuje sampl 16 do bufferu (8-bit mono)
;musi platit vsechny promenne a ebx je adresa kanalu
mov edi,_mixpos ;vezmi mixovaci pozici
mov ecx,_mixsize ;vezmi delku mixovani
mov esi,[ebx] ;nacti ukazatel na aktualni pozici v samplu
push ebp ;uchovej docasne BP
mov bp,minorpos[ebx] ;bp ma novou ulohu, drzi minor pozici
mov al,byte ptr volumeleft[ebx+1] ;vypocti hlasitost
mov ah,byte ptr volumeright[ebx+1]
add al,ah
rcr al,1 ;jak prumer leve a prave hlasitosti
mov dh,al
mixmlp2:mov al,[esi+1] ;vezmi sample
imul dh ;vynasob s hlasitosti
shl eax,1 ;vydel /256x (ah je vysledek)
mov al,[edi] ;vezmi momentalni obsah bufferu
addc al,ah,7fh ;secti s clippingem
mov [edi],al ;je smixovano
inc di ;dalsi pozice
add bp,speedmin[ebx]
lahf ;uchovej priznaky v ah (hlavne cf)
adc esi,speedmaj[ebx] ;skok po major hodnotach
sahf ;obnov cf
adc esi,speedmaj[ebx] ;a jeste jednou celkem o 2xvic nez je rychlost
cmp esi,endloop[ebx]
jc mixmskp2
mov esi,startloop[ebx]
cmp esi,endloop[ebx]
jnz mixmskp2
mov smptype[ebx],0
jmp mixmend2
mixmskp2:dec ecx
jnz mixmlp2
mixmend2:mov minorpos[ebx],bp
mov playpos[ebx],esi
pop ebp
ret
m8mido: mov esi,_mixpos ;vem mixovaci pozici
dec si ;o jeden sampl dozadu
lea edi,_backfine ;ukazatel na back sound buffer
mov ebx,_backsnd ;pozice v bufferu
mov ecx,_mixsize ;pocet bajtu
dec ecx
shl ecx,16 ;uloz do horni poloviny ecx
mov al,[esi] ;vezmi sample
xor eax,80h ;neznaminkova korekce
m8mido1:inc si ;dalsi sample
mov dl,[esi] ;nacti do dx
xor edx,80h ;neznaminkova korekce
add al,dl ;secti kanal
rcr al,1 ;nasleduje deleni 2x prumer
xor eax,80h ;vysledek oznamenkuj - bude se scitat
mov cl,byte ptr _backsndbuff[1+ebx*4];nacti back sound pro levej kanal
mov ch,byte ptr _backsndbuff[3+ebx*4];nactu back sound pro pravej kanal
add di,word ptr _backstep ;pricti fine pozici
adc bx,word ptr [_backstep+2];preteceni jde do bx plus step
; and ebx,03ffffh ;celkem 16384*4 samplu
sar cl,1 ;del levy kanal 2ma
sar ch,1 ;del pravy kanal 2ma
add cl,ch ;secti oba kanaly
addc al,cl,7fh ;secti s clippingem kanal
xor eax,80h ;neznaminkova korekce pro SB Pro
dec si ;uloz na zdrojovou pozici
mov [esi],al
inc si
mov eax,edx ;pouzity sampl pro prumerovani se
sub ecx,10000h ;do ax a odecti jeden takt pro citac
jnc m8mido1 ;a opakuj dokud neni konec
mov _backsnd,ebx
ret ;navrat
m8midos:mov esi,_mixpos ;vem mixovaci pozici
dec si ;o jeden sampl dozadu
lea edi,_backfine ;ukazatel na back sound buffer
mov ebx,_backsnd ;pozice v bufferu
mov ecx,_mixsize ;pocet bajtu
dec ecx
shl ecx,16 ;uloz do horni poloviny ecx
mov al,[esi] ;vezmi sample
xor eax,80h ;neznaminkova korekce
m8mido2:inc si ;dalsi sample
mov dl,[esi] ;nacti do dx
xor edx,80h ;neznaminkova korekce
add al,dl ;secti kanal
rcr al,1 ;nasleduje deleni 2x prumer
xor eax,80h ;vysledek oznamenkuj - bude se scitat
mov cl,byte ptr _backsndbuff[1+ebx*4];nacti back sound pro levej kanal
mov ch,byte ptr _backsndbuff[3+ebx*4];nactu back sound pro pravej kanal
add di,word ptr _backstep ;pricti fine pozici
adc bx,word ptr [_backstep+2];preteceni jde do bx plus step
; and ebx,03ffffh ;celkem 16384*4 samplu
sar cl,1 ;del levy kanal 2ma
sar ch,1 ;del pravy kanal 2ma
add cl,ch ;secti oba kanaly
addc al,cl,7fh ;secti s clippingem kanal
dec si ;uloz na zdrojovou pozici
mov [esi],al
inc si
mov eax,edx ;pouzity sampl pro prumerovani se
sub ecx,10000h ;do ax a odecti jeden takt pro citac
jnc m8mido2 ;a opakuj dokud neni konec
mov _backsnd,ebx
ret ;navrat
PUBLIC setsb2_
setsb2_:
lea edi,_jumptable
mov eax,offset mixskip
stosd
mov eax,offset mixm_
stosd
mov eax,offset mixm2
stosd
mov _getdma,offset sbdma
mov _ido,offset m8mido
ret
PUBLIC setsb2_s_
setsb2_s_:
lea edi,_jumptable
mov eax,offset mixskip
stosd
mov eax,offset mixm_
stosd
mov eax,offset mixm2
stosd
mov _getdma,offset sbdma
mov _ido,offset m8midos
ret
MIX16_ :;primixuje sampl do bufferu (16-bit stereo)
;musi platit vsechny promenne a ebx je adresa kanalu
mov edi,_mixpos ;vem mixovaci pozici
mov ecx,_mixsize ;vem mixovaci delku
mov esi,[ebx] ;vyzvedni ukazatel na sample
push ebp ;uchovej BP
mov bp,minorpos[ebx] ;bp bude drzet minor pozice
mix1lp: mov al,[esi] ;nacti sample
mov dl,al ;al a dl obsahuji levej a pravej kanal
mov ah,byte ptr volumeright[ebx+1] ;nacti pravou hlastitot
imul ah ;vynasob hlasitosti
shl eax,1 ;vse je vyreseno, deleni neni potreba
xchg edx,eax ;ted pracuj s druhym kanalem
mov ah,byte ptr volumeleft[ebx+1] ;nactu hlasitost
imul ah ;vynasob
shl eax,1
addc [edi],dx,7fffh ;k aktualnimu vzorku pricti hodnotu
add di,2 ;dalsi pozice
addc [edi],ax,7fffh ;je smixovano
add di,2 ;dalsi pozice
add bp,speedmin[ebx]
adc esi,speedmaj[ebx]
cmp esi,endloop[ebx]
jc mix1skp
mov esi,startloop[ebx]
cmp esi,endloop[ebx]
jnz mix1skp
mov smptype[ebx],0
jmp mix1end
mix1skp:sub ecx,4
jnz mix1lp
mix1end:mov minorpos[ebx],bp
mov playpos[ebx],esi
pop ebp
ret
mix162: ;primixuje sampl do bufferu (16-bit stereo)
;musi platit vsechny promenne a ebx je adresa kanalu
mov edi,_mixpos ;vem mixovaci pozici
mov ecx,_mixsize ;vem mixovaci delku
mov esi,[ebx] ;vyzvedni ukazatel na sample
push ebp ;uchovej BP
mov bp,minorpos[ebx] ;bp bude drzet minor pozice
mix12lp:movsx eax,word ptr [esi] ;nacti sample
imul word ptr volumeright[ebx] ;nacti pravou hlastitot a vynasob
shl edx,1 ;vse je vyreseno, deleni neni potreba
addc [edi],dx,7fffh ;k aktualnimu vzorku pricti hodnotu
add di,2 ;dalsi pozice
movsx eax,word ptr [esi] ;nacti sample
imul word ptr volumeleft[ebx] ;nacti pravou hlastitot a vynasob
shl edx,1 ;vse je vyreseno, deleni neni potreba
addc [edi],dx,7fffh ;k aktualnimu vzorku pricti hodnotu
add di,2 ;dalsi pozice
add bp,speedmin[ebx]
lahf ;uchovej priznaky v ah (hlavne cf)
adc esi,speedmaj[ebx] ;skok po major hodnotach
sahf ;obnov cf
adc esi,speedmaj[ebx]
cmp esi,endloop[ebx]
jc mix12skp
mov esi,startloop[ebx]
cmp esi,endloop[ebx]
jnz mix12skp
mov smptype[ebx],0
jmp mix12end
mix12skp:sub ecx,4
jnz mix12lp
mix12end:mov minorpos[ebx],bp
mov playpos[ebx],esi
pop ebp
ret
m16ido: push ebp
mov esi,_mixpos ;vem mixovaci pozici
sub si,4 ;o jeden sampl dozadu
mov edi,_backfine ;finepozice
mov ebx,_backsnd ;pozice v bufferu
mov ecx,_mixsize ;pocet bajtu
sub ecx,4
shl ecx,16 ;uloz do horni poloviny ecx
mov eax,[esi] ;vezmi sample
xor eax,80008000h ;neznaminkova korekce
m16ido1:add si,4 ;dalsi sample
mov ebp,eax
and ebp,0ffff0000h
mov edx,[esi] ;nacti do dx sample
xor edx,80008000h ;neznaminkova korekce
add ax,dx ;secti leve kanaly
rcr ax,1 ;nasleduje deleni 2x prumer
add ebp,edx ;totez pro prave kanaly
rcr ebp,1
shld eax,ebp,16
xor eax,80008000h ;neznaminkova korekce
mov cx,word ptr _backsndbuff[ebx*4] ;nacti back sound pro levej kanal
addc ax,cx,7fffh ;secti s clippingem levy kanal
mov cx,word ptr _backsndbuff[2+ebx*4];nacti back sound pro pravej kanal
rol eax,16
addc ax,cx,7fffh ;secti s clippingem pravy kanal
add di,word ptr _backstep ;pricti fine pozici
adc bx,word ptr [_backstep+2];preteceni jde do bx plus step
; and ebx,03ffffh ;celkem 16384*4 samplu
sub si,4 ;uloz na zdrojovou pozici
mov [esi],eax
add si,4
mov eax,edx ;pouzity sampl pro prumerovani se
sub ecx,40000h ;do ax a odecti ctyri takty pro citac
jnc m16ido1 ;a opakuj dokud neni konec
pop ebp
mov _backsnd,ebx
mov _backfine,edi
ret ;navrat
PUBLIC setsb16_
setsb16_:
lea edi,_jumptable
mov eax,offset mixskip
stosd
mov eax,offset mix16_
stosd
mov eax,offset mix162
stosd
mov _getdma,offset sbdma
mov _ido,offset m16ido
ret
dpmibufalloc:
mov ax,0100h
int 31h
ret
public buff_dealloc_
buff_dealloc_:
mov dx,_dpmiselector
mov ax,0101h
int 31h
ret
public buff_alloc_
buff_alloc_:
mov ebx,4200
call dpmibufalloc
jc allcerror
test eax,0fffh
jz allc_ok
push eax
mov eax,0101h
int 31h
pop eax
mov ebx,eax
and ebx,0f000h
add ebx,1000h
sub ebx,eax
dec ebx
call dpmibufalloc
jc allcerror
push edx
call buff_alloc_
mov ecx,edx
pop edx
push eax
mov eax,0101h
int 31h
pop eax
ret
allc_ok:mov _dpmiselector,dx
shl eax,4
ret
allcerror:
mov word ptr _dpmiselector,0
xor eax,eax
ret
public int_relocation_
int_relocation_:
mov eax,0de0ah
int 67h
shl ebx,16
mov bx,cx
rol ebx,16
mov eax,ebx
ret
public int_mixer_alloc_
int_mixer_alloc_:
lea eax,_idt_map
sidt [eax]
; db 0fh
; db 01
; db 08h
add eax,2
mov eax,[eax]
shl ebx,3
add eax,ebx
cli
mov edi,eax
push ds
pop es
mov ecx,offset int_normal_
mov eax,ecx
stosw
mov ax,cs
stosw
mov eax,8e00h
stosw
mov eax,ecx
shr eax,16
stosw
sti
mov ebx,1000h
call dpmibufalloc
mov esi,4*8
mov edi,offset rm_old
mov ecx,4
rep movsb
mov _call_back_sel,dx
mov esi,offset rm_data_
mov edi,eax
shl edi,4
mov _call_back_data,edi
mov ecx,1000
rep movsb
mov edi,4*8
mov word ptr [edi],8
mov [edi+2],ax
ret
public int_high_alloc_
int_high_alloc_:
lea eax,_idt_map
sidt [eax]
add eax,2
mov eax,[eax]
shl ebx,3
add eax,ebx
cli
mov edi,eax
push ds
pop es
mov ecx,offset int_hspd_
mov eax,ecx
stosw
mov ax,cs
stosw
mov eax,8e00h
stosw
mov eax,ecx
shr eax,16
stosw
sti
mov ebx,1000h
call dpmibufalloc
mov esi,4*8
mov edi,offset rm_old
mov ecx,4
rep movsb
mov _call_back_sel,dx
mov esi,offset rm_data_
mov edi,eax
shl edi,4
mov _call_back_data,edi
mov ecx,1000
rep movsb
mov edi,4*8
; mov word ptr [edi],(high_speed - rm_data_)
; mov [edi+2],ax
ret
public high_speed_parm_
;eax dos delay
;edx port
;ebx mixbuffer
;esi xlattab
high_speed_parm_:
mov edi,offset w_max
mov [edi],ax
mov edi,offset rm_hspd
mov ecx,64
rep movsd
xor eax,eax
stosw
mov eax,ebx
shr eax,4
stosw
mov eax,edx
stosw
ret
public int_dealloc_
int_dealloc_:
mov edi,4*8
mov esi,offset rm_old
mov ecx,4
rep movsb
mov dx,_call_back_sel
mov ax,101h
int 31h
ret
public write_adlib_
write_adlib_:
mov dx,_timer_test_port
out dx,al
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
mov al,ah
inc edx
out dx,al
mov ah,36
dec edx
wwait: in al,dx
dec ah
jnz wwait
ret
public write_adlib_nodelay_
write_adlib_nodelay_:
mov dx,_timer_test_port
out dx,al
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
mov al,ah
inc edx
out dx,al
ret
;public int_normal_:
int_normal_:
cli
pushad
push ds
push es
mov ax,seg _DATA
mov ds,ax
mov es,ax
mov al,20h
out 20h,al
mov dx,_timer_test_port
or dx,dx
jz intn_ok
in al,dx
test al,80h
jz intn_call_dos;
mov ax,8004h
call write_adlib_
intn_ok:inc _test_counter
sti
call mixer_
cli
intn_sk:pop es
pop ds
popad
iretd
intn_call_dos:call _oldvect
jmp intn_sk
public int_hspd_: ;high speed mode interrupt - pro D/A a PC Speaker
int_hspd_:
push ds
push esi
push ebx
push edx
push eax
mov al,20h
out 20h,al
mov ax,seg _DATA
mov ds,ax
mov ebx,_call_back_data
add ebx,(offset rm_hspd-offset rm_data_)
xor eax,eax
xor esi,esi
mov ax,[ebx+scanofs]
mov si,[ebx+scanseg]
shl esi,4
add esi,eax
mov dx,[ebx+port]
lodsb
xlatb
out dx,al
inc word ptr [ebx+scanofs]
mov ebx,_call_back_data
dec word ptr [ebx]
jnz hs_end
mov ax,[ebx+2]
mov [ebx],ax
sti
call mixer_
cli
hs_end:
pop eax
pop ebx
pop edx
pop esi
pop ds
iretd
;------------------------------- ULTRASND LIB -----------------
;Special thanx for Dalibor Straka
gus_sv macro voice
mov edx,_devport
add edx,gus_voice
mov al,voice
out dx,al
ENDM
gus_w macro reg,data
mov edx,_devport
mov al,reg
add edx,gus_reg
out dx,al
mov eax,data
add edx,gus_reg_data-gus_reg
out dx,ax
in ax,dx
in ax,dx
in ax,dx
in ax,dx
in ax,dx
in ax,dx
mov eax,data
out dx,ax
ENDM
gus_wb macro reg,data
mov edx,_devport
mov al,reg
add edx,gus_reg
out dx,al
mov al,data
add edx,gus_reg_data-gus_reg+1
out dx,al
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
in al,dx
mov al,data
out dx,al
ENDM
gus_wbd macro reg,data
mov edx,_devport
mov al,reg
add edx,gus_reg
out dx,al
mov al,data
add edx,gus_reg_data-gus_reg+1
out dx,al
endm
gus_r macro reg ;vysledek v eax
mov edx,_devport
mov al,reg
add edx,gus_reg
out dx,al
add edx,gus_reg_data-gus_reg
in ax,dx
movzx eax,ax
ENDM
;organizace GUS RAM
;<0 - gus_block> prehravaci blok
;<32768 - +gus_block> mirror buffer (prazdny)
extrn prepare_dma_:proc ;priprava DMA
public stop_gus_ ;deinicializuje GUS
stop_gus_:
mov cl,31 ;ted se vyresetuji vsechny kanaly
igus_2: gus_sv cl ;vyber hlas
gus_wb 0,2 ;vypni hlas
gus_wb 1,0 ;nastav krok na 0
gus_w 2,0003h ;nastav hlas na konec 64KB bloku
gus_w 3,0ff00h
gus_w 4,0003h
gus_w 5,0ff00h
gus_w 0Ah,0003h
gus_w 0Bh,0ff00h
gus_wb 0Dh,3fh ;vypni volume ramp
gus_wb 07h,0fh ;hlasitost 0
gus_wb 08h,10h ;hlasitost 0
gus_w 09h,0 ;hlasitost 0
sub cl,1
jnc igus_2
ret
gus_dma db 0,11h,11h,22h,22h,33h,44h,55h
public init_gus_ ;inicializuje GUS do rezimu prehravani samplu
init_gus_:
mov edx,_devport
mov al,19h ;zapni out
out dx,al
mov edx,_devport
lea edx,[edx+gus_irq_dma]
movzx eax,_dmanum
mov al,cs:gus_dma[eax]
out dx,al ;nastav DMA
gus_wbd 4ch,0 ;reset gus
mov edx,_devport
add edx,6
mov ecx,1000
igus_3: in al,dx
loop igus_3 ;cekani
gus_wbd 4ch,1 ;reset gus
add edx,6
mov ecx,1000
igus_4: in al,dx
loop igus_4
gus_wbd 4ch,3 ;povol dac
mov edx,_devport
mov edi,_mixbuffer
mov ecx, 65536 shr 2
xor eax,eax
rep stosd ;vynuluj dma_buffer
mov edx,_devport
add edx,gus_irqs
in al,dx
gus_r 41h
gus_wb 41h,0
mov edx,_devport
add edx,gus_irqs
in al,dx
gus_r 41h
gus_r 41h
gus_w 42h,0
mov eax,_mixbuffer
mov edx,65536
call prepare_dma_
movzx ecx,_gus_dma_type
gus_wb 41h,cl ;vynuluj prvnich 64KB GUSRAM
xor edx,edx
mov eax,617400
mov ecx,_samplerate
div ecx
add dx,8000h
adc al,0
cmp al,33
jc igus_1
mov al,32
igus_1: dec al
or al,0c0h
mov cl,al
gus_wb 0eh,cl
call stop_gus_
gus_sv 0
mov ecx,0 ;nastaveni hlasu cislo 0
gus_w 2,ecx ;zacni na 0
gus_w 3,ecx
gus_w 0Ah,ecx
gus_w 0Bh,ecx
mov ecx,(gus_block-4) shl 8 ;konec az za gus_blockem
gus_w 5,ecx
shr ecx,16
gus_w 4,ecx
mov ecx,(1 shl 0bh)
gus_w 1,ecx ;krok 2
gus_w 9,0ffffh ;hlasitost max
gus_wb 0ch,0 ;panning vlevo
gus_wb 00,0ch ;spust hlas
gus_sv 1 ;nastaveni hlasu cislo 1
mov ecx,2 shl 8
gus_w 3,ecx ;zacni na 2
gus_w 0Bh,ecx
shr ecx,16
gus_w 2,ecx
gus_w 0Ah,ecx
mov ecx,(gus_block-2) shl 8 ;konec az za gus_blockem
gus_w 5,ecx
shr ecx,16
gus_w 4,ecx
mov ecx,(1 shl 0bh)
gus_w 1,ecx ;krok 2
gus_w 9,0ffffh ;hlasitost max
gus_wb 0ch,0fh ;panning vpravo
gus_wb 00,0ch ;spust hlas
ret
gus_move_buff: ;presun bufferu do GUS
push eax
mov edx,_devport
add edx,gus_irqs
in al,dx
gus_r 41h
gus_wbd 41h,0
mov edx,_devport
add edx,gus_irqs
in al,dx
gus_r 41h
gus_r 41h
mov edx,_devport
add edx,gus_irqs
in al,dx
pop eax
xor esi,esi
and ah,1fh
or ah,ah
jz gus_mb1
mov esi,(gus_block shr 1)
gus_mb1:mov cl,4
test _gus_dma_type,4
jz gus_mb2
inc cl
gus_mb2:shr esi,cl
push esi
mov eax,_mixbuffer
mov edx,ebx
call prepare_dma_
pop esi
gus_w 42h,esi
movzx ecx,_gus_dma_type
gus_wbd 41h,cl
ret
gus_skip:mov eax,_mixbuffer
mov _mixpos,eax
xor ecx,ecx
mov _mixsize,ecx
mov cl,_gus_last_buff
gus_sv 0
gus_r 8Ah
shl eax,8
cmp eax,gus_block shr 1
rcl ch,1
xor cl,ch
jz gus_ie
mov ah,ch
mov _gus_last_buff,ch
mov ecx,(gus_block shr 1)
mov _mixsize,ecx
gus_ie: pop eax
ret
m16idog:push ebp
mov esi,_mixpos ;vem mixovaci pozici
mov edi,_backfine ;finepozice
mov ebx,_backsnd ;pozice v bufferu
mov ecx,_mixsize ;pocet bajtu
shr ecx,2
dec ecx
shl ecx,16
m16ido2:mov eax,[esi]
mov cx,word ptr _backsndbuff[ebx*4] ;nacti back sound pro levej kanal
addc ax,cx,7fffh ;secti s clippingem levy kanal
mov cx,word ptr _backsndbuff[2+ebx*4];nacti back sound pro pravej kanal
rol eax,16
addc ax,cx,7fffh ;secti s clippingem pravy kanal
add di,word ptr _backstep ;pricti fine pozici
adc bx,word ptr [_backstep+2];preteceni jde do bx plus step
and ebx,03ffffh ;celkem 16384*4 samplu
mov [esi],eax
add si,4
sub ecx,10000h ;do ax a odecti ctyri takty pro citac
jnc m16ido2 ;a opakuj dokud neni konec
pop ebp
mov _backsnd,ebx
mov _backfine,edi
mov ah,_gus_last_buff
mov ebx,_mixsize ;pocet bajtu
call gus_move_buff
ret ;navrat
PUBLIC setGUS_
setGUS_:
lea edi,_jumptable
mov eax,offset mixskip
stosd
mov eax,offset mix16_
stosd
mov eax,offset mix162
stosd
mov _getdma,offset GUS_SKIP
mov _ido,offset m16idog
ret
public gus_setchan_vol_
gus_setchan_vol_: ;ecx,eax
gus_sv al
gus_w 9,ecx
ret
public gus_setchan_pan_
gus_setchan_pan_: ;ecx,eax
gus_sv al
gus_wb 0ch,cl
ret
_TEXT16 SEGMENT BYTE PUBLIC USE16 'CODE'
ASSUME cs:_TEXT16
public rm_proc_:
rm_data_:
w_count:dw 2 ;citac preruseni
w_max dw 2 ;maximalni hodnota citace
rm_old dw ? ;stary vektor preruseni
dw ?
rm_proc_:
cli
int 1ch
cli
push si
xor si,si
dec word ptr cs:[si]
jnz w_skip
push ax
mov ax,cs:[si+2]
mov cs:[si],ax
pop ax
pushf
call dword ptr cs:[si+4]
w_skip: pop si
iret
rm_hspd db 300 dup(?)
high_speed:
push ds
push si
push bx
push dx
push ax
mov bx,offset rm_hspd-offset rm_data_
lds si,cs:[bx+scanofs]
mov dx,cs:[bx+port]
lodsb
xlat cs:
out dx,al
mov cs:[bx+scanofs],si
mov al,20h
out 20h,al
dec word ptr cs:[0]
jnz hspd_end
mov ax,cs:[2]
mov cs:[0],ax
pushf
call dword ptr cs:[4]
int 1ch
hspd_end:
pop ax
pop dx
pop bx
pop si
pop ds
iret
_TEXT16 ends
_TEXT ends
END