mirror of
https://github.com/erkyrath/infocom-zcode-terps.git
synced 2026-01-13 07:10:02 +00:00
429 lines
12 KiB
Plaintext
429 lines
12 KiB
Plaintext
SUBTTL GETBYT - LOW LEVEL FUNCTIONS
|
|
PAGE +
|
|
|
|
;GET A BYTE, BLOCK-POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX,
|
|
;UPDATE AX & BX TO REFLECT BYTE GOTTEN
|
|
;
|
|
; GETBYT UNDERWENT SERIOUS RE-WRITING AND EVALUATION IN THE UPDATE TO USE
|
|
; ALL OF MEMORY. THE ORIGINAL ROUTINE WAS KEPT BUT CHANGES WERE MADE IN
|
|
; TWO SETS: THE FIRST TO HANDLE THE CASE IN WHICH ALL OF THE GAME IS IN
|
|
; MEMORY; AND THE SECOND IN WHICH THE GAME BUFFERS EXTEND PAST 64K AND THUS
|
|
; REQUIRING A SEGMENT SWITCH TO RETRIEVE THE BYTE.
|
|
;
|
|
; FOR THE FIRST CASE, THE BLOCK PTR IS USED TO DETERMINE THE SEGMENT IN
|
|
; WHICH THE BLOCK RESIDES, THE GAME SEGMENT IS SET ACCORDINGLY, AND THE
|
|
; BYTE IS FETCHED.
|
|
;
|
|
; THE SECOND CASE WILL CALL GETPAG TO DETERMINE WHERE THE PAGE IS LOCATED IN
|
|
; CORE.CALLING GETPAG WILL SET A VARIABLE CALLED CURSEG TO 0 OR 1 TO INDICATE
|
|
; THAT THE PAGE WE ARE TOUCHING IS IN THE FIRST OR SECOND SEGMENT. GETPAG
|
|
; RETURNS A VALID POINTER ASSUMING THAT THIS ROUTINE WILL SET ES ACCORDING TO
|
|
; CURSEG. IF CURSEG IS 0, GAMESEG (THE FIRST SEGMENT [OR ZEROTH]) WILL
|
|
; CONTAIN THE BLOCK, AND IF CURSEG IS 1, SEG1 (GAMESEG + 64K) WILL CONTAIN
|
|
; THE BLOCK.
|
|
;
|
|
; NOTE THAT ES ALWAYS CONTAINS THE VALUE GAMESEG UNLESS WE NEED TO FETCH
|
|
; OR PUT SOMETHING IN THE SECOND SEGMENT. AT THAT POINT ES IS SET TO SEG1
|
|
; ONLY FOR THAT OPERATION.
|
|
;
|
|
PUBLIC GETBYT,FETCH,GTY1A$,GTSEG,GTY1$,GTY1B$,GTY2$,GTY3$
|
|
GETBYT PROC
|
|
PUSH SI ; SAVE THIS BEAR
|
|
PUSH AX ;SAVE BLOCK-POINTER
|
|
CMP FITS,1 ; (6) IS ALL OF THE GAME RESIDENT
|
|
JZ FETCH ; (6) IT'S THERE, GO GET IT
|
|
CMP AX,ENDLOD ;IS THIS A PRELOADED LOCATION?
|
|
JGE GTY1$ ;NO
|
|
FETCH: CMP AX,128 ; (A0) FIRST SEG IS SPECIAL CASE
|
|
JB GTY1A$ ; (A0) SEGS ALREADY SET UP RIGHT
|
|
SUB AX,128 ; (A0) BASIFY BLOCK NUMBER FOR SEG
|
|
MOV SI,SEG1 ; (A0) SET UP TO FIND SEG
|
|
MOV CURSEG,1 ; (A0) INIT THIS FOR LOOP
|
|
FETCH1: CMP AX,128 ; (6) CHECK SEGMENT FOR BLOCK
|
|
JB GTSEG ; (A0) GO AHEAD AND GET IT
|
|
SUB AX,128 ; (A0) IS IT IN THE NEXT SEG
|
|
ADD SI,1000H ; (A0) INC SEG POINTER
|
|
INC CURSEG ; (A0) INCREMENT OUR SEGMENT POINTER
|
|
JMP FETCH1
|
|
GTY1A$: MOV CL,9 ;YES, RECONSTRUCT POINTER
|
|
SHL AX,CL ;SHIFT BLOCK POINTER BY 9
|
|
OR AX,BX ;ADD IN THE OFFSET
|
|
XCHG AX,BX
|
|
|
|
JMP GTY1B$ ; (A16) GET BYTE (OR WORD)
|
|
|
|
GTSEG: MOV ES,SI ; (6) ADDRESS SEG1
|
|
JMP GTY1A$ ; (6) USE SEG0 LOGIC
|
|
GTY1$: CALL GETPAG ;FIND THE PROPER PAGE
|
|
ADD AX,BX ;POINT TO DESIRED BYTE
|
|
XCHG AX,BX
|
|
CMP CURSEG,0 ;(A0) CHECK SEGMENT THAT WERE LOOKING IN
|
|
JZ GTY1B$ ;(A0) ITS IN 0, GET IT NORMALLY
|
|
|
|
PUSH AX ; (A0) SAVE IMPORT REGISTERS
|
|
PUSH BX
|
|
PUSH DX
|
|
MOV DX,0 ; (A0) ZERO THIS FOR MUL
|
|
MOV AX,1000H ; (A0) INITIAL SEG ADDR
|
|
MOV BL,CURSEG ; (A0) GET CURRENT SEGMENT NUMBER
|
|
MOV BH,0 ; (A0) ZERO TOP HALF
|
|
MUL BX ; (A0) SEG NUMBER * GAMESEG
|
|
ADD AX,GAMESEG ; (A0) GET GAMESEG AS OFFSET
|
|
MOV SI,AX ; (A0) SAVE IN SI
|
|
POP DX ; (A0) RESTORES
|
|
POP BX
|
|
POP AX
|
|
MOV ES,SI ;(6) GETPAG RETURNED RIGHT POINTER
|
|
|
|
GTY1B$: CMP BX,0FFFFH ; (A16) CAN'T READ A WORD ACROSS SEG
|
|
JNE GTWRD1$
|
|
MOV CL,ES:[BX] ; GET BYTE
|
|
JMP GTY2$
|
|
GTWRD1$:MOV CX,ES:[BX] ; GET A WORD AND SAVE A BYTE
|
|
MOV LSTGET,CH ; SAVE NEXT SEQUENTIAL BYTE
|
|
MOV LSTGGD,1 ; (A16) INDICATE GOOD GET NEXT BYTE
|
|
|
|
GTY2$: SUB CH,CH ;CLEAR UNWANTED BYTE & RETURN IT
|
|
MOV BX,AX
|
|
MOV SI,GAMESEG ; (6) MAKE SURE GAME SEG IS RESTORED
|
|
MOV ES,SI ; (6) TO SEG 0
|
|
POP AX ;RESTORE BLOCK-POINTER
|
|
POP SI ; RESTORE THIS
|
|
INC BX ;UPDATE POINTER
|
|
CMP BX,200H ;END-OF-PAGE?
|
|
JNE GTY3$ ;NO
|
|
SUB BX,BX ;YES, CLEAR BYTE-POINTER
|
|
INC AX ;AND UPDATE BLOCK-POINTER
|
|
MOV LSTGGD,0 ; (A16) INDICATE NO NEXT BYTE
|
|
GTY3$: RET
|
|
GETBYT ENDP
|
|
|
|
; GET THE BYTE FOLLOWING THE LAST BYTE GOTTEN BY GETBYT
|
|
;
|
|
PUBLIC GETLST
|
|
GETLST PROC
|
|
MOV CL,LSTGET ; (A16) GET THE SAVED BYTE
|
|
MOV CH,0 ; (A16) ZERO TOP HALF
|
|
MOV LSTGGD,0 ; (A16) RESET FLAG
|
|
INC BX ; (A16) UPDATE POINTER
|
|
CMP BX,200H ; (A16) END OF PAGE?
|
|
JNE GTLST2
|
|
MOV BX,0 ; (A16) UPDATE BYTE POINTER
|
|
INC AX ; (A16) AND PAGE POINTER
|
|
GTLST2: RET
|
|
GETLST ENDP
|
|
|
|
|
|
;GET A WORD, BLOCK POINTER ES:AX, BYTE-POINTER ES:BX, RESULT IN CX
|
|
PUBLIC GETWRD
|
|
GETWRD PROC
|
|
PUSH DX ;SAVE
|
|
CALL GETBYT ;GET HIGH-ORDER BYTE
|
|
PUSH CX ;SAVE IT
|
|
CMP LSTGGD,1 ; (A16) FAST GET?
|
|
JNZ GETWRD1
|
|
CALL GETLST ; (A16) GET LAST BYTE
|
|
JMP GETWRD2
|
|
GETWRD1:CALL GETBYT ;GET LOW-ORDER BYTE
|
|
GETWRD2:POP DX ;GET OTHER BYTE
|
|
MOV CH,DL ;POSITION IT
|
|
POP DX ;RESTORE
|
|
RET
|
|
GETWRD ENDP
|
|
|
|
;GET THE NEXT BYTE, RETURN IT IN AX
|
|
; THIS ROUTINE ALSO WENT UNDER SIGNIFICANT REVISION TO ACCOMODATE MORE
|
|
; PAGING SPACE. TWO CASES HAD TO BE HANDLED: ALL OF GAME IN MEMORY AND
|
|
; MORE THAN 64K OF PAGING SPACE. THE FIRST CASE REQUIRED THAT THE VARIABLE
|
|
; ZPCSEG BE SET IN NEWZPC TO INDICATE IN WHICH SEGMENT OUR ZPC BLOCK COULD
|
|
; BE FOUND. THE SECOND CASE REQUIRES THAT ZPCSEG BE SET ONLY WHEN GETPAG
|
|
; IS CALLED FROM NEWZPC AND THE PAGE THAT IT GOT WAS PUT IN THE SECOND GAME
|
|
; SEGMENT.
|
|
;
|
|
PUBLIC NXTBYT,NXBA$,NXB1$
|
|
NXTBYT PROC
|
|
CMP LSTNGD,1 ; (A16) HAS THE ZPC BEEN PLAYED WITH SINCE?
|
|
JNE NXTBYT1 ; YES
|
|
JMP NXTLST ; (A16) NOPE, GET A BYTE QUICKLY
|
|
NXTBYT1:PUSH SI ;(6) PRESERVE THIS ONE TOO
|
|
PUSH BX ;SAVE
|
|
TEST ZPCFLG,1 ;(7n) HAS THIS PAGE SEEN FOUL PLAY?
|
|
JZ NXB0$ ; (7n) NOPE
|
|
CALL NEWZPC ; (7n) FIX INDEX INTO CURRENT PAGE
|
|
NXB0$: MOV BX,ZPC2 ;BYTE POINTER
|
|
ADD BX,CURPAG ;INDEX INTO CURRENT PAGE
|
|
CMP ZPCSEG,0 ;(6) WHERE ARE WE?
|
|
JZ NXBA$ ;(6) SEG0, ACT NORMALLY
|
|
PUSH BX ; (A0) SAVE THIS TO USE AS INDEX
|
|
PUSH DX ; (A0) SAVE THIS 'CUZ IT GETS CLOBBERED
|
|
XOR BH,BH ; (A0) STARTING FROM ZERO
|
|
MOV BL,ZPCSEG ; (A0) THIS VAR HAS WHAT SEG WERE IN
|
|
DEC BX ; (A0) SEG 1 MULS 1000*0+SEG1
|
|
MOV AX,1000H ; (A0) FIRST SEGMENT VALUE
|
|
MUL BX ; (A0) MULTIPLY BY SEGMENT NUMBER
|
|
ADD AX,SEG1 ; (A0) ADD IN ADDR OF SEG1
|
|
POP DX ; (A0) RESTORE IT
|
|
POP BX ; (A0) RESTORE OFFSET
|
|
MOV ES,AX ;(6) INTO ES
|
|
NXBA$: CMP BX,0FFFFH ; (A16) CAN'T CROSS SEG BOUNDARY
|
|
JNE NXBB$
|
|
MOV AL,ES:[BX] ; (A6) THIS COULD BE CROSSING A SEG
|
|
JMP NXBC$
|
|
|
|
NXBB$: MOV AX,ES:[BX] ; (A16) GET A WORD AND SWAP BYTES
|
|
MOV LSTNXT,AH ; (A16) SAVE HIGH BYTE FOR NEXT NXTBYT
|
|
MOV LSTNGD,1 ; (A16) SET FLAG TO INDICATE QUICK NEXT
|
|
|
|
NXBC$: PUSH AX ; (A6) SO PREVENT A CRASH
|
|
MOV SI,GAMESEG ;(6) GET BASE GAME SEG
|
|
MOV ES,SI ;(6) BACK INTO ES
|
|
INC ZPC2 ;UPDATE PC
|
|
CMP ZPC2,200H ;END-OF-PAGE?
|
|
JL NXB1$ ;NO
|
|
MOV LSTNGD,0 ; (A16) RESET FLAG, BYTE UNRELIABLE
|
|
CALL NEWZPC ;YES, UPDATE PAGE
|
|
NXB1$: POP AX ;RETRIEVE BYTE
|
|
SUB AH,AH ;CLEAR UNWANTED BYTE
|
|
POP BX ;RESTORE
|
|
POP SI
|
|
RET ;AND RETURN IT
|
|
NXTBYT ENDP
|
|
|
|
;
|
|
; GET THE NEXT BYTE FOLLOWING PREVIOUS NXTBYT CALL
|
|
PUBLIC NXTLST
|
|
NXTLST PROC
|
|
MOV AH,0 ; (A16) ZERO TOP HALF
|
|
MOV AL,LSTNXT ; (A16) GET BYTE
|
|
PUSH AX ; (A16) SAVE THE BYTE
|
|
MOV LSTNGD,0 ; (A16) GO THRU THE BIGGIE NEXT TIME
|
|
INC ZPC2 ; (A16) BUMP PC
|
|
CMP ZPC2,200H ; (A16) END OF PAGE?
|
|
JNE NXTL1
|
|
CALL NEWZPC
|
|
NXTL1: POP AX
|
|
RET
|
|
NXTLST ENDP
|
|
|
|
;GET THE NEXT WORD, RETURN IT IN AX
|
|
PUBLIC NXTWRD
|
|
NXTWRD PROC
|
|
PUSH BX ;SAVE
|
|
CALL NXTBYT ;GET HIGH-ORDER BYTE
|
|
PUSH AX ;SAVE IT
|
|
CALL NXTBYT ;GET LOW-ORDER BYTE
|
|
POP BX ;GET HIGH-ORDER BYTE
|
|
MOV AH,BL ;POSITION IT
|
|
POP BX ;RESTORE
|
|
RET ;RETURN THE WORD
|
|
NXTWRD ENDP
|
|
|
|
;GET AN ARGUMENT GIVEN ITS TYPE IN AX
|
|
PUBLIC GETARG
|
|
GETARG PROC
|
|
DEC AX ;EXAMINE ARGUMENT
|
|
JL NXTWRD ;0 MEANT LONG IMMEDIATE
|
|
JE GETAR2 ;1 MEANT SHORT IMMEDIATE
|
|
GETAR1: CALL NXTBYT ;2 MEANT VARIABLE, GET THE VAR
|
|
CMP AX,0 ;STACK?
|
|
JNE GETVAR ;NO, JUST GET THE VAR'S VALUE
|
|
POPZ AX ;YES, POP THE STACK
|
|
RET
|
|
GETAR2: JMP NXTBYT
|
|
GETARG ENDP
|
|
|
|
;GET VALUE OF A VARIABLE, VAR IN AX, VALUE RETURNED IN AX
|
|
PUBLIC GETVAR
|
|
GETVAR PROC
|
|
CMP AX,0 ;STACK?
|
|
JNE GTV1$ ;NO
|
|
POPZT AX ;YES, GET TOP-OF-STACK
|
|
RET
|
|
GTV1$: PUSH BP ;SAVE
|
|
CMP AX,16 ;LOCAL?
|
|
JGE GTV3$ ;NO
|
|
DEC AX ;YES, POINT TO PROPER STACK ELEMENT
|
|
SHL AX,1
|
|
MOV BP,ZLOCS
|
|
SUB BP,AX
|
|
MOV AX,[BP] ;AND GET IT
|
|
GTV2$: POP BP ;RESTORE
|
|
RET
|
|
GTV3$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT
|
|
SHL AX,1
|
|
ADD AX,GLOTAB
|
|
MOV BP,AX ;AND GET IT
|
|
GTAWRD A,[BP]
|
|
JMP GTV2$
|
|
GETVAR ENDP
|
|
|
|
;UPDATE VALUE OF A VARIABLE, VAR IN AX, NEW VALUE IN BX
|
|
PUBLIC PUTVAR
|
|
PUTVAR PROC
|
|
CMP AX,0 ;STACK?
|
|
JNE PTV1$ ;NO
|
|
PUSHZT BX ;YES, UPDATE TOP-OF-STACK
|
|
RET
|
|
PTV1$: CMP AX,16 ;LOCAL?
|
|
JGE PTV2$ ;NO
|
|
PUSH BP ;SAVE
|
|
DEC AX ;YES, POINT TO PROPER STACK ELEMENT
|
|
SHL AX,1
|
|
MOV BP,ZLOCS
|
|
SUB BP,AX
|
|
MOV [BP],BX ;AND UPDATE IT
|
|
POP BP ;RESTORE
|
|
RET
|
|
PTV2$: SUB AX,16 ;GLOBAL, POINT TO PROPER GLOBAL TABLE ELEMENT
|
|
SHL AX,1
|
|
ADD AX,GLOTAB
|
|
XCHG AX,BX ;AND UPDATE IT
|
|
PTAWRD [BX],A
|
|
RET
|
|
PUTVAR ENDP
|
|
|
|
;RETURN VAL IN AX TO LOCATION SPECIFIED BY NEXTBYTE
|
|
;DESTROYS BX, BUT IS USUALLY CALLED AT END OF TOP-LEVEL FUNCTION
|
|
PUBLIC BYTVAL
|
|
BYTVAL PROC
|
|
SUB AH,AH ;THIS ENTRY FOR BYTE VALUE TO CLEAR HIGH BYTE
|
|
JMP PUTVAL
|
|
BYTVAL ENDP
|
|
|
|
PUBLIC PUTVAL
|
|
PUTVAL PROC
|
|
MOV BX,AX ;NORMAL ENTRY
|
|
CALL NXTBYT ;GET VAR TO USE
|
|
CMP AX,0 ;STACK?
|
|
JNE PUTVAR ;NO, GO STORE VALUE
|
|
PUSHZ BX ;YES, PUSH ONTO STACK
|
|
RET ;AND RETURN
|
|
PUTVAL ENDP
|
|
|
|
;PREDICATE HANDLERS TRUE & FALSE
|
|
;DESTROYS REGISTERS, BUT ARE ONLY CALLED FROM END OF TOP-LEVEL FCNS
|
|
PUBLIC PFALSE,PTRUE
|
|
PFALSE PROC
|
|
SUB BX,BX ;PREDICATE WAS FALSE, CLEAR FLAG
|
|
JMP PPRED
|
|
PFALSE ENDP
|
|
|
|
PTRUE PROC
|
|
MOV BX,1 ;PREDICATE WAS TRUE, SET FLAG
|
|
JMP PPRED
|
|
PTRUE ENDP
|
|
|
|
PUBLIC PPRED
|
|
PPRED PROC
|
|
CALL NXTBYT ;GET FIRST (OR ONLY) PREDICATE JUMP BYTE
|
|
TEST AX,80H ;NORMAL POLARITY PREDICATE?
|
|
JE PPR1$ ;NO, LEAVE FLAG ALONE
|
|
INC BX ;YES, INCREMENT FLAG
|
|
PPR1$: TEST AX,40H ;ONE-BYTE JUMP OFFSET?
|
|
JE PPR2$ ;NO
|
|
AND AX,0FF3FH ;YES, CLEAR SPECIAL BITS
|
|
JMP PPR3$
|
|
PPR2$: AND AX,0FF3FH ;CLR SPECIAL BITS FROM HIGH-ORDER OFFSET BYTE
|
|
MOV CX,AX ;HIGH-ORDER BYTE
|
|
CALL NXTBYT ;GET LOW-ORDER BYTE
|
|
MOV AH,CL ;MOVE IN HIGH-ORDER BITS
|
|
TEST AX,2000H ;IS NUMBER NEGATIVE (14-BIT 2'S COMP NUMBER)?
|
|
JE PPR3$ ;NO
|
|
OR AX,0C000H ;YES, MAKE 16-BIT NUMBER NEGATIVE
|
|
PPR3$: DEC BX ;TEST FLAG
|
|
JE PPR6$ ;WAS 1, THAT MEANS DO NOTHING
|
|
CMP AX,0 ;ZERO JUMP?
|
|
JNE PPR4$ ;NO
|
|
JMP OPRFAL ;YES, THAT MEANS DO AN RFALSE
|
|
PPR4$: DEC AX ;ONE JUMP?
|
|
JNE PPR5$ ;NO
|
|
JMP OPRTRU ;YES, THAT MEANS DO AN RTRUE
|
|
PPR5$: DEC AX ;ADJUST OFFSET
|
|
MOV LSTNGD,0 ; (A16) NXTBYT WILL BE LONG
|
|
ADD ZPC2,AX ;ADD TO PC
|
|
CMP ZPC2,200H ; (A15) DID WE CROSS A BOUNDARY?
|
|
JB PPR6$ ; (A15) DO NEWZPC ONLY IF PAGE IS CROSSED
|
|
JMP NEWZPC ;AND UPDATE ZPC STUFF
|
|
PPR6$: RET
|
|
PPRED ENDP
|
|
|
|
;SPLIT BYTE-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE OFFSET IN BX
|
|
PUBLIC BSPLTB
|
|
BSPLTB PROC
|
|
MOV BX,AX
|
|
XCHG AL,AH ;EXTRACT BLOCK BITS
|
|
SHR AX,1
|
|
AND AX,7FH ;CLEAR UNWANTED BITS
|
|
AND BX,1FFH ;CLEAR ALL BUT BYTE OFFSET BITS
|
|
RET
|
|
BSPLTB ENDP
|
|
|
|
;SPLIT WORD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX
|
|
PUBLIC BSPLIT
|
|
BSPLIT PROC
|
|
MOV BX,AX
|
|
MOV AL,AH ;EXTRACT BLOCK BITS
|
|
SUB AH,AH ;CLEAR UNWANTED BITS
|
|
SUB BH,BH ;CLEAR ALL BUT WORD OFFSET BITS
|
|
SHL BX,1 ;CONVERT TO BYTE OFFSET
|
|
RET
|
|
BSPLIT ENDP
|
|
|
|
;SPLIT QUAD-POINTER IN AX TO BLOCK-POINTER IN AX & BYTE-OFFSET IN BX
|
|
PUBLIC BSPLITQ
|
|
BSPLITQ PROC
|
|
PUSH CX ; (A0) SAVE AND USE FOR SHIFT COUND
|
|
MOV CL,7 ; (A0) ZIP BIT SHIFT WOULD LOSE BITS
|
|
MOV BX,AX
|
|
SHR AX,CL ; (A0) RIGHT SHIFT 7 TO GET BLOCK POINTER
|
|
AND BX,7FH ;CLEAR ALL BUT WORD OFFSET BITS
|
|
ADD BX,BX
|
|
ADD BX,BX
|
|
POP CX ; (A0) RESTORE CX
|
|
RET
|
|
BSPLITQ ENDP
|
|
|
|
SUBTTL OBJECT HACKERS
|
|
PAGE +
|
|
|
|
PUBLIC OBJLOC,NXTPRP
|
|
;GIVEN OBJ NUMBER IN AX, RETURN OBJ LOCATION IN AX
|
|
OBJLOC PROC
|
|
PUSH BX ;MULTIPLY BY OBJECT LENGTH
|
|
PUSH DX ; (A0) PRESERVE FROM SIGN EXTENSION
|
|
MOV BX,OBJLEN ; (A0) GET LENGTH OF OBJECT FOR MULTIPLY
|
|
MUL BX ; (A0) USE BX AS MULTIPICAND
|
|
POP DX ; (A0) RESTORE DX
|
|
POP BX ;RESTORE
|
|
ADD AX,OBJTAB ;INDEX INTO OBJECT TABLE
|
|
ADD AX,PROPDEF ; (A0) SKIPPING DEFAULT PROPERTY TABLE
|
|
RET
|
|
OBJLOC ENDP
|
|
|
|
;GIVEN POINTER TO A PROPERTY IN BX!, UPDATE IT TO POINT TO NEXT PROP
|
|
NXTPRP PROC
|
|
PUSH AX ;SAVE
|
|
PUSH CX ;SAVE
|
|
MOV AL,ES:[BX] ; GET PROPERTY IDENTIFIER
|
|
INC BX ; (A0) ADVANCE PROP BYTE POINTER
|
|
TEST AL,80H ; (A0) PROPERTY LENGTH GREATER THAN 2?
|
|
JNZ NXTPR1 ; (A0) YES
|
|
TEST AL,40H ; (A0) NO, PROPERTY LENGTH 2?
|
|
JZ NXTPR2 ; (A0) NO, PROPERTY LENGTH 1
|
|
INC BX ; (A0) UPDATE THE POINTER
|
|
NXTPR2: INC BX ; (A0) UPDATE THE POINTER
|
|
POP CX
|
|
POP AX
|
|
RET
|
|
;
|
|
NXTPR1: MOV AL,ES:[BX] ; (A0) GET SECOND PROPERTY LENGTH BYTE
|
|
AND AL,MASK PROPNUM ; (A0) MASK OFF HIGH BITS
|
|
INC BX ; (A0) UPDATE POINTER
|
|
XOR AH,AH ; (A0) CLEAR THIS FOR SAFETY
|
|
ADD BX,AX ; (A0) ADD IN LENGTH OF PROPERTY
|
|
POP CX ;RESTORE
|
|
POP AX ;RESTORE
|
|
RET
|
|
NXTPRP ENDP
|
|
|