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

620 lines
11 KiB
Plaintext

PAGE
SBTTL "--- Z-DOS: CBM PLUS/4 ---"
; ---------------------
; GET Z-BLOCK FROM DISK
; ---------------------
; ENTRY: Z-BLOCK # IN [BLOCK]
; TARGET PAGE IN [DBUFF+HI]
GETDSK: CLD
LDA #8
STA DRIVE ; GAME ALWAYS PLAYS FROM DRIVE #8
LDA DBLOCK+LO
STA DVD+LO
LDA DBLOCK+HI
AND #%00000001 ; FOR 128K VIRTUAL SYSTEM
STA DVD+HI
LDA #0
STA DSOR+HI ; CLEAR MSB
STA DTEMP+LO ; AND [DTEMP]
STA DTEMP+HI
LDX #17 ; 17 SECTORS/TRACK
STX DSOR+LO ; LSB OF DIVISOR
DEX ; (= 16) INIT DIVIDE LOOP INDEX
CLC
DVLP: ROL DVD+LO
ROL DVD+HI
ROL DTEMP+LO
ROL DTEMP+HI
LDA DTEMP+LO
SEC
SBC DSOR+LO
TAY
LDA DTEMP+HI
SBC DSOR+HI
BCC DVLP1
STY DTEMP+LO
STA DTEMP+HI
DVLP1: DEX
BNE DVLP
ROL DVD+LO
ROL DVD+HI ; SHIFT LAST CARRY
LDA DTEMP+LO ; REMAINDER IN [DTEMP]
STA SECTOR ; IS SECTOR ID (0-16)
LDA DVD+LO ; QUOTIENT IN [DVD] IS TRACK ID
CLC
ADC #5 ; Z-CODE STARTS ON TRACK 5
CMP #17 ; BELOW TRACK 17?
BCC DVLP2 ; YES, DONE
CLC
ADC #1 ; ELSE SKIP OVER 17
CMP #36 ; OUT OF RANGE?
BCS TRKERR ; ERROR IF SO
CMP #18 ; IS THIS TRACK 18?
BNE DVLP2 ; NO, DONE
INC SECTOR ; ELSE SKIP OVER
INC SECTOR ; SECTORS 0 & 1
DVLP2: STA TRACK
; LDA DBLOCK+LO ; GET LSB OF BLOCK ID
; AND #%00001111 ; MASK TO GET
; STA SECTOR ; SECTOR # (0-15)
; LDA DBLOCK+HI ; GET MSB OF BLOCK ID
; AND #%00001111 ; MASK OUT GARBAGE IN BITS 7-4
; ASL A ; SHIFT THE LOW NIBBLE
; ASL A ; INTO THE HIGH NIBBLE
; ASL A
; ASL A
; STA TRACK ; AND SAVE IT HERE FOR A MOMENT
; LDA DBLOCK+LO ; GET LSB OF BLOCK ID AGAIN
; AND #%11110000 ; MASK OUT SECTOR #
; LSR A ; SHIFT THE HIGH NIBBLE
; LSR A ; INTO THE LOW NIBBLE
; LSR A
; LSR A
; ORA TRACK ; SUPERIMPOSE NEW HIGH NIBBLE
; CLC
; ADC #5 ; Z-CODE STARTS ON TRACK 5
; CMP #17 ; BELOW TRACK 17?
; BCC TRAKOK ; USE AS-IS IF SO
; CLC ; ELSE SKIP OVER
; ADC #2 ; TRACKS 17 & 18
; CMP #36 ; ANYTHING HIGHER THAN TRACK 35
; BCS TRKERR ; IS AN ERROR
;TRAKOK:STA TRACK
; ENTRY FOR "RESTORE" ([TRACK], [SECTOR] & [DRIVE] PRE-ASSIGNED)
GETRES: CLC ; CARRY CLEAR = "READ BLOCK"
JSR DISK ; GO DO IT!
BCS DSKERR ; ERROR IF CARRY SET
LDY #0 ; MOVE CONTENTS OF [IOBUFF]
GDKL: LDA IOBUFF,Y ; TO THE
STA (DBUFF),Y ; TARGET PAGE IN [DBUFF]
INY
BNE GDKL
INC DBLOCK+LO ; POINT TO NEXT
BNE GDEX ; Z-BLOCK
INC DBLOCK+HI
GDEX: JMP NXTSEC ; POINT TO NEXT SECTOR & PAGE
; --------------------
; PUT [DBLOCK] TO DISK
; --------------------
; ENTRY: [TRACK], [SECTOR] & [DRIVE] ASSIGNED
; PAGE TO WRITE IN [DBUFF]
PUTDSK: LDY #0 ; MOVE PAGE AT [DBUFF]
PTKL: LDA (DBUFF),Y ; INTO
STA IOBUFF,Y ; [IOBUFF] FOR I/O
INY
BNE PTKL
SEC ; CARRY SET = "WRITE BLOCK"
JSR DISK
BCS WRTERR ; CARRY SET IF ERROR
NXTSEC: INC SECTOR ; POINT TO NEXT SECTOR
LDA SECTOR
AND #%00001111 ; OVEFLOWED?
BNE SECTOK ; CONTINUE IF NOT
INC TRACK ; ELSE UPDATE TRACK #
SECTOK: STA SECTOR ; AND SECTOR #
INC DBUFF+HI ; POINT TO NEXT RAM PAGE
WRTERR: RTS
; *** ERROR #12: DISK ADDRESS OUT OF RANGE ***
TRKERR: LDA #12
JMP ZERROR
; *** ERROR #14: DRIVE ACCESS ***
DSKERR: LDA #14
JMP ZERROR
; -----------------------------
; SET UP SAVE & RESTORE SCREENS
; -----------------------------
SAVRES: JSR ZCRLF ; CLEAR THE BUFFER
JSR CLS
LDX #0
STX SCRIPT ; DISABLE SCRIPTING
LDY #0
CLC
JMP PLOT ; HOME CURSOR & RETURN
; -----------------
; DISPLAY A DEFAULT
; -----------------
; ENTRY: DEFAULT (0-8) IN [A]
DEFAL: DB " (Default is "
DEFNUM: DB "*):"
DEFALL EQU $-DEFAL
DODEF: CLC
ADC #'1' ; CONVERT TO ASCII 1-9
STA DEFNUM ; INSERT IN STRING
LDX #LOW DEFAL
LDA #HIGH DEFAL
LDY #DEFALL
JSR DLINE ; PRINT THE STRING
LDA #0
STA NDX ; CLEAR KEY QUEUE
RTS
; -----------------------------
; GET SAVE & RESTORE PARAMETERS
; -----------------------------
POSIT: DB EOL
DB "Position 1-5"
POSITL EQU $-POSIT
WDRIV: DB EOL
DB "Drive 8 or 9"
WDRIVL EQU $-WDRIV
MIND: DB EOL
DB EOL
DB "Position "
MPOS: DB "*; Drive #"
MDRI: DB "*."
DB EOL
DB "Are you sure? (Y or N):"
MINDL EQU $-MIND
INSM: DB EOL
DB "Insert SAVE disk into Drive #"
SAVDRI: DB "*."
INSML EQU $-INSM
YES: DB 'YES'
DB EOL
YESL EQU $-YES
NO: DB 'NO'
DB EOL
NOL EQU $-NO
PARAMS: LDA #WHITE
STA COLOR ; WHITE TEXT
LDX #LOW POSIT
LDA #HIGH POSIT
LDY #POSITL
JSR DLINE ; "POSITION (1-5)"
; GET GAME POSITION
CHANGE: LDA GPOSIT ; SHOW THE CURRENT
JSR DODEF ; DEFAULT POSITION
GETPOS: JSR GETKEY ; WAIT FOR A KEY
CMP #EOL ; IF [RETURN],
BEQ POSSET ; USE DEFAULT
SEC
SBC #'1' ; ELSE CONVERT ASCII TO BINARY
CMP #5 ; IF BELOW "6"
BCC SETPOS ; MAKE IT THE NEW DEFAULT
JSR BOOP ; ELSE RAZZ
JMP GETPOS ; AND TRY AGAIN
POSSET: LDA GPOSIT ; USE DEFAULT
SETPOS: STA TPOSIT ; USE KEYPRESS
CLC
ADC #'1' ; CONVERT TO ASCII "1"-"5"
STA MPOS ; STORE IN TEMP STRING
STA SVPOS
STA RSPOS
JSR LETTER ; AND DISPLAY IT
; GET DRIVE ID
LDX #LOW WDRIV
LDA #HIGH WDRIV
LDY #WDRIVL
JSR DLINE ; "DRIVE 8 OR 9"
LDA GDRIVE ; SHOW DEFAULT
CLC ; CONVERT 0 OR 1
ADC #7 ; TO 7 OR 8
JSR DODEF ; SO DEFAULT WILL BE CORRECT
GETDRV: JSR GETKEY ; GET A KEYPRESS
CMP #EOL ; IF [RETURN],
BEQ DRVSET ; USE DEFAULT
SEC
SBC #'8' ; CONVERT TO BINARY 0 OR 1
CMP #2 ; IF WITHIN RANGE,
BCC SETDRV ; SET NEW DEFAULT
JSR BOOP
JMP GETDRV ; ELSE TRY AGAIN
DRVSET: LDA GDRIVE ; USE DEFAULT
SETDRV: STA TDRIVE ; USE [A]
CLC
ADC #'8' ; CONVERT TO ASCII 8 OR 9
STA SAVDRI ; STORE IN DRIVE STRING
STA MDRI ; AND IN TEMP STRING
JSR LETTER ; AND SHOW NEW SETTING
LDX #LOW MIND ; SHOW TEMPORARY SETTINGS
LDA #HIGH MIND
LDY #MINDL
JSR DLINE
GETYES: LDA #0
STA NDX ; CLEAR KEY QUEUE
JSR GETKEY
CMP #'Y' ; IF REPLY IS "Y"
BEQ ALLSET ; ACCEPT RESPONSES
CMP #'y'
BEQ ALLSET
CMP #'N' ; IF REPLY IS N,
BEQ RETRY ; DO A RETRY
CMP #'n'
BEQ RETRY
JSR BOOP ; INSIST ON Y/RETURN
JMP GETYES ; OR N
RETRY: LDX #LOW NO ; ELSE PRINT "NO"
LDA #HIGH NO
LDY #NOL
JSR DLINE
JMP PARAMS ; AND TRY AGAIN
ALLSET: LDX #LOW YES ; PRINT "YES"
LDA #HIGH YES
LDY #YESL
JSR DLINE
LDA TDRIVE ; MAKE THE TEMPORARY DRIVE
STA GDRIVE ; THE DEFAULT DRIVE
LDA TPOSIT ; AND THE TEMP POSITION
STA GPOSIT ; THE DEFAULT POSITION
; CALC TRACK & SECTOR OF GAME POSITION
ASL A ; * 2
STA TRACK ; SAVE HERE FOR A MOMENT
ASL A ; * 4
CLC
ADC TRACK ; * 6 (6 TRACKS PER POSITION)
STA TRACK
INC TRACK ; 1ST TRACK IS 1!
LDA #0
STA SECTOR ; ALWAYS START ON SECTOR #0
; LDA FAST ; FAST-READ ENABLED?
; BEQ PRY ; NO, CONTINUE
; JSR FOFF ; ELSE DISENGAGE FAST-READ
PRY: LDA GDRIVE ; TRY TO OPEN SPECIFIED DRIVE
CLC
ADC #8
JSR DOPEN ; THE DEFAULT DRIVE
BCS PARERR ; CARRY SET IF OPEN FAILED
LDX #LOW INSM
LDA #HIGH INSM
LDY #INSML
JSR DLINE ; "INSERT SAVE DISK IN DRIVE X."
JSR RETURN ; "PRESS [RETURN] TO CONTINUE."
CLC ; FOR SUCCESS
PARERR: RTS
; ---------------------
; "PRESS RETURN" PROMPT
; ---------------------
RETURN: LDX #LOW RTN
LDA #HIGH RTN
LDY #RTNL
JSR DLINE ; SHOW PROMPT
; ENTRY FOR QUIT/RESTART
GETRET: LDA #0
STA NDX ; CLEAR KEY QUEUE
JSR GETKEY ; WAIT FOR [RETURN]
CMP #EOL
BEQ RETEX
JSR BOOP ; ACCEPT NO
JMP GETRET ; SUBSTITUTES!
RETEX: RTS
RTN: DB EOL
DB "Press [RETURN] to continue."
DB EOL
RTNL EQU $-RTN
; --------------------
; PROMPT FOR GAME DISK
; --------------------
GAME: DB EOL
DB "Insert STORY disk into drive #8."
GAMEL EQU $-GAME
TOBOOT: LDA #8
JSR DOPEN ; CLOSE OLD, OPEN BOOT DRIVE
LDX #LOW GAME
LDA #HIGH GAME
LDY #GAMEL
JSR DLINE ; "INSERT STORY DISK IN DRIVE #8."
JSR RETURN ; "PRESS [RETURN] TO CONTINUE:"
; LDA FAST ; FAST-READ ENABLED?
; BEQ TBT0 ; NO, SCRAM
; JSR FINIT ; ELSE RE-INIT FAST CODE
TBT0: LDA #$FF ; RE-ENABLE
STA SCRIPT ; SCRIPTING
JMP CLS ; CLEAR SCREEN & RETURN
; -------------------------
; SET UP PHONEY STATUS LINE
; -------------------------
; ENTRY: TEXT SET UP FOR "DLINE"
SROOM: JSR DLINE
LDX #39 ; INVERT & BLACKEN TOP LINE
SRLP: LDA SCREEN,X
ORA #%10000000
STA SCREEN,X
LDA #0
STA COLRAM,X
DEX
BPL SRLP
RTS
; ---------
; SAVE GAME
; ---------
SAV: DB "Save Position"
DB EOL
SAVL EQU $-SAV
SVING: DB EOL
DB "Saving position "
SVPOS: DB "* ..."
DB EOL
SVINGL EQU $-SVING
ZSAVE: JSR SAVRES ; SET UP SCREEN
LDX #LOW SAV
LDA #HIGH SAV
LDY #SAVL
JSR SROOM ; "SAVE POSITION"
JSR PARAMS ; GET PARAMETERS
BCC DOSAVE ; ERROR IF CARRY SET
BADSAV: JSR TOBOOT ; GET BOOT DISK
JMP PREDF ; PREDICATE FAILS
DOSAVE: LDX #LOW SVING
LDA #HIGH SVING
LDY #SVINGL
JSR DLINE ; "SAVING POSITION X ..."
; SAVE GAME PARAMETERS IN [BUFSAV]
LDA ZBEGIN+ZID ; MOVE GAME ID
STA BUFSAV+0 ; INTO 1ST 2 BYTES
LDA ZBEGIN+ZID+1 ; OF THE AUX LINE BUFFER
STA BUFSAV+1
LDA ZSP ; MOVE [ZSP]
STA BUFSAV+2 ; TO 3RD BYTE
LDA OLDZSP ; MOVE [OLDZSP]
STA BUFSAV+3 ; TO 4TH
LDX #2 ; MOVE CONTENTS OF [ZPC]
ZPCSAV: LDA ZPC,X ; TO BYTES 5-7
STA BUFSAV+4,X ; OF [BUFSAV]
DEX
BPL ZPCSAV
; WRITE [LOCALS]/[BUFSAV] PAGE TO DISK
LDA #HIGH LOCALS
STA DBUFF+HI ; POINT TO THE PAGE
JSR PUTDSK ; AND WRITE IT OUT
BCS BADSAV ; CATCH WRITE ERROR HERE
; WRITE CONTENTS OF Z-STACK TO DISK
LDA #HIGH ZSTAKL ; POINT TO 1ST PAGE
STA DBUFF+HI
JSR PUTDSK ; WRITE 1ST AND
BCS BADSAV
JSR PUTDSK ; 2ND PAGE OF Z-STACK
BCS BADSAV
; WRITE ENTIRE GAME PRELOAD TO DISK
LDA ZCODE ; POINT TO 1ST PAGE
STA DBUFF+HI ; OF PRELOAD
LDX ZBEGIN+ZPURBT ; GET # IMPURE PAGES
INX ; USE FOR INDEXING
STX I+LO
LSAVE: JSR PUTDSK
BCS BADSAV
DEC I+LO
BNE LSAVE
JSR TOBOOT ; PROMPT FOR GAME DISK
JMP PREDS ; ELSE PREDICATE SUCCEEDS
; ------------
; RESTORE GAME
; ------------
RES: DB "Restore Position"
DB EOL
RESL EQU $-RES
RSING: DB EOL
DB "Restoring position "
RSPOS: DB "* ..."
DB EOL
RSINGL EQU $-RSING
ZREST: JSR SAVRES
LDX #LOW RES
LDA #HIGH RES
LDY #RESL
JSR SROOM ; "RESTORE POSITION"
JSR PARAMS ; GET PARAMETERS
BCS BADRES ; ERROR IF CARRY SET
LDX #LOW RSING
LDA #HIGH RSING
LDY #RSINGL
JSR DLINE ; "RESTORING POSITION X ..."
; SAVE LOCALS IN CASE OF ERROR
LDX #31
LOCSAV: LDA LOCALS,X ; COPY ALL LOCALS
STA $0100,X ; TO BOTTOM OF MACHINE STACK
DEX
BPL LOCSAV
LDA #HIGH LOCALS
STA DBUFF+HI
JSR GETRES ; RETRIEVE 1ST BLOCK OF PRELOAD
LDA BUFSAV+0 ; DOES 1ST BYTE OF SAVED GAME ID
CMP ZBEGIN+ZID ; MATCH THE CURRENT ID?
BNE WRONG ; WRONG DISK IF NOT
LDA BUFSAV+1 ; WHAT ABOUT THE 2ND BYTE?
CMP ZBEGIN+ZID+1
BEQ RIGHT ; CONTINUE IF BOTH BYTES MATCH
; HANDLE INCORRECT SAVE DISK
WRONG: LDX #31 ; RESTORE ALL SAVED LOCALS
WR0: LDA $0100,X
STA LOCALS,X
DEX
BPL WR0
BADRES: JSR TOBOOT ; PROMPT FOR GAME DISK
JMP PREDF ; PREDICATE FAILS
; CONTINUE RESTORE
RIGHT: LDA ZBEGIN+ZSCRIP ; SAVE BOTH FLAG BYTES
STA I+LO
LDA ZBEGIN+ZSCRIP+1
STA I+HI
LDA #HIGH ZSTAKL ; RETRIEVE OLD CONTENTS OF
STA DBUFF+HI ; Z-STACK
JSR GETRES ; GET 1ST BLOCK OF Z-STACK
JSR GETRES ; AND 2ND BLOCK
LDA ZCODE
STA DBUFF+HI
JSR GETRES ; GET 1ST BLOCK OF PRELOAD
LDA I+LO ; RESTORE THE STATE
STA ZBEGIN+ZSCRIP ; OF THE FLAG WORD
LDA I+HI
STA ZBEGIN+ZSCRIP+1
LDA ZBEGIN+ZPURBT ; GET # PAGES TO LOAD
STA I+LO
LREST: JSR GETRES ; FETCH THE REMAINDER
DEC I+LO ; OF THE PRELOAD
BNE LREST
; RESTORE THE STATE OF THE SAVED GAME
LDA BUFSAV+2 ; RESTORE THE [ZSP]
STA ZSP
LDA BUFSAV+3 ; AND THE [OLDZSP]
STA OLDZSP
LDX #2 ; RESTORE THE [ZPC]
RESZPC: LDA BUFSAV+4,X
STA ZPC,X
DEX
BPL RESZPC
LDA #FALSE
STA ZPCFLG ; INVALIDATE [ZPC]
JSR TOBOOT ; PROMPT FOR GAME DISK
JMP PREDS ; PREDICATE SUCCEEDS
END