;;************ MIDPAK.ASM, flat-model link layer to MIDPAK functions.
;;************ written using Borland Assembler in IDEAL mode.  Assumes
;;************ a DPMI with a flat model address space where selectors
;;************ DS and ES always point to flat address 0000000000000h!
;;************ Written and tested with DOS4GW and Watcom C.  Uses
;;************ standard C calling convention.  Getting this to work
;;************ under any other DPMI is an excercise left for ths student.
;;************ Warning!! The Watcom compiler passes 4 bytes on the stack
;;************ to a cdecl external routine, even if the parameter is only
;;************ a char.	All of these assembly routines have been defined
;;************ this way.  If you are usinga compiler that passes different
;;************ size arguments to cdecl routines, you may want to double
;;************ check for compatibilities sake.
;;***
;;*** Written by John W. Ratcliff (c) 1994
;;***		 Compuserve: 70253,3237
;;***		 Genie: J.RATCLIFF3
;;***		 BBS: 1-314-939-0200
;;***		 Addresss:
;;***			   747 Napa Lane
;;***			   St. Charles, MO 63304
;;***
;;***	 A $500 per product license fee applies to all commercial software
;;***	 products distributed with any MIDPAK drivers.
;;***	 To pay a license, simply write a check for $500 payable to
;;***	 The Audio Solution, 747 Napa Lane, St. Charles, MO 63304
;;***	 with a copy of your commerical product.  You will receive a signed
;;***	 license agreement from The Audio Solution shortly thereafter.
;;***	 This license fee applies specifically to the inclusion with your
;;***	 distribution disk any of the MIDPAK drivers from The Audio Solution
;;***	 These drivers are copyrighted works, created by me, to enhance the
;;***	 use of sound and music in DOS based commercial software.	 The
;;***	 license fees collected are used to maintain the drivers and keep
;;***	 the BBS running.	 There is a seperate license fee for the use
;;***	 and distribution of DIGPAK drivers.
;;***	 See accompaning documentation regarding license fees for DIGPAK
;;***	 distribution.	You would be ill-advised to distribute a commercial
;;***	 product containing either DIGPAK and/or MIDPAK drivers without
;;***	 having paid the distribution license fee.  Since your product would
;;***	 contain unlicensed copyrighted software from The Audio Solution,
;;***	 your product could be immediatly required to be removed from retail
;;***	 distribution.	I doubt this is going to be a problem.	Clearly if
;;***	 your product is enhanced by the use of these drivers, your company
;;***	 can easily afford a nominal license fee of $500 in exchange for
;;***	 getting the use of several man-years of software engineering
;;***	 resources.
;;******************************************************************************
	IDEAL
	P386
	JUMPS
	MODEL FLAT,C
	CODESEG
	LOCALS			;; Enable local labels

	public	PlaySequence
	public	SegueSequence
	public	RegisterXmidi
	public	MidiStop
	public	MidPakClock
	public	MidPakClockAddress
	public	DigPakAvailable
	public	ReportCallbackTrigger
	public	ResetCallbackCounter
	public	ResumePlaying
	public	SequenceStatus
	public	RelativeVolume
	public	SetRelativeVolume
	public	RegisterXmidiFile
	public	PollMidPak
	public	TriggerCountAddress
	public	EventIDAddress
	public	ReportSequenceNumber
	public	CheckMidiIn
	public	InitMP
	public	DeInitMP

MID_PLAYSEQUENCE equ 702h
MID_SEGUESEQUENCE equ 703h
MID_REGISTERXMIDI equ 704h
MID_MIDISTOP equ 705h
MID_MIDPAKCLOCK equ 712h
MID_MIDPAKCLOCKADDRESS equ 712h
MID_DIGPAKAVAILABLE equ 701h
MID_REPORTCALLBACKTRIGGER equ 707h
MID_RESETCALLBACKCOUNTER equ 708h
MID_RESUMEPLAYING equ 70Bh
MID_SEQUENCESTATUS equ 70Ch
MID_RELATIVEVOLUME equ 70Eh
MID_SETRELATIVEVOLUME equ 70Fh
MID_REGISTERXMIDIFILE equ 70Dh
MID_POLLMIDPAK equ 711h
MID_TRIGGERCOUNTADDRESS equ 713h
MID_EVENTIDADDRESS equ 714h
MID_REPORTSEQUENCENUMBER equ 716h
MID_BOOTSTRAP equ 710h

