mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-02-08 01:01:24 +00:00
268 lines
7.9 KiB
Plaintext
268 lines
7.9 KiB
Plaintext
|
|
SUBTTL OBJECT OPERATIONS
|
|
PAGE +
|
|
|
|
PUBLIC OPMOVE,OPREMO,OPQFSE,OPFSET
|
|
;MOVE (OBJ1 INTO OBJ2)
|
|
OPMOVE PROC
|
|
PUSH AX ;PROTECT OPRS FROM REMOVE CALL
|
|
PUSH BX
|
|
CALL OPREMO ;REMOVE OBJ1 FROM WHEREVER IT IS
|
|
POP DX ;OBJ2
|
|
MOV AX,DX
|
|
CALL OBJLOC ;FIND ITS LOCATION
|
|
MOV BX,AX ;MOVE TO BASE
|
|
POP CX ;OBJ1
|
|
MOV AX,CX
|
|
CALL OBJLOC ;FIND ITS LOCATION
|
|
MOV BP,AX ;MOVE TO BASE
|
|
PTAWRD ES:[BP].PARENT,D ; (A0) PUT OBJ2 INTO OBJ1'S LOC SLOT
|
|
GTAWRD D,ES:[BX].CHILD1 ; (A0) GET CONTENTS OBJ2'S FIRST SLOT
|
|
PTAWRD ES:[BX].CHILD1,C ; (A0) MAKE OBJ1 FIRST CONTENT OBJ2
|
|
CMP DX,0 ;WERE THERE ANY OTHER CONTENTS?
|
|
JE OMV1$ ;NO
|
|
PTAWRD ES:[BP].SIBLING,D ; YES, CHAIN ONTO OBJ1'S SIBLING SLOT
|
|
OMV1$: RET
|
|
OPMOVE ENDP
|
|
|
|
;REMOVE (OBJ FROM ITS PARENT)
|
|
OPREMO PROC
|
|
MOV DX,AX ; (A0) SAVE OBJ FOR LATER
|
|
CALL OBJLOC ;FIND ITS LOCATION
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD C,ES:[BX].PARENT ; (A0) GET ITS PARENT
|
|
CMP CX,0 ;DOES IT HAVE A PARENT?
|
|
JE ORM3$ ;IF NOT, WE'RE DONE
|
|
MOV AX,CX ; (A0) PARENT
|
|
CALL OBJLOC ;FIND PARENT'S LOCATION
|
|
MOV BP,AX ;MOVE TO BASE
|
|
MOV CX,DX ; (A0) MOVE OBJECT TO CX
|
|
GTAWRD D,ES:[BP].CHILD1 ; (A0) GET PARENT'S FIRST CONTENT
|
|
CMP DX,CX ; (A0) IS IT OBJ?
|
|
JNE ORM1$ ;NO
|
|
MOVM ES:[BP].CHILD1,ES:[BX].SIBLING,AX ;YES, CHANGE SLOT TO
|
|
;OBJ'S SIBLING
|
|
JMP ORM2$ ;AND RETURN
|
|
ORM1$: MOV AX,DX ; (A0) CURRENT SIBLING
|
|
CALL OBJLOC ;FIND ITS LOCATION
|
|
MOV BP,AX ;MOVE TO BASE
|
|
GTAWRD D,ES:[BP].SIBLING ; (A0) GET NEXT SIBLING IN CHAIN
|
|
CMP DX,CX ; (A0) IS IT OBJ?
|
|
JNE ORM1$ ;NO, CONTINUE LOOP
|
|
MOVM ES:[BP].SIBLING,ES:[BX].SIBLING,AX ; (A0) YES, CHANGE IT
|
|
; TO OBJ'S SIBLING
|
|
ORM2$: MOV ES:[BX].PARENT,0 ;OBJ NOW HAS NO PARENT
|
|
MOV ES:[BX].SIBLING,0 ;OR SIBLING
|
|
ORM3$: RET
|
|
OPREMO ENDP
|
|
|
|
;FSET? (IS FLAG SET IN OBJ?)
|
|
OPQFSE PROC
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
CMP BX,32 ; (A0) FIND WHICH WORD TO SET FLAG IN
|
|
JL OQF0$ ; (A0) NOT IN THE THIRD
|
|
SUB BX,32 ; (A0) YES, IT IS
|
|
ADD AX,4 ; (A0) SKIP OTHER FLAG WORDS IN OBJECT
|
|
JMP OQF1$ ; (A0) AND SET THE FLAG
|
|
OQF0$: CMP BX,16 ;SECOND WORD FLAG?
|
|
JL OQF1$ ;NO
|
|
SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER
|
|
INC AX ;AND USE SECOND FLAG WORD
|
|
INC AX
|
|
OQF1$: MOV CX,BX ;MOVE TO COUNT
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD A,[BX] ;GET THE FLAG WORD
|
|
MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION
|
|
SHR DX,CL
|
|
TEST AX,DX ;IS THIS BIT SET IN FLAG WORD?
|
|
JE OQF2$ ;NO, PREDICATE FALSE
|
|
JMP PTRUE ;YES, PREDICATE TRUE
|
|
OQF2$: JMP PFALSE
|
|
OPQFSE ENDP
|
|
|
|
;FSET (SET A FLAG IN OBJ)
|
|
OPFSET PROC
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
CMP BX,32 ; (A0) FIND WHICH WORD TO SET FLAG IN
|
|
JL OFS0$ ; (A0) NOT IN THE THIRD
|
|
SUB BX,32 ; (A0) YES, IT IS
|
|
ADD AX,4 ; (A0) SKIP OTHER FLAG WORDS IN OBJECT
|
|
JMP OFS1$ ; (A0) AND SET THE FLAG
|
|
OFS0$: CMP BX,16 ;SECOND WORD FLAG?
|
|
JL OFS1$ ;NO
|
|
SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER
|
|
INC AX ;AND USE SECOND FLAG WORD
|
|
INC AX
|
|
OFS1$: MOV CX,BX ;MOVE TO COUNT
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD A,[BX] ;GET THE FLAG WORD
|
|
MOV DX,8000H ;SHIFT A BIT TO PROPER POSITION
|
|
SHR DX,CL
|
|
OR AX,DX ;SET THIS BIT IN FLAG WORD
|
|
PTAWRD [BX],A ;STORE THE NEW FLAG WORD
|
|
RET
|
|
OPFSET ENDP
|
|
|
|
PUBLIC OPFCLE,OPLOC,OPQFIR,OPQNEX,OPQIN
|
|
;FCLEAR (CLEAR A FLAG IN OBJ)
|
|
OPFCLE PROC
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
CMP BX,32 ; (A0) FIND WHICH FLAG WORD WE WANT
|
|
JL OFC0$ ; (A0) MAYBE IN SECOND WORD
|
|
ADD AX,4 ; (A0) POINT TO THIRD WORD
|
|
SUB BX,32 ; (A0) BASIFY FLAG NUMBER
|
|
JMP OFC1$ ; (A0) AND CLEAR FLAG
|
|
OFC0$: CMP BX,16 ;SECOND WORD FLAG?
|
|
JL OFC1$ ;NO
|
|
SUB BX,16 ;YES, SUBTRACT 16 FROM FLAG NUMBER
|
|
INC AX ;AND USE SECOND FLAG WORD
|
|
INC AX
|
|
OFC1$: MOV CX,BX ;MOVE TO COUNT
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD A,[BX] ;GET THE FLAG WORD
|
|
MOV DX,7FFFH ;SHIFT A BIT TO PROPER POSITION
|
|
ROR DX,CL
|
|
AND AX,DX ;CLEAR THIS BIT IN FLAG WORD
|
|
PTAWRD [BX],A ;STORE THE NEW FLAG WORD
|
|
RET
|
|
OPFCLE ENDP
|
|
|
|
;LOC (RETURN CONTAINER OF OBJ)
|
|
OPLOC PROC
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD A,ES:[BX].PARENT ; (A0) GET LOC SLOT
|
|
JMP PUTVAL ; (A0) RETURN THE WORD VALUE
|
|
OPLOC ENDP
|
|
|
|
;FIRST? (RETURN FIRST SLOT OF OBJ, FAIL IF NONE)
|
|
OPQFIR PROC
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD A,ES:[BX].CHILD1 ; (A0) GET FIRST SLOT
|
|
PUSH AX ;SAVE IT
|
|
CALL PUTVAL ; (A0) RETURN THE BYTE VALUE
|
|
POP AX ;RESTORE IT
|
|
CMP AX,0 ;WAS IT ZERO?
|
|
JE JPF1 ;YES, PREDICATE FALSE
|
|
JPT1: JMP PTRUE ;NO, PREDICATE TRUE
|
|
JPF1: JMP PFALSE
|
|
OPQFIR ENDP
|
|
|
|
;NEXT? (RETURN THE NEXT (SIBLING) SLOT OF OBJ, FAIL IF NONE)
|
|
OPQNEX PROC
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
MOV BX,AX ;MOVE TO BASE
|
|
GTAWRD A,ES:[BX].SIBLING ; (A0) GET SIBLING SLOT
|
|
PUSH AX ;SAVE IT
|
|
CALL PUTVAL ; (A0) RETURN THE BYTE VALUE
|
|
POP AX ;RESTORE IT
|
|
CMP AX,0 ;WAS IT ZERO?
|
|
JE JPF1 ;YES, PREDICATE FALSE
|
|
JMP JPT1 ;NO, PREDICATE TRUE
|
|
OPQNEX ENDP
|
|
|
|
;IN? (IS OBJ1 CONTAINED IN OBJ2?)
|
|
OPQIN PROC
|
|
CALL OBJLOC ;FIND OBJ1'S LOCATION
|
|
XCHG AX,BX ;MOVE TO BASE
|
|
XCHG AH,AL ; (A0) FLOP BYTES
|
|
CMP ES:[BX].PARENT,AX ; (A0) IS OBJ1'S PARENT OBJ2?
|
|
XCHG AH,AL ; (A0) REFLOP BYTES
|
|
JE JPT1 ;YES, PREDICATE TRUE
|
|
JMP JPF1 ;NO, PREDICATE FALSE
|
|
OPQIN ENDP
|
|
|
|
PUBLIC OPGETP
|
|
;GETP (GET SPECIFIED PROPERTY OF OBJ, DEFAULT IF NONE)
|
|
OPGETP PROC
|
|
MOV DX,BX ;PROPERTY
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
CALL FSTPRP ; (A0) GET FIRST PROPERTY POINTER
|
|
JMP OGP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP
|
|
OGP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY
|
|
OGP2$: MOV AL,ES:[BX] ; (A0) GET PROPERTY IDENTIFIER
|
|
AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS
|
|
CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE
|
|
JG OGP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE)
|
|
JL OGP3$ ;IF LESS, NO SUCH PROPERTY HERE
|
|
|
|
MOV AL,ES:[BX] ; (A0) NOW FIND PROPERTY SIZE
|
|
INC BX ; (A0) ADVANCE PROP BYTE POINTER
|
|
AND AL,3FH ; (A0) MASK OFF LENGTH BITS
|
|
|
|
CMP AL,0 ;BYTE VALUE?
|
|
JNE OGP5$ ;NO
|
|
MOV AL,ES:[BX] ;GET THE BYTE
|
|
JMP BYTVAL ;AND RETURN IT
|
|
OGP3$: DEC DX ;POINT INTO DEFAULT PROPERTY TABLE
|
|
SHL DX,1
|
|
MOV BX,DX
|
|
OGP4$: ADD BX,OBJTAB ;GET THE WORD
|
|
OGP5$: GTAWRD A,[BX]
|
|
JMP PUTVAL ;AND RETURN IT
|
|
OPGETP ENDP
|
|
|
|
;PUTP (CHANGE VALUE OF A PROPERTY, ERROR IF BAD NUMBER)
|
|
PUBLIC OPPUTP,OPP2$
|
|
OPPUTP PROC
|
|
PUSH CX ;SAVE NEW VALUE
|
|
MOV DX,BX ;PROPERTY
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
CALL FSTPRP ; (A0) GET FIRST PROPERTY
|
|
JMP OPP2$ ;SKIP NEXT LINE FIRST TIME THROUGH LOOP
|
|
OPP1$: CALL NXTPRP ;POINT TO NEXT PROPERTY
|
|
OPP2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER
|
|
AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS
|
|
CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE
|
|
JE OPP3$ ;IF EQUAL, GOT IT
|
|
JG OPP1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE)
|
|
FATAL FTL2 ;OTHERWISE, FATAL ERROR
|
|
|
|
OPP3$: MOV AL,ES:[BX] ;NOW FIND LENGTH OF PROPERTY
|
|
INC BX ;POINT TO PROPERTY VALUE
|
|
AND AL,3FH ; (A0) MASK OFF LENGTH BITS
|
|
|
|
CMP AL,0 ;BYTE VALUE?
|
|
POP AX ;RESTORE NEW VALUE
|
|
JNE OPP4$ ;ZERO MEANS BYTE VALUE
|
|
MOV ES:[BX],AL ;STORE THE NEW BYTE
|
|
RET ;AND RETURN
|
|
OPP4$: PTAWRD [BX],A ;STORE THE NEW WORD VALUE
|
|
RET
|
|
OPPUTP ENDP
|
|
|
|
;NEXTP (RETURN NUMBER OF NEXT PROP FOLLOWING GIVEN PROB IN OBJ)
|
|
PUBLIC OPNEXT,ONX2$
|
|
OPNEXT PROC
|
|
MOV DX,BX ;PROPERTY
|
|
CALL OBJLOC ;FIND OBJ'S LOCATION
|
|
CALL FSTPRP ; (A0) POINT TO FIRST PROPERTY
|
|
CMP DX,0 ;WERE WE GIVEN ZERO AS PROP?
|
|
JE ONX4$ ;YES, GO RETURN FIRST PROPERTY NUMBER
|
|
JMP ONX2$ ;NO, SKIP NEXT LINE FIRST TIME THROUGH LOOP
|
|
ONX1$: CALL NXTPRP ;POINT TO NEXT PROPERTY
|
|
ONX2$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER
|
|
AND AL,MASK PROPNUM ;CLEAN OFF LENGTH BITS
|
|
CMP AL,DL ;COMPARE PROPERTY NUMBER WITH DESIRED ONE
|
|
JE ONX3$ ;IF EQUAL, GOT IT
|
|
JG ONX1$ ;IF GREATER, LOOP (TABLE SORTED IN REVERSE)
|
|
FATAL FTL2 ;OTHERWISE, FATAL ERROR
|
|
ONX3$: CALL NXTPRP ;POINT TO NEXT PROPERTY
|
|
ONX4$: MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER
|
|
AND AL,MASK PROPNUM ;EXTRACT PROPERTY NUMBER
|
|
JMP PUTVAL ;AND RETURN IT
|
|
OPNEXT ENDP
|
|
|
|
; GIVEN OBJLOC IN AX, RETURN A PTR TO FIRST PROPERTY IN BX
|
|
PUBLIC FSTPRP
|
|
FSTPRP PROC
|
|
MOV BP,AX ;MOVE TO BASE
|
|
GTAWRD B,[BP].PROPS ;GET LOCATION OF ITS PROPERTY TABLE
|
|
MOV AL,ES:[BX] ;LENGTH OF SHORT DESCRIPTION IN WORDS
|
|
XOR AH,AH ; (A0) ZERO THE TOP HALF
|
|
SHL AX,1 ;CONVERT TO BYTES
|
|
ADD BX,AX ;ADJUST POINTER TO SKIP IT
|
|
INC BX ; SKIP LENGTH BYTE
|
|
RET
|
|
FSTPRP ENDP |