mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-01-11 23:43:24 +00:00
348 lines
6.5 KiB
Plaintext
348 lines
6.5 KiB
Plaintext
PAGE
|
|
SBTTL "--- X-OPS ---"
|
|
|
|
; ------
|
|
; EQUAL?
|
|
; ------
|
|
|
|
; IS [ARG1] = [ARG2] (OR [ARG3] OR [ARG4])?
|
|
|
|
ZEQUAL: DEC NARGS ; DOUBLE-CHECK # ARGS
|
|
BNE DOEQ ; MUST BE AT LEAST TWO, OR ...
|
|
|
|
; *** ERROR #9: NOT ENOUGH "EQUAL?" ARGS ***
|
|
|
|
LDA #9
|
|
JMP ZERROR
|
|
|
|
DOEQ: LDA ARG1+LO ; FETCH LSB
|
|
LDX ARG1+HI ; AND MSB OF [ARG1]
|
|
|
|
CMP ARG2+LO ; TEST LSB OF [ARG2]
|
|
BNE TRY2 ; NO GOOD, LOOK FOR ANOTHER ARG
|
|
CPX ARG2+HI ; ELSE TRY MSB OF [ARG2]
|
|
BEQ EQOK ; MATCHED!
|
|
|
|
TRY2: DEC NARGS ; OUT OF ARGS YET?
|
|
BEQ EQBAD ; YES, WE FAILED
|
|
|
|
CMP ARG3+LO ; TRY LSB OF [ARG3]
|
|
BNE TRY3 ; NO GOOD, LOOK FOR ANOTHER ARG
|
|
CPX ARG3+HI ; HOW ABOUT MSB OF [ARG3]?
|
|
BEQ EQOK ; YAY!
|
|
|
|
TRY3: DEC NARGS ; OUT OF ARGS YET?
|
|
BEQ EQBAD ; IF NOT ...
|
|
|
|
CMP ARG4+LO ; TRY [ARG4]
|
|
BNE EQBAD ; SORRY, CHUM
|
|
CPX ARG4+HI ; MSB MATCHED?
|
|
BNE EQBAD ; TOO BAD
|
|
|
|
EQOK: JMP PREDS ; FINALLY MATCHED!
|
|
|
|
EQBAD: JMP PREDF ; FAILURE (SNIFF!)
|
|
|
|
; ----
|
|
; CALL
|
|
; ----
|
|
|
|
; BRANCH TO FUNCTION AT ([ARG1]*2), PASSING
|
|
; OPTIONAL PARAMETERS IN [ARG2]-[ARG4]
|
|
|
|
ZCALL: LDA ARG1+LO
|
|
ORA ARG1+HI ; IS CALL ADDRESS ZERO?
|
|
BNE DOCALL ; NO, CONTINUE
|
|
|
|
JMP PUTBYT ; ELSE RETURN THE ZERO IN [A]
|
|
|
|
DOCALL: LDX OLDZSP ; SAVE OLD STACK POINTER
|
|
LDA ZPCL ; AND LSB OF [ZPC]
|
|
JSR PUSHXA ; ON THE Z-STACK
|
|
|
|
LDX ZPCM ; SAVE MIDDLE 8 BITS
|
|
LDA ZPCH ; AND TOP BIT OF [ZPC]
|
|
JSR PUSHXA ; AS WELL
|
|
|
|
; FORM 16-BIT ADDRESS FROM [ARG1]
|
|
|
|
LDA #0 ; CLEAR HIGH BIT FOR ROTATE
|
|
STA ZPCFLG ; AND INVALIDATE [ZPC]
|
|
|
|
ASL ARG1+LO ; MULTIPLY [ARG1]
|
|
ROL ARG1+HI ; BY TWO
|
|
ROL A ; HIGH BIT INTO [A]
|
|
STA ZPCH ; NEW HIGH BIT OF [ZPC]
|
|
|
|
LDA ARG1+HI ; GET NEW LOW BYTES
|
|
STA ZPCM
|
|
LDA ARG1+LO
|
|
STA ZPCL
|
|
|
|
JSR NEXTPC ; FETCH # LOCALS TO PASS
|
|
STA J+LO ; SAVE HERE FOR COUNTING
|
|
STA J+HI ; AND HERE FOR LATER REFERENCE
|
|
BEQ ZCALL2 ; SKIP IF NO LOCALS
|
|
|
|
LDA #0
|
|
STA I+LO ; ELSE INIT STORAGE INDEX
|
|
|
|
ZCALL1: LDY I+LO
|
|
LDX LOCALS+LO,Y ; GET LSB OF LOCAL INTO [X]
|
|
LDA LOCALS+HI,Y ; AND MSB INTO [A]
|
|
STY I+LO ; SAVE THE INDEX
|
|
JSR PUSHXA ; PUSH LOCAL IN [X/A] ONTO Z-STACK
|
|
|
|
JSR NEXTPC ; GET MSB OF NEW LOCAL
|
|
STA I+HI ; SAVE IT HERE
|
|
JSR NEXTPC ; NOW GET LSB
|
|
|
|
LDY I+LO ; RESTORE INDEX
|
|
STA LOCALS+LO,Y ; STORE LSB INTO [LOCALS]
|
|
LDA I+HI ; RETRIEVE MSB
|
|
STA LOCALS+HI,Y ; STORE IT INTO [LOCALS]
|
|
|
|
INY
|
|
INY ; UPDATE
|
|
STY I+LO ; THE STORAGE INDEX
|
|
|
|
DEC J+LO ; ANY MORE LOCALS?
|
|
BNE ZCALL1 ; YES, KEEP LOOPING
|
|
|
|
; MOVE UP TO 3 ARGUMENTS TO [LOCALS]
|
|
|
|
ZCALL2: DEC NARGS ; EXTRA ARGS IN THIS CALL?
|
|
BEQ ZCALL3 ; NO, CONTINUE
|
|
|
|
LDA ARG2+LO ; MOVE [ARG2] TO LOCAL #1
|
|
STA LOCALS+LO
|
|
LDA ARG2+HI
|
|
STA LOCALS+HI
|
|
|
|
DEC NARGS ; ANY LEFT?
|
|
BEQ ZCALL3 ; NO, SCRAM
|
|
|
|
LDA ARG3+LO ; MOVE [ARG3] TO LOCAL #2
|
|
STA LOCALS+LO+2
|
|
LDA ARG3+HI
|
|
STA LOCALS+HI+2
|
|
|
|
DEC NARGS ; ANY LEFT?
|
|
BEQ ZCALL3 ; NO, EXUENT
|
|
|
|
LDA ARG4+LO ; MOVE [ARG4] TO LOCAL #3
|
|
STA LOCALS+LO+4
|
|
LDA ARG4+HI
|
|
STA LOCALS+HI+4
|
|
|
|
ZCALL3: LDX J+HI ; RETRIEVE # LOCALS
|
|
TXA ; DUPE FOR NO GOOD REASON
|
|
JSR PUSHXA ; PUSH # LOCALS ONTO Z-STACK
|
|
|
|
LDA ZSP ; REMEMBER WHERE
|
|
STA OLDZSP ; WE CAME FROM
|
|
|
|
RTS ; WHEW!
|
|
|
|
; ---
|
|
; PUT
|
|
; ---
|
|
|
|
; SET ITEM [ARG2] IN WORD-TABLE [ARG1] EQUAL TO [ARG3]
|
|
|
|
ZPUT: ASL ARG2+LO ; WORD-ALIGN [ARG2]
|
|
ROL ARG2+HI
|
|
|
|
JSR PCALC ; GET ITEM ADDR INTO [I]
|
|
LDA ARG3+HI ; STORE MSB OF [ARG3]
|
|
STA (I),Y ; INTO MSB OF TABLE POSITION
|
|
INY ; POINT TO LSB
|
|
BNE PUTLSB ; BRANCH ALWAYS
|
|
|
|
; ----
|
|
; PUTB
|
|
; ----
|
|
|
|
; SET ITEM [ARG2] IN BYTE-TABLE [ARG1] EQUAL TO [ARG3]
|
|
|
|
ZPUTB: JSR PCALC
|
|
|
|
; ENTRY FOR "PUT"
|
|
|
|
PUTLSB: LDA ARG3+LO ; GET LSB OF [ARG3]
|
|
STA (I),Y ; STORE IN TABLE AT [Y]
|
|
RTS
|
|
|
|
; ---------------------------
|
|
; CALC ITEM ADDRESS FOR "PUT"
|
|
; ---------------------------
|
|
|
|
PCALC: LDA ARG2+LO ; ADD ITEM OFFSET IN [ARG2]
|
|
CLC ; TO TABLE ADDR IN [ARG1]
|
|
ADC ARG1+LO ; TO FORM A POINTER
|
|
STA I+LO ; IN [I]
|
|
|
|
LDA ARG2+HI ; SAME FOR MSB
|
|
ADC ARG1+HI
|
|
CLC
|
|
ADC ZCODE ; MAKE IT ABSOLUTE
|
|
STA I+HI
|
|
|
|
LDY #0 ; ZERO FOR INDEXING
|
|
RTS
|
|
|
|
; ----
|
|
; PUTP
|
|
; ----
|
|
|
|
; SET PROPERTY [ARG2] IN OBJECT [ARG1] EQUAL TO [ARG3]
|
|
|
|
ZPUTP: JSR PROPB
|
|
|
|
PUTP1: JSR PROPN
|
|
CMP ARG2+LO
|
|
BEQ PUTP2
|
|
BCC PNERR ; ERROR IF LOWER
|
|
|
|
JSR PROPNX ; TRY NEXT PROPERTY
|
|
JMP PUTP1
|
|
|
|
PUTP2: JSR PROPL
|
|
INY ; MAKE [Y] POINT TO 1ST PROPERTY BYTE
|
|
TAX ; (SET FLAGS) IF LENGTH IN [A] = 0
|
|
BEQ PUTP3 ; PUT A BYTE
|
|
CMP #1 ; PUT A WORD IF [A] = 1
|
|
BNE PLERR ; ELSE LENGTH IS BAD
|
|
|
|
LDA ARG3+HI ; GET MSB OF PROPERTY
|
|
STA (I),Y ; AND STORE IN OBJECT
|
|
INY ; POINT TO LSB SLOT
|
|
|
|
PUTP3: LDA ARG3+LO ; FETCH LSB
|
|
STA (I),Y ; AND STORE IN OBJECT
|
|
RTS
|
|
|
|
; *** ERROR #10: BAD PROPERTY NUMBER ***
|
|
|
|
PNERR: LDA #10
|
|
JMP ZERROR
|
|
|
|
; *** ERROR #11: PUTP PROPERTY LENGTH ***
|
|
|
|
PLERR: LDA #11
|
|
JMP ZERROR
|
|
|
|
; ------
|
|
; PRINTC
|
|
; ------
|
|
|
|
; PRINT CHAR WITH ASCII VALUE IN [ARG1]
|
|
|
|
ZPRC: LDA ARG1+LO ; GRAB THE CHAR
|
|
JMP COUT ; AND SHIP IT OUT
|
|
|
|
; ------
|
|
; PRINTN
|
|
; ------
|
|
|
|
; PRINT VALUE OF [ARG1] AS A SIGNED INTEGER
|
|
|
|
ZPRN: LDA ARG1+LO ; MOVE [ARG1] TO [QUOT]
|
|
STA QUOT+LO
|
|
LDA ARG1+HI
|
|
STA QUOT+HI
|
|
|
|
; PRINT [QUOT]
|
|
|
|
NUMBER: LDA QUOT+HI ; IF VALUE IS POSITIVE
|
|
BPL DIGCNT ; CONTINUE
|
|
|
|
LDA #$2D ; ELSE START WITH A MINUS SIGN
|
|
JSR COUT
|
|
|
|
JSR ABQUOT ; AND CALC ABS([QUOT])
|
|
|
|
; COUNT # OF DECIMAL DIGITS
|
|
|
|
DIGCNT: LDA #0 ; RESET
|
|
STA DIGITS ; DIGIT INDEX
|
|
|
|
DGC: LDA QUOT+LO ; IS QUOTIENT
|
|
ORA QUOT+HI ; ZERO YET?
|
|
BEQ PRNTN3 ; YES, READY TO PRINT
|
|
|
|
LDA #10 ; ELSE DIVIDE [QUOT]
|
|
STA REMAIN+LO ; BY 10 (LSB)
|
|
LDA #0
|
|
STA REMAIN+HI ; 10 (MSB)
|
|
|
|
JSR UDIV ; UNSIGNED DIVIDE
|
|
|
|
LDA REMAIN+LO ; FETCH LSB OF REMAINDER (THE DIGIT)
|
|
PHA ; SAVE IT ON STACK
|
|
INC DIGITS ; UPDATE DIGIT COUNT
|
|
BNE DGC ; LOOP TILL QUOTIENT=0
|
|
|
|
PRNTN3: LDA DIGITS ; IF DIGIT COUNT IS NZ
|
|
BNE PRNTN4 ; CONTINUE
|
|
|
|
LDA #'0' ; ELSE PRINT "0"
|
|
JMP COUT ; AND RETURN
|
|
|
|
PRNTN4: PLA ; PULL A DIGIT OFF THE STACK
|
|
CLC
|
|
ADC #'0' ; CONVERT TO ASCII
|
|
JSR COUT ; AND PRINT IT
|
|
DEC DIGITS ; OUT OF DIGITS YET?
|
|
BNE PRNTN4 ; NO, KEEP LOOPING
|
|
RTS
|
|
|
|
; ------
|
|
; RANDOM
|
|
; ------
|
|
|
|
; RETURN A RANDOM VALUE BETWEEN 0 AND [ARG1]
|
|
|
|
ZRAND: LDA ARG1+LO ; MAKE [ARG1] THE DIVISOR
|
|
STA ARG2+LO
|
|
LDA ARG1+HI
|
|
STA ARG2+HI
|
|
|
|
JSR RANDOM ; GET RANDOM BYTES INTO [A] AND [X]
|
|
STX ARG1+LO ; MAKE THEM THE DIVIDEND
|
|
AND #$7F ; MAKE SURE MSB IS POSITIVE
|
|
STA ARG1+HI
|
|
|
|
JSR DIVIDE ; SIGNED DIVIDE, [ARG1] / [ARG2]
|
|
|
|
LDA REMAIN+LO ; MOVE REMAINDER
|
|
STA VALUE+LO ; INTO [VALUE]
|
|
LDA REMAIN+HI
|
|
STA VALUE+HI
|
|
|
|
JSR INCVAL ; INCREMENT [VALUE]
|
|
JMP PUTVAL ; AND RETURN RESULT
|
|
|
|
; ----
|
|
; PUSH
|
|
; ----
|
|
|
|
; PUSH [ARG1] ONTO THE Z-STACK
|
|
|
|
ZPUSH: LDX ARG1+LO
|
|
LDA ARG1+HI
|
|
JMP PUSHXA
|
|
|
|
; ---
|
|
; POP
|
|
; ---
|
|
|
|
; POP WORD OFF Z-STACK, STORE IN VARIABLE [ARG1]
|
|
|
|
ZPOP: JSR POPVAL ; VALUE INTO [VALUE]
|
|
LDA ARG1+LO ; GET VARIABLE ID
|
|
JMP VARPUT ; AND CHANGE THE VARIABLE
|
|
|
|
END
|
|
|
|
|