0100 ;
0110 ;
0120 ;  The Mage's Magic Handler
0130 ; Written by Nathan Hartwell
0140 ;        Version 2.20
0150 ;
0160 ;
0170 ;
0180 ;
0190 ;Designed for the PSI Upgrade
0200 ;
0210 ;
0220 ;
0230 ;
0240     .OPT NO LIST
0250     .OPT OBJ
0260 ;================================
0270 ;      EQUATES AND VARIABLES
0280 ;================================
0290 ;
0300 ; GENERAL VALUE EQUATES
0310 ;
0320 ASYNC = $73     ;POKEY MODE 7
0330 PURE =  $A0     ;PURE TONE VAL
0340 AUDVAL = $78    ;AUDCTL INIT VAL
0350 ;
0360 ; GENERAL ADDRESS EQUATES
0370 ;
0380 DOSVEC = $0A    ;DOS RUN VECTOR
0390 DOSINI = $0C    ;DOS INIT VECTOR
0400 RTCLOK = $12    ;JIFFIE COUNTER
0410 IRQVEC = $0216
0420 MEMLO = $02E7   ;SYSTEM MEMLO
0430 DVSTAT = $02EA  ;DEVICE STATUS
0440 HATAB = $031A   ;HANDLER TABLE
0450 AUDF1 = $D210   ;AUDIO FREQ 1
0460 AUDF2 = $D212   ;AUDIO FREQ 2
0470 AUDF3 = $D214   ;AUDIO FREQ 3
0480 AUDF4 = $D216   ;AUDIO FREQ 4
0490 AUDCTL = $D218  ;AUDIO CONTROL
0500 SERIN = $D21D   ;SERIAL INPUT REG
0510 SEROUT = $D21D  ;SERIAL OUTPUT REG
0520 IRQEN = $D21E   ;INTERUPT ENABLE
0530 IRQST = $D21E   ;INTERUPT STATUS
0540 SKCTL = $D21F   ;POKEY MODE REG
0550 SKSTAT = $D21F  ;POKEY STAT REG
0560 PCCTL = $D312   ;DTR LEAD
0570 PDCTL = $D313   ;I/O CONTROL
0580 PORTF = $D320
0590 ;
0600 ; IOCB RELATED EQUATES
0610 ;
0620 ICDNOZ = $21    ;DEVICE NUMBER
0630 ICCOMZ = $22    ;COMMAND BYTE
0640 ICAX1Z = $2A    ;AUX 1 BYTE
0650 ICAX2Z = $2B    ;AUX 2 BYTE
0660 ;
0670 ; VARIABLES
0680 ;
0690     *=  $4000   ;VAR TABLE ORG
0700     RTS         ;EXIT BACK TO DOS
0710 OIRQV .WORD 0   ;OLD IRQ VEC
0720 JIFFIE .BYTE 0  ;JIFFIE COUNT
0730 TMPCHR .BYTE 0  ;TEMP CHR STORAGE
0740 TDNFLG .BYTE 0  ;TRANS DONE FLAG
0750 BAUDRT .WORD 40 ;BAUD IN DEF 19.2K
0760 MODE .BYTE 0    ;OPEN MODE
0770 RDYOUT .BYTE 1  ;READY OUT FLAG
0780 CONFLG .BYTE 0  ;CONC MODE I/O FLAG
0790 SAVFLG .BYTE 0  ;VEC SAVED FLAG
0800 HNDMSK .BYTE 128 ;TYPE HANDSHAKING
0810 IOFLAG .BYTE 0  ;I/O ON/OFF FLAG
0820 HISTRY .BYTE 0  ;STATUS HISTRY
0830 POKMSK .BYTE 0
0840 ;================================
0850 ;      QUEUE HANDLER ROUTINE
0860 ;================================
0870 ;
0880 ; INITIALIZE QUE
0890 ;
0900 QINIT
0910     LDA #0      ;INITIAL VALUE
0920     STA QHEAD   ;INIT QUEUE HEAD
0930     STA QTAIL   ;INIT QUEUE TAIL
0940     STA QLEN    ;INIT QUEUE LEN
0950     RTS 
0960 ;
0970 ; PUT BYTE IN QUEUE
0980 ;
0990 QPUT
1000     LDX QLEN    ;CHECK QUEUE LEN
1010     INX         ;IF LEN=FF THEN
1020     BNE QP0     ;  QUE FULL RET
1030     RTS         ;ELSE
1040 QP0 LDX QHEAD   ;  GET HEAD PSN
1050     STA QORG,X  ;  PUT BYTE
1060     INC QHEAD   ;  INC HEAD PSN
1070     INC QLEN    ;  INC QUEUE LEN
1080     RTS 
1090 ;
1100 ; GET BYTE FROM QUEUE
1110 ;
1120 QGET
1130     LDX QLEN    ;IF QUEUE EMPTY
1140     BNE QG0     ;  RETURN
1150     RTS         ;ELSE
1160 QG0 LDX QTAIL   ;  GET TAIL PSN
1170     LDA QORG,X  ;  GET BYTE
1180     INC QTAIL   ;  INC TAIL PSN
1190     DEC QLEN    ;  DEC QUEUE LEN
1200     RTS 
1210 ;
1220 ; GET QUEUE STATUS
1230 ;
1240 QSTAT
1250     LDA QLEN    ;GET QUEUE STAT
1260     RTS 
1270 ;
1280 ; QUEUE VARIABLES & STORAGE
1290 ;
1300 QHEAD .BYTE 0   ;QUEUE HEAD PSN
1310 QTAIL .BYTE 0   ;QUEUE TAIL PSN
1320 QLEN .BYTE 0    ;QUEUE LENGTH
1330 ;================================
1340 ;      QUEUE HANDLER ROUTINE
1350 ;================================
1360 ;
1370 ; INITIALIZE QUE
1380 ;
1390 OQINIT
1400     LDA #0      ;INITIAL VALUE
1410     STA OQHEAD  ;INIT QUEUE HEAD
1420     STA OQTAIL  ;INIT QUEUE TAIL
1430     STA OQLEN   ;INIT QUEUE LEN
1440     RTS 
1450 ;
1460 ; PUT BYTE IN QUEUE
1470 ;
1480 OQPUT
1490     LDX OQLEN   ;CHECK QUEUE LEN
1500     INX         ;IF LEN=FF THEN
1510     BNE OQP0    ;  QUE FULL RET
1520     RTS         ;ELSE
1530 OQP0 LDX OQHEAD ;  GET HEAD PSN
1540     STA OQORG,X ;  PUT BYTE
1550     INC OQHEAD  ;  INC HEAD PSN
1560     INC OQLEN   ;  INC QUEUE LEN
1570     RTS 
1580 ;
1590 ; GET BYTE FROM QUEUE
1600 ;
1610 OQGET
1620     LDX OQLEN   ;IF QUEUE EMPTY
1630     BNE OQG0    ;  RETURN
1640     RTS         ;ELSE
1650 OQG0 LDX OQTAIL ;  GET TAIL PSN
1660     LDA OQORG,X ;  GET BYTE
1670     INC OQTAIL  ;  INC TAIL PSN
1680     DEC OQLEN   ;  DEC QUEUE LEN
1690     RTS 
1700 ;
1710 ; GET QUEUE STATUS
1720 ;
1730 OQSTAT
1740     LDA OQLEN   ;GET QUEUE STAT
1750     RTS 
1760 ;
1770 ; QUEUE VARIABLES & STORAGE
1780 ;
1790 OQHEAD .BYTE 0  ;QUEUE HEAD PSN
1800 OQTAIL .BYTE 0  ;QUEUE TAIL PSN
1810 OQLEN .BYTE 0   ;QUEUE LENGTH
1820 ;
1830 ; SAVE OLD DOSINI VECTOR
1840 ;
1850 START LDA #$60
1860     STA START
1870     LDA DOSINI  ;OLD DOSINI LO
1880     STA HINIT+1 ;INDIR JUMP LO
1890     LDA DOSINI+1 ;OLD DOSINI HI
1900     STA HINIT+2 ;INDIR JUMP HI
1910     LDA #HINIT&$FF ;NEW DOSINI LO
1920     STA DOSINI  ;STORE DOSINI LO
1930     LDA #HINIT/256 ;NEW DOSINI HI
1940     STA DOSINI+1 ;STORE DOSINI HI
1950     JMP SKIPIN
1960 ;
1970 ; SET UP NEW DOSINI & MEMLO  
1980 ;
1990 HINIT JSR $FFFF ;IND OLD DOSINI
2000 SKIPIN LDA # <MLOW ;GET NEW MEMLO LO
2010     STA MEMLO   ;SET NEW MEMLO LO
2020     LDA # >MLOW ;GET NEW MEMLO HI
2030     STA MEMLO+1 ;SET NEW MEMLO HI
2040     LDA #0      ;FILE CLOSED VAL
2050     STA MODE    ;SET MODE CLOSED
2060     STA CONFLG  ;TURN OFF CONC I/O
2070     STA POKMSK
2080 ;
2090 ; INSTALL HANDLER
2100 ;
2110 FINDR LDX #0    ;START 1ST HAND 
2120     LDY #16     ;# POS HANDLERS
2130 CHKR LDA HATAB,X ;GET HAND NAME
2140     BEQ FOUND   ;IF NAME=0 OR
2150     CMP #'*     ;IF NAME=* THEN
2160     BEQ FOUNDIT ;  INSTALL NEW ONE
2170     INX         ;ELSE INC 
2180     INX         ;  INDEX
2190     INX         ;  BY 3
2200     DEY         ;IF NOT FOUND 
2210     BNE CHKR    ;  TRY AGAIN
2220     RTS 
2230 FOUND LDA #'*   ;INSTALL *: HAND
2240     STA HATAB,X ;
2250     LDA #RTAB&$FF ;INSTALL ADR LO
2260     STA HATAB+1,X ;
2270     LDA #RTAB/256 ;INSTALL ADR HI
2280     STA HATAB+2,X ;
2290     JSR SAVVEC
2300     RTS 
2310 FOUNDIT RTS 
2320 ;================================
2330 ;      DRIVER ADDRESS TABLE
2340 ;================================
2350 ;
2360 ; DRIVER ADDRESS TABLE
2370 ;
2380 RTAB .WORD OPEN-1 ;OPEN ROUTINE
2390     .WORD CLOSE-1 ;CLOSE ROUTINE
2400     .WORD GET-1 ;GET ROUTINE
2410     .WORD PUT-1 ;PUT ROUTINE
2420     .WORD STAT-1 ;STATUS ROUTINE
2430     .WORD XIO-1 ;XIO ROUTINE
2440     JMP INIT
2450 ;
2460 ; OPEN ROUTINE
2470 ;
2480 OPEN LDA MODE   ;CHECK MODE
2490     BEQ NOTOPN  ;IF MODE<>0 THEN
2500     LDY #129    ;  ALREADY OPEN ERR
2510     RTS         ;  RETURN
2520 NOTOPN LDA ICAX1Z ;GET TYPE OPEN
2530     STA MODE    ;SAVE OPEN MODE
2540     JSR QINIT   ;INIT QUEUE
2550     JSR OQINIT  ;INIT OUT QUEUE
2560     LDY #0      ;OFF VALUE
2570     STY IOFLAG  ;SET FLAG OFF
2580     STA DVSTAT+1 ;SET STATUS TO 0
2590     INY         ;NO ERROR STATUS
2600     STY RDYOUT  ;SET OUPUT RDY
2610     RTS 
2620 ;
2630 ; CLOSE ROUTINE
2640 ;
2650 CLOSE LDA #0    ;FALSE FLAG VAL
2660     STA MODE    ;RESET MODE VARIABLE
2670     STA CONFLG  ;RESET CONCURENT FLG
2680     JSR IOOFF   ;TURN CONC I/O OFF
2690     LDY #1      ;NO ERROR STATUS
2700     RTS 
2710 ;
2720 ; GET ROUTINE
2730 ;
2740 GET LDA CONFLG  ;IF CON I/O OFF THEN
2750     BEQ GETRET  ;  RETURN
2760 GWT JSR QSTAT   ;CHECK QUEUE STAT
2770     BEQ GWT     ;WAIT FOR DATA
2780     JSR QGET    ;GET BYTE FROM QUEUE
2790     LDY #1      ;NO ERROR STATUS
2800 GETRET RTS 
2810 ;
2820 ; PUT ROUTINE
2830 ;
2840 PUT LDY MODE    ;CHECK OPEN MODE
2850     BNE PUTCHR  ;IF NOT OPEN THEN
2860     LDY #133    ;  SET ERROR #
2870     RTS         ;  RETURN
2880 PUTCHR CMP #155
2890     BNE PC1
2900     LDA #$0A
2910     JSR OQPUT
2920     JMP FLUSH
2930 PC1 STA TMPCHR
2940     LDA CONFLG  ;CHECK CONC FLAG
2950     BNE PUTCON  ;IF NOT SET THEN  
2960 PUTREG LDA TMPCHR ;GET CHR
2970     JSR OQPUT   ;PUT IN OUT QUEUE
2980 CHKOLN LDA OQLEN ;  GET QUEUE LEN
2990     CMP #255    ;  CHECK IF FULL
3000     BNE PRGRET  ;  IF FULL THEN
3010 FLUSH JSR SNDBLK ;    SEND BLOCK
3020 PRGRET LDY #1   ;STATUS GOOD
3030     RTS         ;RETURN  
3040 PUTCON JSR PWAIT ;  WAIT OUTPUT RDY
3050     JSR SNDOUT  ;  SEND CHARACTER
3060     LDY #1      ;  STATUS GOOD    
3070     RTS         ;  RETURN
3080 PWAIT LDA OQLEN ;CHECK QUEUE LEN
3090     CMP #255    ;IF FULL THEN
3100     BEQ PWAIT   ;  WAIT NOT FULL
3110     RTS         ;RETURN
3120 SNDOUT SEI      ;DISABLE IRQ
3130     LDA RDYOUT  ;IF Q EMPTY THEN
3140     BNE SNDCHR  ;  SEND CHR ELSE
3150     LDA TMPCHR  ;ELSE
3160     JSR OQPUT   ;  PUT IN QUEUE
3170     CLI         ;ENABLE IRQ
3180     RTS 
3190 SNDCHR LDA TMPCHR
3200     STA SEROUT  ;SEND CHARACTER
3210     LDA #0      ;FLAG FALSE
3220     STA RDYOUT  ;OUTPUT NOT READY
3230     CLI         ;ENABLE IRQ
3240     RTS         ;
3250 WTHAND LDA HNDMSK ;GET HNDSHK REQ
3260     BEQ WTHRET  ;IF HNDS REQ THEN
3270 CHKST JSR STAT  ;  UPDATE STATUS
3280     LDA HNDMSK  ;  GET HNDS MASK
3290     AND DVSTAT+1 ;  CHECK " STATUS
3300     CMP HNDMSK  ;IF HANDS NOT GOOD
3310     BNE CHKST   ;  TRY AGAIN
3320     RTS         ;RETURN
3330 WTHRET JSR IOON ;TURN IOON
3340     RTS         ;RETURN
3350 ; SEND BLOCK          
3360 SNDBLK LDA OQLEN ;GET OUT Q LEN
3370     BEQ SBRET   ;IF LEN>0 THEN
3380     JSR WTHAND  ;  WAIT HNDSHK OK
3390     JSR IOON
3400     LDA #0      ;  NOT READY VAL
3410     STA RDYOUT  ;  RESET FLAG
3420     STA TDNFLG  ;  RESET FLAG
3430     JSR OQGET   ;  GET CHR
3440     STA SEROUT  ;  SEND CHR
3450 WSB1 LDA RDYOUT ;  WAIT UNTIL BYTE
3460     BEQ WSB1    ;  IN SHIFT REG
3470     LDA POKMSK
3480     ORA #$08    ;  SET DON INT BIT
3490     STA POKMSK
3500     STA IRQEN   ;  SAVE POKEY REG
3510 WSB2 LDA TDNFLG ;  WAIT UNTIL     
3520     BEQ WSB2    ;  SHIFT REG CLEAR
3530     JMP SNDBLK  ;  SEND NEXT CHR
3540 SBRET JSR IOOFF ;  TURN IO OFF
3550     RTS         ;RETURN
3560 ;
3570 ; STAT ROUTINE
3580 ;
3590 STAT LDA CONFLG ;CHECK MODE
3600     BEQ CHKCLK  ;IF CONC MODE THEN
3610 MOVLEN LDA QLEN ;  GET QUEUE LEN
3620     STA DVSTAT+1 ;  SAVE LEN LO
3630     LDA #0      ;  GET ZERO VAL
3640     STA DVSTAT+2 ;  SAVE LEN HI
3650     LDA OQLEN   ;  GET OUT Q LEN
3660     STA DVSTAT+3 ;  SAVE LENGTH
3670     JMP STARET  ;ELSE
3680 CHKCLK LDA RTCLOK+2 ;  REAL TIME CLOCK
3690     STA JIFFIE  ;  SAVE JIF COUNT
3700     LDA PORTF   ;  GET INTER STAT
3710     EOR #$08
3720     STA DVSTAT+1 ;  SAVE STATUS
3730     LDA RTCLOK+2 ;  CHECK JIFFIES 
3740     CMP JIFFIE  ;  IF CHANGE THEN
3750     BNE CHKCLK  ;    REPEAT AGAIN
3760 STARET LDA MODE ;ENDIF
3770     STA ICAX1Z  ;RESTORE OPEN TYPE
3780     LDY #0      ;NO ERROR STATUS
3790     STY DVSTAT  ;SAVE DEVICE STAT
3800     INY         ;SET Y TO 1
3810     RTS 
3820 ;
3830 ; XIO ROUTINE
3840 ;
3850 XIO LDA CONFLG  ;IF CONC=ON THEN
3860     BNE XIORET  ;  RETURN
3870     LDA ICCOMZ  ;GET COMMAND NO.
3880     CMP #32     ;IF CMD=32 THEN
3890     BNE XI0     ;  EXEC XIO32
3900     JSR XIO32   ;  FORCE SHORT BLK
3910 XI0 CMP #34     ;IF CMD=34 THEN
3920     BNE XI1     ;  EXEC XIO34  
3930     JSR XIO34   ;  DTR/RTS/XMT
3940 XI1 CMP #36     ;IF CMD=36 THEN
3950     BNE XI3     ;  EXEC XIO36
3960     JSR XIO36   ;  SET BAUD RATE
3970 XI3 CMP #40     ;IF CMD=40 THEN
3980     BNE XIORET  ;  EXEC XIO40  
3990     JSR XIO40   ;  START CONC I/O
4000 XIORET LDA MODE ;GET OPEN TYPE
4010     STA ICAX1Z  ;RESTORE OPEN TYPE
4020     LDY #1      ;NO ERROR STATUS
4030     RTS 
4040 ;
4050 ; INIT ROUTINE
4060 ;
4070 INIT LDY #1
4080     RTS 
4090 ;================================
4100 ;         SUBROUTINES
4110 ;================================
4120 ;
4130 ; FORCE SHORT BLOCK
4140 ;
4150 XIO32 PHA       ;SAVE CMD BYTE 
4160     JSR SNDBLK  ;SEND BLOCK
4170     PLA         ;RESTORE CMD BYTE
4180     RTS 
4190 ;
4200 ; DTR/RTS/XMT
4210 ;
4220 XIO34 PHA       ;SAVE CMD BYTE
4230     LDA ICAX1Z  ;GET CONTROL CODE
4240     AND #$C0    ;IGNORE RTS/XMT
4250     CMP #$C0    ;CHECK FOR ON
4260     BNE DTROFF  ;NO, GO TO OFF
4270     LDA #$3C    ;LOAD VALUE FOR ON
4280     STA PCCTL   ;GO STORE IT
4290     BNE XMT0
4300 DTROFF CMP #$80
4310     BNE XMT0
4320     LDA #$34    ;LOAD VALUE FOR OFF
4330     STA PCCTL   ;STORE IT
4340 XMT0 LDA ICAX1Z
4350     AND #$03
4360     CMP #$03
4370     BNE XMTOFF
4380     LDA #ASYNC
4390     ORA #$80
4400     STA SKCTL
4410     BNE X34R
4420 XMTOFF CMP #$02
4430     BNE X34R
4440     LDA #ASYNC
4450     STA SKCTL
4460 X34R PLA 
4470     RTS 
4480 ;
4490 ; SET BAUD RATE, STOP BITS, & HANDSHAK
4500 ;
4510 XIO36 PHA       ;SAVE CMD BYTE
4520     LDA ICAX1Z  ;GET BAUD OFFSET
4530     AND #$0F    ;ASSURE GOOD VAL
4540     ASL A       ;MULT BY 2
4550     TAY         ;SET INDEX
4560     LDA BAUD,Y  ;GET BAUD LO
4570     STA BAUDRT  ;SET BAUD LO
4580     LDA BAUD+1,Y ;GET BAUD HI
4590     STA BAUDRT+1 ;SET BAUD HI
4600     LDA ICAX2Z  ;GET AUX2 TYP HANDS
4610     AND #$07    ;MASK SIG BITS
4620     TAY 
4630     LDA HSMTAB,Y
4640     STA HNDMSK  ;SAVE HNDSHK MASK
4650     PLA         ;RESTORE CMD BYTE
4660     RTS 
4670 HSMTAB .BYTE $00,$08,$10,$18
4680     .BYTE $80,$88,$90,$98
4690 ;
4700 ; DO NOTHING
4710 ;
4720 ; XIO38 RTS       ;NULL XIO CALL
4730 ;
4740 ; START CONCURRENT MODE I/O
4750 ;
4760 XIO40 PHA       ;SAVE CMD BYTE
4770     LDA MODE    ;CHECK OPEN MODE
4780     BNE CHKMOD  ;IF NOT OPEN THEN
4790     LDY #133    ;  NOT OPEN ERROR
4800     RTS         ;  RETURN
4810 CHKMOD CMP #8   ;IF MODE=8 THEN
4820     BNE OPENOK  ;  CONC NOT ALLOWED
4830     LDY #131    ;  OUTPUT ONLY ERR
4840     RTS         ;  RETURN
4850 OPENOK LDA #1   ;TRUE VAL
4860     STA CONFLG  ;SET CONC FLAG
4870     JSR QINIT   ;CLEAR INPUT Q
4880     JSR OQINIT  ;CLEAR INPUT Q
4890     JSR IOON    ;START CONC I/O
4900     PLA         ;RESTORE CMD BYTE
4910     RTS 
4920 ;
4930 ; SET UP BAUD RATE
4940 ;
4950 STBAUD LDA BAUDRT ;
4960     STA AUDF1   ;SET BAUD LO
4970     STA AUDF3   ;SET BAUD LO
4980     LDA BAUDRT+1 ;
4990     STA AUDF2   ;SET BAUD HI
5000     STA AUDF4   ;SET BAUD HI
5010     RTS 
5020 ;
5030 ; TURN RS232 I/O ON
5040 ;
5050 IOON LDA IOFLAG ;IF I/O ON THEN
5060     BNE IONRET  ;  RETURN
5070     JSR SETPOK  ;SETUP POKEY
5080     JSR STBAUD  ;SETUP BAUD RATE
5090     JSR ENINTR  ;ENABLE INTRPTS
5100     LDA #$3C
5110     STA PDCTL
5120     LDY #1      ;ON VALUE
5130     STY IOFLAG  ;INDICATE I/O ON
5140 WTON INY        ;WAIT TRANSITION
5150     BNE WTON
5160 IONRET RTS 
5170 ;
5180 ; TURN RS232 I/O OFF
5190 ;
5200 IOOFF LDA IOFLAG ;CHECK IF I/O OFF
5210     BEQ IOFRET  ;IF OFF RETURN
5220     LDA #0      ;OFF VALUE
5230     STA IOFLAG  ;SET IOFLAG OFF
5240     LDA #$34
5250     STA PDCTL
5260     JSR DSINTR  ;DISABLE INTRPTS
5270 IOFRET RTS 
5280 ;
5290 ; SETUP POKEY
5300 ;
5310 SETPOK LDA #AUDVAL ;AUDCTL VALUE
5320     STA AUDCTL  ;SET AUDCTL
5330     LDA #ASYNC  ;POKEY MODE 7
5340     STA SKCTL   ;SET MODE REG
5350     RTS 
5360 ;
5370 ; SAVE IMIRQ VEC
5380 ;
5390 IMIRQV .WORD 0
5400 SAVVEC LDA IRQVEC
5410     STA IMIRQV
5420     STA OIRQV
5430     LDA IRQVEC+1
5440     STA IMIRQV+1
5450     STA OIRQV+1
5460     RTS 
5470 ;
5480 ; ENABLE INTERUPTS
5490 ;
5500 ENINTR SEI      ;GET INTR SHADOW
5510     LDA POKMSK
5520     ORA #$30
5530     STA POKMSK
5540     STA IRQEN   ;ENABLE INTRPTS
5550     LDA # <DOIRQ
5560     STA IRQVEC
5570     LDA # >DOIRQ+1
5580     STA IRQVEC+1
5590     CLI 
5600     RTS 
5610 ;
5620 ; DISABLE INTERUPTS
5630 ;
5640 DSINTR SEI      ;GET INTR SHADOW
5650     LDA POKMSK
5660     AND #$C7
5670     STA POKMSK
5680     STA IRQEN   ;DISABLE INTRPTS
5690     LDA IMIRQV
5700     STA IRQVEC
5710     LDA IMIRQV+1
5720     STA IRQVEC+1
5730     CLI 
5740     RTS 
5750 ;
5760 ; NEW IMIRQ ROUTINE
5770 ;
5780 IRQT0 .BYTE $20,$10,$08
5790 IRQT1 .WORD INPUT
5800     .WORD OUTPUT
5810     .WORD TDONE
5820 TJMPVEC .WORD 0
5830 DOIRQ PHA 
5840     TXA 
5850     PHA 
5860     LDX #2
5870 D0  LDA IRQT0,X
5880     CPX #2
5890     BNE D1
5900     AND POKMSK
5910     BEQ D2
5920 D1  BIT IRQST
5930     BEQ D3
5940 D2  DEX 
5950     BPL D0
5960     JMP XITIRQ
5970 D3  EOR #$FF
5980     STA IRQEN
5990     LDA POKMSK
6000     STA IRQEN
6010     TXA 
6020     ASL A
6030     TAX 
6040     LDA IRQT1,X
6050     STA TJMPVEC
6060     LDA IRQT1+1,X
6070     STA TJMPVEC+1
6080     PLA 
6090     TAX 
6100     JMP (TJMPVEC)
6110 XITIRQ PLA 
6120     TAX 
6130     PLA 
6140     JMP (OIRQV)
6150 ;================================
6160 ;        INTERUPT ROUTINES
6170 ;================================
6180 ;
6190 ; INPUT INTERUPT ROUTINE
6200 ;
6210 INPUT TYA       ;SAVE Y REG
6220     PHA         ;
6230     TXA         ;SAVE X REG
6240     PHA         ;
6250     LDA SERIN   ;GET INPUT BYTE
6260     JSR QPUT    ;PUT CHR IN QUEUE
6270     PLA         ;
6280     TAX         ;RESTORE X REG
6290     PLA         ;
6300     TAY         ;RESTORE Y REG
6310     PLA         ;
6320     RTI 
6330 ;
6340 ; OUTPUT INTERUPT ROUTINE
6350 ;
6360 OUTPUT TYA      ;SAVE Y REG
6370     PHA         ;
6380     TXA         ;SAVE X REG
6390     PHA         ;
6400     LDA OQLEN   ;GET QUEUE LEN
6410     BEQ SETRDY  ;IF NOT EMPTY THEN
6420     LDA CONFLG  ;  IF BLOCK MODE
6430     BEQ SETRDY  ;    SET READY
6440     JSR OQGET   ;  GET BYTE
6450     STA SEROUT  ;  SEND BYTE
6460     JMP OUTRET  ;ELSE
6470 SETRDY LDA #1   ;  GET TRUE VALE
6480     STA RDYOUT  ;  SET OUTRDY FLAG
6490 OUTRET PLA      ;
6500     TAX         ;RESTORE X REG
6510     PLA         ;
6520     TAY         ;RESTORE Y REG
6530     PLA         ;
6540     RTI 
6550 ;
6560 ; TRANS. DONE INTERUPT ROUTINE
6570 ;
6580 TDONE LDA #1    ;TRUE VAL
6590     STA TDNFLG  ;SET DONE FLAG
6600     LDA POKMSK
6610     AND #$F7
6620     STA POKMSK
6630     STA IRQEN   ;SAVE TO POKEY REG
6640     PLA 
6650     RTI 
6660 ;================================
6670 ;           DATA TABLES
6680 ;================================
6690 ;
6700 ; BAUD RATE TABLE
6710 ;
6720 BAUD .WORD 2976 ;0)  300    BAUD
6730     .WORD 23    ;1)  MIDI
6740     .WORD 16    ;2)  38400  BAUD
6750     .WORD 9     ;3)  57600  BAUD
6760     .WORD 1     ;4)  115200 BAUD
6770     .WORD 8128  ;5)  110    BAUD
6780     .WORD 6646  ;6)  134.5  BAUD
6790     .WORD 5958  ;7)  150    BAUD
6800     .WORD 2976  ;8)  300    BAUD
6810     .WORD 1484  ;9)  600    BAUD
6820     .WORD 739   ;10) 1200   BAUD
6830     .WORD 490   ;11) 1800   BAUD
6840     .WORD 366   ;12) 2400   BAUD
6850     .WORD 179   ;13) 4800   BAUD
6860     .WORD 86    ;14) 9600   BAUD
6870     .WORD 40    ;15) 19200  BAUD
6880 ;
6890 ; SETUP MEMLO & START ON LOAD
6900 ;
6910 QORG *= *+256
6920 OQORG *= *+256
6930 MLOW =  *       ;NEW MEMLO
6940     *=  $02E2   ;INIT ADR VEC
6950     .WORD START
