;HYP_R.COM›;›;Optimized R: handler›;for Multi-I/O and Black Box›;›;Copyright 1995, 1997 Lenard R. Spencer›;›;Multi-I/O tm FTe›;Black Box tm CSS›;Atari tm Atari Corporation›;›;THIS PROGRAM MAY BE FREELY DISTRIBUTED›;BUT MAY NOT BE INCORPORATED INTO ANY›;OTHER SOFTWARE PACKAGE.›;›;This is a replacement handler for the›;ROM handlers in the Multi-I/O and›;Black Box, in and effort to provide a›;more efficient handler for the newer›;high-speed modems. The problem is not›;so much the handlers themselves, but›;rather the Atari XL/XE operating›;system, and its overhead of code in›;what is called the "generic handler"›;just to access the ROM handlers.›;There is also an excess of overhead›;code in the interrupt handler just to›;get to the ROM interrupt service›;routines. This memory-resident›;handler has its own IRQ routine that›;is patched into the IRQ vector at›;$0216, so it can check the hardware›;directly.›;›;This source code assembles into two›;versions, one for the Multi-I/O, the›;other for the Black Box, depending on›;how the variable MIO is set. If›;MIO=0, a Black Box version will be›;assembled. If MIO=non-zero, a MIO›;version will result.›;›;This handler is optimized for using›;the RS-232 port strictly for modem›;operations, so do not attempt to use›;it for a serial printer or the system›;will lock up.›;›;Now, ON TO THE CODE!›;› .PAGE "HARDWARE CONSTANTS"›;›BRKKEY = $11 ;BREAK key flag›ICCOMZ = $22 ;ZP IOCB COMMAND›ICAX1Z = $2A ;ZP IOCB AUX 1›ICAX2Z = $2B ;ZP IOCB AUX 2›IRQVEC = $0216 ;IRQ vector›MEMLO = $02E7 ;free memory start›DVSTAT = $02EA ;device status›;›;DEVICE REGISTERS AND VARIABLES›;›;ÁÓÓÅÍÂÌÙ Ó×ÉÔÃÈ ÆÏÒ ÍÉÏ ÏҠ›;›MIO = 1 ;1=MIO, 0=BB›;›;› .IF MIO›ACIAREG = $D1C0 ;ACIA register›ACIASTAT = $D1C1 ;ACIA status reg -› ;DO NOT WRITE!›ACIACOM = $D1C2 ;ACIA command reg›ACIACTL = $D1C3 ;ACIA control reg›HWLINES = $D1FF ;RS232 lines›DTRREG = $D1C2 ;DTR location›RTSREG = $D1C2 ;RTS location›DTRMASK = $FE ;mask for DTR›RTSMASK = $F3 ;mask for RTS›CTS = $04 ;CTS line bit›RTS = $08 ;RTS enable›DTR = $01 ;DTR enable›;› .ELSE ›ACIAREG = $D130 ;ACIA register›ACIASTAT = $D131 ;ACIA status reg -› ; DO NOT WRITE!›ACIACOM = $D132 ;ACIA command reg›ACIACTL = $D133 ;ACIA control reg›HWLINES = $D1C0›DTRREG = $D1BF ;DTR location›RTSREG = $D1BD ;RTS location›DTRMASK = $F7 ;mask for DTR›RTSMASK = $F7 ;mask for RTS›CTS = $40 ;CTS line bit›RTS = $08 ;RTS enable›DTR = $08 ;DTR enable› .ENDIF ›;› *= $4000 ;To be relocated›START ; Needed by relocator›;› .PAGE "INTERRUPT ROUTINE"›;›IRQ PHA ;save accum.,X› TXA › LDX ACIASTAT ;ACIA IRQ?› BMI IRQ2 ;yes - skip› TAX › PLA ›SYSIRQ JMP $C030 ;otherwise out›IRQ2 PHA › TYA › PHA › TXA ;get status› AND #8 ;receive?› BEQ TRYSEND ;no - try send›W01 LDY LASTIN› LDA ACIAREG ;get byte›W02 STA INBUFF,Y ;store it› INY ›W03 STY LASTIN›W04 CPY NEXTIN ;rolled over?› BNE TRYSEND ;no - go to send›W05 INC NEXTIN ;else set flag›W06 LDA STATERR ; for buffer› ORA #$10 ; overflow›W07 STA STATERR›TRYSEND TXA › AND #$10 ;Tx reg empty?› BEQ IRQEXIT ; › LDA ACIACOM ;Tx enabled?› AND #$0C› CMP #4› BNE IRQEXIT ;no - exit›SEND02 LDA HWLINES ;CTS monitoring› AND #CTS ;CTS = 1?› BEQ IRQEXIT ;no - bail out›W09 LDY NEXTOUT›W10 CPY LASTOUT ;buffer empty?› BNE SENDIT ;no - send byte›W11 JSR DSTXIRQ ;disable Tx IRQ›IRQEXIT PLA ;restore regs› TAY › PLA › TAX › PLA › RTI ;bail out!›SENDIT INY ›W12 LDA OUTBUFF,Y› STA ACIAREG›W13 STY NEXTOUT›W14 JMP IRQEXIT›DSTXIRQ LDA #8› .BYTE $2C ;imp. BIT inst.›ENTXIRQ LDA #4› EOR ACIACOM› AND #$0C› EOR ACIACOM› STA ACIACOM› RTS ›;› .PAGE "GET BYTE ROUTINE"›;›GET BIT BRKKEY ;BREAK key pressed?› BPL GET10 ;yes - bail out!›W15 LDX NEXTIN ;get pointer›W16 CPX LASTIN ;buffer empty?› BEQ GET ;yes - loop back›W17 LDY INBUFF,X ;get byte› INX ;bump pointer›W18 STX NEXTIN ;save it›W19 LDA TRANS› AND #$20 ;ATASCII?› BNE GET10 ;yes - skip› CPY #$0D ;ASCII CR?› BNE GET10 ;no - skip› LDY #$9B ;make ATASCII EOL› BNE GET10›W20 LDA TRANS› AND #$10› BEQ GET10› TYA › AND #$7F› TAY › CPY #$7D› BCS GET08› CPY #$20› BCS GET10›W21›GET08 LDY TCHR›GET10 TYA ›W22 JMP SETBREAK›;› .PAGE "PUT BYTE, SET BREAK"›;›PUT TAY ›W23 LDA TRANS› AND #$20 ;ATASCII?› BNE PUT03 ;yes - skip› CPY #$9B ;ATASCII EOL?› BNE PUT03 ;no - skip› LDY #$0D ;else make CR›W24 JSR PUT10 ;send it›W25 BIT TRANS ;need LF?› BVC SETBREAK ;no - skip› LDY #$0A ;else send LF›W26›PUT03 JSR PUT10 ;send character›SETBREAK LDY #1 ;assume OK› BIT BRKKEY ;BREAK pressed?› BMI SETEXIT ;no - skip› LDY #$80 ;else ERROR 128› STY BRKKEY ;reset BREAK flag›SETEXIT CPY #0 ;set exit flags› SEC ;yes we handled it› RTS ›W27›PUT10 LDX LASTOUT ;get pointer› INX ›PUT11 BIT BRKKEY ;BREAK pressed?› BPL PUTEXIT ;yes - bail out›W28 CPX NEXTOUT ;buffer full?› BEQ PUT11 ;yes - loop back› SEI › TYA ›W29 STA OUTBUFF,X ;put in buffer›W30 STX LASTOUT ;save pointer›W31 JSR ENTXIRQ ;enable Tx IRQ› CLI ›PUTEXIT RTS ›;› .PAGE "OPEN, CLOSE R: CHANNEL"›;›OPEN LDA ICAX1Z ;get aux 1 byte› AND #$0C›W32 STA MODE ;save› SEI › LDX #5› LDA #0 ;zero out working›W33›OP01 STA STATERR,X ; variables› DEX › BPL OP01›OP02 CLI ›W35›OPEN03 LDA MODE› STA ICAX1Z›W36 JMP SETBREAK›;›; CLOSE R: HANDLER CHANNEL›;›CLOSE LDA #0 ;end concurrent›W37 STA CONCUR ; mode›W38›XIO32 LDA LASTOUT ;get pointer›F01 BIT BRKKEY ;BREAK pressed?› BPL F02 ;yes - exit›W39 CMP NEXTOUT ;buffer empty?› BNE F01 ;no - loop back›W40›F02 JMP OPEN03 ;exit›;› .PAGE "GET STATUS OF R: CHANNEL"›;›STATUS LDA HWLINES ;read H/S lines› .IF MIO=0› LSR A› LSR A› LSR A› LSR A› LSR A› .ENDIF › AND #7 ;get index› TAX ; index›W43 LDA HSFLAGS,X›W44 ORA HSLAST› STA DVSTAT+1› AND #$A8› LSR A›W45 STA HSLAST›W46 BIT CONCUR ;concurrent mode?› BPL STAT02 ;no - skip› SEC ›W47 LDA LASTIN ;calc bytes in›W48 SBC NEXTIN ; input buffer› STA DVSTAT+1› SEC ›W49 LDA LASTOUT ;calc bytes in›W50 SBC NEXTOUT ; output buffer› STA DVSTAT+3›W51›STAT02 LDA STATERR ;status flags› STA DVSTAT› LDA #0 ;clear flags›W52 STA STATERR› STA DVSTAT+2›W53 JMP SETBREAK›HSFLAGS .IF MIO› .BYTE $01,$09,$81,$89› .BYTE $21,$29,$A1,$A9› .ELSE › .BYTE $01,$81,$21,$A1› .BYTE $09,$89,$29,$A9› .ENDIF ›;› .PAGE "XIO 40, 38, 36 CALLS"›;›SPECIAL LDX ICCOMZ ;get command› LDA ICAX1Z ;get aux 1› CPX #$28 ;set concurrent?› BNE XIO38 ;no - try next›W54 LDA CONCUR ;set flag for› ORA #$80 ; concurrent mode›W55 STA CONCUR ; operation›W56 JMP OPEN03›XIO38 CPX #$26 ;trans, parity?› BNE XIO36 ;no - try next›W57 STA TRANS ;save directly› LSR A› LSR A› AND #3 ;get parity bits› TAY › LDA ACIACOM› AND #$1F›W58 ORA PARITY,Y› STA ACIACOM› LDA $2B›W59 STA TCHR›W60 JMP OPEN03›PARITY .BYTE 0,$20,$60,$A0›XIO36 CPX #$24 ;baud, word size?› BNE XIO34 ;no - try next› TAY ;temp save› AND #$D0 ;set word size,› ASL A ; stop bits› PHP › ASL A› PLP › ROR A› PHA ;temp save› TYA › AND #$0F ;get baud rate› BEQ XIO36C ;0 = 300 baud› LDX #8› CMP #5 ;110 baud?› BEQ XIO36A ;yes - skip down› SEC ;otherwise -› CMP #8 ; standard rates?› BCC ERR132 ;no - error out› AND #7 ;get index›XIO36C TAX ›XIO36A PLA ;retrieve byte›W61 ORA BAUD,X ;index baud table› STA ACIACTL›W63›XIO36B JMP OPEN03›BAUD .BYTE $16,$17,$18,$19› .BYTE $1A,$1C,$1E,$1F,$13› .PAGE "ERROR 132; XIO 34, 32"›W64›ERR132 JSR SETBREAK› TYA › BMI ER132A› LDY #$84 ;illegal XIO call›ER132A RTS ›XIO34 CPX #$22 ;set H/S lines?› BNE XIO32A ;no - skip› TAX › BIT ICAX1Z ;set DTR?› BPL XIO34A ;no - skip› PHP › LDA DTRREG› AND #DTRMASK› .IF MIO=0› ORA #$34› .ENDIF › PLP › BVC XIO34B› ORA #DTR ;set DTR true›XIO34B STA DTRREG›XIO34A TXA › AND #$20 ;set RTS?› BEQ XIO34C ;no - skip› TXA › AND #$10› PHP › LDA RTSREG› AND #RTSMASK› .IF MIO=0› ORA #$34› .ENDIF › PLP › BEQ XIO34D› ORA #RTS›XIO34D STA RTSREG›XIO34C TXA › AND #2 ;set XMT?› BEQ X34F ;no - exit› TXA › AND #1› PHP › LDA ACIACOM› AND #$F3› ORA #8› PLP › BEQ XIO34E› ORA #4›XIO34E STA ACIACOM›W65›X34F JMP OPEN03›XIO32A CPX #$20 ;XIO 32?› BNE ERR132 ;no - error out›W66 JMP XIO32› .PAGE "RESET INITIALIZATION"›INIT JSR $FFFF ;DOSINI vector›L01›INIT02 LDA # RELOC› STA MEMLO+1› LDX #0›INIT03 LDA $031A,X ;find handler› BEQ SETHAND ;end of HATABS› CMP #$52 ;"R:"› BEQ SET02 ;R: handler found› INX › INX › INX › BNE INIT03›SETHAND LDA #$52› STA $031A,X›L02›SET02 LDA # HATAB› STA $031C,X› LDA IRQVEC ;patch into›W67 STA SYSIRQ+1 ; IRQ vector› LDA IRQVEC+1›W68 STA SYSIRQ+2› SEI ›L03 LDA # IRQ› STA IRQVEC+1› CLI › .IF MIO› LDA ACIACOM› AND #$FC› STA ACIACOM› .ELSE › LDA ACIACOM› ORA #1› AND #$FD› STA ACIACOM› LDA #$34 ;set DTR low› STA DTRREG› .ENDIF ›INOUT RTS ›;›W69›HATAB .WORD OPEN-1›W70 .WORD CLOSE-1›W71 .WORD GET-1›W72 .WORD PUT-1›W73 .WORD STATUS-1›W74 .WORD SPECIAL-1› .BYTE 0›STATERR .BYTE 0 ;status/error fl.›NEXTIN .BYTE 0 ;next byte in›LASTIN .BYTE 0 ;last byte in›NEXTOUT .BYTE 0 ;next byte out›LASTOUT .BYTE 0 ;last byte out›CONCUR .BYTE 0 ;concurrent flag›MODE .BYTE 0 ;I/O mode›TRANS .BYTE 0 ;translation›TCHR .BYTE 0 ;trans character›HSLAST .BYTE 0 ;last H/S states›INBUFF *= *+256›OUTBUFF *= *+256› .PAGE "GENERIC RELOCATOR"›;GENERIC RELOCATOR - written for use›; with other programs as well.›;›RELOC LDX #0 ;Just to make sure›REL01 LDA $031A,X ;we have room in› BEQ REL01A ;the handler table› INX › INX › INX › CPX #$21› BCC REL01› LDA # ERRMSG› LDY #ERREND-ERRMSG›REL01A LDA # START› SBC MEMLO+1› STA OFFSET+1› LDX #0 ;initialize for› LDY #0 ; relocation loop›REL02 LDA TABLO,X› STA $E0›REL03 LDA TABHI,X› STA $E2› INX ›REL04 LDA TABLO,X› STA $E1›REL05 LDA TABHI,X› STA $E3› ORA $E2 ;end of table?› BEQ MOVEIT ;yes - drop down› LDA ($E0),Y ;else - recalc› SEC ; address› SBC OFFSET› STA ($E0),Y› LDA ($E2),Y› SBC OFFSET+1› STA ($E2),Y› INX ;next address› BNE REL02 ;no wrap - go back› INC REL02+2 ;else bump› INC REL03+2 ; addresses up› INC REL04+2 ; to next page› INC REL05+2› JMP REL02› .PAGE "MOVE CODE TO MEMLO"›MOVEIT LDA # START› STA $E1› LDA MEMLO› STA $E2› LDA MEMLO+1› STA $E3› LDA # RELOC-START› STA $E5›MOVE02 LDA ($E0),Y› STA ($E2),Y› INC $E0› BNE MOVE03› INC $E1›MOVE03 INC $E2› BNE MOVE04› INC $E3›MOVE04 LDA $E4› BNE MOVE05› DEC $E5›MOVE05 DEC $E4› BNE MOVE02› LDA $E5› BNE MOVE02›RELINIT LDA $0C ;DOSINI vector›M06 STA INIT+1 ; patch point› LDA $0D›M07 STA INIT+2›M08 LDA # INIT› STA $0D›M10 JSR INIT02›PRTMSG LDA # MSG› LDY #