

	.386
	.model small
	option oldstructs

	include d:\cw\cw.inc
	include d:\cw\cw-undoc.inc

	include mdv.inc

b	equ	byte ptr
w	equ	word ptr
d	equ	dword ptr
f	equ	fword ptr


	.code


;-------------------------------------------------------------------------------
;
;Load and initialise DigPak and MidPak drivers.
;
;On Entry:
;
;nothing.
;
;On Exit:
;
;Carry set on error and AX=error code.
;
;Error codes:
;
;0	- no error.
;1	- file not found.
;2	- not enough memory.
;3	- corrupt driver file.
;
;Note:
;
;All of the other routines can be called after this routine has failed to
;initialise the drivers. This code sets a flag which is checked by the other
;routines which will simply exit without doing anything if the drivers arn't
;loaded.
;
InitDigMid	proc	near
	public InitDigMid
	cmp	HaveDigMid,0		;Check if we already loaded the
	jnz	@@8		;drivers.
;
;Load the relavent driver files.
;
	sys	cwGetPatch
	cmp	d[edx+4],0
	jz	@@GetDig
	mov	edx,[edx+4]
	mov	sDriverAddr,edx
	jmp	@@GotDig
@@GetDig:	;
	mov	edx,offset DigName	;DigPak selected driver name,
	sys	cwLoad
	jc	@@9
	mov	sDriverAddr,edx
	mov	w[sDriverAddr+4],si
	mov	edi,sDriverAddr
	call	MDV_Init[edi]	;Call init code.
	jc	@@9		;oops, some kind of problem.
@@GotDig:	;
	sys	cwGetPatch
	cmp	d[edx],0
	jz	@@GetMid
	mov	edx,[edx]
	mov	mDriverAddr,edx
	jmp	@@GotMid
@@GetMid:	;
	mov	edx,offset MidName	;MidPak selected driver name.
	sys	cwLoad
	jc	@@9
	mov	mDriverAddr,edx
	mov	w[mDriverAddr+4],si
	mov	edi,mDriverAddr
	mov	eax,50
	call	MDV_Init[edi]	;Call init code.
	jc	@@9		;oops, some kind of problem.
@@GotMid:	;
@@8:	mov	HaveDigMid,1		;flag driver present.
	xor	ax,ax
	ret
	;
@@9:	push	ax		;save error code.
	call	RemDigMid		;Remove everything on error.
	pop	ax
	stc
	ret
InitDigMid	endp


;-------------------------------------------------------------------------------
;
;Remove DigPak and MidPak drivers.
;
RemDigMid	proc	near
	public RemDigMid
;
;Make sure no Midi stuff playing.
;
	call	StopDigi
	call	StopMidi
	call	RemDigiFile
	call	RemMidiFile
;
;Need to de-init MidPak if it was initialised.
;
	cmp	w[mDriverAddr+4],0	;Did we make the init call?
	jz	@@0
	mov	edi,mDriverAddr
	call	MDV_Rem[edi]		;Call remove code.
	xor	bx,bx
	xchg	bx,w[mDriverAddr+4]
	sys	RelMem
;
;Now release memory allocated for all MidPak chunks.
;
@@0:	xor	bx,bx
	xchg	bx,MidiFileSeg
	or	bx,bx
	jz	@@3
	sys	RelMem
;
;Need to de-init DigPak if it was initialised.
;
@@3:	cmp	w[sDriverAddr+4],0	;Did we make the init call?
	jz	@@4
	mov	edi,sDriverAddr
	call	MDV_Rem[edi]		;Call remove code.
	xor	bx,bx
	xchg	bx,w[sDriverAddr+4]
	sys	RelMem
	;
@@4:	mov	HaveDigMid,0
	ret
RemDigMid	endp


;-------------------------------------------------------------------------------
;
;Load and register a midi file.
;
;On Entry:
;
;DS:DX	- file name.
;
;On Exit:
;
;Carry set on error and AX=error code else,
;
;nothing.
;
;Error Codes:
;
;0	- no error.
;1	- file not found.
;2	- not enough memory.
;3	- MidPak driver not loaded.
;
InitMidiFile	proc	near
	public InitMidiFile
	mov	ax,3
	cmp	HaveDigMid,1		;check drivers are loaded.
	jc	@@9
	;
	call	RemMidiFile		;lose anything already loaded.
	call	LoadAllocate		;load requested file.
	jc	@@9
	mov	MidiFileSeg,dx	;stow this for release.
	or	MIDIUsed,-1
	;
	xor	ax,ax
@@9:	ret
InitMidiFile	endp


;-------------------------------------------------------------------------------
;
;Load and register a digi file.
;
;On Entry:
;
;DS:DX	- file name.
;
;On Exit:
;
;Carry set on error and AX=error code else,
;
;nothing.
;
;Error Codes:
;
;0	- no error.
;1	- file not found.
;2	- not enough memory.
;3	- DigPak driver not loaded.
;
InitDigiFile	proc	near
	public InitDigiFile
	mov	ax,3
	cmp	HaveDigMid,1		;check drivers are loaded.
	jc	@@9
	;
	call	RemDigiFile
	call	LoadAllocate		;load requested file.
	jc	@@9
	mov	DigiFileSeg,dx	;stow this for release.
	;
	xor	ax,ax
@@9:	ret
InitDigiFile	endp


