Files
Andrew Plotkin b642da811e Initial commit.
2023-11-16 18:19:54 -05:00

1484 lines
29 KiB
NASM
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
; PAGE
STTL "--- GAME I/O: C128 ---"
; --------------
; INTERNAL ERROR
; --------------
; ENTRY: ERROR CODE IN [A]
; EXIT: HA!
ERRM: DB "Internal error "
ENUMB: DB "00. "
ERRML EQU $-ERRM
ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A]
ZERR0: LDX #0 ; TO ASCII AT "ENUMB"
ZERR1: CMP #10
BCC ZERR2
SBC #10
INX
BNE ZERR1
ZERR2: ORA #'0'
STA ENUMB,Y
TXA
DEY
BPL ZERR0
LDA TOP
STA WTOP ; SCROLL NOT
JSR ZCRLF ; CLEAR BUFFER
LDX #<ERRM
LDA #>ERRM
LDY #ERRML
JSR DLINE ; PRINT ERROR MESSAGE
; FALL THROUGH
; ----
; QUIT
; ----
ZQUIT: JSR ZCRLF ; FLUSH BUFFER
LDA TOP ; AND IF ENTER HERE
STA WTOP ; SCROLL ONLY WHAT SHOULD
LDX #<ENDM
LDA #>ENDM
LDY #ENDML
JSR DLINE ; "END OF STORY"
FREEZE: JMP FREEZE
; -------
; RESTART
; -------
ZSTART: JSR ZCRLF ; FLUSH BUFFER
LDA TOP ; AND IF ENTER HERE
STA WTOP ; SCROLL ONLY WHAT SHOULD
LDX #<RSTRT
LDA #>RSTRT
LDY #RSTRTL
JSR DLINE
DOWARM: JSR GETRET
LDX #0
STX WTOP ; RESET FULL SCREEN FOR CLEAR
REX: JSR SIDE1 ; NEED SIDE 1 AGAIN
JMP WARM1 ; AND DO WARMSTART
ENDM: DB "End of session."
DB EOL
ENDML EQU $-ENDM
RSTRT: DB "Press [RETURN] to restart."
DB EOL
RSTRTL EQU $-RSTRT
; --------------------------
; RETURN TOP RAM PAGE IN [A]
; --------------------------
MEMTOP: LDA #$FB ; FOR NOW, ASSUME LAST "BUFFER"
RTS ; OF AUX MEMORY
; -------------------
; Z-PRINT A CHARACTER
; -------------------
; ENTRY: ASCII CHAR IN [A]
;
; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH,
; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN
; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME
; (DIROUT CHANGES 6/24/85)
COUT: STA IOCHAR ; HOLD IT A SEC
LDX TABLEF ; OUTPUT TO TABLE?
BEQ COUT4 ; NO
JMP TBLRTN ; YES, DO IT (TBL ONLY 4.7.86)
COUT4: LDX SCREENF ; OUTPUT TO SCREEN?
BNE COUT5 ; YES
LDX SCRIPTF ; OUTPUT TO PRINTER?
BNE COUT5 ; YES
RTS ; NO, SO DONE
COUT5: LDA IOCHAR ; RETRIEVE CHAR
LDX BUFFLG ; UNBUFFERED OUTPUT?
BNE UNBUFR ; YES, PLACE ON SCREEN IMMED.
CMP #EOL ; IF ASCII EOL,
BNE COUT3
JMP ZCRLF ; DO IT
COUT3:
LDX CHRCNT ; GET LINE POINTER
STA LBUFF,X ; ADD CHAR TO BUFFER
INC CHRCNT
LDY SPLITF ; don't wrap if we are in SC 1
BNE CEX ; okay, I won't
INC LENGTH ; ELSE UPDATE
LDY LENGTH ; GET LINE LENGTH COUNTER
CPY XSIZE ; END OF SCREEN LINE?
BNE CEX
JMP FLUSH ; YES, FLUSH THE LINE
CEX: RTS
; --------------------------
; DIRECT, UNBUFFERED DISPLAY
; --------------------------
UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT
SEC
JSR PLOT
CPY #80 ; CHECK IF BEYOND SCREEN
BCS UNBEX ; YES, LEAVE
LDA SPLITF ; CHECK WHICH WINDOW
BEQ UNBBOT ; BOTTOM WINDOW
CPX TOP ; CHECK IF WITHIN WINDOW
BCS UNBEX ; NO, JUST LEAVE
BCC UNBDIS ; YES, GO DISPLAY
UNBBOT: CPX TOP
BCC UNBEX ; NOT WITHIN WINDOW, LEAVE
UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN?
BEQ UNBPRN ; NO, CHECK IF PRINTING
UNBD: LDA IOCHAR
JSR CHAR ; DO VOODOO AND DISPLAY
UNBPRN: LDA SPLITF ; SPLIT (NON-TEXT) SCREEN
BNE UNBEX ; DON'T PRINT
;SEND CHAR TO PRINTER
LDA #1 ; SET FOR PRINT RTN
STA PRLEN
LDA IOCHAR
STA LBUFF
JSR PPRINT ; AND GO ATTEMPT IT
LDA #0 ; MAKE SURE NO LEFTOVER
STA PRLEN
UNBEX: RTS
; ---------------
; OUTPUT TO TABLE
; ---------------
TBLRTN: TAX ; HOLD CHAR A SEC.
;PUT BYTE IN TABLE AT CURRENT OFFSET
LDA DIRITM+LO ; ADD IN OFFSET
CLC
ADC DIRTBL+LO
STA I+LO
LDA DIRITM+HI
ADC DIRTBL+HI
STA I+HI
LDY #0
TXA ; PICK UP ASCII CHAR
STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @
;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER
INC DIRITM+LO ; INC OFFSET TO NEXT BYTE
BNE TBLRTS
INC DIRITM+HI
TBLRTS: RTS
; -------------------
; FLUSH OUTPUT BUFFER
; -------------------
; ENTRY: LENGTH OF BUFFER IN [X]
FLUSH:
LDA #SPACE ; SPACE
STX OLDEND ; SAVE CURRENT END OF LINE
FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR
BEQ FL1 ; IN THE LINE
DEX
BNE FL0 ; IF NONE FOUND,
LDX XSIZE ; FLUSH ENTIRE LINE
FL1: STX OLDLEN ; SAVE OLD LINE POS HERE
STX CHRCNT ; MAKE IT THE 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 OLDEND ; CONTINUE IF
BCC FL3 ; INSIDE OR
BEQ FL3 ; AT END OF LINE
STY LENGTH ; ELSE SET NEW LINE LENGTH
STY CHRCNT
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 ; (ALWAYS)
; ---------------
; CARRIAGE RETURN
; ---------------
ZZCRLF:
LDX TABLEF ; OUTPUT TO TBL?
BEQ ZCRLF ; NO
LDA #EOL ; INSTALL EOL
JMP TBLRTN ; YES, DO IT (TBL ONLY)
ZCRLF:
LDA #EOL ; INSTALL EOL
LDX CHRCNT
STA LBUFF,X ; END OF CURRENT LINE
INC CHRCNT ; UPDATE LINE LENGTH
LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN
BEQ ZCRLFX ; NO, GO HANDLE IF PRINTING
LDA SPLITF ; AT SPLIT SCREEN
BNE ZCRLFX ; YES
INC LINCNT ; NEW LINE GOING OUT
ZCRLF0: LDX LINCNT ; IS IT TIME TO
CPX WBOTM ; PRINT "MORE" YET?
BCC ZCRLFX ; NO, CONTINUE
BEQ ZCRLFX ; NO, CONTINUE
LDA TOP
STA LINCNT ; RESET LINE COUNTER
INC LINCNT ; LEAVE 1 LINE ON SCREEN
INC LINCNT ; and leave last line from previous screen
SEC
JSR PLOT ; GET CURSOR POSITION
STY OLDX
STX OLDY
LDX WBOTM ;#23
LDY ZBEGIN+ZLMRG+1 ; SET LEFT MARGIN
CLC
JSR PLOT ; BOTTOM LEFT OF SCREEN
LDA #146 ; IF GET HERE INVERSE
JSR CHROUT ; SHOULD BE OFF SO TURN OFF
LDX #<MORE
LDA #>MORE
LDY #MOREL
JSR DLINE ; PRINT MORE DIRECTLY
LDA #0
STA NDX ; CLEAR INPUT QUEUE
ZCR0: JSR GETIN ; GET ANY KEYPRESS
TAX
BEQ ZCR0
LDX WBOTM ;#23
LDY ZBEGIN+ZLMRG+1
CLC
JSR PLOT ; RESTORE CURSOR
LDX #<MCLR
LDA #>MCLR
LDY #MOREL
JSR DLINE ; RUB OUT "MORE"
LDY OLDX
LDX OLDY
CLC
JSR PLOT ; RESTORE CURSOR
ZCRLFX: JSR LINOUT ; DISPLAY LINE
JSR CHKFNC ; CHECK FOR [CR] FUNCTION (XZIP)
LDA #0
STA LENGTH ; AND RESET LINE COUNT
STA CHRCNT ; new line, new chars,
RTS
LINOUT: LDY CHRCNT ; IF BUFFER EMPTY,
BEQ LINEX ; DON'T PRINT ANYTHING
STY PRLEN ; SAVE LENGTH HERE FOR "PPRINT"
LDA SCREENF ; DISPLAY TO SCREEN?
BEQ LOUT1 ; NO, GO CHECK IF PRINT
LDA WTOP
PHA
LDA SPLITF
BNE LOUT2 ; NON SCROLLING SCREEN
LDA TOP
STA WTOP
LOUT2: LDY CHRCNT ; how many to send
LDX #0 ; where to start sending
LOUT: LDA LBUFF,X ; TO SCREEN
JSR CHAR
INX
DEY
BNE LOUT
PLA ; RESET FOR FULL SCREEN ACCESS
STA WTOP
LOUT1: LDA SPLITF
BNE LINEX ; NON SCROLLING SCREEN
JSR PPRINT ; PRINT [LBUFF] IF ENABLED
LINEX:
RTS ; AND RETURN
;
; CHECK IF THERE IS A PENDING FUNCTION CALL ASSOCIATED WITH <CR>'S
;
CHKFNC: LDA ZBEGIN+ZCRCNT+0 ; IF NULL IGNORE
ORA ZBEGIN+ZCRCNT+1
BEQ CHKDUN
LDA ZBEGIN+ZCRCNT+1 ; DECR COUNTER
SEC
SBC #1
STA ZBEGIN+ZCRCNT+1
LDA ZBEGIN+ZCRCNT+0
SBC #0
STA ZBEGIN+ZCRCNT+0
LDA ZBEGIN+ZCRCNT+1 ; IF NULL NOW, CALL FCN
ORA ZBEGIN+ZCRCNT+0
BNE CHKDUN
LDA ZBEGIN+ZCRFUNC+1 ; SET UP FUNCTION
STA J+LO
LDA ZBEGIN+ZCRFUNC+0
STA J+HI
JSR INTCLL ; DO FUNCTION CALL
CHKDUN: RTS
; ----------------------
; UPDATE THE STATUS LINE
; ----------------------
; NOT APPLICABLE IN EZIP.
ZUSL: RTS
; ------
; VERIFY
; ------
; VERIFY GAME CODE ON DISK
ZVER: LDA TOP ; SET SO MSG'S DON'T SCROLL
STA WTOP ; OVER STATUS LINES
JSR ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1
LDX #3
LDA #0
ZVR: STA K+LO,X ; CLEAR [K], [L]
STA MPC,X ; [MPC] AND [MPCFLG]
DEX
BPL ZVR
LDA #64 ; POINT [MPC] TO Z-ADDRESS $00040
STA MPCL ; 1ST 64 BYTES AREN'T CHECKED
LDA ZBEGIN+ZLENTH ; GET MSB
STA I+HI ; AND
LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES
ASL A ; MULTIPLY BY
ROL I+HI ; FOUR
ROL K+LO
ASL A
STA I+LO
ROL I+HI ; TO GET # BYTES
ROL K+LO ; IN GAME
LDA #0 ; START AT BEGINNING
STA DBLOCK+LO
STA DBLOCK+HI
JMP READIN ; READ FIRST BLOCK IN
VSUM: LDA MPCL ; NEW PAGE?
BNE VSUM2 ; NO, CONTINUE
READIN: LDA #>IOBUFF ; FAKE READ OUT SO
STA DBUFF+HI ; IT DOESN'T MOVE BUFFER
LDA #MAIN
STA DSKBNK ; SET FOR MAIN BANK
JSR GETDSK ; GO READ A PAGE
BCC VSUM2
JMP DSKERR ; BAD DISK!!!!!
VSUM2: LDY MPCL ; GET THIS BYTE
LDA IOBUFF,Y
INC MPCL ; SET FOR NEXT BYTE
BNE VSUM3
INC MPCM
BNE VSUM3
INC MPCH
VSUM3: CLC
ADC L+LO ; ADD IT TO SUM
STA L+LO ; IN [J]
BCC VSUM1
INC L+HI
VSUM1: LDA MPCL ; END OF Z-CODE YET?
CMP I+LO ; CHECK LSB
BNE VSUM
LDA MPCM ; MIDDLE BYTE
CMP I+HI
BNE VSUM
LDA MPCH ; AND HIGH BIT
CMP K+LO
BNE VSUM
LDA #0 ; RESET SCREEN ROLL
STA WTOP ; TO INDIVIDUAL CONTROL
LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM
CMP L+LO ; DOES IT MATCH?
BNE BADVER ; NO, PREDICATE FAILS
LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB
CMP L+HI ; LOOK GOOD?
BNE BADVER ; IF MATCHED,
JMP PREDS ; GAME IS OKAY
BADVER:
JMP PREDF
; ------
; BUFOUT
; ------
; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE
; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO
ZBUFOUT: LDX ARG1+LO
BNE ZBUF1 ; SET TO BUFFERED OUTPUT
JSR CLRBUF ; CLEAR OUTPUT BUFFER
LDX #1
STX BUFFLG ; SET FUTURE OUTPUT TO BE UNBUFFERED
RTS
ZBUF1: DEX
BNE ZBUFEX ; INVALID
STX BUFFLG ; SET TO BUFFERED
ZBUFEX: RTS
; CLEAR OUTPUT BUFFER BEFORE DOING ANY FANCY DISPLAY
CLRBUF: JSR LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT)
LDX #0
STX CHRCNT
RTS
; ------
; DIROUT
; ------
; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT
; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT
; MULTIPLE DEVICE USAGE IS POSSIBLE.
ZDIRT: LDX ARG1+LO
BMI DIRRES ; NEGATIVE VALUE, DESELECTING
DEX
BEQ DIR1 ; 1 = SET OUTPUT TO SCREEN
DEX
BEQ DIR2 ; 2 = SCRIPTING
DEX
BEQ DIR3 ; 3 = TABLE
DEX
BEQ DIR4 ; 4 = RECORDING DEVICE (NOT IMPLEMENTED)
DIR4: RTS ; INVALID VALUE
DIRRES: INX
BEQ DRES1 ; -1 = RESET TO SCREEN
INX
BEQ DRES2
INX
BEQ DRES3
INX
BEQ DRES4
DRES4: RTS ; INVALID VALUE, JUST LEAVE
DIR1: INX ; 1, TURN SCREEN OUTPUT ON
STX SCREENF
RTS
DRES1:
; JSR CLRBUF ; don't do this (eh?)
STX SCREENF ; 0, TURN SCREEN OFF
RTS
DIR2: INX
STX SCRIPTF ; SET SCRIPT FLAG ON
LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO
ORA #%00000001
STA ZBEGIN+ZSCRIP+1
RTS ; YES, READY TO LEAVE
DRES2: STX SCRIPTF ; TURN PRINTER OFF
LDA ZBEGIN+ZSCRIP+1 ; AND TURN OFF GAME FLAG TOO
AND #%11111110
STA ZBEGIN+ZSCRIP+1
RTS
DIR3: INX
STX TABLEF ; TURN TABLE OUTPUT FLAG ON
LDA ARG2+HI ; SET UP TBL
CLC
ADC ZCODE
LDX ARG2+LO ; TO STORE CHARS IN
STX DIRTBL+LO
STA DIRTBL+HI
LDA #2
STA DIRITM+LO
LDA #0
STA DIRITM+HI
RTS
DRES3: LDA TABLEF ; IF ALREADY OFF
BEQ DROUT ; LEAVE AS IS
STX TABLEF ; TURN TBL OUTPUT OFF
LDA DIRITM+LO ; MARK END OF CHARS IN TBL
CLC ; WITH A NULL CHAR
ADC DIRTBL+LO
STA I+LO
LDA DIRITM+HI
ADC DIRTBL+HI
STA I+HI ; ALIGNED AT EOL
LDA #0
TAY
STA (I),Y ; PLACE 0 IN TBL
LDY #1 ; GET CHAR COUNT
LDA DIRITM+LO ; (2 LESS THAN [DIRITM])
SEC
SBC #2
STA (DIRTBL),Y
BCS RESET0
DEC DIRITM+HI
RESET0: LDA DIRITM+HI
DEY
STA (DIRTBL),Y ; STORE CHAR COUNT IN TBL
LDA #0 ; CLEAR COUNT FOR NEXT TIME
STA DIRFLG ; SET OUTPUT TO SCREEN
DROUT: RTS
; ------
; CURSET
; ------
; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW
; AND AT COLUMN (ARG2)
ZCURST:
JSR CLRBUF
LDX ARG1+LO ; GET LINE
DEX ; ZERO ALIGN IT
LDY ARG2+LO ; GET COLUMN
DEY ; ZERO ALIGN IT
CLC
JMP PLOT ; MOVE THE CURSOR
; ------
; CURGET
; ------
ZCURGT: LDA ARG1+LO
STA I+LO
LDA ARG1+HI
CLC
ADC ZCODE ; ABSOLUTE
STA I+HI
SEC
JSR PLOT
INX
INY ; 1 ALIGN
TYA ; NOW SLIP CURSOR POSITION
LDY #3 ; INTO PLACE TO RETURN IT
STA (I),Y
DEY
LDA #0
STA (I),Y
DEY
TXA
STA (I),Y
DEY
LDA #0
STA (I),Y
RTS
; -----
; DIRIN
; -----
; NOT YET IMPLEMENTED, BUT RESERVED
ZDIRIN: RTS
; ------
; HIGHLIGHT
; ------
ZLIGHT: LDX ARG1+LO ; GET CHOICE OF MODE
BNE ZL1
LDA #0 ; turn off inversed
STA RVFLAG ; voila
LDA #146 ; REVERSE OFF
JSR HLIGHT
LDA #130 ; UNDERLINE OFF
JMP HLIGHT
ZLOUT: RTS
ZL1: CPX #1 ; INVERSE?
BNE ZL2
LDA #$12 ; INVERSE
STA RVFLAG ; mark as inversed
JMP HLIGHT
ZL2: CPX #4 ; UNDERLINE?
BNE ZLOUT ; NO OTHER ON C128
LDA #$02 ; UNDERLINE
HLIGHT: STA IOCHAR ; HOLD COMMAND CHAR
LDA TABLEF ; IF IN TBL MODE
BNE DOTBL ; PUT CHAR TO TBL
LDA SCREENF ; IF NOT PRINTING TO
BNE DOLIGHT ; SCREEN OR PRINTER, SKIP THIS
LDA SCRIPTF
BNE DOLIGHT
RTS
DOLIGHT:
LDA IOCHAR
JSR ADDBUF ; add the unprinting char to buffer
RTS
DOTBL: LDA IOCHAR
JMP TBLRTN
; -----
; ERASE
; -----
ZERASE: LDA ARG1+LO
CMP #1
BNE ZEROUT ; INVALID
JSR CLRBUF
SEC ; CLEAR TO END OF LINE
JSR PLOT
STX OLDX
STY OLDY
ZERLP: INY
CPY #80
BCS ZERDUN
LDA #SPACE
JSR CHROUT
JMP ZERLP
ZERDUN: LDX OLDX ; RESET CURSOR
LDY OLDY
CLC
JSR PLOT
ZEROUT: RTS
; -----
; CLEAR
; -----
ZCLR: JSR CLRBUF
SEC ; READ CURRENT POSITION
JSR PLOT
STY OLDY
STX OLDX
LDA ARG1+LO ; CHECK WHAT TO DO
BEQ CLR0 ; BOTTOM SCREEN
CMP #1
BEQ CLR1 ; TOP SCREEN
CMP #$FF
BNE ZEROUT ; INVALID
; UNSPLIT SCREEN & CLEAR IT
JSR NORL ; RESET TO FULL
LDA #CLS ; & CLEAR IT
JSR CHROUT
RTS
CLR0: LDA WTOP ; KEEP
PHA
LDA TOP ; SET COUNT
STA LINCNT ; FOR "MORE"
STA WTOP ; AND PROPER WINDOW TOP
LDA #CLS ; CLEAR & HOME
JSR CHROUT
PLA
STA WTOP
LDX #0
JMP SETOLD
CLR1: LDA WBOTM
PHA
LDY #0 ; TOP OF SCREEN
STY WTOP
LDX TOP
STX WBOTM ; MAKE BOTTOM OF TOP SCREEN
LDA #CLS
JSR CHROUT
PLA ; RESET TOP & BOTTOM
STA WBOTM
LDX #1 ; SET SO NEXT TIME INTO WINDOW TOP LEFTS
SETOLD: LDA #0
STA OLD0Y,X
STA OLD0X,X
CPX SPLITF ; IF IN WINDOW JUST CLEARED
BEQ CLROUT ; LEAVE CURSOR TOP LEFT
LDX OLDX ; OTHERWISE SET CURSOR
LDY OLDY ; BACK WHERE IT WAS
CLC
JMP PLOT
CLROUT: RTS
; ------
; PRINTT
; ------
; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES
; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT
ZPRNTT: LDA ARG1+LO ; USE GETBYT AS TBL COULD
STA MPCL ; BE ANYWHERE
LDA ARG1+HI
STA MPCM
LDA #0
STA MPCH
JSR VLDMPC
LDA ARG2+LO ; ONLY A BYTE AS MAX
CMP #0
BEQ PTTDUN ; QUIT NOW IF NULL
STA J+HI ; SCREEN WIDTH IS 80
STA J+LO
DEC NARGS
LDA NARGS
CMP #1
BEQ NOHIGHT ; DEFAULT HEIGHT IS 1
LDA ARG3+LO ; & SCREEN LENGTH MAX IS 25
NOHIGHT: STA K+LO
LDA SPLITF ; don't clear in window 0
BEQ PTTj ; cuz we are wrapping
;
; 5/6/87 jdarnold -- flush the buffer to send out anything that is
; ready to go
JSR CLRBUF
PTTj:
SEC ; GET CURSOR POS & SAVE
JSR PLOT
STX OLDX
STY OLDY
PTTLP: JSR GETBYT ; GET A BYTE
JSR COUT ; use cout to do wrapping if necessary
; JSR UNBUFR ; AND PUT IT TO SCREEN
DEC J+LO
BNE PTTLP
PASTX: DEC K+LO ; IF DONE ALL LINES
BEQ PTTDUN ; LEAVE
INC OLDX ; TO NEXT LINE
LDY OLDY
LDX OLDX
CLC
JSR PLOT ; PLACE CURSOR ON NEXT LINE
LDA J+HI ; RESET COUNT
STA J+LO
JMP PTTLP ; GO DO NEXT LINE
PTTDUN: RTS
; ------------
; SET NEW FONT
; ------------
ZFONT:
LDA ARG1+LO ; CHECK WHICH FONT
;
; need to check CURRENT font, not font for this window
;
LDX SPLITF ; get old font
CMP FONT,X
BEQ ZFRET ; don't bother changing if the same
JSR CHFONT ; go change it
BCS ZFBAD ; but we had problems!
ZFRET:
LDX SPLITF ; get old font
LDA FONT,X ; for returning
PHA
LDA ARG1+LO
STA FONT,X ; REMEMBER NEW FONT FOR NEXT TIME
PLA
LDX #0
JMP PUTVAL ; RETURN PREVIOUS FONT
ZFBAD:
JMP RET0 ; TELL IT DOESN'T WORK
;
; change to the font located in [A]
; Set the carry if there are any problems
;
CHFONT:
CMP #4
BEQ CFONT4
CMP #3
BEQ CFONT3
CMP #1
BEQ CFONT1
JMP CFBAD ; NO OTHER OPTIONS AVAILABLE
; MAY BE A PROBLEM WITH SETTING SPACE CHAR TO SOMETHING ELSE
; AS ALL SPACES MAY BECOME THAT CHAR WHEN SWITCH TO GRAPHICS
; MODE, BUT THAT SHOULD NOT HAPPEN CAUSE CLEAR WITH UP/LOW
; SPACE AND THAT IS WHAT IS ON SCREEN SO IF DON'T TRY TO USE
; NORMAL CHARS (INCL CLEAR) WHILE SET UP FOR FONT3 & FONT4
; SHOULD BE NO PROBLEM
CFONT1:
LDA RVFLAG ; was inverse on?
BEQ FNT1 ; nope
LDA #$12 ; we must turn it back on
JMP FNT1a ; and change font
FNT1:
LDA #$92 ; turn inverse off
FNT1a:
JSR ADDBUF ; make inverse state correct
LDA #$0E ; SET UPPER/LOWER CHAR SET ON
JMP FOUT
CFONT3:
LDA F3FLG ; CHECK IF FONT3 HAS BEEN LOADED IN
BNE CFBAD ; NO, WAS NOT ON DISK, RET FAIL
; FONT 3 IS IN PLACE OF NORMAL UPPER/GRAPHICS CHAR SET
LDA #$92 ; turn off reverse video
JSR ADDBUF
LDA #$8E ; SET UPPER/GRAPHICS SET
JMP FOUT
CFONT4:
LDA F4FLG ; CHECK FOR FONT 4
BNE CFBAD
; FONT 4 IS IN PLACE OF INVERSE UPPER/GRAPHICS SET
LDA #$8E ; upper/graphics set
JSR ADDBUF
LDA #$12 ; turn on inverse
FOUT:
JSR ADDBUF ; add font switch to output
CFRET:
CLC ; going just fine
RTS
CFBAD:
SEC ; sorry, but problems!
RTS
;
; 6/3/87 jdarnold -- add Non-printable chars to output buffer
;
ADDBUF:
LDX BUFFLG ; is it unbuffered?
BEQ ADB1 ; no, it is bufferin'
JMP CHAR ; send it out
ADB1:
LDX CHRCNT ; BUFFERED, PLACE
STA LBUFF,X ; DISPLAY BUFFER
INX ; INC CHRCNT
STX CHRCNT ; and save it
CPX #50 ; flush after 80 chars, please
BCC ADBR
JSR CLRBUF ; so get rid of it, please
ADBR:
RTS
; ---------------------
; FETCH A LINE OF INPUT
; ---------------------
;
; 5/11/87 jdarnold -- major change of this input routine; here's how it goes
; start cursor and time
; check for key
; if no key, check for cursor blink and time out
; if key, display it, and do blink and time out check
;
; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1]
; EXIT: # CHARS READ IN [A]
INPUT: JSR CLRBUF ; FLUSH [LBUFF]
LDA #0 ; RESET LINE COUNT
STA BRKCHR
STA I+HI ; clear local variables
STA I+LO
STA J+HI
STA J+LO
STA NDX ; CLEAR INPUT QUEUE
LDY #0 ; GET length stuff
LDA (RDTBL1),Y ; get maximum size of buffer
CMP #79 ; IF OVER 78, CUT DOWN TO 78
BCC STORIT ; LEAVE IT AS IT IS, IT IS LESS
LDA #78
STORIT:
STA CHRMAX ; and save it
LDY #1
LDA (RDTBL1),Y ; get current offset into buffer
TAX ; get so we can inc it
INX ; and not
INX ; count the 2 info-bytes
STX CHARCNT ; save how many chars out there
LDY TOP
STY LINCNT ; RESET LINE COUNT
JSR STCUR ; start the cursor
LDA NARGS ; CHECK IF TIME LIMIT (EZIP)
CMP #2
BEQ INP0 ; NO
LDA ARG3+LO ; GET DELAY WANTED
STA I+HI
LDA NARGS ; IS THERE A FCN?
CMP #4
BNE INP4 ; NO
LDA ARG4+LO ; YES, SET IT
STA J+LO
LDA ARG4+HI
STA J+HI
INP4: LDA I+HI
STA I+LO ; RESET EA TIME THRU
INP0:
LDA #250 ; = 7, TIME COUNTS UP
STA TIME
INP1:
JSR GETIN ; do we have a key?
CMP #0 ; 1 is yes
BNE INPJ1
INP15:
JSR TOGCUR ; toggle the cursor?
LDA TIME ; how's the time?
BNE INP1 ; still time left
JMP INP6 ; .1 sec, check for timeout
INP6: LDA I+LO ; check for i/o timer
BEQ INP0 ; no timer, just continue waiting
DEC I+LO
BNE INP0 ; SOME TIME LEFT, TRY AGAIN
; TIME OUT, CHECK IF THERE IS A FCN TO CALL
JSR OFFCUR ; turn off cursor, if necessary
LDA J+LO ; IS THERE A FCN
ORA J+HI
BNE INP3
JMP ENDIN ; NO FCN, LEAVE WITH NOTHING
INP3: JSR INTCLL ; INTERNALLY CALL THE FCN
LDA VALUE+LO ; CHECK RESULTS
BEQ INPCNT ; return == 0, so continue
JMP ENDIN ; != 0, so ABORT!
INPCNT:
LDA LINCNT ; see if anything got printed out
CMP TOP ; if ==, then nothing new
BEQ INPCNTj ; nope
JSR FLUSHRD ; send out input so far typed
INPCNTj:
JSR STCUR ; turn cursor back on
JMP INP4 ; and start timer over
INPJ1:
JSR GOTKEY ; OK, GO DO THE VOODOO
CMP #0 ; if == 0, not a good key
BNE INPJ2
JMP AGAIN ; don't use the bad key
INPJ2:
JSR ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY
BCS NOTYET
STA BRKCHR ; save for later
JSR OFFCUR ; make sure the cursor is off
LDA BRKCHR
CMP #EOL
BEQ ENDLIN ; PUT EOL TO SCREEN
JMP ENDIN ; ELSE JUST END
NOTYET:
TAY ; check for function keys
BMI CBAD ; beep for > 127 keys if not terminators
CMP #EOL ; EOL?
BEQ ENDLIN ; LINE DONE IF SO
CMP #BACKSP ; BACKSPACE?
BEQ BACKUP ; SPECIAL HANDLING
LDY CHARCNT ; where do we put char?
CPY CHRMAX ; are we filled up?
BCS CBAD ; boy, am i full
CMP #$80 ; DON'T SHOW FCN KEYS
BCS NOSHOW
SHOWIT:
STA IOCHAR ; save it
JSR CHAR ; SEND TO SCREEN
LDA IOCHAR ; get it back
NOSHOW:
CMP #'A' ; IF CHAR IS UPPERCASE ALPHA,
BCC LEX ; CONVERT TO LOWER CASE
CMP #'Z'+1
BCS LEX
ADC #$20 ; converting away
LEX:
LDY CHARCNT ; where does next char go
STA (RDTBL1),Y ; ADD CHAR TO INPUT BUFFER
INC CHARCNT ; NEXT POSITION IN LINE
AGAIN:
JSR STCUR ; start the cursor again
JMP INP15 ; go back to main loop
;
; HANDLE BACKSPACE
;
BACKUP:
STA BRKCHR ; save it
LDA CHARCNT ; if == 2, then buffer is empty
CMP #2 ; and if not, then we still have room
BEQ CBAD ; JMP to beeping
DEC CHARCNT ; get rid of it
LDA BRKCHR ; go get BS
JSR CHAR ; show <BSP>
JMP AGAIN ; try another one
CBAD: JSR BEEP ; ELSE SCREAM WITH PAIN
JMP AGAIN ; and start anew
;
; HANDLE END OF LINE
;
ENDLIN:
STA BRKCHR ; save the break char
JSR OFFCUR ; make sure the cursor is off
LDA BRKCHR ; get break char back
LDX TOP ; SET TOP SO SCROLLS CORRECTLY
STX WTOP
JSR CHAR ; AND SEND EOL TO SCREEN
INC LINCNT ; count eol out there
LDX #0
STX WTOP ; AND SET BACK TO EASY USE
;
; now, build lbuff so we can send it to the printer if necessary
; but only build it if it is necessary, really!
;
LDA SCRIPT ; find out if we are scripting
BEQ ENDIN ; i guess not
LDA ZBEGIN+ZSCRIP+1 ; check for printing
AND #$01 ; check bit flag
BEQ ENDIN ; no printing, continue on
LDY CHARCNT ; start at end of buffer
LDA #EOL ; and put <CR> in there
STA (RDTBL1),Y
LDX CHARCNT ; fill in backwards
DEX
STX LINLEN ; say how many chars for printing
DEX ; we don't need to count info-bytes here
SLOOP:
LDA (RDTBL1),Y ; get char
STA LBUFF,X ; store char
DEY ; point to next get place
DEX ; point to next lbuff place
BPL SLOOP ; go to some more
SDONE:
JSR CLEARP ; CLEAR OFF FCN KEYS BEFORE PRINTING
JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED
ENDIN:
LDY CHARCNT ; how many chars in buffer
LDA #00 ; show 0 end of line
STA (RDTBL1),Y
DEY ; DON'T INCLUDE info-bytes
DEY ; in the char count
TYA
LDY #1
STA (RDTBL1),Y ; tell caller how many good chars there
LEXBAD: RTS ; INTO [A]
STCUR: ; turn cursor on and start count
SEC
JSR PLOT ; get where we are
STX OLDX ; save old x
STY OLDY ; and the old y
LDA #$E4 ; TURN CURSOR ON
STA ULINE
JSR CHROUT
LDX OLDX ; now move back to original place
LDY OLDY
CLC ; move back to
JSR PLOT ; where we were
LDX #0
STX BLINK+LO ; RESET THE BLINK COUNTER
STX BLINK+HI ; FOR A LONG DELAY
RTS
TOGCUR: ; blink cursor when necessary
INC BLINK+LO ; TIME TO BLINK YET?
BNE TOGNO ; NOT TILL LOWER is ZERO
INC BLINK+HI
LDA BLINK+HI ; and upper is 8
CMP #8
BNE TOGNO
LDA #0 ; reset uppper one
STA BLINK+HI
LDA ULINE
EOR #$C4 ; MAKE _ OR BLANK, SO "BLINKS"
STA ULINE
JSR CHROUT
LDX OLDX
LDY OLDY
CLC
JSR PLOT
TOGNO:
RTS ; goodbye cruel world
OFFCUR: ; just plain turn the cursor off!
LDA #SPACE ; erase with a space
JSR CHROUT ; and then erase it
LDX OLDX
LDY OLDY
CLC
JSR PLOT ; put cursor back there
NOOFF:
RTS
;
; send out the input chars type in so far
;
FLUSHRD:
ldy #1 ; start at 1 to skip junk in front
FRLOOP:
iny ; next char?
cpy CHARCNT ; see if we are full
beq FREND ; nope, still some more
lda (RDTBL1),Y ; get the char
jsr CHAR ; and send it out
jmp FRLOOP
FREND:
lda TOP
sta LINCNT
rts
CHARCNT: DB 0
; ------------------------
; IS IT A TERMINATOR CHAR?
; ------------------------
ISTCHR:
PHA
LDA TCHARS+HI
ORA TCHARS+LO
BEQ ISDUN ; no tchars table
PLA
LDX ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS
BEQ ISCHK ; 0 = NO, GO CHECK LIST
CMP #$80 ; YES, SO CHECK IF PAST 127
BCS ISFND ; YUP
BCC ISNOT
ISCHK:
LDY #0
ISLP:
CMP (TCHARS),Y ; IS CHAR WE HAVE A TCHAR?
BEQ ISFND ; YES
PHA
LDA (TCHARS),Y ; NULL = END OF STRING
BEQ ISDUN
PLA
INY
BNE ISLP ; SHOULD ALWAYS LOOP
ISDUN: PLA ; RETRIEVE CHAR
ISNOT: SEC
RTS ; NOT FOUND
;****
;**** IF FOUND DO YOU WANT IT IN BUFFER? CHECK WITH AND W/OUT, HOW CHANGES
;****
ISFND:
CLC
RTS
; ------------------------
; CLEAR LBUFF FOR PRINTING
; ------------------------
CLEARP: LDY #0
LDX #0
CLRLP: LDA LBUFF,Y
CMP #$80
BCS CLSKIP ; DON'T PRINT FCN KEYS
CMP #00 ; (X) EOL BECOMES 00 IN XZIP
BNE CLRLP0
LDA #$0D ; PRINTER NEEDS $0D
CLRLP0: STA LBUFF,X
INX
CLSKIP: INY
CPY LINLEN
BNE CLRLP ; CHECK ALL CHARS
STX PRLEN ; X = NEW LENGTH FOR PRINT
RTS
; -----
; INPUT
; -----
ZINPUT: LDA ARG1+LO
CMP #1 ; KEYBOARD?
BEQ ZINP7
JMP RET0 ; NO, INVALID
ZINP7: LDA WTOP ; RESET LINE COUNT
STA LINCNT
;
; first, flush anything that is ready to print
;
JSR CLRBUF
LDA #0
STA NDX ; CLEAR INPUT QUEUE
DEC NARGS
BNE ZINP8
JMP ZINP3 ; NO TIME LIMIT
ZINP8: LDA ARG2+LO ; GET DELAY WANTED
STA I+HI
LDA #0 ; SET FCN IF IS ONE
STA J+HI
STA J+LO
DEC NARGS
BEQ ZINP4 ; NO FCN
LDA ARG3+LO
STA J+LO
LDA ARG3+HI
STA J+HI
ZINP4:
JSR STCUR ; turn cursor on
ZINP0:
LDA I+HI
STA I+LO ; RESET EA TIME THRU
ZINP1:
LDA #250 ; = 7, TIME COUNTS UP
STA TIME
ZINP2:
JSR GETIN ; GET A KEY
CMP #0
BNE ZINP25 ; we must have one then
JSR TOGCUR ; see if it is blink time
LDA TIME ; is it .1 second yet
BNE ZINP2 ; no, loop again
JMP ZINP6 ; timeout
ZINP25:
JSR GOTKEY
CMP #0 ; 0 means bad key
BEQ ZINP6
JMP ZINP5 ; [A] NOW HAS PROPER CODE
ZINP6:
DEC I+LO
BNE ZINP1 ; SOME TIME LEFT, TRY AGAIN
; TIME OUT, CHECK IF THERE IS A FCN TO CALL
JSR OFFCUR ; make sure the cursor is off
LDA J+LO ; FCN IN J IF THERE IS ONE
ORA J+HI
BEQ ZINPEX ; NO FCN, SEND 0 FOR FAILED
LDA J+LO ; FCN IN J IF THERE IS ONE
ORA J+HI
JSR INTCLL ; INTERNAL CALL
LDA VALUE+LO ; GET RESULTS
BNE ZINPEX ; ABORT
JSR STCUR ; put cursor back on
BEQ ZINP0 ; TRY AGAIN
ZINP3:
JSR GETKEY ; OK, GO WAIT FOR A KEY
ZINP5:
STA I+LO ; save char
JSR OFFCUR ; make sure the cursor is off, please
LDA I+LO ; go back and get the char
CMP #BACKSP ; GAME EXPECTS ASCII BS
BNE ZINP9
LDA #$08 ; WHICH IS $08
ZINP9: LDX #0
JMP PUTBYT ; RETURN CHAR
ZINPEX: JMP RET0 ; OOPS
INTCLL:
LDA I+HI ; SAVE VALUES FOR CALLING RTN
PHA
LDA J+HI
STA ARG1+HI ; pretend it's arg1 for zcall
PHA
LDA J+LO
STA ARG1+LO ; and here's the low part
PHA
LDX #1
STX NARGS
DEX
STX IRET ; make sure it returns back here!
LDA ZPCL ; now, save this zpc, and put back
PHA
STX ZPCL ; a 0 one to show return to internal
LDA ZPCM ; call
PHA
STX ZPCM
LDA ZPCH
PHA
STX ZPCH
JSR DOCALL
JMP MLOOP ; GO DO FCN
; RETURN FROM FCN WILL COME HERE
ZIRET:
PLA ; GET RID OF RTS FROM ZRET
PLA
PLA ; now get real ZPC
STA ZPCH
PLA
STA ZPCM
PLA
STA ZPCL
JSR VLDZPC
PLA ; RESTORE FOR CALLING RTN
STA J+LO
PLA
STA J+HI
PLA
STA I+HI
RTS ; GO BACK TO CALLER
IN: DB 00,00,00,00,00,00,00,00,00
OUT: DB 00,00,00,00,00,00,00,00,00
QUOT: DB 00,00 ; RDTBL1+4 ; (WORD) QUOTIENT FOR DIVISION
REMAIN: DB 00,00 ; QUOT+2 ; (WORD) REMAINDER FOR DIVISION
MTEMP: DB 00,00 ; REMAIN+2 ; (WORD) MATH TEMPORARY REGISTER
RDFLAG: DB 00 ; TEMP FLAG FOR READ TO USE
QSIGN: DB 00 ; MTEMP+2 ; (BYTE) SIGN OF QUOTIENT
RSIGN: DB 00 ; QSIGN+1 ; (BYTE) SIGN OF REMAINDER
DIGITS: DB 00 ; RSIGN+1 ; (BYTE) DIGIT COUNT FOR "PRINTN"
BLINK: DB 00,00 ; (WORD) COUNT CYCLE BETWEEN CURSOR BLINKS
ULINE: DB 00 ; (BYTE) UNDERLINE VALUE FOR CURSOR
IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL
OLD0Y: DB 0 ; HOLDS WHERE CURSOR WAS WHEN LEFT
OLD1Y: DB 0 ; A WINDOW SO CAN RETURN THERE
OLD0X: DB 0 ; WHEN REENTER THE WINDOW
OLD1X: DB 0 ; (MUST BE IN THIS ORDER!!)
OLDX: DB 0 ; HOLD X & Y TEMPORARILY
OLDY: DB 0
OLDWL: DB 0
OLDWD: DB 0
TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE
ASSVLU: DB 0
BRKCHR: DB 0 ; READ BREAK CHAR
F3FLG: DB 0 ; 0 = FONT 3 IN CHAR RAM 1 = NO FONT 3
F4FLG: DB 0 ; " " " " "
FONT: DB 1,1 ; KEEP TRACK OF CURRENT FONT FOR CHANGES
STRT: DB 0 ; HIGH BYTE OF START ADDR FOR CHAR 48
STRT96: DB 0 ; AND FOR CHAR 64
GCHAR: DB 0 ; FONTS
GEND: DB 0 ; FONTS
ALLFLG: DB 0 ; 1 = ALL CHARS OVER $80 ARE TERMINATORS
PSVFLG: DB 0 ; FOR READ, PRESERVE TBL CONTENTS?
VOCFLG: DB 0 ; FOR READ, WHICH VOCAB TBL TO USE
RVFLAG: DB 0 ; is the normal font inverse? (0=FALSE)
SRHOLD: DB 0,0 ; random spot holder flag
XEXIST: DB 0 ; is there expansion ram?
RESFLG: DB 0 ; have we already loaded it?
ISRBANK: DB 0 ; bank for any internal save/restore stuff
ISRPAGE: DB 0 ; page " " "
ISRFLAG: DB 0 ; to show we are internally saving/restoring
ISAVED: DB 0 ; have we done internal save?
SAVSIZ: DB 0 ; (BYTE) # OF SECTORS PER SAVE
NUMSAV: DB 0 ; (BYTE) # SAVES OF THIS GAME POSSIBLE
MORE: DB "[MORE]"
MOREL EQU $-MORE
MCLR: DB " "
SLOTM: DB EOL
DB "Printer Slot 1-7: "
SLOTML EQU $-SLOTM
STRYM: DB "The story is loading ..."
STRYML EQU $-STRYM
END