;;	int  PlaySequence(short seqnum)
Proc	C PlaySequence near
	ARG	DATA:DWORD
	uses	ebx,ds,es
	mov	eax,MID_PLAYSEQUENCE
	mov	ebx,[DATA]
	int	66h
	ret
	endp


;;	int  SegueSequence(int seqnum,int activate)
PROC	C  SegueSequence near
	ARG	SEQ:DWORD,ACT:DWORD
	uses	ebx,ecx,ds,es
	mov	eax,MID_SEGUESEQUENCE	     ;
	mov	ebx,[SEQ]
	mov	ecx,[ACT]
	int	66h
	ret
	endp


;;	int  RegisterXmidi(char far *midi,int length)
Proc	C   RegisterXmidi near
	ARG	SEQ:DWORD,SLEN:DWORD
	uses	ebx,ecx,esi,edi,es,ds

	mov	ebx,[SEQ]		; Address of sequence.
	mov	ecx,ebx 	; into segment reg
	shr	ecx,4		; Into segment format
	and	ebx,0Fh 	; offset.
	mov	esi,[SLEN]		; length of sequence.
	mov	edi,esi 	; into EDI for high word.
	shr	edi,16
	and	esi,0FFFFh	; Leve low word.
	mov	eax,MID_REGISTERXMIDI	     ; Register XMIDI file.
	int	66h
	ret
	endp


;;	int  MidiStop(void)
PROC	C   MidiStop near
	uses	ds,es
	mov	eax,MID_MIDISTOP	; Stop playing current sequence.
	int	66h
	ret
	endp

;; long int MidPakClock(void)
Proc	C   MidPakClock near
	uses	ebx,ecx,edx,ds,es
	mov	eax,MID_MIDPAKCLOCK
	int	66h
	shl	edx,16
	add	eax,edx 	; return in EAX flat-model format
	ret
	endp

;; long int MidPakClock(void)
PROC	C   MidPakClockAddress near
	uses	ebx,ecx,edx,ds,es

	xor	ecx,ecx 	; Zero all of EBX
	mov	eax,MID_MIDPAKCLOCKADDRESS
	int	66h
	shl	ecx,4
	mov	ax,bx		; Offset portion.
	add	eax,ecx 	; form flat-model address.
	ret
	endp

PROC	C DigPakAvailable near
	uses	ds,es
	mov	eax,MID_DIGPAKAVAILABLE
	int	66h
	ret
	endp

PROC	C ReportCallbackTrigger near
	uses	edx,ds,es
	mov	eax,MID_REPORTCALLBACKTRIGGER
	int	66h
	shl	edx,16		; Into high word.
	add	eax,edx 	; Form long int result.
	ret
	endp

Proc	C   ResetCallbackCounter near
	uses	ds,es
	mov	eax,MID_RESETCALLBACKCOUNTER
	int	66h
	ret
	endp

Proc	C  ResumePlaying near
	uses	ds,es
	mov	eax,MID_RESUMEPLAYING
	int	66h
	ret
	endp

PROC	C SequenceStatus near
	uses	ds,es
	mov	eax,MID_SEQUENCESTATUS
	int	66h
	ret
	endp

PROC	C RelativeVolume near
	uses	ds,es
	mov	ax,MID_RELATIVEVOLUME
	int	66h
	ret
	endp

PROC	C SetRelativeVolume near
	ARG	VOL:DWORD,TIME:DWORD
	uses	ebx,ecx,ds,es
	mov	eax,MID_SETRELATIVEVOLUME
	mov	ebx,[VOL]
	mov	ecx,[TIME]
	int	66h
	ret
	endp

PROC	C RegisterXmidiFile near
	ARG	FNAME:DWORD
	uses	ebx,ecx,ds,es

	mov	ecx,[FNAME]	; Get flat model address.
	cmp	ecx,0FFFFFh	; in the first 1mb of address space?
	jle	@@LOW
	mov	eax,4		; Treat it like a registration error.
	jmp short @@OUT
