2023-11-16 18:19:54 -05:00

539 lines
10 KiB
Plaintext

PAGE
SBTTL "--- MACHINE-DEPENDENT I/O: ATARI ---"
; ----------------------------
; FETCH ASCII KEYCODE INTO [A]
; ----------------------------
; EXIT: ASCII IN [A] & [IOCHAR]
BADKEY: JSR BOOP
JMP GKEY0
GETKEY: CLD
TXA ; SAVE [X] & [Y]
PHA
TYA
PHA
GKEY0: LDA #0
STA BLINK+LO ; LENGTHEN BLINK DELAY
STA BLINK+HI ; TO MAXIMUM
LDA COLCRS+LO ; CALC CURSOR X-POS
ASL A
ASL A
CLC
ADC #48
STA HPOSM0
LDA ROWCRS ; CALC CURSOR Y-POS
ASL A
ASL A
ASL A
CLC
ADC #39
TAY ; MOVE HERE FOR DRAWING
LDA #%00000011 ; FORCE CURSOR "ON"
STA CSHAPE
STA MISSL,Y ; AND DRAW IT
GKEY1: LDX CH ; CHECK HARDWARE FOR A KEYPRESS
INC BLINK+LO
BNE NOBLIN
INC BLINK+HI
BNE NOBLIN
LDA #$80
STA BLINK+HI ; RESET BLINK TIMER
LDA CSHAPE
EOR #%00000011
STA CSHAPE ; FLIP CURSOR SHAPE
STA MISSL,Y ; DRAW CURSOR INTO MISSILE RAM
NOBLIN: CPX #$FF ; KEY PRESSED?
BEQ GKEY1 ; NO, KEEP SCANNING
LDA #$FF
STA CH ; RESET KEY HARDWARE
TXA
BMI BADKEY ; REJECT CTRL KEYS
LDA ATASCI,X ; GET CODE INTO [A]
CMP #EOL ; WAS IT EOL?
BEQ CLICK ; OKAY IF SO
TAX ; ANY OTHER NEGATIVE CODE
BMI BADKEY ; IS ILLEGAL
; ERASE CURSOR, "CLICK" THE SPEAKER
CLICK: STA IOCHAR ; SAVE KEYCODE
LDA #0
STA MISSL,Y ; ERASE CURSOR
LDY #$80
CLK0: STY CONSOL
LDX #8
CLK1: DEX
BNE CLK1
DEY
BNE CLK0
PLA ; RESTORE
TAY ; EVERYTHING
PLA
TAX
LDA IOCHAR ; GET CHAR INTO [A]
RTS ; AND RETURN IT
; -----------------
; PRINT CHAR IN [A]
; -----------------
CHAR: STA IOCHAR ; SAVE HERE
TXA ; SAVE [X] AND [Y]
PHA
TYA
PHA
LDY ROWCRS ; Y-POS INTO [Y]
LDX COLCRS+LO ; X-POS INTO [X]
LDA IOCHAR ; RESTORE CHAR
CMP #EOL ; IS IT EOL?
BEQ OUTEOL ; YES, SPECIAL HANDLING
CMP #$0D ; ALSO CHECK FOR
BEQ OUTEOL ; ASCII EOL
; HANDLE A NON-EOL CHAR
CPY #YSIZE-1 ; ON LAST SCREEN LINE?
BCC NOSCRL ; NO, NO SCROLL NEEDED
CPX #XSIZE ; LAST CHAR ON LINE?
BCC NOSCRL ; NO, DON'T SCROLL
; SCROLL THE SCREEN
DOSCRL: DEY ; PUSH CURSOR UP ONE LINE
STY ROWCRS
LDX SLINE ; GET CURRENT SCROLL LINE
SRL0: CPX #YSIZE
BEQ SRL2 ; SCROLL DONE
LDA LOLINE,X ; GET ADDR OF DEST LINE
STA LTO+LO ; INTO [LTO]
LDA HILINE,X
STA LTO+HI
INX
LDA LOLINE,X ; GET ADDR OF SOURCE LINE
STA LFROM+LO ; INTO [LFROM]
LDA HILINE,X
STA LFROM+HI
LDY #XSIZE
SRL1: LDA (LFROM),Y ; MOVE SOURCE LINE
STA (LTO),Y ; TO DEST LINE
DEY
BPL SRL1
BMI SRL0 ; LOOP TILL [X] = YSIZE
SRL2: LDX #XSIZE
LDA #0
SRL3: STA SCREEN+920,X ; CLEAR LAST LINE
DEX ; OF SCREEN RAM
BPL SRL3
NOSCRL: LDA IOCHAR ; RESTORE CHAR
LDX #$0B ; CIO "PUT CHAR"
STX ICCOM ; COMMAND
LDX #0 ; IOCB #0 (E:)
STX ICBLEN+LO ; ZERO THE
STX ICBLEN+HI ; BUFFER LENGTH
JSR CIOV ; SEND IT OUT!
PLA ; RESTORE [X] AND [Y]
TAY
PLA
TAX
RTS
; HANDLE EOL
OUTEOL: LDA #$9B ; MAKE SURE [IOCHAR]
STA IOCHAR ; IS AN ATASCII EOL
CPY #YSIZE-1 ; LAST SCREEN LINE?
BCC NOSCRL ; NO, DON'T SCROLL
BCS DOSCRL ; ELSE SCROLL
; ---------------------
; FETCH A LINE OF INPUT
; ---------------------
; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1]
; EXIT: # CHARS READ IN [A]
INPUT: JSR LINOUT ; FLUSH [LBUFF]
LDY #$FF
STY CH ; CLEAR KEYBOARD
INY ; = 0
STY LINCNT ; RESET LINE COUNT
INLOOP: JSR GETKEY ; GET ASCII INTO [A] AND [IOCHAR]
CMP #EOL ; EOL?
BEQ ENDLIN ; LINE DONE IF SO
CMP #BACKSP ; BACKSPACE?
BEQ BACKUP ; SPECIAL HANDLING
STA LBUFF,Y ; ELSE ADD CHAR TO INPUT BUFFER
INY ; NEXT POSITION IN LINE
SHOWIT: JSR CHAR ; SEND TO SCREEN
CPY #77 ; 2 SCREEN LINES FULL?
BCC INLOOP ; NO, GET ANOTHER CHAR
; HANDLE LINE OVERFLOW
NOMORE: JSR GETKEY
CMP #EOL ; IF EOL,
BEQ ENDLIN ; WRAP UP THE LINE
CMP #BACKSP ; BACKSPACE
BEQ BACKUP ; IS OKAY TOO
JSR BOOP ; ELSE COMPLAIN
JMP NOMORE ; AND INSIST
; HANDLE BACKSPACE
BACKUP: DEY ; BACK UP THE POINTER
BPL SHOWIT ; SEND BS IF NOT START OF LINE
JSR BOOP ; ELSE SCREAM WITH PAIN
LDY #0 ; RESET POINTER
BEQ INLOOP ; AND WAIT FOR SOMETHING BETTER
; HANDLE END OF LINE
ENDLIN: STA LBUFF,Y ; SHIP EOL TO BUFFER
INY ; UPDATE INDEX
STY LINLEN ; SAVE HERE FOR "READ"
STY PRLEN ; AND HERE FOR "PPRINT"
JSR CHAR ; AND SEND EOL TO SCREEN
; MOVE [LBUFF] TO [ARG1] W/LC CONVERSION
LEX0: LDA LBUFF-1,Y ; GET A CHAR FROM [LBUFF]
CMP #EOL ; ATASCII EOL?
BNE LEX1 ; IF SO,
LDA #$0D ; CONVERT TO ASCII
BNE LEX2
LEX1: CMP #'A' ; IF CHAR IS ALPHA,
BCC LEX2 ; CONVERT TO LOWER CASE
CMP #'Z'+1
BCS LEX2
ADC #$20
LEX2: STA (ARG1),Y ; MOVE CHAR TO INPUT BUFFER AT [ARG1]
DEY ; LOOP TILL
BPL LEX0 ; ALL CHARS MOVED
JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED
LDA LINLEN ; RESTORE # CHARS
RTS ; INTO [A]
; -----------------------
; DIRECT PRINT LINE [X/A]
; -----------------------
; ENTRY: STRING ADDRESS IN [X/A] (LSB/MSB)
; STRING LENGTH IN [Y]
DLINE: STX STRING+LO ; DROP STRING ADDRESS
STA STRING+HI ; INTO DUMMY BYTES
LDX #0 ; INIT CHAR-FETCH INDEX
DOUT: DB $BD ; 6502 "LDA nnnn,X" OPCODE
STRING: DW $0000 ; DUMMY OPERAND BYTES
JSR CHAR
INX
DEY ; LOOP TILL
BNE DOUT ; OUT OF CHARS
RTS
; -----------------------
; SEND [LBUFF] TO PRINTER
; -----------------------
; ENTRY: LENTH OF LINE IN [PRLEN]
PNAME: DB "P:" ; FILENAME FOR PRINTER
DB EOL
SFLAG: DB 0 ; PREVIOUS SCRIPTING STATE
PPRINT: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED?
BEQ PEX ; NO, SCRAM IMMEDIATELY
LDA ZBEGIN+ZSCRIP+1 ; CHECK SCRIPT FLAG
AND #%00000001 ; SCRIPTING ON?
BEQ PEX ; NO, EXIT
LDA PSTAT ; CHECK PRINTER STATUS
BMI PEX ; CAN'T OPEN IF NEGATIVE
BNE PP1 ; ALREADY OPEN, SCRIPT THE LINE
; OPEN THE PRINTER FOR OUTPUT
JSR CLOSEP ; CLOSE IOCB #1 FIRST FOR SAFETY
LDX #$10 ; IOCB #1 (P:)
LDA #LOW PNAME ; POINT
STA ICBADR+LO,X ; TO
LDA #HIGH PNAME ; P:
STA ICBADR+HI,X ; FILENAME
LDA #$03 ; CIO "OPEN"
STA ICCOM,X ; COMMAND
LDA #$08 ; SET CHANNEL
STA ICAUX1,X ; FOR WRITE-ONLY
LDA #0
STA ICAUX2,X ; ZERO THIS BYTE
JSR CIOV ; OPEN IT!
TYA ; STATUS CODE IN [Y]
BMI BADP ; ERROR IF NEGATIVE
LDA #$70
STA POKMSK
STA IRQEN ; DISABLE BREAK KEY
LDA #1 ; SET [PSTAT]
STA PSTAT ; TO INDICATE "PRINTER READY"
; PRINT [LBUFF]
PP1: LDX #$10 ; IOCB #1 (P:)
LDA #LOW LBUFF ; TELL CIO
STA ICBADR+LO,X ; WHERE
LDA #HIGH LBUFF ; [LBUFF]
STA ICBADR+HI,X ; IS HIDING
LDA PRLEN ; # CHARS TO PRINT
STA ICBLEN+LO,X
LDA #0 ; CLEAR THE
STA ICBLEN+HI,X ; MSB OF LINE LENGTH
LDA #$0B ; CIO "PUT BUFFER" COMMAND (BM 4/9/85)
STA ICCOM,X ; COMMAND
JSR CIOV
TYA
BPL PEX ; EXIT IF NO ERROR
; HANDLE PRINTER ERROR
BADP: LDA #$FF ; SET PRINTER STATUS
STA PSTAT ; TO "CAN'T OPEN"
; CLOSE PRINTER CHANNEL (IOCB #1)
CLOSEP: LDX #$10 ; IOCB #1 (P:)
LDA #$0C ; CIO "CLOSE"
STA ICCOM,X ; COMMAND
JSR CIOV ; CLOSE THE CHANNEL
PEX: RTS
; ------------
; SPLIT SCREEN
; ------------
; SPLIT SCREEN AT LINE [ARG1]
; DISABLE SPLIT IF [ARG1] = 0
; IGNORE IF SPLIT ALREADY ENABLED OR [ARG1] >= 20
ZSPLIT: LDX ARG1+LO ; IF [ARG1] = 0,
BEQ OFFSPL ; TURN OFF SPLIT SCREEN
LDA SPSTAT ; SPLIT ALREADY ENABLED?
BNE SPLEX ; IGNORE REQUEST IF SO
CPX #20 ; IF [ARG1] >= 20,
BCS SPLEX ; IGNORE
INX
STX SLINE ; ELSE SET NEW SPLIT LINE
STX SPSTAT ; SET "SPLIT ENABLED" FLAG
SPL0: LDA LOLINE,X ; MAKE [LFROM] POINT TO
STA LFROM+LO ; LINE [X] IN WINDOW
LDA HILINE,X
STA LFROM+HI
LDY #XSIZE ; CLEAR LINE [X]
LDA #0
SPL1: STA (LFROM),Y
DEY
BPL SPL1
DEX ; DONE ALL LINES?
BNE SPL0 ; LOOP TILL WINDOW CLEARED
STX LINCNT ; RESET LINE COUNT TO ZERO
SPCALC: LDA #YSIZE-1 ; CALCULATE # LINES TO SCROLL
SEC ; BEFORE "MORE" APPEARS:
SBC SLINE ; LMAX = YSIZE-SLINE-1
STA LMAX
DEC LMAX
SPLEX: RTS
; --------------------
; DISABLE SPLIT SCREEN
; --------------------
OFFSPL: JSR TOBOT1 ; SET CURSOR TO BOTTOM
SPLOFF: LDX #1
STX SLINE ; SPLIT AT LINE 1
DEX ; = 0
STX SPSTAT ; TURN OFF STATUS FLAG
STX LINCNT ; RESET LINE COUNT
LDA #21
STA LMAX ; SET MAXIMUM LINE SCROLL
BNE NEWLOG ; RESET LINE MAP & RETURN
; ------
; SCREEN
; ------
; GO TO TOP WINDOW IF [A] = 0
; GO TO BOTTOM IF [A] = 1
; IGNORE IF SPLIT NOT ENABLED OR [A] <> 0 OR 1
ZSCRN: LDA SPSTAT ; IF SPLIT NOT ENABLED,
BEQ SPLEX ; IGNORE REQUEST
LDA ARG1+LO ; IF [ARG1] = 0,
ORA ARG1+HI
BEQ TOBOT0 ; GO TO BOTTOM WINDOW
CMP #1 ; IF [ARG1] <> 1,
BNE SPLEX ; IGNORE THE REQUEST
; SET TO TOP WINDOW
TOTOP: LDY #21 ; TEMPORARILY RESET
STY LMAX ; [LMAX] TO KILL "MORE"
LDY #1 ; Y-POS = 1
BNE DOSCRN
; SET TO BOTTOM WINDOW
TOBOT0: JSR SPCALC ; RE-CALC [LMAX]
TOBOT1: LDY #23 ; Y-POS = 23
DOSCRN: STY ROWCRS ; Y-POS = [Y]
LDA #0 ; X-POS = 0
STA COLCRS+LO
STA LINCNT ; RESET LINE COUNT
; FALL THROUGH ...
; ----------------------
; RESET LOGICAL LINE MAP
; ----------------------
NEWLOG: LDA #$FF
STA LOGMAP
STA LOGMAP+1
STA LOGMAP+2
RTS
; ---------
; RAZZ USER
; ---------
BOOP: LDA #200 ; SET
STA AUDF1 ; FREQUENCY
LDA #$AA ; PURE TONE, VOLUME #10
STA AUDC1
LDA #252 ; 4 JIFFY DELAY
STA RTCLOK
BOOP0: LDA RTCLOK
BNE BOOP0
STA AUDC1 ; SHUT OFF SOUND
RTS
; ------------
; CLEAR SCREEN
; ------------
CLS: LDA #LOW SCREEN
STA I+LO
LDA #HIGH SCREEN ; POINT [I] TO
STA I+HI ; SCREEN RAM
LDA #0
STA LENGTH ; RESET LINE LENGTH
TAY
LDX #4 ; CLEAR 4 PAGES
CLS0: STA (I),Y ; FOR SCREEN
INY
BNE CLS0
INC I+HI ; POINT TO NEXT PAGE
DEX ; 4 PAGES DONE?
BNE CLS0 ; LOOP TILL EMPTY
LDY #1 ; SET Y-POS TO 1
STY ROWCRS
DEY ; X-POS TO 0
STY COLCRS+LO
JMP SPLOFF ; DISABLE SPLIT-SCREEN & RETURN
; -------------------
; LINE ADDRESS TABLES
; -------------------
LOLINE: DB $40,$68,$90,$B8,$E0,$08,$30,$58
DB $80,$A8,$D0,$F8,$20,$48,$70,$98
DB $C0,$E8,$10,$38,$60,$88,$B0,$D8
HILINE: DB $BC,$BC,$BC,$BC,$BC,$BD,$BD,$BD
DB $BD,$BD,$BD,$BD,$BE,$BE,$BE,$BE
DB $BE,$BE,$BF,$BF,$BF,$BF,$BF,$BF
; ------------------------
; ATASCII CONVERSION TABLE
; ------------------------
ATASCI: DB $6C,$6A,$3B,$FF,$FF,$6B,$FF,$FF ; UNSHIFTED
DB $6F,$FF,$70,$75,$9B,$69,$2D,$FF
DB $76,$FF,$63,$FF,$FF,$62,$78,$7A
DB $34,$FF,$33,$36,$FF,$35,$32,$31
DB $2C,$20,$2E,$6E,$FF,$6D,$2F,$FF
DB $72,$FF,$65,$79,$FF,$74,$77,$71
DB $39,$FF,$30,$37,$7E,$38,$FF,$FF
DB $66,$68,$64,$FF,$FF,$67,$73,$61
DB $4C,$4A,$3A,$FF,$FF,$4B,$FF,$FF ; SHIFTED
DB $4F,$FF,$50,$55,$9B,$49,$2D,$FF
DB $56,$FF,$43,$FF,$FF,$42,$58,$5A
DB $24,$FF,$23,$36,$FF,$35,$22,$21
DB $2C,$20,$2E,$4E,$FF,$4D,$3F,$FF
DB $52,$FF,$45,$59,$FF,$54,$57,$51
DB $39,$FF,$30,$27,$7E,$38,$FF,$FF
DB $46,$48,$44,$FF,$FF,$47,$53,$41
END