mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-01-11 23:43:24 +00:00
539 lines
10 KiB
Plaintext
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
|
|
|