;***************************************************************************
;* Driver pour le PC speaker
;*
;* Programmé par Sébastien Granjoux
;* Commencé le 07/01/95
;* Modification le 07/01/95
IDEAL
P386N
INCLUDE "CRYSERR.INC"
INCLUDE "CRYSDEV.INC"
PUBLIC USESPK
PUBLIC setspk
PUBLIC startspk
PUBLIC makespk
PUBLIC stopspk
PUBLIC defbpmspk
SEGMENT CODE PARA PUBLIC USE16 'CODE'
ASSUME cs:CODE,ds:CODE
;*************************************************************************
;* Fonction de detection du driver
PROC USESPK
call USEDEVICE
DEVICE <01h,'$',OFFSET setspk,OFFSET startspk,OFFSET stopspk,OFFSET makespk,OFFSET defbpmspk,OFFSET peekdef,0,0,0>
ENDP
Counter DD 0
Count DD 0
OtherCount DW 0
;***************************************************************************
;* routine permettant d'initialiser le speaker
PROC setspk
mov [(DEVICE PTR ds:si).irq],0
shr [MixRate],1
mov cl,[NbVoice]
call calvoltab
clc
ret
ENDP
;***************************************************************************
;* routine permettant de démarrer l'envoit du son sur le speaker
PROC startspk
cli
mov ax,OFFSET soundspk
mov dx,cs
xor bl,bl
call setirq
mov al,00110110b
out 43h,al
jmp $+2
jmp $+2
mov dx,1
mov ax,0D216h
div [ds:MixRate]
shr ax,1
out 40h,al
jmp $+2
jmp $+2
rol ax,8
out 40h,al
jmp $+2
jmp $+2
rol ax,8
movzx ecx,ax
mov eax,80000000h
xor edx,edx
div ecx
add eax,eax
mov [ds:Counter],eax
shr eax,16
mov [ds:OtherCount],ax
mov ax,[ds:VoicesLen]
sub [ds:OtherCount],ax
mov [ds:Count],1
mov al,10010000b
out 43h,al
jmp $+2
jmp $+2
in al,61h
jmp $+2
jmp $+2
or al,11b
out 61h,al
jmp $+2
jmp $+2
; call setautoeoi
sti
ret
ENDP
;**************************************************************************
;* cette procédure est en fait un bloc que l'on doit mettre à
;* l'adresse Voices
PROC makespk FAR
mov cl,[NbVoice]
sub cl,2
push cx
mov di,OFFSET Voice1
mov dx,[Voice1.effet]
call dx
mov di,[ds:OFFSET SoundPage]
mov bx,[Voice1.play]
shl bx,1
xor edx,edx
mov dx,[word ptr ds:bx+OFFSET Notes]
ror edx,10
mov cx,[Voice1.samplen]
les esi,[Voice1.adrvoc]
mov bx,[Voice1.replen]
cmp si,cx
jbe @@ok1
@@adjust1:
sub si,bx
cmp si,cx
ja @@adjust1
@@ok1:
mov bx,OFFSET VolumeTab
mov al,[MasterVol]
and al,[Voice1.mute]
mul [Voice1.volume]
add bh,ah
push ebp
@@voix1:
add esi,edx
mov al,[byte ptr es:si]
adc esi,edx
xlat
mov ah,al
mov al,[byte ptr es:si]
adc si,0
xlat
mov [ds:di+OFFSET SoundBuf],ax
add di,4
cmp di,bp
jne @@voix1
rol ebp,16
xor di,di
cmp bp,BUF_LEN
jne @@voix1
pop ebp
mov [dword ptr OFFSET Voice1.adrvoc],esi
pop cx
mov di,OFFSET Voice1+SIZE VOICE
@@next_voice:
push cx
mov dx,[(VOICE ptr ds:di).effet]
call dx
mov bx,[(VOICE ptr ds:di).play]
shl bx,1
xor edx,edx
mov dx,[word ptr ds:bx+OFFSET Notes]
ror edx,10
mov cx,[(VOICE ptr ds:di).samplen]
mov bx,OFFSET VolumeTab
mov al,[MasterVol]
and al,[(VOICE PTR ds:di).mute]
mul [(VOICE ptr ds:di).volume]
add bh,ah
mov ax,[(VOICE ptr ds:di).replen]
push di
les esi,[(VOICE ptr ds:di).adrvoc]
cmp si,cx
jbe @@ok2
@@adjust2:
sub si,ax
cmp si,cx
ja @@adjust2
@@ok2:
push ebp
mov di,[ds:OFFSET SoundPage]
@@voix2:
add esi,edx
mov al,[byte ptr es:si]
adc esi,edx
xlat
mov ah,al
mov al,[byte ptr es:si]
adc si,0
xlat
add [ds:di+OFFSET SoundBuf],al
add [ds:di+OFFSET SoundBuf+1],ah
add di,4
cmp di,bp
jne @@voix2
rol ebp,16
xor di,di
cmp bp,BUF_LEN
jne @@voix2
pop ebp
pop di
mov [dword ptr ((VOICE ptr ds:di).adrvoc)],esi
add di,SIZE VOICE
pop cx
dec cl
jne @@next_voice
mov dx,[(VOICE ptr ds:di).effet]
call dx
mov bx,[(VOICE ptr ds:di).play]
shl bx,1
xor edx,edx
mov dx,[word ptr ds:bx+OFFSET Notes]
ror edx,10
mov cx,[(VOICE ptr ds:di).samplen]
les esi,[(VOICE ptr ds:di).adrvoc]
mov bx,[(VOICE ptr ds:di).replen]
cmp si,cx
jbe @@ok4
@@adjust4:
sub si,bx
cmp si,cx
ja @@adjust4
@@ok4:
mov bx,OFFSET VolumeTab
mov al,[MasterVol]
and al,[(VOICE PTR ds:di).mute]
mul [(VOICE ptr ds:di).volume]
add bh,ah
push di
mov di,[ds:OFFSET SoundPage]
@@voix4:
add esi,edx
mov al,[byte ptr es:si]
adc esi,edx
xlat
mov ah,al
mov al,[byte ptr es:si]
adc si,0
xlat
add al,[ds:di+OFFSET SoundBuf]
add ah,[ds:di+OFFSET SoundBuf+1]
mov [ds:di+OFFSET SoundBuf],ah
mov [ds:di+OFFSET SoundBuf+1],ah
mov ah,al
mov [ds:di+OFFSET SoundBuf+2],ax
add di,4
cmp di,bp
jne @@voix4
rol ebp,16
xor di,di
cmp bp,BUF_LEN
jne @@voix4
pop di
mov [dword ptr ((VOICE ptr ds:di).adrvoc)],esi
@@fin4voix:
shr ebp,16
and bp,65535-BUF_LEN
mov [word ptr ds:OFFSET SoundPage],bp
mov [byte ptr cs:OFFSET switch_makemod],1Eh
pop edi
pop esi
pop ebp
pop es
pop ds
ret
ENDP
;***************************************************************************
;* interruption 8 permettant d'envoyer le son sur le speaker
PROC soundspk FAR
push ax
push bx
mov bx,[cs:OFFSET SoundPtr]
inc bx
and bx,65535-BUF_LEN
mov [cs:OFFSET SoundPtr],bx
mov al,[cs:bx+OFFSET SoundBuf]
mov bx,OFFSET AMPLI8
xlat [cs:bx]
out 42h,al
pop bx
dec [word cs:OFFSET Count+2]
irq_switch:
jle @@imakemod
mov al,20h
out 20h,al
pop ax
iret
@@int08:
mov ax,[word ptr cs:OFFSET Counter+2]
xchg ax,[cs:OtherCount]
add [cs:OFFSET Count+2],ax
sub [cs:OtherCount],ax
add [byte ptr cs:OFFSET irq_switch+1],OFFSET @@imakemod - OFFSET @@int08
pop ax
jmp [dword ptr cs:OldIrq]
@@imakemod:
mov al,60h
out 20h,al
mov ax,[cs:VoicesLen]
cmp ax,[cs:OtherCount]
jb @@next_make
push eax
xchg ax,[cs:OtherCount]
sub [cs:OtherCount],ax
shl eax,16
mov ax,[word ptr cs:Counter]
add [cs:OFFSET Count],eax
sub [byte ptr cs:OFFSET irq_switch+1],OFFSET @@imakemod - OFFSET @@int08
pop eax
pop ax
jmp IMAKEMOD
@@next_make:
sub [cs:OtherCount],ax
add [word ptr cs:OFFSET Count+2],ax
pop ax
jmp IMAKEMOD
ENDP
;***************************************************************************
;* cette routine permet d'arreter l'envoit du son sur le speaker
PROC stopspk
in al,61h
and al,11111100b
out 61h,al
cli
mov al,00110110b
out 43h,al
xor al,al
out 40h,al
out 40h,al
; call reseteoi
ret
ENDP
;***************************************************************************
;* Change la vitesse en BPM
;*
;* Entrée:
;* AL nouvelle vitesse
PROC defbpmspk
movzx cx,al
mov ax,[MixRate]
mov dx,25
mul dx
div cx
inc ax
and ax,0fffch
shl ax,1
mov [VoicesLen],ax
ret
ENDP
ENDS
END