@@LOW:	mov	ebx,ecx 	; Offset into EBX
	and	ebx,0Fh 	; Just leave offset.
	shr	ecx,4		; Into segment portion.
	mov	ax,MID_REGISTERXMIDIFILE
	int	66h
@@OUT:
	ret
	endp

PROC	C PollMidPak near
	uses	ds,es
	mov	eax,MID_POLLMIDPAK
	int	66h
	ret
	endp

PROC	C TriggerCountAddress near
	uses	edx,ds,es
	xor	edx,edx
	mov	eax,MID_TRIGGERCOUNTADDRESS
	int	66h
	shl	edx,4		; Segment shift into flat space.
	add	eax,edx 	; add offset, into flat space.
	ret
	endp

PROC	C EventIDAddress near
	uses	edx,ds,es
	xor	edx,edx
	mov	eax,MID_EVENTIDADDRESS
	int	66h
	shl	edx,4
	add	eax,edx
	ret
	endp

PROC	C ReportSequenceNumber near
	uses	ds,es
	mov	eax,MID_REPORTSEQUENCENUMBER
	int	66h
	ret
	endp


Proc	C CheckMidiIn	    near
	uses	ebx,ds,es

	mov	ebx,66h*4h
	mov	eax,[ds:ebx]	; Get addresss or interrupt vector.
	or	eax,eax
	jz	@@NOT		; Exit if vector is null.
	mov	bx,ax		; Get offset portion.
	shr	eax,(16-4)	; Get segment portion down.
	and	eax,0FFFFF0h	; and off remainder.
	add	ebx,eax 	; now have real-address.
	sub	ebx,6		; point back to identifier
	xor	eax,eax 	; Zero out entire EAX return register.
	cmp	[word ebx],'IM'  ; Midi driver?
	jne	@@NOT
	cmp	[word ebx+2],'ID'  ; full midi driver identity string?
	jne	@@NOT
	mov	eax,1
@@EXT:
	ret
@@NOT:	xor    eax,eax		 ; Zero return code.
	jmp short @@EXT
	endp

Proc	C InitMP near
	ARG	MIDPAK:DWORD,ADV:DWORD,AD:DWORD
	uses	ebx,ecx,esi,edi,es,ds

	mov	ebx,[MIDPAK]	; Get the address of the 'supposed' DIGPAK.
	cmp	[byte ebx+3],'M'        ; Does it say digpak?
	jne	@@FREE
	cmp	[byte ebx+4],'I'        ;
	jne	@@FREE
	cmp	[byte ebx+5],'D'
	jne	@@FREE
	cmp	[byte ebx+6],'P'
	jne	@@FREE
	cmp	[byte ebx+7],'A'
	jne	@@FREE
	cmp	[byte ebx+8],'K'
	jne	@@FREE
;; Ok, it SAY's MIDPAK
	shr	ebx,4		; Into segment size.
	sub	ebx,10h 	; org 100h, segment
	mov	ecx,200h	; offset
	mov	eax,0301h	; simulate realmode far proc.
	int	66h
	or	ax,ax
	jnz	@@FREE
	mov	ebx,[ADV]	; Get far address of ADV.
	shr	ebx,4		; Into SEGMENT.
	xor	ecx,ecx 	; Offset MUST be ZERO!
	mov	edx,[AD]	; get flat address of .AD file.
	mov	esi,edx 	; Into SI
	and	esi,0Fh 	; Leave just offset portion.
	shr	edx,4		; into segment.
	mov	eax,MID_BOOTSTRAP
	int	66h
@@RET:
	ret
@@FREE: mov	eax,9999	 ; Invalid driver return code.
	jmp short @@RET
	endp

Proc	C DeInitMP near
	ARG	MIDPAK:DWORD
	uses	ebx,ecx,esi,edi,ds,es

	mov	ebx,[MIDPAK]
	shr	ebx,4		; Into segment size.
	sub	ebx,10h 	; org 100h
	mov	ecx,203h	; offset.
	mov	eax,0301h	; simulate realmode far proc.
	int	66h
	or	ax,ax
	jnz	@@FREE
	mov	ax,1		; Success.
@@RET:
	ret
@@FREE:
	xor	ax,ax	; Zero failed return code
	jmp short @@RET
	ret
	endp


	ends
	end