;-------------------------------------------------------------------------------
;
;Make sure no midi stuff is playing and release memory used by current file.
;
RemMidiFile	proc	near
	public RemMidiFile
	pushad
	xor	bx,bx
	xchg	bx,MidiFileSeg	;check if a previous allocation
	or	bx,bx		;needs releaseing.
	jz	@@0
	call	StopMidi
	sys	RelMem		;release memory.
@@0:	popad
	ret
RemMidiFile	endp


;-------------------------------------------------------------------------------
;
;Make sure no digi stuff is playing and release memory used by current file.
;
RemDigiFile	proc	near
	public RemDigiFile
	pushad
	xor	dx,dx
	xchg	dx,DigiFileSeg
	or	dx,dx
	jz	@@0
	call	StopDigi
	mov	bx,dx
	sys	RelMem
@@0:	popad
	ret
RemDigiFile	endp


;-------------------------------------------------------------------------------
;
;Start X-Midi sequence playing.
;
;On Entry:
;
;AX	- Sequence number.
;
PlayMidi	proc	near
	public PlayMidi
	cmp	HaveDigMid,1
	jc	@@9
	or	MIDIUsed,-1
	call	StopMidi
	push	eax
	push	esi
	push	edx
	push	ecx
	push	ebx
	mov	bx,MidiFileSeg
	sys	GetSelDet32
	mov	esi,edx
	pop	ebx
	pop	ecx
	pop	edx
	mov	eax,1
	mov	edi,mDriverAddr
	call	MDV_Play[edi]	;Play tune.
	pop	esi
	pop	eax
	clc
@@9:	ret
PlayMidi	endp


;-------------------------------------------------------------------------------
;
;Update Midi player.
;
UpdateMidi	proc	near
	public UpdateMidi
	cmp	HaveDigMid,1
	jc	@@9
	push	edi
	mov	edi,mDriverAddr
	call	MDV_Update[edi]	;Update tune.
	pop	edi
@@9:	ret
UpdateMidi	endp


;-------------------------------------------------------------------------------
;
;Start a digi sample playing.
;
;On Entry:
;
;AX	- Sample number.
;
PlayDigi	proc	near
	public PlayDigi
	pushad
	cmp	HaveDigMid,1
	jc	@@9
	;
	movzx	edi,ax
	shl	edi,2
	add	edi,4
	;
	push	es
	mov	es,DigiFileSeg
	mov	esi,es:[edi]
	mov	ecx,es:[edi]
	and	ecx,0FFFFFFh
	sub	ecx,2
	add	esi,5
	push	eax
	push	ebx
	push	ecx
	push	edx
	mov	bx,es
	sys	GetSelDet32
	add	esi,edx
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	mov	edi,sDriverAddr
	call	MDV_Play[edi]	;Play sample.
	pop	es
	;
@@9:	popad
@@return:	ret
PlayDigi	endp


;-------------------------------------------------------------------------------
;
;Stop any midi sounds that are playing.
;
StopMidi	proc	near
	public StopMidi
	cmp	HaveDigMid,1
	jc	@@9
	cmp	MIDIUsed,0
	jz	@@9
	push	edi
	mov	edi,mDriverAddr
	call	MDV_Stop[edi]	;Update tune.
	pop	edi
@@9:	ret
StopMidi	endp


;-------------------------------------------------------------------------------
;
;Stop any digi sounds that are playing.
;
StopDigi	proc	near
	public StopDigi
	cmp	HaveDigMid,1
	jc	@@9
	push	edi
	mov	edi,sDriverAddr
	call	MDV_Stop[edi]	;Update tune.
	pop	edi
@@9:	ret
StopDigi	endp


;-------------------------------------------------------------------------------
;
;Allocate memory for, and load, specified file.
;
;On Entry:
;
;DS:DX	- File name.
;
;On Exit:
;
;Carry set on error and AX=error code else,
;
;DX	- Selector for memory file loaded to.
;SI	- low word length.
;DI	- high word length.
;
;Error codes:
;
;0	- no error.
;1	- file not found.
;2	- not enough memory.
;
;All other registers preserved.
;
LoadAllocate	proc	near
	mov	ax,3d00h
	int	21h
	mov	bx,ax
	jc	@@10
	xor	cx,cx
	xor	dx,dx
	mov	ax,4202h
	int	21h
	shl	edx,16
	mov	dx,ax
	push	edx
	xor	cx,cx
	xor	dx,dx
	mov	ax,4200h
	int	21h
	pop	ecx
	push	bx
	sys	GetMem32
	mov	ax,bx
	pop	bx
	jc	@@9
	push	ax
	push	ds
	mov	ds,ax
	xor	edx,edx
@@read:	or	cx,-1
	mov	ah,3fh		;Read the driver into memory.
	int	21h
	jc	@@readover
	movzx	eax,ax
	add	edx,eax
	or	eax,eax
	jnz	@@read
	clc
@@readover:	pop	ds
	pop	dx
	jc	@@9
	push	dx
	mov	ah,3eh		;close the file.
	int	21h
	pop	dx
	clc
	ret
	;
@@9:	mov	ah,3eh		;close the file.
	int	21h
@@10:	stc
	ret
LoadAllocate	endp


	.data

	public HaveDigMid, sDriverAddr, mDriverAddr, MIDIUsed

HaveDigMid	db 0
;
sDriverAddr	dd 0,0
DigiFileSeg	dw 0
DigName	db "SOUND\SAMPLE.DRV",0
;
mDriverAddr	dd 0,0
MidiFileSeg	dw 0
MidName	db "SOUND\MIDI.DRV",0
;
MIDIUsed	db 0

	end

