;; ======================================================================== ;; ;; MOB_LL.ASM: Low level MOB manipulation code. ;; ;; ;; ;; Note: This code does not implement animation or motion. ;; ;; ;; ;; For each MOB, we maintain the following status information: ;; ;; ;; ;; -- X/Y coordinate. This coordinate pair is stored as a 16-bit ;; ;; 8.8 quantity across two 8-bit locations for each MOB. ;; ;; The MOB display code ignores the fractional portion of the X/Y ;; ;; coordinates. ;; ;; ;; ;; -- Attribute index. This is a small integer index that points to ;; ;; an MOB attribute table entry in ROM. This attribute table entry ;; ;; sets up X/Y adjust values, flags (mirror, size, flip, color) and ;; ;; color. (Some games may need to factor color out separately.) ;; ;; ;; ;; -- Picture index. This is an 8-bit value which indexes into the ;; ;; GFX_DATA array. We multiply this value by 4 words prior to ;; ;; generating the index. Valid indices are 0..127. We use bit ;; ;; 7 to indicate that the picture number has changed since the ;; ;; last interrupt. (Strictly, we don't need to remember this ;; ;; value after we've loaded the card into GRAM, except that ;; ;; animation code might wish to refer to this to know what frame ;; ;; number is next.) Note that we actually store TWO picture ;; ;; indices for each MOB, one for the upper half, and one for the ;; ;; lower half. ;; ;; ;; ;; Thus, this code stores 7 bytes for each MOB. The X/Y data is ;; ;; stored interleaved in its own array. The attribute and picture ;; ;; index tables are each stored separately. The total storage devoted ;; ;; to the 8 MOBs by this code is 56 bytes. ;; ;; ;; ;; Notice that we do not store the GRAM card allocated to the MOB. The ;; ;; MOBs are assigned to GRAM cards 48 through 63, with two GRAM cards ;; ;; devoted to each MOB, thus allowing 8x16 MOBs to be displayed. If a ;; ;; given MOB is only an 8x8 MOB, the neighboring GRAM card can be used ;; ;; for other purposes. ;; ;; ;; ;; In addition to the tables described above, we also store a 16-bit ;; ;; collision dispatch pointer. Whenever a collision is detected between ;; ;; a MOB and another MOB, the background or the screen border, we will ;; ;; schedule the dispatch function for that MOB, if one is set. In order ;; ;; to filter out unwanted collisions, we AND each collision entry with ;; ;; a collision mask. A second 16-bit pointer points to the collision ;; ;; mask table. ;; ;; ;; ;; For performance reasons, we store a 32 word STIC register shadow in ;; ;; 16-bit RAM. This allows us to do most of our computation outside ;; ;; the time-critical vertical blank period. ;; ;; ;; ;; ------------------------------------------------------------------------ ;; ;; GLOBAL VARIABLES REQUIRED BY THIS MODULE ;; ;; ;; ;; Name Length Width Purpose ;; ;; MOB_FLG 1 8-bit Flag indicating what MOB updates to do ;; ;; MOB_PIC 16 8-bit MOB picture table; 2 cards per MOB. ;; ;; MOB_ATR 8 8-bit MOB attribute index table. 1 per MOB. ;; ;; MOB_XYP 32 8-bit MOB X/Y position table, 8.8 data. ;; ;; MOB_IGN 1 16-bit MOB collision ignore table ptr. ;; ;; MOB_DIS 1 16-bit MOB collision dispatch table ptr. ;; ;; STICSH 32 16-bit STIC MOB register shadow. ;; ;; TSKQHD 1 8-bit \_ Task queue vars. Collision disp. ;; ;; TSKQTL 1 8-bit / uses these to avoid overflows. ;; ;; ;; ;; ------------------------------------------------------------------------ ;; ;; EXTERNAL STRUCTURES REFERENCED BY THIS MODULE ;; ;; ;; ;; GFX_DATA Actual graphics picture data to load into GRAM. ;; ;; ATR_DATA MOB attribute table; 3 words per record. ;; ;; ;; ;; ------------------------------------------------------------------------ ;; ;; HELPER MACROS ;; ;; ;; ;; AtrAddr(n) Address of Attribute Table slot for MOB #n ;; ;; PicAddr(n,top) Address of upper Picture Table slot for MOB #n ;; ;; PicAddr(n,bot) Address of lower Picture Table slot for MOB #n ;; ;; XYPAddr(n,x_lo) Address of LSB of X Position in XYP slot for MOB #n. ;; ;; XYPAddr(n,x_hi) Address of MSB of X Position in XYP slot for MOB #n. ;; ;; XYPAddr(n,y_lo) Address of LSB of Y Position in XYP slot for MOB #n. ;; ;; XYPAddr(n,y_hi) Address of MSB of Y Position in XYP slot for MOB #n. ;; ;; ;; ;; ======================================================================== ;; ;; ======================================================================== ;; ;; AtrAddr(n) -- Computes address of attribute table entry for MOB n ;; ;; ======================================================================== ;; MACRO AtrAddr(n) (MOB_ATR + (%n%)) ENDM ;; ======================================================================== ;; ;; PicAddr(n,top|bot) -- Computes address of upper/lower picture for MOB ;; ;; ======================================================================== ;; MACRO PicAddr(n, lh) (MOB_PIC + 2*(%n%) + MOB_MACRO.pic_%lh%) ENDM ;; ======================================================================== ;; ;; XYPAddr(n,byte) -- Computes address of specified byte in X/Y posn tbl. ;; ;; ======================================================================== ;; MACRO XYPAddr(n, b) (MOB_XYP + 4*(%n%) + MOB_MACRO.xyp_%b%) ENDM MOB_MACRO STRUCT 0 @@pic_top EQU 0 @@pic_bot EQU 1 @@xyp_x_lo EQU 0 @@xyp_x_hi EQU 1 @@xyp_y_lo EQU 2 @@xyp_y_hi EQU 3 ENDS ;; ======================================================================== ;; ;; MOB_ISR -- Update the MOB registers for the 8 MOBs. ;; ;; ======================================================================== ;; MOB_ISR PROC PSHR R5 ;; ------------------------------------------------------------ ;; ;; Now for the time critical stuff. When we get here, we ;; ;; have about 3600 cycles to do all the STIC/GRAM stuff. We ;; ;; actually have a little more than that, but not much. ;; ;; ------------------------------------------------------------ ;; ;; ------------------------------------------------------------ ;; ;; Copy X, Y and A registers to STIC from the shadow if the ;; ;; flag says we need to. ;; ;; ------------------------------------------------------------ ;; MVII #4, R0 ; 8 \ AND MOB_FLG, R0 ; 10 | If bit 2 is clear, we BEQ @@skip_xya ; 9/7 |- don't need STIC X/Y/A XOR MOB_FLG, R0 ; 10 | copy for this frame MVO R0, MOB_FLG ; 11 / CLRR R4 ; 6 MVII #STICSH, R5 ; 8 ;---- ; 60 REPEAT 24 MVI@ R5, R0 ; 8 get a word from shadow MVO@ R0, R4 ; 9 put a word to the STIC ENDR ;---- ; 408 = (17 * 24) ; 60 (carried forward) ;---- ; 468 @@skip_xya: ;; ------------------------------------------------------------ ;; ;; Copy collision registers out of STIC, clearing the ones ;; ;; that are there. We actually do a merge, just in case not ;; ;; all the collisions were processed last frame. ;; ;; ------------------------------------------------------------ ;; @@c1 SET $18 ; 0 @@c2 SET STICSH + 24 ; 0 MVII #$18, R4 ; 8 MVII #STICSH+24, R5 ; 8 CLRR R2 ; 6 ;---- ; 22 ; 468 (carried forward) ;---- ; 480 REPEAT 8 MVI @@c1, R0 ; 10 Read collision register MOVR R0, R1 ; 6 store a copy XOR @@c2, R1 ; 10 merge bits into shadow copy AND @@c2, R0 ; 10 some might be repeats XORR R1, R0 ; 6 make sure those stay merged MVO@ R2, R4 ; 9 clear collision register MVO@ R0, R5 ; 9 store merged collision to shadow @@c1 SET @@c1 + 1 ; 0 @@c2 SET @@c2 + 1 ; 0 ENDR ;---- ; 480 = 60 * 8 ; 480 (carried forward) ;---- ; 960 @@pic_ok: ;; ------------------------------------------------------------ ;; ;; Step through picture-index array, copying in GRAM cards. ;; ;; We only have enough time to copy a handful of cards each ;; ;; frame. This means we might get some animations out of sync ;; ;; if too much is moving per frame. ;; ;; ------------------------------------------------------------ ;; MVII #$3800+48*8,R5 ; 8 point to card #48 in GRAM MVII #MOB_PIC, R3 ; 8 pointer to picture number table MVII #10, R2 ; 8 maximum number of cards per frame MVII #16, R1 ; 8 up to 16 pictures to worry about ;---- ; 32 ; 960 (carried forward) ;---- ; 992 @@pic_loop: MVI@ R3, R0 ; 8 Get the picture number SUBI #$80, R0 ; 8 is the 'update flag' set? BMI @@pic_next ; 9/7 No? Skip this one MVO@ R0, R3 ; 9 Store picture number sans flag ;---- ; 25 (branch taken) ; 32 (branch not taken) SLL R0, 2 ; 8 Multiply picture number by 4 MVII #GFX_DATA, R4 ; 8 ADDR R0, R4 ; 6 Index into graphics data ;---- ; 22 ; 32 (carried forward) ;---- ; 54 REPEAT 4 MVI@ R4, R0 ; 8 get 2 rows of data MVO@ R0, R5 ; 9 store 1st row SWAP R0 ; 6 MVO@ R0, R5 ; 9 store 2nd row ENDR ;---- ; 128 = 32*4 ; 54 ;---- ; 182 DECR R2 ; 6 Have we reached our card limit? BEQ @@pic_done ; 9/7 yes: leave ;---- ; 13 ; 182 (carried forward) ;---- ; 195 (branch not taken) INCR R3 ; 6 DECR R1 ; 6 BNEQ @@pic_loop ; 9 ;---- ; 21 ; 195 (carried forward) ;---- ; 216 per iteration w/ copy B @@pic_done ; 9 @@pic_next: ADDI #8, R5 ; 8 INCR R3 ; 6 DECR R1 ; 6 BNEQ @@pic_loop ; 7/9 ;---- ; 29 ; 25 (carried forward) ;---- ; 54 per iteration w/out copy @@pic_done: ; worst case perf: 216*max_copy + 54*(16-max_copy) ; ; assume max_copy = 10: ;2484 = 216*10 + 54*6 ; 9 (lonely exit branch above) ; 997 (carried forward) ;---- ;3490 we just fit. :-) PULR PC ENDP ;; ======================================================================== ;; ;; MOB_STICSH -- Recalculate the STIC Shadow. This could be called ;; ;; in the non-interrupt per-frame code. ;; ;; ======================================================================== ;; MOB_STICSH PROC PSHR R5 ; 9 ;; ------------------------------------------------------------ ;; ;; Step through attribute table, loading the STIC registers ;; ;; for each MOB. We do this first, since STIC registers have ;; ;; the tightest timing constraints. Note: If we start to ;; ;; run out of cycles, we'll have to compute the STIC register ;; ;; image outside the ISR into a STIC shadow, and then block ;; ;; copy the shadow into the STIC. ;; ;; ------------------------------------------------------------ ;; MVII #2, R0 ; 8 Do we need to recompute STICSH? AND MOB_FLG, R0 ; 10 BNEQ @@skip_sticsh ; 9/7 If bit 1 set, then no. MVO R0, MOB_FLG ; 10 disable STICSH copying. MVII #STICSH, R2 ; 8 point R2 to STIC shadow MVII #MOB_XYP+1, R3 ; 8 point R3 to MOB X/Y pos table MVII #MOB_ATR, R4 ; 8 point R4 to MOB attribute table MVII #$980, R1 ; 8 point to GRAM card #48 ;---- ; 76 @@sticsh_loop: MVI@ R4, R0 ; 8 get attribute table index MVII #ATR_DATA, R5 ; 8 point to global attribute table ADDR R0, R5 ; 6 \ ADDR R0, R5 ; 6 |- multiply by 3 ADDR R0, R5 ; 6 / MVI@ R5, R0 ; 8 get X register template ADD@ R3, R0 ; 8 add in upper 8 from X position MVO@ R0, R2 ; 9 store X register ADDI #2, R3 ; 8 point to upper 8 of Y position ADDI #8, R2 ; 8 point to Y register MVI@ R5, R0 ; 8 get Y register template ADD@ R3, R0 ; 8 add in upper 8 from Y position MVO@ R0, R2 ; 9 store Y register ADDI #2, R3 ; 8 point to upper 8 of next X pos ADDI #8, R2 ; 8 point to A register MVI@ R5, R0 ; 8 get A register value ADDR R1, R0 ; 6 offset to appropriate GRAM card MVO@ R0, R2 ; 9 store A register SUBI #15, R2 ; 8 point to next X register ADDI #16, R1 ; 8 move by two GRAM cards per MOB CMPI #STICSH+8, R2 ; 8 are we at the end? BNEQ @@sticsh_loop ; 9 ;---- ;1376 = 172*8 cycles for loop ; 76 (carried forward) MVII #6, R0 ; 8 Flag: STICSH done, do STIC upd MVO R0, MOB_FLG ; 11 ;---- ;1471 @@skip_sticsh PULR PC ENDP ;; ======================================================================== ;; ;; MOB_COLDISP -- Dispatch for MOB collisions. ;; ;; ======================================================================== ;; MOB_COLDISP PROC PSHR R5 ;; ------------------------------------------------------------ ;; ;; Dispatch collisions that we found. To avoid saturating ;; ;; the task queue, look at the task queue and decide how many ;; ;; collisions we can dispatch this frame. ;; ;; ------------------------------------------------------------ ;; MVI TSKQHD, R0 ; 10 \ ADDI #TSKQM-1, R0 ; 8 |- find room in task queue, SUB TSKQTL, R0 ; 10 / minus an extra slot. BLE @@col_done ; 9/7 if underflow, don't do any. ;---- ; 43 (fallthru) MVII #STICSH+24, R4 ; 8 MVI MOB_IGN, R5 ; 10 MVI MOB_DIS, R2 ; 10 CLRR R3 ; 6 ;---- ; 34 ; 43 (carried forward) ;---- ; 77 @@col_loop: MVI@ R4, R1 ; 8 get collision bits AND@ R5, R1 ; 8 clear away ignored bits BEQ @@col_next ; 9/7 all ignored? goto next MOB ;---- ; 23 (fallthru) DECR R4 ; 6 \__ clear this MOB's MVO@ R3, R4 ; 9 / collision history PSHR R0 ; 9 \ PSHR R2 ; 9 | PSHR R4 ; 9 | PSHR R5 ; 9 | MVI@ R2, R0 ; 8 | Queue dispatch for this JSRD R5, QTASK ; 150 |- MOB's collision handler. PULR R5 ; 11 | (cycle count approximate.) PULR R4 ; 11 | PULR R2 ; 11 | PULR R0 ; 11 / DECR R0 ; 6 \__ make sure we don't saturate BEQ @@col_done ; 9/7 / the task queue. ;---- ; ; 23 (carried forward) ;---- ; @@col_next: INCR R2 ; 6 CMPI #STICSH+32, R4 ; 8 BLT @@col_loop ; 7/9 ;---- ; 23 ; (carried forward) ;---- ; = 8 * worst case (8 iters) ; 77 (carried forward) ;---- ; worst case. @@col_done: PULR PC ENDP ;; ======================================================================== ;; ;; FLG_STICSH -- Flag that STICSH needs to be recomputed. ;; ;; ======================================================================== ;; FLG_STICSH PROC MVI MOB_FLG, R2 ; \ ANDI #$FFFF XOR 2, R2 ; |- force STICSH update. MVO R2, MOB_FLG ; / JR R5 ENDP ;; ======================================================================== ;; ;; MOB_CREATE -- Initialize and activate a MOB ;; ;; ;; ;; INPUTS for MOB_CREATE ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB number (0..7) ;; ;; 1 decle: MOB X/Y position, packed ;; ;; 1 decle: MOB attribute record. ;; ;; 1 decle: MOB picture numbers, packed ;; ;; ;; ;; INPUTS for MOB_CREATE.1 ;; ;; R1 -- MOB # (0..7) ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB X/Y position, packed ;; ;; 1 decle: MOB attribute record. ;; ;; 1 decle: MOB picture numbers, packed ;; ;; ;; ;; INPUTS for MOB_CREATE.2 ;; ;; R1 -- MOB # (0..7) ;; ;; R2 -- MOB X/Y position, packed ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB attribute record. ;; ;; 1 decle: MOB picture numbers, packed ;; ;; ;; ;; OUTPUT ;; ;; R1 -- MOB # * 4 ;; ;; R2, R3 -- trashed ;; ;; R0, R5 -- unmodified ;; ;; ;; ;; NOTES on packed input formats: ;; ;; ;; ;; Packed picture numbers are stored with the 'upper half' picture ;; ;; number in the lower 8 bits, and the 'lower half' picture number ;; ;; in the upper 8 bits. If there is no 'lower half' picture (eg. ;; ;; this is an 8x8 MOB), put $80 in that byte. ;; ;; ;; ;; Packed coordinates are stored w/ the X coordinate in the lower 8 ;; ;; bits, and the Y coordinate in the upper 8 bits. Valid range for ;; ;; the X coordinate is 0..255. Valid range for the Y coordinate is ;; ;; 0..127. ;; ;; ======================================================================== ;; MOB_CREATE PROC MVI@ R5, R1 ; get MOB # @@1: MVI@ R5, R2 ; get X, Y coordinates (packed) @@2: PSHR R2 MVI@ R5, R2 ; get attribute # MVII #MOB_ATR, R3 ADDR R1, R3 ; index into MOB attribute table MVO@ R2, R3 ; store attribute # ADDI #(MOB_PIC-MOB_ATR) AND $FFFF, R3 ; point to MOB pic tbl ADDR R1, R3 ; 2 bytes per MOB. MVI@ R5, R2 ; get picture #s XORI #$8080, R2 ; set 'need refresh' flag MVO@ R2, R3 ; store upper card's picture # INCR R3 SWAP R2 BPL @@no_lower ; is lower card empty? MVO@ R2, R3 ; store lower card's picture # @@no_lower: ADDI #(MOB_XYP-MOB_PIC-1) AND $FFFF, R3 ; point to MOB X/Y tbl SLL R1, 1 ADDR R1, R3 ; 4 bytes per MOB PULR R2 CLRR R1 MVO@ R1, R3 ; fractional part of X is 0 INCR R3 MVO@ R2, R3 ; store integer part of X INCR R3 SWAP R2 MVO@ R1, R3 ; fractional part of Y is 0 INCR R3 MVO@ R2, R3 ; store integer part of X B FLG_STICSH ; flag that STIC shadow update needed ENDP ;; ======================================================================== ;; ;; MOB_DESTROY -- Destroys a given MOB. ;; ;; ;; ;; INPUTS for MOB_DESTROY ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB number (0..7) ;; ;; ;; ;; INPUTS for MOB_DESTROY.1 ;; ;; R1 -- MOB # (0..7) ;; ;; ;; ;; OUTPUT ;; ;; R1 -- MOB # * 4 ;; ;; R2 -- trashed ;; ;; R3 -- trashed ;; ;; ======================================================================== ;; MOB_DESTROY PROC MVI@ R5, R1 ; get MOB # @@1: MVII #ATR.dead, R2 MVII #MOB_ATR, R3 ; point to attribute table ADDR R1, R3 MVO@ R2, R3 ; clear attribute MVII #XYPAddr(0,x_hi),R3 ; SLL R1, 2 ; ADDR R1, R3 ; 4 bytes per MOB MVO@ R2, R3 ; zero out MSB of X coord only. B FLG_STICSH ; force STICSH update ENDP ;; ======================================================================== ;; ;; MOB_MOVE -- Given a DX/DY, update the relative position for one MOB. ;; ;; ;; ;; INPUTS for MOB_MOVE ;; ;; R5 -- Invocation record ;; ;; 1 decle: DX (8.8 number) ;; ;; 1 decle: DY (8.8 number) ;; ;; 1 decle: MOB # (0..7) ;; ;; ;; ;; INPUTS for MOB_MOVE.1 ;; ;; R2 -- DX (8.8 number) ;; ;; R3 -- DY (8.8 number) ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB # (0..7) ;; ;; ;; ;; INPUTS for MOB_MOVE.2 ;; ;; R1 -- MOB # (0..7) ;; ;; R2 -- DX (8.8 number) ;; ;; R3 -- DY (8.8 number) ;; ;; ;; ;; OUTPUT ;; ;; ======================================================================== ;; MOB_MOVE PROC MVI@ R5, R2 ; get DX MVI@ R5, R3 ; get DY @@1: MVI@ R5, R1 ; get MOB update bitmap @@2: MVII #MOB_XYP,R4 ; point to MOB XY position table SLL R1, 2 ADDR R1, R4 SDBD ; \ ADD@ R4, R2 ; |_ add X to DX and Y to DY. SDBD ; | ADD@ R4, R3 ; / SUBI #4, R4 ; rewind back to start of record MVOD@ R2, R4 ; \ ANDI #$7FFF, R3 ; |- Store updated X and Y MVOD@ R3, R4 ; / Also, don't let Y above 127. B FLG_STICSH ; force STICSH update ENDP ;; ======================================================================== ;; ;; MOB_MOVE_M -- Given a DX/DY, update the relative position for one or ;; ;; more MOBs. This is useful when multiple MOBs form a ;; ;; single object. ;; ;; ;; ;; INPUTS for MOB_MOVE_M ;; ;; R5 -- Invocation record ;; ;; 1 decle: DX (8.8 number) ;; ;; 1 decle: DY (8.8 number) ;; ;; 1 decle: MOB update bitmap (1 bit per MOB#) ;; ;; ;; ;; INPUTS for MOB_MOVE_M.1 ;; ;; R2 -- DX (8.8 number) ;; ;; R3 -- DY (8.8 number) ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB update bitmap (1 bit per MOB#) ;; ;; ;; ;; INPUTS for MOB_MOVE_M.2 ;; ;; R1 -- MOB update bitmap (1 bit per MOB#) ;; ;; R2 -- DX (8.8 number) ;; ;; R3 -- DY (8.8 number) ;; ;; ;; ;; OUTPUT ;; ;; ======================================================================== ;; MOB_MOVE_M PROC MVI@ R5, R2 ; get DX @@0: MVI@ R5, R3 ; get DY @@1: MVI@ R5, R1 ; get MOB update bitmap @@2: PSHR R5 MOVR R3, R5 MVII #MOB_XYP-4,R4 ; point to MOB XY position table @@loop1: ADDI #4, R4 @@loop: SARC R1 BNC @@skip MOVR R2, R0 ; copy DX to a scratch register MOVR R5, R3 ; copy DY to a scratch register SDBD ; \ ADD@ R4, R0 ; |_ add X to DX and Y to DY. SDBD ; | ADD@ R4, R3 ; / SUBI #4, R4 ; rewind back to start of record MVOD@ R0, R4 ; \ ANDI #$7FFF, R3 ; |- Store updated X and Y MVOD@ R3, R4 ; / Also, don't let Y above 127. TSTR R1 ; any more? BNEQ @@loop PULR R5 B FLG_STICSH ; force STICSH update @@skip BNEQ @@loop1 PULR R5 B FLG_STICSH ; force STICSH update ENDP ;; ======================================================================== ;; ;; MOB_GOTO -- Put a MOB at the specified X/Y. ;; ;; ;; ;; INPUTS for MOB_GOTO ;; ;; R5 -- Invocation record ;; ;; 1 decle: X (8.8 number) ;; ;; 1 decle: Y (8.8 number) ;; ;; 1 decle: MOB # (0..7) ;; ;; ;; ;; INPUTS for MOB_GOTO.1 ;; ;; R2 -- X (8.8 number) ;; ;; R3 -- Y (8.8 number) ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB # (0..7) ;; ;; ;; ;; INPUTS for MOB_GOTO.2 ;; ;; R1 -- MOB # (0..7) ;; ;; R2 -- X (8.8 number) ;; ;; R3 -- Y (8.8 number) ;; ;; ;; ;; OUTPUT ;; ;; ======================================================================== ;; MOB_GOTO PROC MVI@ R5, R2 ; get X MVI@ R5, R3 ; get Y @@1: MVI@ R5, R1 ; get MOB # @@2: MVII #MOB_XYP,R4 ; point to MOB XY position table SLL R1, 2 ADDR R1, R4 MVOD@ R2, R4 ; \ ANDI #$7FFF, R3 ; |- Store updated X and Y MVOD@ R3, R4 ; / Also, don't let Y above 127. B FLG_STICSH ; force STICSH update ENDP ;; ======================================================================== ;; ;; MOB_GOTO_M -- Put one or more MOBs at a given X/Y location. ;; ;; This is useful when multiple MOBs form a single object. ;; ;; ;; ;; INPUTS for MOB_GOTO_M ;; ;; R5 -- Invocation record ;; ;; 1 decle: X (8.8 number) ;; ;; 1 decle: Y (8.8 number) ;; ;; 1 decle: MOB update bitmap (1 bit per MOB#) ;; ;; ;; ;; INPUTS for MOB_GOTO_M.1 ;; ;; R2 -- X (8.8 number) ;; ;; R3 -- Y (8.8 number) ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB update bitmap (1 bit per MOB#) ;; ;; ;; ;; INPUTS for MOB_GOTO_M.2 ;; ;; R1 -- MOB update bitmap (1 bit per MOB#) ;; ;; R2 -- X (8.8 number) ;; ;; R3 -- Y (8.8 number) ;; ;; ;; ;; OUTPUT ;; ;; ======================================================================== ;; MOB_GOTO_M PROC MVI@ R5, R2 ; get DX @@0: MVI@ R5, R3 ; get DY @@1: MVI@ R5, R1 ; get MOB update bitmap @@2: ANDI #$7FFF, R3 ; don't let Y above 127. MVII #MOB_XYP-4,R4 ; point to MOB XY position table @@loop1: ADDI #4, R4 @@loop: SARC R1 BNC @@skip MVOD@ R2, R4 ; \ NOP ; |- store updated X and Y MVOD@ R3, R4 ; / NOP SWAP R2 SWAP R3 TSTR R1 ; any more? BNEQ @@loop B FLG_STICSH ; force STICSH update @@skip BNEQ @@loop1 B FLG_STICSH ; force STICSH update ENDP ;; ======================================================================== ;; ;; MOB_SETATR -- Change the attribute for a MOB ;; ;; ;; ;; INPUTS for MOB_SETATR ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB # (0..7) ;; ;; 1 decle: Attribute value ;; ;; ;; ;; INPUTS for MOB_SETATR.1 ;; ;; R1 -- MOB # (0..7) ;; ;; R5 -- Invocation record ;; ;; 1 decle: Attribute value ;; ;; ;; ;; INPUTS for MOB_SETATR.2 ;; ;; R1 -- MOB # (0..7) ;; ;; R2 -- Attribute value ;; ;; ;; ;; OUTPUT ;; ;; ======================================================================== ;; MOB_SETATR PROC MVI@ R5, R1 ; get MOB # @@1: MVI@ R5, R2 ; get attribute # @@2: MVII #MOB_ATR,R4 ; point to MOB XY position table ADDR R1, R4 MVO@ R2, R4 B FLG_STICSH ; force STICSH update ENDP ;; ======================================================================== ;; ;; MOB_SETATR_M -- Change the attribute for multiple MOBs ;; ;; ;; ;; INPUTS for MOB_SETATR_M ;; ;; R5 -- Invocation record ;; ;; 1 decle: MOB update bitmap (1 bit per MOB#) ;; ;; N decle: Attribute value ;; ;; ;; ;; INPUTS for MOB_SETATR.1 ;; ;; R1 -- MOB update bitmap ;; ;; R5 -- Invocation record ;; ;; N decle: Attribute value ;; ;; ;; ;; OUTPUT ;; ;; ======================================================================== ;; MOB_SETATR_M PROC MVI@ R5, R1 ; get MOB update bitmap @@1: MVII #MOB_ATR,R4 ; point to MOB attribute bitmap @@loop1: ADDI #4, R4 @@loop: SARC R1 BNC @@skip MVI@ R5, R2 ; \__ copy attribute to MOB MVO@ R2, R4 ; / TSTR R1 ; any more? BNEQ @@loop B FLG_STICSH ; force STICSH update @@skip BNEQ @@loop1 B FLG_STICSH ; force STICSH update ENDP ;* ======================================================================== *; ;* This program is free software; you can redistribute it and/or modify *; ;* it under the terms of the GNU General Public License as published by *; ;* the Free Software Foundation; either version 2 of the License, or *; ;* (at your option) any later version. *; ;* *; ;* This program is distributed in the hope that it will be useful, *; ;* but WITHOUT ANY WARRANTY; without even the implied warranty of *; ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *; ;* General Public License for more details. *; ;* *; ;* You should have received a copy of the GNU General Public License *; ;* along with this program; if not, write to the Free Software *; ;* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *; ;* ======================================================================== *; ;* Copyright (c) 2003, Joseph Zbiciak *; ;* ======================================================================== *;