;***************************************************************************
;*	Driver pour Adlib
;*
;* Programm‚ par S‚bastien Granjoux
;* Commenc‚ le 14/01/95
;* Modification le 14/01/95

IDEAL
P386N

INCLUDE "CRYSERR.INC"
INCLUDE "CRYSDEV.INC"

PUBLIC	USEADL

SEGMENT CODE PARA PUBLIC USE16 'CODE'

ASSUME cs:CODE,ds:CODE

;*************************************************************************
;*	Fonction de detection du driver

PROC	USEADL

	call	USEDEVICE
	DEVICE <06h,'$',OFFSET setadl,OFFSET startadl,OFFSET stopadl,OFFSET makeadl,OFFSET defbpm,OFFSET peekdef,0,0,0>

ENDP

ADLPORT	EQU	388h

OldInt		DD	0
Counter         DD      0
Count           DD      0
OtherCount      DW      0

;**************************************************************************
;*	Fixe la valeur d'un registre de la carte adlib
;*
;* Entr‚e:
;*	AL	numero du registre … modifier
;*	AH	nouvelle valeur
;*	DX	adresse de port de la carte adlib

PROC	putreg

	out	dx,al
	mov	cx,7 		; attend 3.3æs
@@wait_reg:
	in	al,dx
	loop	@@wait_reg

	inc	dx
	mov	al,ah
	out	dx,al
	dec	dx
	mov	cx,46
@@wait_data:
	in	al,dx
	loop	@@wait_data

	ret

ENDP

;***************************************************************************
;*	routine permettant d'initialiser la carte adlib

PROC	setadl

	mov	dx,ADLPORT
	mov	ax,6004h
	call	putreg
	mov	ax,8004h
	call	putreg

	in	al,dx
	test	al,0E0h
	jz	@@adlib

	mov	ax,ADL_NOT_FOUND
	stc
	ret

@@adlib:
	mov	[(DEVICE PTR ds:si).irq],0

	xor	ax,ax
	call	putreg

	mov	ax,02120h
	call	putreg
	mov	ax,03F40h
	call	putreg
	mov	ax,0F060h
	call	putreg
	mov	ax,0F080h
	call	putreg
	mov	ax,000E0h
	call	putreg

	mov	ax,03F43h
	call	putreg

	mov	ax,001C0h
	call	putreg

	mov	cl,[NbVoice]
	call	calvoltab

	clc
	ret
ENDP

;***************************************************************************
;*	routine permettant de d‚marrer l'envoit du son sur la carte adlib

PROC	startadl

	cli
	mov	ax,OFFSET soundadl
	mov	dx,cs
	xor	bl,bl
	call	setirq

	mov	dx,ADLPORT
@@next_try:
	mov	ax,00B0h
	call	putreg
	mov	ax,8FA0h
	call	putreg
	mov	ax,2EB0h
	call	putreg
	xor	al,al
	out	43h,al
	jmp	$+2
	jmp	$+2
	in	al,40h
	jmp	$+2
	jmp	$+2
	mov	cl,al
	in	al,40h
	jmp	$+2
	jmp	$+2
	mov	ch,al
	cmp	cx,1400h
	jb	@@next_try
AdlTest:
	sub	cx,752h

@@wait_wave:
	xor	al,al
	out	43h,al
	jmp	$+2
	jmp	$+2
	in	al,40h
	jmp	$+2
	jmp	$+2
	mov     dl,al
	in	al,40h
	jmp	$+2
	jmp	$+2
	mov	dh,al
	cmp	dx,cx
	ja	@@wait_wave

	mov	dx,ADLPORT
	mov	ax,20B0h
	call	putreg
	mov	ax,00A0h
	call	putreg
	mov	ax,3F40h
	call	putreg

	mov	al,00110110b
	out     43h,al
	jmp	$+2
	jmp	$+2

	mov	dx,1
	mov	ax,0D216h
	div	[ds:MixRate]

	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

	sti

	ret

ENDP

;**************************************************************************
;*	cette proc‚dure est en fait un bloc que l'on doit mettre …
;*	l'adresse Voices

PROC	makeadl FAR

	mov	cl,[NbVoice]
	sub	cl,2
	push	cx

	mov	di,OFFSET Voice1
	mov     dx,[(VOICE PTR di).effet]
	call    dx

	mov	di,[ds:OFFSET SoundPage]

	mov	bx,[(VOICE PTR Voice1).play]
	shl	bx,1
	xor	edx,edx
	mov	dx,[word ptr ds:bx+OFFSET Notes]

	ror	edx,10
	mov	cx,[(VOICE PTR Voice1).samplen]
	les	esi,[(VOICE PTR Voice1).adrvoc]
	mov	bx,[(VOICE PTR 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,[(VOICE PTR Voice1).mute]
	mul	[(VOICE PTR 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,2

	cmp	di,bp
	jne	@@voix1
	rol	ebp,16
	xor	di,di
	cmp	bp,BUF_LEN
	jne	@@voix1
	pop	ebp

	mov	[dword ptr ((VOICE PTR 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]
	les	esi,[(VOICE ptr ds:di).adrvoc]
	mov	bx,[(VOICE ptr ds:di).replen]
	cmp	si,cx
	jbe	@@ok2
@@adjust2:
	sub	si,bx
	cmp	si,cx
	ja	@@adjust2
@@ok2:

	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

	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],ax
	add	di,2

	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	[ds:di+OFFSET SoundBuf],ax
	add	di,2

	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

@@fin4voice:

	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    soundadl FAR

	push	eax
	push	bx
	push	dx

	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]

	mov	dx,ADLPORT+1
	out	dx,al

	pop	dx
	pop	bx

	dec	[word cs:OFFSET Count+2]
irq_switch:
	jle	@@imakemod

	mov	al,20h
	out	20h,al

	pop	eax
	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	eax
	jmp	[dword ptr cs:OldIrq]

@@imakemod:

	mov	al,20h
	out	20h,al

	mov     ax,[cs:VoicesLen]
	cmp     ax,[cs:OtherCount]
	jb      @@next_make
	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

	jmp     IMAKEMOD

@@next_make:
        sub     [cs:OtherCount],ax
        add     [word ptr cs:OFFSET Count+2],ax
	pop     eax

	jmp     IMAKEMOD

ENDP

;***************************************************************************
;*	cette routine permet d'arreter l'envoit du son sur le speaker

PROC	stopadl

	cli
	mov	dx,ADLPORT
	mov	ax,000B0h
	call	putreg

	mov     al,00110110b
	out     43h,al
	jmp	$+2
	jmp	$+2
	xor	al,al
	out     40h,al
	jmp	$+2
	jmp	$+2
	out     40h,al

	ret

ENDP

ENDS

END