Files
erkyrath.infocom-zcode-terps/acorn/io.asm
Andrew Plotkin b642da811e Initial commit.
2023-11-16 18:19:54 -05:00

445 lines
7.5 KiB
NASM

PAGE
SBTTL 'GAME I/O'
;INTERNAL ERROR
;ENTRY: ERROR CODE IN A
ERRM: DB "INTERNAL ERROR "
ENUMB: DB "00."
ERRML EQU $-ERRM
ZERROR: LDY #1 ;CONVERT ERROR BYTE IN A
ECON: JSR DIV10 ;TO ASCII DECIMAL IN ENUMB
ORA #'0' ;DIV10 RETS REMAINDER IN A (LSD)
STA ENUMB,Y
TXA ;AND QUOTIENT IN X (WILL BE MSD)
DEY
BPL ECON ;DO BOTH DIGITS
JSR ZCRLF ;CLEAR BUFFER
LDA #0
STA SCRIPT ;DISABLE SCRIPTING
LDX #LOW ERRM ;PRINT MSG
LDA #HIGH ERRM
LDY #ERRML
JSR DLINE
;FALL THROUGH ...
;QUIT/RESTART
ZSTART: ;FLUSH BUFFER, DEMAND <RET> TO RESTART, GO TO WARM START
JSR ZCRLF ;FLUSH BUFFER
LDX #LOW TORES
LDA #HIGH TORES
LDY #TORESL
JSR DLINE ;"PRESS <RET> TO RESTART"
JSR GETRET ;WAIT FOR <RET>
JMP WARM1 ;AND DO WARMSTART
TORES: DB "End of story."
DB EOL
DB "Press <RETURN> to restart."
DB EOL
TORESL EQU $-TORES
ZQUIT EQU ZSTART ;0-OP
;PRINT VERSION #
VERS: DB "ACORN Version A"
DB EOL
VERSL EQU $-VERS
VERNUM: JSR ZCRLF ;CLEAR BUFFER
LDX #LOW VERS
LDA #HIGH VERS
LDY #VERSL
JMP DLINE ;DISPL VERSION # (RET TO CALLING FROM DLINE)
;************************
;RETURN TOP RAM PAGE IN A
;************************
MEMTOP: LDA #$7B ;IT'S A GIVEN
RTS
;****************************
;RETURN RANDOM BYTES IN A & X
;****************************
RANDOM: LDA #3 ; READ INTERVAL TIMER
LDX #LOW CLOCK
LDY #HIGH CLOCK
JSR OSWORD
LDA CLOCK
ADC RAND1
TAX
LDA CLOCK+1
SBC RAND2
STA RAND1
STX RAND2
CLC
RTS
; CLOCK = LSB, CLOCK+4 = MSB
CLOCK: DB 0,0,0,0,0
;*******************
;Z-PRINT A CHARACTER MOVE A (1) CHAR TO LBUFF, IF EOL REACHED
;******************* (CHAR OR ACTUAL), DISPLAY/PRINT LINE
;ENTRY: ASCII CHAR IN A
COUT: CMP #EOL ;IF EOL
BNE COUT1
JMP ZCRLF
COUT1: CMP #SPACE ;IGNORE ALL OTHER CONTROLS
BCC CEX ;(OUT)
COUT2: LDX LENGTH ;ELSE GET LINE POINTER
STA LBUFF,X ;ADD CHAR TO BUFFER
CPX #XSIZE ;END OF LINE?
BCC COUT3
JMP FLUSH
COUT3: INC LENGTH ;ELSE UPDATE POINTER
CEX: RTS
;*******************
;FLUSH OUTPUT BUFFER - PRINT UP THRU LAST FULL WORD (MARKED BY BLANK)
;******************* IF NO BLANK PRINT ENTIRE BUFFR
; MOVE ANY REMAINING CHARS TO TOP OF BUFFER FOR
; NEXT LINE
;ENTRY: LENGTH OF BUFFER IN X
FLUSH: LDA #SPACE
FL0: CMP LBUFF,X ;FIND LAST SPACE CHAR
BEQ FL1 ;IN THE LINE
DEX
BNE FL0
LDX #XSIZE ;IF NONE FOUND, FLUSH ENTIRE LINE
FL1: STX OLDLEN ;SAVE OLD LINE END POS HERE
STX LENGTH ;MAKE IT NEW LINE LENGTH
JSR ZCRLF ;PRINT LINE UP TO LAST SPACE
;START NEW LINE WITH REMAINDER OF OLD
LDX OLDLEN ;GET OLD LINE POS
LDY #0 ;START NEW LINE AT BEGINNING
FL2: INX
CPX #XSIZE ;CONTINUE IF
BCC FL3 ;INSIDE OR
BEQ FL3 ;AT END OF LINE (ie NOT ENTIRE LINE)
STY LENGTH ;ELSE SET NEW LINE LENGTH TO 0
RTS
FL3: LDA LBUFF,X ;GET CHAR FROM OLD LINE
STA LBUFF,Y ;MOVE TO START OF NEW LINE
INY ;UPDATE LENGTH OF NEW LINE
BNE FL2 ;MOVE ALL CHARS
;**************
;CARRIAGE RETURN
;**************
ZCRLF: INC LINCNT ;NEW LINE GOING OUT
LDA LINCNT ;IS IT TIME TO
CMP #LMAX ;PRINT "MORE" YET?
BCC CR1 ;NO, CONTINUE
;SCREEN FULL; PRINT "MORE"
JSR ZUSL ;UPDATE STATUS LINE
LDX #LOW MORE
LDA #HIGH MORE
LDY #MOREL
JSR DLINE ;DISPLAY "MORE"
JSR OSRDCH ;WAIT FOR ANY CHAR
;ERASE "MORE"
LDY #MOREL ;GET # CHARS DISPLAYED
ZCR0: LDA #BACKSP
JSR OSWRCH ;BACK UP ERASING AS GO
DEY
BNE ZCR0 ;COVER ALL LETTERS
LDA #1
STA LINCNT ;RESET FOR NEW SCREEN FULL
;AND GO DO MORE
CR1: LDX LENGTH
LDA #EOL ;INSTALL EOL AT
STA LBUFF,X ;END OF CURRENT LINE
INC LENGTH ;UPDATE LINE LENGTH
LINOUT: LDY LENGTH ;IF BUFFER EMPTY
BEQ LINEX ;DON'T PRINT ANYTHING
STY PRLEN ;SAVE LENGTH FOR "PPRINT"
LDX #0 ;SEND CONTENTS OF LBUFF TO SCREEN
LOUT: LDA LBUFF,X
JSR CHAR
INX
DEY
BNE LOUT ;DO ALL CHARS
JSR PPRINT ;PRINT LBUFF IF ENABLED
LINEX: LDA #0 ;RESET LINE LENGTH TO TOP
STA LENGTH
RTS ;AND RETURN
MORE: DB "-MORE-"
MOREL EQU $-MORE
;**********************
;UPDATE THE STATUS LINE
;**********************
ZUSL: LDA LENGTH ;SAVE ALL STRING-PRINTING VARIABLES
PHA
LDA MPCH
PHA
LDA MPCM
PHA
LDA MPCL
PHA
LDA TSET
PHA
LDA PSET
PHA
LDA ZWORD+HI
PHA
LDA ZWORD+LO
PHA
LDA ZFLAG
PHA
LDA DIGITS
PHA
LDX #XSIZE
USL0: LDA LBUFF,X ;MOVE CONTENTS OF LBUFF
STA BUFSAV,X ;TO BUFSAV
LDA #SPACE ;CLEAR LBUFF WITH SPACES
STA LBUFF,X
DEX
BPL USL0
LDA #0
STA LENGTH ;RESET LINE LENGTH
STA SCRIPT ;DISABLE SCRIPTING
LDA #RDCPOS ;GET CURSOR POSITION
JSR OSBYTE
STX OLDX ;SAVE REGULAR POSITION OF CURSOR
STY OLDY
LDA #HOME ;HOME CURSOR
JSR VDU
LDA #BLUE ;SET STATUS LINE TO BLUE SO STANDS OUT
JSR COUT ;PLACE COLOR CONTROL IN LBUFF SO WHEN PRINTS
;WILL BE INCLUDED IN LINE COUNT
;(NO NEED TO RESET, COMMAND AFFECTS 1 LINE ONLY)
;MOVE ROOM DESCRIPTION TO LBUFF
LDA #16 ;GLOBAL VAR #16 9ROOM ID)
JSR GETVRG ;GET IT INTO VALUE
LDA VALUE+LO
JSR PRNTDC ;PRINT SHORT ROOM DESC.
LDA #23 ;MOVE LINE INDEX UP
STA LENGTH ;TO TIME/SCORE POSITION
LDA #SPACE
JSR COUT ; OUTPUT A SPACE FOR SAFETY
LDA #17 ;GLOBAL VAR #17 (SCORE/HOURS)
JSR GETVRG ;GET IT INTO VALUE
LDA TIMEFL ;GET MODE FLAG
BNE DOTIME ;USE TIME MODE IF NON-ZERO
;PRINT 'SCORE' (DO BY HAND NO REGISTERS PRESERVED THRU COUT)
LDA #'S'
JSR COUT
LDA #'c'
JSR COUT
LDA #'o'
JSR COUT
LDA #'r'
JSR COUT
LDA #'e'
JSR COUT
LDA #':'
JSR COUT
LDA #SPACE
JSR COUT
LDA VALUE+LO ;MOVE SCORE VALUE
STA QUOT+LO ;INTO QUOT
LDA VALUE+HI ;FOR PRINTING
STA QUOT+HI
JSR NUMBER ;CONVERT TO DECIMAL, MOVE TO LBUFF ("PRINT")
LDA #'/' ;PRINT A SLASH
BNE MOVMIN ;BRANCH ALWAYS
;PRINT 'TIME'
DOTIME: LDA #'T'
JSR COUT
LDA #'i'
JSR COUT
LDA #'m'
JSR COUT
LDA #'e'
JSR COUT
LDA #':'
JSR COUT
LDA #SPACE
JSR COUT
LDA VALUE+LO ;00 IS REALLY 24
BNE DTO
LDA #24
DTO: CMP #13 ;HOURS > 12?
BCC DT1 ;NO, SKIP THIS
SBC #12 ;CONVERT TO 1-12
DT1: STA QUOT+LO ;MOVE FOR PRINTING
LDA #0
STA QUOT+HI ;CLEAR MSB
JSR NUMBER
LDA #':' ;COLON
MOVMIN: JSR COUT ;PRINT SLASH OR COLON
LDA #18 ;GLOBAL VAR #18 (MOVES/MINUTES)
JSR GETVRG ;MOVE TO VALUE
LDA VALUE+LO ;MOVE TO QUOT
STA QUOT+LO
LDA VALUE+HI
STA QUOT+HI
LDA TIMEFL ;WHICH MODE?
BNE DOMINS ;TIME IF NZ
;PRINT # OF MOVES
JSR NUMBER ;CONVERT & MOVE TO LBUFF
JMP STATEX ;ALL DONE
;PRINT MINUTES
DOMINS: LDA VALUE+LO ;CHECK MINUTES
CMP #10 ;IF OVER 10
BCS DOMO ;CONTINUE
LDA #'0' ;ELSE PRINT A
JSR COUT ;PADDING "0" FIRST
DOMO: JSR NUMBER ;CONVERT, MOVE TO PRINT
LDA #SPACE
JSR COUT ;SEPARATE THINGS
LDA #17 ;CHECK 'HOURS' AGAIN
JSR GETVRG
LDA VALUE+LO
CMP #12 ;PAST NOON
BCS DOPM ;YES, "PM"
LDA #'a' ;ELSE "AM"
BNE DOXM ;BRANCH ALWAYS
DOPM: LDA #'p'
DOXM: JSR COUT
LDA #'m'
JSR COUT
;STATUS LINE READY
STATEX: LDA #40 ;PRINT THE ENTIRE STATUS LINE ***LINE LENGTH PROB?****
STA LENGTH
JSR CR1
LDX #XSIZE ;RESTORE OLD LBUFF
USLX: LDA BUFSAV,X
STA LBUFF,X
DEX
BPL USLX ;MOVE ALL CHARS
PLA ;RESTORE ALL SAVED VARIABLES
STA DIGITS
PLA
STA ZFLAG
PLA
STA ZWORD+LO
PLA
STA ZWORD+HI
PLA
STA PSET
PLA
STA TSET
PLA
STA MPCL
PLA
STA MPCM
PLA
STA MPCH
PLA
STA LENGTH
;RESTORE CURSOR
LDA #MVTXC ;MOVE TEXT CURSOR
JSR VDU
LDA OLDX ;TO OLD COORDINATES
JSR VDU
LDA OLDY
JSR VDU
LDX #$FF
STX SCRIPT ;RE-ENABLE SCRIPTING
INX
STX MPCFLG ;(0) INVALIDATE MPC
RTS
;****************
;DIVIDE [A] BY 10
;****************
;EXIT: QUOTIENT IN X, REMAINDER IN A
DIV10: LDX #0 ;START WITH ZERO QUOTIENT
D10L: CMP #10 ;IF DIVISOR < 10,
BCC D10EX ;WE'RE DONE
SBC #10 ;ELSE SUBTRACT ANOTHER 10
INX ;UPDATE QUOTIENT
BNE D10L ;BRANCH ALWAYS
D10EX: RTS
END