mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-01-11 23:43:24 +00:00
340 lines
6.2 KiB
Plaintext
340 lines
6.2 KiB
Plaintext
PAGE
|
|
SBTTL "--- OPCODE SUPPORT SUBROUTINES ---"
|
|
|
|
; -----------------------
|
|
; FETCH A SHORT IMMEDIATE
|
|
; -----------------------
|
|
|
|
GETSHT: LDA #0 ; CLEAR MSB OF [VALUE]
|
|
BEQ GLG ; AND GRAB LSB
|
|
|
|
; ----------------------
|
|
; FETCH A LONG IMMEDIATE
|
|
; ----------------------
|
|
|
|
GETLNG: JSR NEXTPC ; GRAB MSB
|
|
|
|
GLG: STA VALUE+HI ; STORE IT
|
|
JSR NEXTPC ; GRAB LSB
|
|
STA VALUE+LO ; STORE THAT TOO
|
|
RTS
|
|
|
|
; ----------------
|
|
; FETCH A VARIABLE
|
|
; ----------------
|
|
|
|
; FROM WITHIN AN OPCODE (VARIABLE ID IN [A])
|
|
|
|
VARGET: TAX ; IF NON-ZERO,
|
|
BNE GETVR1 ; ACCESS A VARIABLE
|
|
|
|
JSR POPVAL ; ELSE PULL VAR OFF Z-STACK
|
|
JMP PSHVAL ; WITHOUT ALTERING STACK
|
|
|
|
; FROM THE MAIN LOOP (ID BYTE IN Z-CODE)
|
|
|
|
GETVAR: JSR NEXTPC ; GRAB VAR-TYPE BYTE
|
|
BEQ POPVAL ; VALUE IS ON Z-STACK
|
|
|
|
; IS VARIABLE LOCAL OR GLOBAL?
|
|
|
|
GETVR1: CMP #$10 ; IF >= 16,
|
|
BCS GETVRG ; IT'S GLOBAL
|
|
|
|
; HANDLE A LOCAL VARIABLE
|
|
|
|
GETVRL: SEC
|
|
SBC #1 ; FORM A ZERO-ALIGNED
|
|
ASL A ; WORD INDEX
|
|
TAX ; INTO THE [LOCALS]
|
|
|
|
LDA LOCALS+LO,X ; GRAB LSB
|
|
STA VALUE+LO
|
|
LDA LOCALS+HI,X ; AND MSB
|
|
STA VALUE+HI
|
|
RTS
|
|
|
|
; HANDLE A GLOBAL VARIABLE
|
|
|
|
GETVRG: JSR GVCALC ; GET ADDRESS OF GLOBAL INTO [I]
|
|
LDA (I),Y ; MSB OF GLOBAL ([Y] = 0)
|
|
STA VALUE+HI
|
|
INY ; = 1
|
|
LDA (I),Y ; LSB OF GLOBAL
|
|
STA VALUE+LO ; SAVE IT
|
|
RTS ; AND WE'RE DONE
|
|
|
|
; ----------------------------------
|
|
; POP G-STACK INTO [VALUE] AND [X/A]
|
|
; ----------------------------------
|
|
|
|
POPVAL: DEC GSP
|
|
BEQ UNDER ; UNDERFLOW IF ZERO!
|
|
|
|
LDY GSP ; READ STACK POINTER
|
|
LDX GSTAKL,Y ; GRAB LSB OF STACK VALUE
|
|
STX VALUE+LO ; GIVE TO [VALUE]
|
|
LDA GSTAKH,Y ; ALSO GRAB MSB
|
|
STA VALUE+HI ; A SIMILAR FATE
|
|
RTS
|
|
|
|
; *** ERROR #6: G-STACK UNDERFLOW ***
|
|
|
|
UNDER: LDA #6
|
|
JMP GERROR
|
|
|
|
; -----------------------
|
|
; PUSH [VALUE] TO G-STACK
|
|
; -----------------------
|
|
|
|
PSHVAL: LDX VALUE+LO
|
|
LDA VALUE+HI
|
|
|
|
; FALL THROUGH ...
|
|
|
|
; ---------------------
|
|
; PUSH [X/A] TO G-STACK
|
|
; ---------------------
|
|
|
|
PSHXA: LDY GSP
|
|
STA GSTAKH,Y
|
|
TXA
|
|
STA GSTAKL,Y
|
|
|
|
INC GSP
|
|
BEQ OVER ; OVERFLOW IF ZEROED!
|
|
RTS
|
|
|
|
; *** ERROR #7: G-STACK OVERFLOW ***
|
|
|
|
OVER: LDA #7
|
|
JMP GERROR
|
|
|
|
; --------------
|
|
; RETURN A VALUE
|
|
; --------------
|
|
|
|
; FROM WITHIN AN OPCODE (VARIABLE ID IN [A])
|
|
|
|
VARPUT: TAX ; IF ZERO,
|
|
BNE PUTVR1
|
|
|
|
DEC GSP ; FLUSH TOP WORD OFF STACK
|
|
BNE PSHVAL ; AND REPLACE WITH [VALUE]
|
|
BEQ UNDER ; ERROR IF ZSP BECAME ZERO!
|
|
|
|
; RETURN A ZERO
|
|
|
|
RET0: LDA #0
|
|
|
|
; RETURN BYTE IN [A]
|
|
|
|
PUTBYT: STA VALUE+LO
|
|
LDA #0
|
|
STA VALUE+HI ; CLEAR MSB
|
|
|
|
; RETURN [VALUE]; VARIABLE ID IN NEXT Z-BYTE
|
|
|
|
PUTVAL: JSR NEXTPC ; GET VAR-TYPE BYTE
|
|
BEQ PSHVAL ; VALUE GOES TO STACK IF ZERO
|
|
|
|
; LOCAL OR GLOBAL VARIABLE?
|
|
|
|
PUTVR1: CMP #$10 ; IF >= 16,
|
|
BCS PUTVLG ; IT'S GLOBAL
|
|
|
|
; PUT A LOCAL VARIABLE
|
|
|
|
PUTVLL: SEC
|
|
SBC #1 ; FORM A ZERO-ALIGNED
|
|
ASL A ; WORD INDEX
|
|
TAX ; INTO [LOCALS]
|
|
|
|
LDA VALUE+LO ; GRAB LSB
|
|
STA LOCALS+LO,X ; SAVE IN LOCAL TABLE
|
|
LDA VALUE+HI ; DO SAME TO
|
|
STA LOCALS+HI,X ; MSB
|
|
RTS
|
|
|
|
; PUT A GLOBAL VARIABLE
|
|
|
|
PUTVLG: JSR GVCALC ; GET ADDR OF GLOBAL INTO [I]
|
|
LDA VALUE+HI ; GET MSB
|
|
STA (I),Y ; STORE AS 1ST BYTE ([Y] = 0)
|
|
INY ; [Y] = 1
|
|
LDA VALUE+LO ; NOW GET LSB
|
|
STA (I),Y ; STORE AS 2ND BYTE
|
|
RTS
|
|
|
|
; -----------------------
|
|
; CALC GLOBAL WORD OFFSET
|
|
; -----------------------
|
|
|
|
; ENTRY: VAR-ID BYTE (16-255) IN [A]
|
|
; EXIT: ADDRESS OF GLOBAL VAR IN [VAL]
|
|
; [Y] = 0 FOR INDEXING
|
|
|
|
GVCALC: SEC
|
|
SBC #$10 ; FORM A ZERO-ALIGNED INDEX
|
|
LDY #0 ; MAKE SURE MSB OF OFFSET AND [Y]
|
|
STY I+HI ; ARE CLEARED
|
|
|
|
ASL A ; MULTIPLY OFFSET BY 2
|
|
ROL I+HI ; TO WORD-ALIGN IT
|
|
|
|
CLC ; TO ADDRESS OF GLOBAL TABLE
|
|
ADC GLOBAL+LO ; TO FORM THE ABSOLUTE
|
|
STA I+LO ; ADDRESS OF THE
|
|
LDA I+HI ; DESIRED GLOBAL VARIABLE
|
|
ADC GLOBAL+HI ; STORE ADDRESS BACK IN [I]
|
|
STA I+HI ; AS A POINTER
|
|
|
|
WCEX: RTS
|
|
|
|
; ---------------
|
|
; PREDICATE FAILS
|
|
; ---------------
|
|
|
|
PREDF: JSR NEXTPC ; GET 1ST BRANCH BYTE
|
|
BPL PREDB ; BRANCH IF BIT 7 CLEAR
|
|
|
|
; -----------------------
|
|
; IGNORE PREDICATE BRANCH
|
|
; -----------------------
|
|
|
|
; ENTRY: 1ST BRANCH BYTE IN [A]
|
|
|
|
PREDNB: AND #%01000000 ; TEST BIT 6
|
|
BNE WCEX ; SHORT BRANCH IF SET
|
|
JMP NEXTPC ; ELSE SKIP OVER 2ND BRANCH BYTE
|
|
|
|
; ------------------
|
|
; PREDICATE SUCCEEDS
|
|
; ------------------
|
|
|
|
PREDS: JSR NEXTPC ; GET 1ST BRANCH BYTE
|
|
BPL PREDNB ; DON'T BRANCH IF BIT 7 CLEAR
|
|
|
|
; --------------------------
|
|
; PERFORM A PREDICATE BRANCH
|
|
; --------------------------
|
|
|
|
; ENTRY: 1ST PRED BYTE IN [A]
|
|
|
|
PREDB: TAX ; COPY FOR LATER
|
|
AND #%01000000 ; LONG OR SHORT BRANCH?
|
|
BEQ PREDLB ; LONG IF BIT 6 IS CLEAR
|
|
|
|
; HANDLE A SHORT BRANCH
|
|
|
|
TXA ; RESTORE PRED BYTE
|
|
AND #%00111111 ; FORM SHORT OFFSET
|
|
STA VALUE+LO ; USE AS LSB OF BRANCH OFFSET
|
|
LDA #0
|
|
STA VALUE+HI ; MSB OF OFFSET IS ZERO
|
|
BEQ PREDB1 ; DO THE BRANCH
|
|
|
|
; HANDLE A LONG BRANCH
|
|
|
|
PREDLB: TXA ; RESTORE 1ST PRED BYTE
|
|
AND #%00111111 ; FORM MSB OF OFFSET
|
|
TAX ; SAVE HERE FOR REFERENCE
|
|
|
|
AND #%00100000 ; CHECK SIGN OF 14-BIT VALUE
|
|
BEQ DOB2 ; POSITIVE IF ZERO, USE [X] FOR MSB
|
|
|
|
TXA ; ELSE RESTORE BYTE
|
|
ORA #%11100000 ; EXTEND SIGN BIT
|
|
TAX ; BACK HERE FOR STORAGE
|
|
|
|
DOB2: STX VALUE+HI
|
|
JSR NEXTPC ; FETCH LSB OF 14-BIT OFFSET
|
|
STA VALUE+LO
|
|
|
|
; BRANCH TO Z-ADDRESS IN [VALUE]
|
|
|
|
PREDB1: LDA VALUE+HI ; CHECK MSB OF OFFSET
|
|
BNE PREDB3 ; DO BRANCH IF NZ
|
|
LDA VALUE+LO ; IF LSB IS NON-ZERO,
|
|
BNE PREDB2 ; MAKE SURE IT ISN'T 1
|
|
JMP GRFALS ; ELSE DO AN "RFALSE" IF [VALUE] = 0
|
|
|
|
PREDB2: CMP #1 ; IF OFFSET = 1
|
|
BNE PREDB3
|
|
JMP GRTRUE ; DO AN "RTRUE"
|
|
|
|
; ENTRY POINT FOR "JUMP"
|
|
|
|
PREDB3: JSR DECVAL ; CALC [VALUE]-2
|
|
JSR DECVAL
|
|
;***
|
|
LDA VALUE+HI
|
|
LDX VALUE+LO
|
|
JSR ADDGPC
|
|
|
|
LDA VALUE+HI ; EXTEND SIGN
|
|
AND #$80
|
|
CLC
|
|
ADC GPCH
|
|
STA GPCH
|
|
;***
|
|
|
|
|
|
; LDA VALUE+LO ; GET LSB OF OFFSET
|
|
; CLC
|
|
; ADC GPCL ; ADD LSB OF GPC
|
|
; BCC PREDB5 ; IF OVERFLOWED,
|
|
; INC VALUE+HI ; UPDATE MSB OF OFFSET
|
|
|
|
;PREDB5: STA GPCL ; UPDATE ZPCL
|
|
; LDA VALUE+HI ; IF MSB IS ZERO,
|
|
; BEQ GNOOP ; PAGE IS STILL VALID
|
|
; CLC
|
|
; ADC GPCH
|
|
; STA GPCH ; ELSE SWITCH PAGES
|
|
|
|
; LDA #0 ; INVALIDATE [GPC]
|
|
; STA GPCFLG
|
|
|
|
; FALL THROUGH ...
|
|
|
|
; ----
|
|
; NOOP
|
|
; ----
|
|
|
|
GNOOP: RTS
|
|
|
|
; -----------------
|
|
; INCREMENT [VALUE]
|
|
; -----------------
|
|
|
|
INCVAL: INC VALUE+LO
|
|
BNE IVX
|
|
INC VALUE+HI
|
|
IVX: RTS
|
|
|
|
; -----------------
|
|
; DECREMENT [VALUE]
|
|
; -----------------
|
|
|
|
DECVAL: LDA VALUE+LO
|
|
SEC
|
|
SBC #1
|
|
STA VALUE+LO
|
|
BCS DVX
|
|
DEC VALUE+HI
|
|
DVX: RTS
|
|
|
|
; ----------------------
|
|
; MOVE [ARG1] TO [VALUE]
|
|
; ----------------------
|
|
|
|
A12VAL: LDA ARG1+LO
|
|
STA VALUE+LO
|
|
LDA ARG1+HI
|
|
STA VALUE+HI
|
|
RTS
|
|
|
|
END
|
|
|