; ; 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