impulsetracker/SoundDrivers/MIDDRV2.ASM

829 lines
22 KiB
NASM
Executable File

;
; MID File generator
;
REPEATSTATUSBYTE EQU 0
.386P
Segment DriverHeader PARA Public 'Code' Use16
Assume CS:Driver, DS:Nothing
;***** Driver Header *******
include drhead.inc
EndS
Segment Driver PARA Public 'Code' Use16
Assume CS:Driver, DS:Nothing
ORG 0
StartDriver:
include vtable.inc
;******** Required ProcedureTable *************
include reqproc.inc
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
include wavswitc.inc
FileHandle DW 0
MIDOutputMsg DB "MIDI File Generator", 13
DB "Writing to disk", 0
MIDOutputError DB "Unable to create output file!", 0FFh, 29, " ", 0
WriteErrorMsg DB "Error writing to output file. Output file closed", 0FFh, 11, " ", 0
ClosedMsg DB "Closed output file", 0FFh, 42, " ", 0
CreateMsg DB "Creating file "
Filename DB " ", 0
OUTPUT DB "OUTPUT"
DriverName DB "ITMID.DRV", 0
CONFIGURATIONOFFSET EQU $+128
CONFIGSIZE EQU 80
MIDDirectory DB ".", 79 Dup (0)
AccumulatedTime DD 0
AccumulatedTimeError DD 0
FrameTime DD 0
FrameTimeError DD 0
MIDIHeader DB "MThd", 0, 0, 0, 6, 0, 0, 0, 1, 0E7h, 28h
DB "MTrk"
MIDIFileSize DD 0
DB 0, 0FFh, 01, 28
DB "Created with Impulse Tracker"
MTrkEnd DB 0, 0FFh, 2Fh, 0
MIDIBuffer DB 256 Dup (0)
MIDIBufferOffset DW Offset MIDIBuffer
MIDScreenList DW 6
DW IdleFunctionList
DW GlobalKeyLink
DW Near Ptr FullScreenBox ; 0
DW Near Ptr ScreenHeader
DW Near Ptr FillHeader
DW Near Ptr MIDHeader
DW Near Ptr DirectoryInputText
DW Near Ptr DirectoryInputBox
DW Near Ptr DirectoryInput ; 6
DW 0
IdleFunctionList DD 0
DD 0
GlobalKeyLink DB 7
GlobalKeyLink2 DD 0
FillHeader DW 8
FillHeader2 DD 0
FullScreenBox DW 0
DB 0, 0, 79, 49
DB 4
ScreenHeader DW 8
ScreenHeader2 DD 0
MIDHeader DW 10
DB "MIDI File Export Driver", 0
DirectoryInputText DW 1
DB 2, 14
DB 20h
DB "Output Directory", 0
DirectoryInputBox DW 0
DB 18, 13, 78, 15
DB 25
DirectoryInput DW 16
DB 19, 14
Segment1 DW 0
DW Offset MIDDirectory
DW 59
DD 0
DW 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh
TRACEENABLED EQU 0
CREATENEWLOGFILE EQU 1
include debug.inc
; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Returns carry set if error, else carry clear. Has to setup internal vars
; (eg. appropriate IRQ/DMA whatever).
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc DetectCard Far
Mov EAX, 'Jeff'
ClC
Ret
EndP DetectCard
;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Sets up any memory required for output
; Initiates output
;
; Parameters: AX = Number of Channels
;
; If sucessful, returns:
; Carry flag clear
; DS:SI = pointer to text to display
; AX = parameter 1 in text
; BX = parameter 2 in text
; CX = parameter 3 in text
; DX = parameter 4 in text
; DI = parameter 5 in text
;
; If unsucessful, returns:
; Carry flag set
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc InitSound Far
Push CS
Pop DS
Mov Segment1, DS
Mov ECX, IdleUpdateInfoLine
Mov EDX, GlobalKeyList
Mov IdleFunctionList, ECX
Mov GlobalKeyLink2, EDX
Mov ECX, FillHeaderFunction
Mov EDX, DrawHeaderFunction
Mov FillHeader2, ECX
Mov ScreenHeader2, EDX
Call GotoHomeDirectory
Mov SI, Offset MIDDirectory
Call SetDirectory
Mov SI, Offset MIDOutputMsg
ClC
Ret
EndP InitSound
;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Reinitialises sound output
; Initiates sound output
;
; Parameters: AX = number of channels.
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc ReInitSound Far
Ret
EndP ReInitSound
;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Stops sound output, releases any memory used by driver
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc CheckFileClosed
Push CS
Pop DS
Assume DS:Driver
Mov BX, FileHandle
Test BX, BX
JZ CheckFileClosedEnd
Mov AH, 40h
Mov CX, 4
Mov DX, Offset MTrkEnd
Int 21h
Mov FileHandle, 0
Mov AX, 4200h ; Move to start of file
Xor CX, CX
Xor DX, DX
Int 21h ; Start of file
Mov AX, Word Ptr [MIDIFileSize]
Mov DX, Word Ptr [MIDIFileSize+2]
XChg AL, DH
XChg AH, DL
Mov Word Ptr [MIDIFileSize], AX
Mov Word Ptr [MIDIFileSize+2], DX
Mov AH, 40h
Mov CX, 22+32
Mov DX, Offset MIDIHeader
Int 21h
Mov AH, 3Eh
Int 21h
Mov SI, Offset ClosedMsg
Mov BX, 40
Call SetInfoLine
CheckFileClosedEnd:
Ret
EndP CheckFileClosed
Assume DS:Nothing
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc UnInitSound Far
Call GotoHomeDirectory
Push CS
Pop DS
Assume DS:Driver
Mov AX, 3D02h ; Read write access
Mov DX, Offset DriverName
Int 21h
JC SaveConfig2
Mov BX, AX
Mov AX, 4200h
Xor CX, CX
Mov DX, Offset CONFIGURATIONOFFSET
Int 21h
JC SaveConfig1
Mov AH, 40h
Mov CX, CONFIGSIZE
Mov DX, Offset MIDDirectory
Int 21h
SaveConfig1:
Mov AH, 3Eh
Int 21h
SaveConfig2:
Call CheckFileClosed
Ret
EndP UnInitSound
Assume DS:Nothing
;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; This procedure is called as often as possible by IT.EXE
; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song)
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc WriteMIDIBlock
Assume DS:Driver
Xor ECX, ECX
Mov CX, MIDIBufferOffset
Mov DX, Offset MIDIBuffer
Mov AH, 40h
Mov BX, FileHandle
Sub CX, DX
JZ NoDataToWrite
Add MIDIFileSize, ECX
Trace "Writing MIDI block"
Int 21h
NoDataToWrite:
Mov MIDIBufferOffset, Offset MIDIBuffer
Ret
EndP WriteMIDIBlock
Assume DS:Nothing
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc Poll Far
Assume DS:Nothing
Mov CS:Countdown, 0
Mov CS:MIDIBufferOffset, Offset MIDIBuffer
Call Update ; Got DS:SI, CX
; Scan through channels and if any channels are samples, turn them off.
TurnOffSamples1:
Test Byte Ptr [SI], 1 ; Channel on?
JZ TurnOffSamples2
Mov Word Ptr [SI], 0
Test Byte Ptr [SI+3Ah], 80h
JNZ TurnOffSamples2
Mov BX, [SI+38h]
And Byte Ptr [BX], Not 4 ; Signify channel off
TurnOffSamples2:
Add SI, 128
Loop TurnOffSamples1
; OK.. check whether any MIDI data requires dumping... also whether file
; needs to be created.
Test AX, AX ; Currently not playing
JNZ Poll1
Call CheckFileClosed
Ret
Poll1:
Push CS
Pop DS
Assume DS:Driver
Cmp FileHandle, 0
JNE Poll2
Trace "New file to create"
Mov SI, Offset MIDDirectory
Call SetDirectory
Xor EAX, EAX
Mov AccumulatedTime, EAX
Mov AccumulatedTimeError, EAX
Mov AL, 4+32
Mov MIDIFileSize, EAX
; Have to create a file
Call GetFileName
Assume DS:Nothing ; Returns DS:SI
Push CS
Pop ES
Mov DI, Offset FileName
Push DI
Mov CX, 12
Mov AL, ' '
Rep StosB
Pop DI
Cmp Byte Ptr [DS:SI], 0
JE PollFileNameNone
Cmp Byte Ptr [DS:SI], '.'
JE PollFileNameNone
Mov CX, 8
PollFileName1:
LodsB
Cmp AL, 0
JE PollFileNameExt
Cmp AL, '.'
JE PollFileNameExt
StosB
Loop PollFileName1
Jmp PollFileNameExt
PollFileNameNone:
Push CS
Pop DS
Mov SI, Offset Output
Mov CX, 6
Rep MovsB
PollFileNameExt:
Mov EAX, 'DIM.'
StosD
Xor AL, AL
StosB
Push CS
Pop DS
Assume DS:Driver
Mov SI, Offset CreateMsg
Mov BX, 40
Call SetInfoLine
Mov AH, 3Ch
Xor CX, CX
Mov DX, Offset Filename
Int 21h
JC WriteError
Mov BX, AX
Mov FileHandle, BX
Trace "File opened"
; Write header once
Mov AH, 40h
Mov CX, 22+32
Mov DX, Offset MIDIHeader
Int 21h
JC WriteError
Trace "Header written"
Poll2:
Call WriteMIDIBlock
JC WriteError
; Update time counters
Mov EAX, FrameTimeError
Mov EBX, FrameTime
Add AccumulatedTimeError, EAX
AdC AccumulatedTime, EBX
Ret
WriteError:
Call CheckFileClosed
Mov SI, Offset WriteErrorMsg
Mov BX, 40
Call SetInfoLine
Call StopPlayback
Ret
EndP Poll
Assume DS:Nothing
;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: BX = tempo
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc SetTempo Far ; Frames per second = 0.4*BX
; -> Milliseconds per frame = 1000/(0.4/BX)
; = 2500/BX
PushAD
Mov EAX, 2500
And EBX, 0FFFFh
Xor EDX, EDX
Div EBX ; EAX = milliseconds
Mov CS:FrameTime, EAX
Mov CS:FrameTimeError, EDX
PopAD
Ret
EndP SetTempo
;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AX = MixVolume
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc SetMixVolume Far
Ret
EndP SetMixVolume
;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AL = Stereo on/off, 0 = off.
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc SetStereo Far
Ret
EndP SetStereo
;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AX = sample to load (0 based)
; DS:SI points to sample header
; ES:0 points to first sample
;
; Returns: **Carry set if NO error**
; **Carry clear if error**
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc LoadSample Far
StC
Ret
EndP LoadSample
;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AX = sample to release (1 based)
; DS:SI points to sample header
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc ReleaseSample Far
Ret
EndP ReleaseSample
;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Frees all on-board memory
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc ResetMemory Far
Ret
EndP ResetMemory
;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Returns text to show on status line, AX = display parameter
; Carry set if not to show anything.
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc GetStatus Far
StC
Ret
EndP GetStatus
;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Function to have driver interactive part of program
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc SoundCardScreen Far
Mov AX, 5
Mov SI, 1
Mov CX, CS
Mov DX, Offset MIDScreenList
ClC
Ret
Ret
EndP SoundCardScreen
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc GetVariable Far
Ret
EndP GetVariable
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc SetVariable Far
Ret
EndP SetVariable
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
StatusByte DB 0
CountDown DB 0
StatusByteLUT DB 2, 2, 2, 2, 1, 1, 2
InSysex DW 0
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc BufferMIDIOutput
PushAD
Push DS
Push CS
Pop DS
Assume DS:Driver
Mov BX, InSysex
Mov SI, MIDIBufferOffset
Test BX, BX
JZ BufferMIDINoSysex
Cmp AL, 0F7h
JNE BufferMIDIOutput1
Mov DX, SI
Sub DX, BX ; DX = count of sysex bytes
Mov [BX], DL
Mov InSysex, 0
Jmp BufferMIDIOutput1
BufferMIDINoSysex:
Cmp Countdown, 0
JNE BufferMIDIOutput1
Cmp AL, 0F0h
JA BufferMIDIOutput2
; Delta time required
Xor EDX, EDX
Mov EBX, AccumulatedTime
Mov CX, 4
Mov AccumulatedTime, EDX
DeltaTimeOutput1:
ShL EDX, 8
Mov DL, BL
Or DL, 80h
ShR EBX, 7
LoopNZ DeltaTimeOutput1
; EDX = output bytes, DL = most signif
DeltaTimeOutput2:
Mov [SI], DL
Inc SI
ShR EDX, 8
JNZ DeltaTimeOutput2
And Byte Ptr [SI-1], 7Fh
Xor BX, BX
Xor DL, DL
Test AL, AL
JNS BufferMIDINoStatus
Cmp AL, 0F0h
JE BufferMIDISysex
Mov StatusByte, AL
Inc DX
Jmp BufferMIDINoStatus
BufferMIDISysex:
Mov [SI], AL
Inc SI
Mov InSysex, SI
Jmp BufferMIDIOutput1
BufferMIDINoStatus:
Mov BL, StatusByte
ShR BX, 4
Sub BL, 8
JC BufferMIDIOutput1
Add DL, [StatusByteLUT+BX]
Mov Countdown, DL
BufferMIDIOutput1:
Mov [SI], AL
Inc SI
Dec Countdown
Mov MIDIBufferOffset, SI
Cmp SI, Offset MIDIBuffer+200
JB BufferMIDIOutput2
Cmp InSysex, 0
JNE BufferMIDIOutput2
Call WriteMIDIBlock
BufferMIDIOutput2:
Pop DS
PopAD
Ret
EndP BufferMIDIOutput
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
InterpretState DB 0
InterpretType DB 0
Proc SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h.
Mov AH, CS:InterpretState
Cmp AH, 2
JB SendUARTOut1
; In interpreter.
JE SendUARTOut3
SendUARTOut4:
Mov CS:InterpretState, 0
Ret
SendUARTOut3:
Cmp AL, 2
JAE SendUARTOut4
Mov CS:InterpretType, AL
Jmp SendUARTOutStateInc
SendUARTOut1:
Cmp AL, 0F0h
JNE SendUARTOut2
SendUARTOutStateInc:
Inc CS:InterpretState
Ret
SendUARTOut2:
Test AH, AH
JZ SendUARTOutEnd
Push AX
Mov AL, 0F0h
Call BufferMIDIOutput
Pop AX
Mov CS:InterpretState, 0
SendUARTOutEnd:
Call BufferMIDIOutput
Ret
EndP SendUARTOut
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
EndDriver:
;******** Provided Variable Table *************
MaxNumberOfChannels DW 32 ; Maximum number of channels the
; driver can handle.
StopAfterPlay DW 1
DefaultChannels DW 32
DriverFlags DW 1 ; Supports MIDI Out.
DW 4 Dup (0)
;******** Provided Procedure Table *************
ProvidedTableStart:
DW Offset DetectCard
DW Offset InitSound ; Playing related
DW Offset ReinitSound
DW Offset UninitSound
DW Offset Poll
DW Offset SetTempo ; Sound variable related
DW Offset SetMixVolume
DW Offset SetStereo
DW Offset LoadSample ; Sample related
DW Offset ReleaseSample
DW Offset ResetMemory
DW Offset GetStatus ; Returns string to show on status line
DW Offset SoundCardScreen ; Sound card 'screen'
DW Offset GetVariable ; For interface
DW Offset SetVariable
DW Offset SendUARTOut
ProvidedTableEnd:
DW 32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0)
EndS
End