home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Set of Apple II Hard Drive Images
/
eric.hdv
/
SOURCE
/
AUXMIDI.SR.txt
< prev
next >
Wrap
Text File
|
2020-08-13
|
28KB
|
990 lines
; ********************************************
; * AUXMIDI.SRC - BACKGROUND MIDI MUSIC QUEUE
; * (C) 1994, ERIC RANGELL
; ********************************************
;
ORG $2000
;
; *** CONSTANTS ***
;
JMPINST EQU $4C ; JMP INSTRUCTION
RTSINST EQU $60 ; RTS INSTRUCTION
OFFSET EQU $06 ; BYTES FROM BEGINNING OF PGM ON STACK
MAXSUBS EQU $40 ; MAX ENTRIES IN SUBROUTINE TABLE (64*2=128)
;
;
; *** ZERO PAGE ***
;
MYADRS EQU $06 ;POINTER TO MY CODE
MEMPTR EQU $08 ;POINTER TO MEMORY ADDRESS FOR RELOCATION
;
USRVECT EQU $0A ;APPLESOFT USR VECTOR
BASL EQU $0B ;WILL HOLD POINTER TO
BASH EQU $0C ;BEGINNING OF RELOCATED PROGRAM
;
OLDSTRT EQU $3C ;START ADRS FOR MOVE
OLDEND EQU $3E ;END ADRS FOR MOVE
NEWSTRT EQU $42 ;DESTINATION FOR MOVE
;
LINNUM EQU $50 ;CONVERTED USR ARGUMENT
;
;*** PARM AREA FOR CALLING SUBROUTINES ***
ADRS1L EQU $FA
ADRS1H EQU $FB
ADRS2L EQU $FC
ADRS2H EQU $FD
FUNCTION EQU $FE
RETCODE EQU $FE
FLAG EQU $FF
;
; *** ADDRESSES ***
;
STACK EQU $100
MLIALLOC EQU $BEF5 ;MEMORY ALLOCATION
PRINTHEX EQU $FDDA ;PRINT ACCUM IN HEX
MOVE EQU $FE2C ;MONITOR MOVE ROUTINE
MLI EQU $BF00 ;MLI INTERFACE
GETADR EQU $E752 ;FIX FAC TO LINNUM ($50,$51)
GIVAYF EQU $E2F2 ;FLOAT A,Y TO FAC
AUXMOVE EQU $C311 ;AUX MEMORY MOVE ROUTINE
;
;
; *** BEGINNING OF CODE ***
;
; FIND OUT WHERE THIS CODE IS LOCATED IN MEMORY
;
START LDA #RTSINST ;STORE AN RTS IN
STA MYADRS ;ZERO PG LOCATION
JSR MYADRS
TSX ;CHECK STACK
DEX
LDA STACK,X ;GET LOW BYTE OF ADRS
SEC
SBC #OFFSET ;ADJUST IT
STA MYADRS ;SET UP POINTER LO
LDA STACK+1,X
STA MYADRS+1 ;AND HI
;
; CALL PRODOS ROUTINE TO ALLOCATE MEMORY FOR RELOCATED PORTION
;
LDA #<EOF ;CALC # PAGES TO MOVE: EOF-ROUTER+1
SEC
SBC #<ROUTER
CLC
ADC #1
STA PAGES
LDA PAGES
JSR MLIALLOC ;ALLOCATE MEMORY
BCS ALLOCERR
STA MEMPTR+1 ;SAVE HI BYTE OF ADDRESS
LDA #00
STA MEMPTR ;LO BYTE = 0
;
;
; USE RETURNED ADDRESS TO ADJUST HARDCODED ADDRESSES FOR INTERRUPT ROUTINES
;
LDA MEMPTR+1 ;A=HI BYTE OF RELOCATED PROGRAM
STA ALLPTRH ;-->HI BYTE OF ADRS IN MLI ALLOC CALL
STA DEALPTRH ;-->HI BYTE OF ADRS IN MLI DEALLOC CALL
LDA #>INTHAND ;A=LO ADDRESS OF INT HANDLER
STA ALLADRSL ;-->PARM LO BYTE OF ADRS OF INT HANDLER
LDA MEMPTR+1 ;A=HI ADRS WHERE INT HANDLER WILL BE RELOCATED
STA ALLADRSH ;-->PARM HI BYTE OF ADRS OF INT HANDLER
;
; MOVE THE ADJUSTED CODE INTO THE ALLOCATED MEMORY AREA
;
LDA MYADRS ;PREPARE FOR MEMORY MOVE
STA OLDSTRT
LDX MYADRS+1
INX
STX OLDSTRT+1 ;FROM MYADRS
LDA MYADRS
CLC
ADC #$FF
STA OLDEND
LDA PAGES ;TO MYADRS + PAGES*256 + $FF
ADC MYADRS+1
STA OLDEND+1
LDA MEMPTR ;MOVE TO ADRS RETURNED BY MEMORY ALLOCATOR
STA NEWSTRT
LDA MEMPTR+1
STA NEWSTRT+1
LDY #$00
JSR MOVE ;MOVE COMPLETED
;
; SET UP USER VECTOR AND PREPARE INTERRUPT ROUTINES, THEN EXIT
;
LDA MEMPTR+1 ;GET OUR NEW ADDRESS
STA MYADRS+1
LDA MEMPTR
STA MYADRS
LDA #JMPINST ;SET UP USR VECTOR
STA USRVECT ;TO POINT TO NEW ADDRESS
LDA MYADRS
STA BASL ;BASL AND BASH ARE OUR NEW HOOKS TO THE ROUTINES
LDA MYADRS+1
STA BASH
;
LDA #STOPSONG ;DEACTIVATE MIDI INTERRUPTS
STA FUNCTION
JSR USRVECT ;(CALL SUBROUTINE ROUTER)
;
LDA #ALLOCINT ;ALLOCATE INTERRUPTS
STA FUNCTION
JSR USRVECT
RTS
;
PAGES DFB $05 ;LENGTH OF ALLOCATION (RECALCULATED BY PGM)
;
ALLOCERR JSR PRINTHEX ;PRINT ERROR CODE
BRK ;AND STOP
;
;
;
;****************************************
;* SUBROUTINE ROUTER & PSEUDO ZERO PAGE
;****************************************
;
ORG START+$100
;
; THIS IS THE CODE THAT WILL BE RELOCATED TO HIGH MEMORY
;
ROUTER CLV
BVC ROUTER1
;
; MAKE SPACE FOR VARIABLES THAT CAN BE CONTROLLED BY CALLER
;
;
MIDISLOT DFB $20 ;SLOT # TIMES 16
TIMERLO DFB $88 ;SEED FOR TIMER - SEE ACTIVATE SUBROUTINE
TIMERHI DFB $08
;
QINSREG DFB $00
QOUTREG DFB $00 ;OUTPUT DATA REGISTER
;
COUNTHI DFB $00
COUNTLO DFB $00
;
QBEGIN DFB $00,$08 ;AUX MEM BEGIN OF QUEUE
QEND DFB $00,$C0 ;AUX MEM END OF QUEUE + 1
QSTAT DFB $00 ;QUEUE STATUS: 0=EMPTY, FF=FULL, 1=IN USE
QHEAD DFB $00,$08 ;HEAD POINTER
QTAIL DFB $00,$08 ;TAIL POINTER
DLYSTAT DFB $00 ;FF=DELAY IN PROGRESS, 00=NO DELAY,
; ;1,2=DELAY BEING READ
;
LASTSTAT DFB $90 ;LAST STATUS BYTE READ
LASTDATA DFB $90 ;LAST DATA BYTE PROCESSED
CODEFLAG DFB $00 ;FLAG TO DETERMINE WHETHER TO EXECUTE USER CODE
CODEHOOK DFB $00,$00 ;IF CODEFLAG IS NON-ZERO, PROGRAM WILL USE THIS
; ;ADDRESS AS A JUMP VECTOR WHENEVER A MIDI BYTE
; ;IS TRANSMITTED
MIDIBYTE DFB $00 ;MIDI OUTPUT REGISTER.
TEMPREQ DFB $00 ;TO REQUEST TEMPO CHANGE, POPULATE TIMERLO AND HI
; ;THEN PUT NON-ZERO VALUE IN TEMPREQ
USERFLAG DFB $FF ;FOR BASIC PROGRAMS, TO DETECT WHEN NOTES PLAYED.
;
FORMAT DFB $00 ;$00 TO PLAY ALBUM FILES, $01 TO PLAY MFF0 FILES
;
;
; *** PARM AREAS ***
;
ALLOCPRM DFB $02 ;PARM AREA FOR ALLOC INTERRUPT
ALINTNUM DFB $00 ;INTERRUPT NUMBER
ALLADRSL DFB >INTHAND ;LOW BYTE OF INTERRUPT HANDLER ADRS
ALLADRSH DFB <INTHAND ;HI BYTE OF INTERRUPT HANDLER ADRS
;
DEALPRM DFB $01 ;PARM AREA FOR DEALLOC INTERRUPT
DEINTNUM DFB $00
;
; ;offset = $22
ROUTER1 LDA FUNCTION
ASL A ;MULTIPLY SUB # BY 2
ADC #>SUBTABLE ;ADD OFFSET OF SUBROUTINE TABLE
PHA ;SAVE ON STACK
TAY
LDA (BASL),Y ;GET LO BYTE OFFSET OF SUB FROM TABLE
LDY #>SUBJMPL
STA (BASL),Y ;STORE AT SUB JUMP VECTOR LOW
PLA ;GET OFFSET
TAY
INY ;ADD 1
LDA (BASL),Y ;GET HI BYTE OFFSET OF SUB FROM TABLE
SEC
SBC #<ROUTER ;SUBTRACT ROUTER HI ADDRESS TO GET PURE OFFSET
CLC
ADC BASH ;ADD BASE ADDRESS TO GET RELOC ADRS OF SUBROUTINE
LDY #>SUBJMPH ;STORE AT SUB VECTOR HIGH
STA (BASL),Y
DFB $4C ;JMP TO SPECIFIED ADRS
SUBJMPL DFB $00
SUBJMPH DFB $00
;
; *** SUBROUTINE - ALLOCATE INTERRUPT (#4)
; offset=$41
ALLOCIN1 JSR MLI ;ALLOCATE INTERRUPT
DFB $40
ALLPTRL DFB >ALLOCPRM ;ADRS OF PARM LIST
ALLPTRH DFB <ALLOCPRM ;HI BYTE WILL BE MODIFIED BY PGM
BCS ERRBRK ;IF ERROR - BREAK OUT
LDY #>ALINTNUM ;GET LO BYTE OF ADRS OF INTERRUPT NUMBER
LDA (BASL),Y ;GET THE INTERRUPT NUMBER
LDY #>DEINTNUM ;GET LO BYTE OF ADRS OF DEALLOC INT NUMBER
STA (BASL),Y ;STORE INT NUMBER AT THAT ADDRESS (PSEUDO ZP)
RTS
;
ERRBRK JSR PRINTHEX ;ANY ERROR - BREAK OUT
BRK
;
; *** SUBROUTINE: DEALLOCATE INTERRUPT (#5)
;offset = $55
DEALLIN1 JSR MLI ;MLI DEALLOC
DFB $41 ;CODE FOR DEALLOC
DEALPTRL DFB >DEALPRM ;ADRS OF PARM LIST
DEALPTRH DFB <DEALPRM
BCS ERRBRK ;ERRORS? BREAK OUT
RTS
;offset=$5e
INTHAND CLD ; FOR PRODOS
LDA #INTHANDL ; GET SUBROUTINE # OF INTERRUPT HANDLER
STA FUNCTION
JMP USRVECT
;offset=$66
;
;
; DEFINE SUBROUTINE NUMBERS RECOGNIZED BY USR VECTOR
USRHOOK EQU $00
INTHANDL EQU $01
;
ACTMIDI EQU $02
STOPSONG EQU $03
ALLOCINT EQU $04
DEALLINT EQU $05
;
ENQBYTE EQU $06
DEQBYTE EQU $07
INCHEAD EQU $08
INCTAIL EQU $09
CMPHDTL EQU $0A
STORHEAD EQU $0B
GETTAIL EQU $0C
;
XMITHOOK EQU $0D
SENDMIDI EQU $0E
OUTHOOK EQU $0F
;
MIDIOUT EQU $10
AUXPEEK EQU $11
AUXPOKE EQU $12
;
ENQEVENT EQU $13
ENQDELTA EQU $14
DEQDELTA EQU $15
DEQINSTR EQU $16
NOTEOFF EQU $17
NOTEON EQU $18
AFTERTO EQU $19
CTRLCHG EQU $20
PROGCHG EQU $21
PRESSUR EQU $22
BENDER EQU $23
SYSEXF0 EQU $24
SYSEXF7 EQU $25
META EQU $26
CONVDLTA EQU $27
PLAYEVNT EQU $28
PLAYSONG EQU $29
;
;
SUBTABLE DFB >USRHOOK1,<USRHOOK1
DFB >INTHAND1,<INTHAND1
DFB >ACTMIDI1,<ACTMIDI1
DFB >STOPSON1,<STOPSON1
DFB >ALLOCIN1,<ALLOCIN1
DFB >DEALLIN1,<DEALLIN1
DFB >ENQBYTE1,<ENQBYTE1
DFB >DEQBYTE1,<DEQBYTE1
DFB >INCHEAD1,<INCHEAD1
DFB >INCTAIL1,<INCTAIL1
DFB >CMPHDTL1,<CMPHDTL1
DFB >STORHEA1,<STORHEA1
DFB >GETTAIL1,<GETTAIL1
DFB >XMITHOO1,<XMITHOO1
DFB >SENDMID1,<SENDMID1
DFB >OUTHOOK1,<OUTHOOK1
;
DFB >MIDIOUT1,<MIDIOUT1
DFB >AUXPEEK1,<AUXPEEK1
DFB >AUXPOKE1,<AUXPOKE1
DFB >ENQEVEN1,<ENQEVEN1
DFB >ENQDELT1,<ENQDELT1
DFB >DEQDELT1,<DEQDELT1
DFB >DEQINST1,<DEQINST1
DFB >NOTEOFF1,<NOTEOFF1
DFB >NOTEON1,<NOTEON1
DFB >AFTERTO1,<AFTERTO1
DFB >CTRLCHG1,<CTRLCHG1
DFB >PROGCHG1,<PROGCHG1
DFB >PRESSUR1,<PRESSUR1
DFB >BENDER1,<BENDER1
DFB >SYSEXF01,<SYSEXF01
DFB >SYSEXF71,<SYSEXF71
DFB >META1,<META1
DFB >CONVDLT1,<CONVDLT1
DFB >PLAYEVN1,<PLAYEVN1
DFB >PLAYSON1,<PLAYSON1
;
;
; SUBROUTINE: SENDMIDI - TRANSMITS MIDI BYTE TO MIDI OUT
;
SENDMID1 LDY #>MIDISLOT ;GET MIDI SLOT IN X
LDA (BASL),Y
TAX
LDA FLAG ;GET BYTE TO XMIT IN A
STA $C089,X ;SEND BYTE OUT VIA MIDI
WAITTDRE LDA $C088,X
AND #$02
BEQ WAITTDRE
RTS
;
; *** SUBROUTINE: MIDIOUT - SEND SEVERAL BYTES OUT TO MIDIOUT
;
; ADRS1 = START ADRS, ADRS2=END ADRS OR 0 TO XMIT UNTIL FF REACHED
;
MIDIOUT1 LDA ADRS2H
CMP ADRS1H
BCC MIDIOUT2
LDA ADRS2H
CMP ADRS1H
BCC MIDIOUT2 ;IF HI < LO ADRS, USE MIDIOUT2 ROUTINE
;
MIDILOOP LDY #$00
LDA (ADRS1L),Y ;SEND BYTE AT ADDRESS 1
STA FLAG
LDA #SENDMIDI
STA FUNCTION
JSR USRVECT
;
LDA ADRS1L ;ADD 1 TO ADDRESS 1
ADC #$01
STA ADRS1L
LDA ADRS1H
ADC #$00
STA ADRS1H
;
LDA ADRS1H ;IF ADDRESS1 <= ADDRESS2, LOOP AGAIN
CMP ADRS2H
BCC MIDILOOP
LDA ADRS1L
CMP ADRS2L
BCC MIDILOOP
BEQ MIDILOOP
MIDIDONE RTS
;
MIDIOUT2 LDY #$00 ;IF ADDRESS1 = FF, GET OUT
LDA (ADRS1L),Y
CMP #$FF
BEQ MIDIDONE
STA FLAG ;ELSE SEND THE BYTE
LDA #SENDMIDI
STA FUNCTION
JSR USRVECT
;
LDA ADRS1L ;ADD 1 AND LOOP AGAIN
ADC #$01
STA ADRS1L
LDA ADRS1H
ADC #$00
STA ADRS1H
CLV
BVC MIDIOUT2
;
;
; *** AUXPEEK ***
;
AUXPEEK1 LDA ADRS1L
STA OLDSTRT
STA OLDEND
LDA ADRS1H
STA OLDSTRT+1
STA OLDEND+1
LDA #>FLAG
STA NEWSTRT
LDA #<FLAG
STA NEWSTRT+1
CLC
JSR AUXMOVE
RTS
;
; *** AUXPOKE ***
;
AUXPOKE1 LDA #>FLAG
STA OLDSTRT
STA OLDEND
LDA #<FLAG
STA OLDSTRT+1
STA OLDEND+1
LDA ADRS1L
STA NEWSTRT
LDA ADRS1H
STA NEWSTRT+1
SEC
JSR AUXMOVE
RTS
;
;
; *** SUBROUTINE: STOPSONG: DEACTIVATE INTERRUPTS
;
STOPSON1 SEI ;STOP INTERRUPTS
LDY #>MIDISLOT ;X=SLOT * 16
LDA (BASL),Y
TAX
LDA #$01 ;PLUG THE TIMER
STA $C080,X
LDA #$13 ;RESET THE MIDI PORTS (MASTER RESET)
STA $C088,X ; 8 BITS NO PARITY 2 STOP BITS
LDA #$11 ;
STA $C088,X
CLI ;RESUME BUSINESS
RTS
;
; *** SUBROUTINE: ACTIVATE INTERRUPTS
;
ACTMIDI1 LDY #>MIDISLOT
LDA (BASL),Y ;GET SLOT*16 IN X
TAX
LDA #$01 ;STOP TIMER
STA $C080,X
SEI ;STOP INTERRUPTS
LDA #$43 ;RESET THE 6840 PTM
STA $C081,X ;INITIALIZE TIMER
LDA #$04
STA $C080,X ;REGISTER=4
LDY #>TIMERHI ;WRITE HI BYTE
LDA (BASL),Y
STA $C084,X
LDA #$05 ;REGISTER=5
STA $C080,X
LDY #>TIMERLO ;WRITE LO BYTE
LDA (BASL),Y
STA $C085,X
LDA #$1 ;WRITE CONTROL REG 2
STA $C080,X
LDA #$C3 ;CONTINUOUS, IRQ AND TIMER OUTPUT ENABLED
STA $C080,X ;
; LDA #$31 ;TDRE INT?
; STA $C088,X
CLI ;GET READY
LDA #$0 ;TO ACTIVATE (ZERO IN CTRL REG 1)
STA $C080,X ;NOW!
RTS
;
; SUBROUTINE 0: USER HOOK
;
USRHOOK1 JSR GETADR ;CONVERT USR ARGUMENT TO INTEGER
LDA LINNUM+1 ;CHECK HI BYTE
BEQ GOODBYT
BADBYT LDY BASL ;IF >255, RETURN BASE ADDRESS
LDA BASH
JSR GIVAYF
RTS
GOODBYT LDA LINNUM
BEQ BADBYT ;IF OUT OF RANGE, RETURN BASE ADRS
CMP #MAXSUBS
BCS BADBYT
STA FUNCTION
JMP USRVECT
;
;SUBROUTINE #1: INTERRUPT HANDLER
;
INTHAND1 CLD ;FOR PRODOS
LDY #>MIDISLOT
LDA (BASL),Y
TAX
LDA $C081,X ;CHECK CLOCK INTERRUPT FLAG
BPL NOTCLOCK
LDA #$01 ;STOP CLOCK AND PROCESS THE PULSE
STA $C080,X
CLV
BVC PULSENOW
;
NOTCLOCK LDA $C088,X ;CHECK BIT 2 OF ACIA CONTROL REG
AND #$02 ;TO SEE IF TDRE CONDITION EXISTS
BNE TDRE
LDA #$00 ;NOT OUR INTERRUPT - GET OUT
STA $C080,X
SEC ;DON'T CLAIM IT
RTS
;
GETOUT LDY #>MIDISLOT
LDA (BASL),Y
TAX
LDA #$00 ;START THE CLOCK AGAIN
STA $C080,X
CLC ;CLAIM THE INTERRUPT
RTS
;
PULSENOW LDY #>DLYSTAT ;FIND OUT WHERE TO GO
LDA (BASL),Y
BPL TDRE ;IF DLYSTAT >= $80
LDY #>COUNTLO ;DELAY IS IN PROGRESS
LDA (BASL),Y ;SO COUNT DOWN YOUR DELTA TIME
SEC
SBC #$01
STA (BASL),Y
CMP #$FF
BNE GETOUT
;
LDY #>COUNTHI
LDA (BASL),Y
SEC
SBC #$01
STA (BASL),Y
CMP #$FF
BNE GETOUT
;
LDA #$00 ;DONE COUNTING-DLYSTAT=0
LDY #>DLYSTAT
STA (BASL),Y
LDY #>COUNTHI
STA (BASL),Y
LDY #>COUNTLO
STA (BASL),Y
;
LDY #>USERFLAG
STA (BASL),Y
CLV
BVC GETOUT
;
TDRE LDY #>FORMAT
LDA (BASL),Y
BEQ OLDFORM
; ; NEW FORMAT: TO PLAY MIDI FORMAT 0
LDA #PLAYEVNT
STA FUNCTION
JSR USRVECT
BCS GETOUT
;
LDA #DEQDELTA
STA FUNCTION
JSR USRVECT
BCS GETOUT
;
LDA #CONVDLTA
STA FUNCTION
JSR USRVECT
;
LDA ADRS2L ;SET COUNTER BASED ON NEW DELTA TIME
LDY #>COUNTHI
STA (BASL),Y
LDA ADRSH
LDY #>COUNTLO
STA (BASL),Y
LDA #$FF ;SET MODE TO COUNTING
LDY #>DLYSTAT
STA (BASL),Y
RTS
;
OLDFORM LDY #>DLYSTAT ;DLYSTAT < $80.
LDA (BASL),Y
BNE CHKDLY ;IF DLYSTAT <> 0, SET UP THE DELAY
; ; ELSE IT IS TIME TO XMIT THE DATA
LDA #DEQBYTE ;GET BYTE FROM QUEUE
STA FUNCTION
JSR USRVECT
BCS GETOUT ;IF ERROR, TRY LATER
LDY #>QOUTREG
LDA (BASL),Y ;GET THE BYTE
CMP #$FD ;IS IT >= $FD?
BCS SIGNAL ;YES - CHECK FOR TEMPO OR DURATION CHANGE
LDA #XMITHOOK ;NO - CALL SUB13 TO PROCESS TRANSMISSION
STA FUNCTION
JSR USRVECT ;
CLV
BVC TDRE ;REPEAT UNTIL STATUS CHANGES
BOOST CLV
BVC GETOUT
;
CHKDLY LDY #>DLYSTAT
LDA (BASL),Y
CMP #$02 ;ARE WE READING THE SECOND BYTE?
BEQ TWO
LDA #DEQBYTE ;NO - READ QUEUE
STA FUNCTION
JSR USRVECT
BCC GOTIT ;IF EMPTY QUEUE
LDA #$01 ;DLYSTAT = 1
LDY #>DLYSTAT ;GET OUT
STA (BASL),Y
CLV
BVC BOOST
GOTIT LDA #$02
LDY #>DLYSTAT ;DLYSTAT = 2
STA (BASL),Y
LDY #>QOUTREG ;GET THE BYTE
LDA (BASL),Y
LDY #>COUNTHI ;FOR THE HI COUNTER
STA (BASL),Y
TWO LDA #DEQBYTE ; READ QUEUE
STA FUNCTION
JSR USRVECT
BCS BOOST
LDY #>QOUTREG ;PUT THE DATA
LDA (BASL),Y
LDY #>COUNTLO ;INTO COUNTLO
STA (BASL),Y
LDA #$FF ;SET DLYSTAT = FF
LDY #>DLYSTAT
STA (BASL),Y
CLV
BVC BOOST
;
DURATION CMP #$FF ;TWO BYTE DURATION (FF)
BEQ CHKDLY ; CONTINUE NORMALLY
; ;ONE BYTE DURATION (FD)
LDA #$00 ; ZERO OUT HI COUNTER
LDY #>COUNTHI
STA (BASL),Y
LDA #$02 ;SET DLYSTAT = 2
LDY #>DLYSTAT
STA (BASL),Y
CLV
BVC TWO ;PROCESS THE ONE BYTE
;
SIGNAL CMP #$FE
BNE DURATION
LDY #>DLYSTAT ;TEMPO CHANGE (FE).
LDA (BASL),Y ;DOES DLYSTAT = 2?
CMP #$02
BEQ TEMPO2
LDA #DEQBYTE
STA FUNCTION
JSR USRVECT
BCC GOODQ
LDA #$01 ;IF ERR READING Q, DLYSTAT=1 AND EXIT
LDY #>DLYSTAT
STA (BASL),Y
BOOST1 CLV
BVC BOOST
GOODQ LDA #$02 ;DLYSTAT=2
LDY #>DLYSTAT
STA (BASL),Y
LDY #>QOUTREG ;PUT BYTE IN TIMER HI REGISTER
LDA (BASL),Y
LDY #>TIMERHI
STA (BASL),Y
TEMPO2 LDA #DEQBYTE
STA FUNCTION
JSR USRVECT
BCS BOOST1
LDY #>QOUTREG
LDA (BASL),Y
LDY #>TIMERLO
STA (BASL),Y
LDA #$00
LDY #>DLYSTAT
STA (BASL),Y
LDA #ACTMIDI
STA FUNCTION
JSR USRVECT
CLV
BVC BOOST1
;
CHN INTRUPT.SRC2
; ********************************************
; * INTRUPT.SRC2 - BACKGROUND MIDI MUSIC QUEUE
; * (C) 1992, ERIC RANGELL
; ********************************************
;
;
; SUBROUTINE - XMITHOOK
;
XMITHOO1 LDY #>DLYSTAT ;SET DLYSTAT = 0
LDA #$00
STA (BASL),Y
LDY #>QOUTREG
LDA (BASL),Y
BPL RUNSTAT ;CHECK IF STATUS BYTE
LDY #>LASTSTAT ;IF YES - STORE IT AS LAST STATUS BYTE
STA (BASL),Y
RUNSTAT LDY #>LASTDATA ;STORE CURR BYTE AS LAST DATA BYTE
STA (BASL),Y
LDY #>MIDIBYTE
STA (BASL),Y ;FOR MIDI OUTPUT SUBROUTINE
LDA #OUTHOOK ;PROCESS THE MIDI BYTE
STA FUNCTION
JSR USRVECT
RTS
;
ENQBYTE1 LDY #>QSTAT
LDA (BASL),Y
BPL DOENQ
LDA #$FF
STA RETCODE
SEC
RTS
;
DOENQ SEI
LDA FLAG
LDY #>QINSREG
STA (BASL),Y
;
LDA #INCHEAD
STA FUNCTION
JSR USRVECT
;
LDA #STORHEAD
STA FUNCTION
JSR USRVECT
;
LDA #$01 ;SET QSTAT = 1 (IN USE)
LDY #>QSTAT
STA (BASL),Y
;
LDA #CMPHDTL
STA FUNCTION
JSR USRVECT
;
BCC QNOTFULL
LDA #$FF ;SET QSTAT = FF (FULL)
LDY #>QSTAT
STA (BASL),Y
;
QNOTFULL CLC
CLI
RTS
;
;
DEQBYTE1 LDY #>QSTAT
LDA (BASL),Y
BNE DODEQ
LDA #$01
STA RETCODE
SEC
RTS
DODEQ SEI
LDA #INCTAIL
STA FUNCTION
JSR USRVECT
;
LDA #GETTAIL
STA FUNCTION
JSR USRVECT
;
LDA #$01 ;SET QSTAT=1
LDY #>QSTAT
STA (BASL),Y
;
LDA #CMPHDTL
STA FUNCTION
JSR USRVECT
;
BCC QNOTEMTY
LDA #$00 ;SET QSTAT = 0 (EMPTY)
LDY #>QSTAT
STA (BASL),Y
;
QNOTEMTY CLC
CLI
RTS
;
;
INCHEAD1 LDY #>QHEAD
LDA (BASL),Y
CLC
ADC #$01
STA (BASL),Y
LDY #>QHEAD+1
LDA (BASL),Y
ADC #$00
STA (BASL),Y
LDY #>QEND+1
LDA (BASL),Y
LDY #>QHEAD+1
CMP (BASL),Y
BNE EXITHD
LDY #>QEND
LDA (BASL),Y
LDY #>QHEAD
CMP (BASL),Y
BNE EXITHD
LDY #>QBEGIN
LDA (BASL),Y
LDY #>QHEAD
STA (BASL),Y
LDY #>QBEGIN+1
LDA (BASL),Y
LDY #>QHEAD+1
STA (BASL),Y
EXITHD RTS
;
;
INCTAIL1 LDY #>QTAIL
LDA (BASL),Y
CLC
ADC #$01
STA (BASL),Y
LDY #>QTAIL+1
LDA (BASL),Y
ADC #$00
STA (BASL),Y
LDY #>QEND+1
LDA (BASL),Y
LDY #>QTAIL+1
CMP (BASL),Y
BNE EXITTL
LDY #>QEND
LDA (BASL),Y
LDY #>QTAIL
CMP (BASL),Y
BNE EXITTL
LDY #>QBEGIN
LDA (BASL),Y
LDY #>QTAIL
STA (BASL),Y
LDY #>QBEGIN+1
LDA (BASL),Y
LDY #>QTAIL+1
STA (BASL),Y
EXITTL RTS
;
;
CMPHDTL1 LDY #>QHEAD+1
LDA (BASL),Y
LDY #>QTAIL+1
CMP (BASL),Y
BNE GOODCMP
LDY #>QHEAD
LDA (BASL),Y
LDY #>QTAIL
CMP (BASL),Y
BNE GOODCMP
SEC
RTS
GOODCMP CLC
RTS
;
;
STORHEAD LDY #>QINSREG
LDA (BASL),Y
STA FLAG
LDY #>QHEAD
LDA (BASL),Y
STA ADRS1L
LDY #>QHEAD+1
LDA (BASL),Y
STA ADRS1H
LDA #AUXPOKE
STA FUNCTION
JSR USRVECT
RTS
;
;
GETTAIL1 LDY #>QTAIL
LDA (BASL),Y
STA ADRS1L
LDY #>QTAIL+1
LDA (BASL),Y
STA ADRS1H
LDA #AUXPEEK
STA FUNCTION
JSR USRVECT
LDA FLAG
LDY #>QOUTREG
STA (BASL),Y
RTS
;
CHN INTRUPT.SRC3
; ********************************************
; * INTRUPT.SRC3- MIDI FILTERING ROUTINE
; ********************************************
;
;
; SUBROUTINE: OUTHOOK - LOOK AT MIDI STREAM AND PROCESS ACCORDINGLY
; CALL THE SENDMIDI SUBROUTINE IF WANT TO XMIT THE BYTE
;
OUTHOOK1 LDY #>CODEFLAG ;CHECK IF USER SET UP OWN CODE
LDA (BASL),Y
BEQ SENDIT ;IF NO CHECK FOR TEMPO REQUEST
LDA #JMPINST ;STORE A JMP IN ZERO PAGE VECTOR
STA MYADRS
LDY #>CODEHOOK ;STORE LO BYTE OF USER'S ADRS
LDA (BASL),Y
STA MYADRS+1
LDY #>CODEHOOK+1 ;STORE HI BYTE
LDA (BASL),Y
STA MYADRS+2
JSR MYADRS ;PERFORM USER'S CODE
BCS CHKTEMP ;IF USER DOESN'T WANT BYTE SENT, GET OUT
;
SENDIT LDA #SENDMIDI ;ELSE SEND THE BYTE
STA FUNCTION
LDY #>MIDIBYTE
LDA (BASL),Y
STA FLAG
JSR USRVECT
;
;
;;;;;NEW SUB: TEMPOCHG
;
CHKTEMP LDY #>TEMPREQ
LDA (BASL),Y
BEQ ESCAPE ; PROCESS REQUESTS TO CHANGE TEMPO
LDA #$0
STA (BASL),Y ;RESET TEMPREQ FLAG TO 0 SO ONLY CALLED ONCE
;
LDY #>MIDISLOT
LDA (BASL),Y
TAX
LDA #$04
STA $C080,X ;REGISTER=4
LDY #>TIMERHI ;WRITE HI BYTE
LDA (BASL),Y
STA $C084,X
LDA #$05 ;REGISTER=5
STA $C080,X
LDY #>TIMERLO ;WRITE LO BYTE
LDA (BASL),Y
STA $C085,X
ESCAPE RTS
;
;
ENQEVEN1 NOP
;
ENQDELT1 NOP
;
DEQDELT1 NOP
;
;
DEQINST1 NOP
;
NOTEOFF1 NOP
;
NOTEON1 NOP
;
AFTERTO1 NOP
;
CTRLCHG1 NOP
;
PROGCHG1 NOP
;
PRESSUR1 NOP
;
BENDER1 NOP
;
SYSEXF01 NOP
;
SYSEXF71 NOP
;
META1 NOP
;
CONVDLT1 NOP
;
PLAYEVN1 NOP
;
PLAYSON1 NOP
;
;
;
EOF BRK