cruisin-usa/OBJ.ASM

1450 lines
28 KiB
NASM
Executable File

.FILE "OBJ.ASM"
*----------------------------------------------------------------------------
*OBJECT SYSTEM
*
*COPYRIGHT (C) 1994 BY TV GAMES, INC.
*ALL RIGHTS RESERVED
*
.include VUNIT.EQU
.include MPROC.EQU
.include OBJ.EQU
.include PALL.EQU
.include SYSID.EQU
.include SYS.EQU
.include MACS.EQU
.include ERROR.EQU
.include GLOBALS.EQU
.text
.bss OACTIVE,1 ;OBJECT ACTIVE LIST
.bss OFREE,1 ;OBJECT FREE LIST
.bss IDLE_LIST,1 ;OBJECT idle elements list
.bss OACTIVE_PRIORITY,1 ;OBJECT priority list
.bss OLOW_PRIORITY,1 ;OBJECT supplimental object list
.bss OHIGH_PRIORITY,1 ;OBJECT higest priority list
.bss OACTIVECNT,1 ;STATISTICAL ANALYSIS ONLY
.bss OFREECNT,1
.bss OMAX_OBJECTS,1 ;STATISTICAL ANALYSIS ONLY
hibss OBJSTR,OBJSIZ*NUM_OBJECTS
.bss COMM_DRONE_PTR,1
OFREEI .word OFREE
OBJSTRI .word OBJSTR
*----------------------------------------------------------------------------
*INITIALIZE OBJECT DATA STRUCTURES
*
OBJ_INIT:
PUSH R0
PUSH AR0
PUSH AR1
LDI NUM_OBJECTS,R0
STI R0,@OFREECNT
LDI 0,R0
STI R0,@OACTIVE
STI R0,@IDLE_LIST
STI R0,@OACTIVE_PRIORITY
STI R0,@OACTIVECNT
STI R0,@OMAX_OBJECTS
STI R0,@OLOW_PRIORITY
STI R0,@OHIGH_PRIORITY
STI R0,@DRIVE_LIST
STI R0,@CAR_LIST
STI R0,@SIGN_LIST
STI R0,@GROUND_LIST
STI R0,@COMM_DRONE_PTR
LDI @OFREEI,AR0 ;GET FREE POINTER
LDI @OBJSTRI,AR1
LDI NUM_OBJECTS-1,RC
RPTB OINITL
STI AR1,*AR0
LDI AR1,AR0
OINITL ADDI OBJSIZ,AR1
LDI 0,R0
STI R0,*AR0
POP AR1
POP AR0
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*OBJ_GETE
* GET EXTENDED OBJECT
*
*PARAMETERS
* AR2 ROMDATA POINTER
*
*RETURNS
* (SUCCESSFUL)
* CARRY CLR
* AR0 OBJECT POINTER
* (UNSUCCESSFUL)
* CARRY SET
*
OBJ_GETE:
CALL OBJ_GET
RETSC ;NO OBJECTS AVAILABLE RETURN ERROR CODE
PUSH R0
PUSH R1
STI AR2,*+AR0(OROMDATA)
LDI *AR2,R0 ;get RADIUS of object
STI R0,*+AR0(ORAD) ;SAVE THE SILLY RADIUS
LDI *-AR2,R0 ;GET CONTROL WORD
TSTB EOBJ_ILLUM,R0
BZ NOT_ILLUM
LDI *+AR0(OFLAGS),R1
OR O_ILLUM,R1
STI R1,*+AR0(OFLAGS)
NOT_ILLUM
TSTB EOBJ_1PAL,R0
BZ NOT_1PAL
LDI *+AR0(OFLAGS),R1
OR O_1PAL,R1
STI R1,*+AR0(OFLAGS)
LDI R0,AR2
AND 0FFfh,AR2
CALL PAL_FIND
BC $
STI R0,*+AR0(OPAL)
NOT_1PAL
CLRC
POP R1
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*OBJ_GET
* ALLOCATE AN OBJECT BLOCK FROM THE OBJECT FREE LIST
*
*RETURNS
* (SUCCESSFUL)
* CARRY CLR
* AR0 OBJECT POINTER
* (UNSUCCESSFUL)
* CARRY SET
*
*
OBJ_GET:
PUSH R0
LDI @OFREE,R0
LDI R0,AR0
BZ NOOBJ ;lockup if out of objects
LDI *AR0,R0
STI R0,@OFREE ;and update free list
LDI @OFREECNT,R0
SUBI 1,R0
STI R0,@OFREECNT
CLRI R0
STI R0,*+AR0(OFLAGS)
STI R0,*+AR0(OPLINK)
STI R0,*+AR0(OUSR1)
STI R0,*+AR0(OID)
STI R0,*+AR0(OLINK2)
STI R0,*+AR0(OLINK3)
STI R0,*+AR0(OLINK4)
CLRF R0
STF R0,*+AR0(OPOSX)
STF R0,*+AR0(OPOSY)
STF R0,*+AR0(OPOSZ)
STF R0,*+AR0(OVELX)
STF R0,*+AR0(OVELY)
STF R0,*+AR0(OVELZ)
STF R0,*+AR0(ORADX)
STF R0,*+AR0(ORADY) ;CLEAR RADIANS TO AVOID LOCKUP
STF R0,*+AR0(ORADZ)
STF R0,*+AR0(OMATRIX+1)
STF R0,*+AR0(OMATRIX+2)
STF R0,*+AR0(OMATRIX+3)
STF R0,*+AR0(OMATRIX+5)
STF R0,*+AR0(OMATRIX+6)
STF R0,*+AR0(OMATRIX+7)
LDF 1.0,R0
STF R0,*+AR0(OMATRIX+0)
STF R0,*+AR0(OMATRIX+4)
STF R0,*+AR0(OMATRIX+8)
CLRC
POP R0
RETS
NOOBJ
ERRON U,EC_OBJ|ET_ALLOC
SETC
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*COMPUTE DISTANCE OF OBJECT
*
*PARAMETERS
* AR2 OBJECT
*
*RETURNS
* R0 ODIST
* STORES IN *+AR2(ODIST)
GETDIST:
PUSH R1
PUSH R2
PUSHF R1
PUSHF R2
LDF *+AR2(OPOSX),R0
LDF *+AR2(OPOSY),R1
LDF *+AR2(OPOSZ),R2
LDP @_CAMERAPOS
SUBF @_CAMERAPOS,R0 ;ADJUST FOR UNIVERSE RELATIVE
SUBF @_CAMERAPOS+1,R1
SUBF @_CAMERAPOS+2,R2
;MULTIPLY BY ROTATION MATRIX TO FIND Z TERM
MPYF @_CAMERAMATRIX+6,R0 ;LAST COLUMN ONLY NEEDED
MPYF @_CAMERAMATRIX+7,R1
MPYF @_CAMERAMATRIX+8,R2
SETDP
ADDF R0,R1
ADDF R1,R2
FIX R2,R0
STI R0,*+AR2(ODIST)
POPF R2
POPF R1
POP R2
POP R1
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*INSERT PRIORITY OBJECT ON LIST
*
*PARAMETERS
* AR2 OBJECT
*
OBJ_INSERTP:
PUSH R0
PUSH R1
PUSH AR0
PUSH AR1
CALL GETDIST ;SETUP (ODIST) FIELD
LDI *+AR2(OFLAGS),R0 ;OR IN PROPER FLAG
OR O_LIST3,R0
STI R0,*+AR2(OFLAGS)
LDI @OACTIVE_PRIORITYI,AR1 ;INSERT TO HEAD OF PROCESS ACTIVE LIST
LDI *+AR2(ODIST),R0 ;GET CURRENT Z COORD OF OBJECT
INSOBJLP
LDI AR1,AR0 ;AR0 IS PREVIOUS LINK
LDI *AR1,R1 ;CHECK END OF LIST
BZ INS_AT_ENDP
LDI R1,AR1
CMPI *+AR1(ODIST),R0
BLE INSOBJLP ;KEEP GOING DUDE
INS_AT_ENDP
STI R1,*AR2 ;LINK TO NEXT
STI AR2,*AR0 ;LINK FROM PREVIOUS
POP AR1
POP AR0
POP R1
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*INSERT LOW PRIORITY OBJECT
*
*THIS IS NOT THE SAME AS OTHER LISTS, FOR THIS LIST THE OBJECT MUST
*BE DELINKED AND FREED BY THE USER
*LIST IS NOT SORTED
*
*PARAMETERS
* AR2 OBJECT TO LINK IN
*
*
OBJ_INSERTLP:
PUSH R0
LDI @OLOW_PRIORITY,R0
STI R0,*+AR2(OLINK)
STI AR2,@OLOW_PRIORITY
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*
*THIS IS NOT THE SAME AS OTHER LISTS, FOR THIS LIST THE OBJECT MUST
*BE DELINKED AND FREED BY THE USER
*LIST IS NOT SORTED
*
*PARAMETERS
* AR2 OBJECT TO LINK IN
*
OBJ_INSERTHP:
PUSH R0
LDI @OHIGH_PRIORITY,R0
STI R0,*+AR2(OLINK)
STI AR2,@OHIGH_PRIORITY
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*INSERT OBJECT ON OBJECT LIST
*
*PARAMETERS
* AR2 OBJECT
*
OBJ_INSERT:
PUSH R0
PUSHF R0
PUSH R1
PUSH AR0
PUSH AR1
CALL GETDIST ;SETUP (ODIST) FIELD
CMPI ACTIVELO,R0 ;TOO FAR BEHIND?
BLT INSIDLE ;YES
; ASH -2,R0
CMPI @ACTIVEHI,R0 ;TOO FAR AHEAD?
BLT INSACT ;NO...
INSIDLE ;INSERT ON IDLE LIST
LDI *+AR2(OFLAGS),R0 ;OR in proper flag
OR O_LIST2,R0
STI R0,*+AR2(OFLAGS)
LDI @IDLE_LISTI,AR1 ;insert to head of process active list
BD INSOBJX
LDI *AR1,R0 ;INSERT AT HEAD OF LIST
STI R0,*AR2
STI AR2,*AR1 ;PUT IT IN FRONT OF IDLE LIST
;------>BD INSOBJX
INSACT ;INSERT ON ACTIVE LIST
LDI *+AR2(OFLAGS),R0 ;OR in proper flag
OR O_LIST1,R0
STI R0,*+AR2(OFLAGS)
LDI @OACTIVEI,AR1 ;insert to head of process active list
LDI *+AR2(ODIST),R0 ;GET CURRENT Z COORD OF OBJECT
INSOBJL
LDI AR1,AR0 ;AR0 IS PREVIOUS LINK
LDI *AR1,R1 ;CHECK END OF LIST
BZ INS_AT_END
LDI R1,AR1
CMPI *+AR1(ODIST),R0
BLT INSOBJL ;KEEP GOING DUDE
INS_AT_END
STI R1,*AR2 ;LINK TO NEXT
STI AR2,*AR0 ;LINK FROM PREVIOUS
INSOBJX
POP AR1
POP AR0
POP R1
POPF R0
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*
*
*
*PARAMETERS
* AR2 ID
*RETURNS
* CARRY CLR NOT FOUND
* CARRY SET FOUND
* AR0 FIRST OBJECT FOUND
*
OBJ_FIND_FIRST_PRIORITY:
PUSH R0
LDI @OACTIVE_PRIORITYI,AR0
BU L89
OBJ_FIND_FIRST:
PUSH R0
LDI @OACTIVEI,AR0
L89 LDI *AR0,R0
BZ FF_ERR
FF_LP
LDI R0,AR0
CMPI *+AR0(OID),AR2
BEQ FF_OK
LDI *AR0,R0
BNZ FF_LP
FF_ERR
CLRC
POP R0
RETS
FF_OK
SETC
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
OBJ_FREE_GROUND:
PUSH R1
BUD DELSLP
PUSH AR1
LDI @GROUND_LISTI,R1 ;we must find dead object to link around
SUBI OLINK3,R1
;----> BUD DELSLP
OBJ_FREE_SIGN:
PUSH R1
PUSH AR1
LDI @SIGN_LISTI,R1 ;we must find dead object to link around
SUBI OLINK3,R1
DELSLP LDI R1,AR1
LDI *+AR1(OLINK3),R1
ERRON Z,EC_OBJ|1 ;lockup on end of list found
BZ NOT_ON_SUPPXLIST
CMPI R1,AR2
BNE DELSLP
LDI *+AR2(OLINK3),R1
STI R1,*+AR1(OLINK3) ;LINK AROUND
NOT_ON_SUPPXLIST
POP AR1
POP R1
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
OBJ_FREE_DRIVE:
PUSH R1
PUSH AR1
LDI @DRIVE_LISTI,R1 ;we must find dead object to link around
SUBI OLINK3,R1
DELRLP LDI R1,AR1
LDI *+AR1(OLINK3),R1
ERRON Z,EC_OBJ|2 ;lockup on end of list found
BZ NOT_ON_SUPPROADLIST
CMPI R1,AR2
BNE DELRLP
LDI *+AR2(OLINK3),R1
STI R1,*+AR1(OLINK3) ;LINK AROUND
NOT_ON_SUPPROADLIST
POP AR1
POP R1
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
OBJ_FREE_PROC:
PUSH AR2
LDI *+AR2(OPLINK),AR2
CALL PRC_KILL
POP AR2
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*DELETE AN OBJECT
*
*PARAMETERS
* AR2 OBJECT
*
*NOTE
* If there is any major change to this code
* please check DELETE_GROUP in BACKGRND.ASM
* this is a speeded up version of this subroutine.
*
OBJ_DELETE:
PUSH R0
PUSH R1
PUSH AR1
PUSH AR2
.if DEBUG
LDI 0C5C5h,R0 ;RANDOM KNOWN #
STI R0,*+AR2(OUSR1)
LDI 0AB5Bh,R0 ;RANDOM KNOWN #
STI R0,*+AR2(OLINK4)
.endif
;
;eliminate any dynamic objects associated with the object...
;
LDI *+AR2(OFLAGS),R0
TSTB O_DYNAMIC,R0
BZ NOTDYNAMIC
PUSH AR2
LDI *+AR2(ODYNALIST),AR0
DYNDEL LDI *AR0,R0 ;LINK TO NEXT
LDI AR0,AR2
CALL DELDYNA
LDI R0,AR0
CMPI 0,AR0
BNE DYNDEL
POP AR2
; PUSH AR2
; LDI *+AR2(ORADZ),AR2
; CALL KILL
; POP AR2
NOTDYNAMIC
; .if DEBUG
; LDI *+AR2(OFLAGS),R0
; AND O_LIST_M,R0
; LOCKON Z
; BZ $ ;this object has invalid list field
; ;note this may change if we have more
; ;then 3 lists
; .endif
;Mirror these checks in BACKGRND.ASM
; 'DELETE_GROUP'
;
LDI *+AR2(OFLAGS),R0 ;KILL PROC ASSOCIATED WITH OBJ
RS (O_DEBRIS_B+1),R0
CALLC FREE_RDDEBRIS
LDI *+AR2(OFLAGS),R0 ;KILL PROC ASSOCIATED WITH OBJ
RS (O_PROC_B+1),R0
CALLC OBJ_FREE_PROC
LDI *+AR2(OFLAGS),R0 ;DELINK IN CASE OF DRIVE LIST
RS (O_DRIVE_SUPP_B+1),R0
CALLC OBJ_FREE_DRIVE
LDI *+AR2(OFLAGS),R0 ;DELINK IN CASE OF GROUND LIST
RS (O_GROUND_B+1),R0
CALLC OBJ_FREE_GROUND
LDI *+AR2(OFLAGS),R0 ;DELINK IN CASE OF SIGN LIST
RS (O_SIGN_SUPP_B+1),R0
CALLC OBJ_FREE_SIGN
;THE OBJECT CAN BE EITHER ON THE ACTIVE LIST, THE IDLE LIST,
;OR THE ACTIVE PRIORITY LIST. ANYTHING ELSE IS AN ERROR.
;
LDI *+AR2(OFLAGS),R0
AND O_LIST_M,R0
LDI @OACTIVEI,R1
CMPI O_LIST2,R0
LDIEQ @IDLE_LISTI,R1
CMPI O_LIST3,R0
LDIEQ @OACTIVE_PRIORITYI,R1
DELLP LDI R1,AR1 ;WE MUST FIND DEAD OBJECT TO LINK AROUND
LDI *AR1,R1
ERRON Z,EC_OBJ|ET_DELETE
BZ DELOBJX
CMPI R1,AR2
BNE DELLP
LDI *AR2,R1
STI R1,*AR1 ;LINK AROUND
LDI @OFREE,R1
STI R1,*AR2
STI AR2,@OFREE
LDI @OFREECNT,R0 ;INCREMENT FREE OBJECT COUNT
ADDI 1,R0
STI R0,@OFREECNT
CLRI R0
STI R0,*+AR2(OLINK2) ;CLEAR SEARCH ID
STI R0,*+AR2(OFLAGS)
DELOBJX
POP AR2
POP AR1
POP R1
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*OBJ_DELETE_CLASS
*
*SEARCHES THE ACTIVE LIST FOR ALL OCCURANCES OF SPECIFIED ID
*AND DELETES THAT OBJECT
*
*PARAMETERS
* R0 ID
* R1 MASK
*
OBJ_DELETE_CLASS:
PUSH AR0
PUSH AR2
PUSH R0
PUSH R1
PUSH R2
PUSH R3
AND R1,R0
LDI @OACTIVEI,AR0
ODC LDI *AR0,R3
BZ ODCX
LDI R3,AR0
ODCL2 LDI *+AR0(OID),R2
AND R1,R2
CMPI R0,R2
BNE ODC
LDI *AR0,R3
LDI AR0,AR2
CALL OBJ_DELETE
LDI R3,R3
LDI R3,AR0
BNZ ODCL2
ODCX
POP R3
POP R2
POP R1
POP R0
POP AR2
POP AR0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*PULL AN OBJECT FROM ACTIVE LIST
*
*Most of the same effect as delobj, except that the object is not
*inserted onto the free list, allowing the user to do hold onto
*the object.
*
*PARAMETERS
* AR2 OBJECT
*
OBJ_PULL:
PUSH R0
PUSH R1
PUSH AR1
PUSH AR2
LDI *+AR2(OFLAGS),R0
AND O_LIST_M,R0
LDI @OACTIVEI,R1 ;we must find dead object to link around
CMPI O_LIST2,R0
LDIEQ @IDLE_LISTI,R1 ;we must find dead object to link around
CMPI O_LIST3,R0
LDIEQ @OACTIVE_PRIORITYI,R1 ;we must find dead object to link around
PULLP
LDI R1,AR1
LDI *AR1,R1
ERRON Z,EC_OBJ|4
BZ PULOBJ_X
CMPI R1,AR2
BNE PULLP
LDI *AR2,R1
STI R1,*AR1 ;LINK AROUND
LDI *+AR2(OFLAGS),R0
ANDN O_LIST_M,R0
STI R0,*+AR2(OFLAGS)
PULOBJ_X
POP AR2
POP AR1
POP R1
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*LINK OBJECT INTO FREE LIST
*(NO ERROR CHECKING)
*
*PARAMETERS
* AR2 OBJECT
*
OBJ_FREE:
PUSH R0
LDI @OFREE,R0
STI R0,*AR2
STI AR2,@OFREE
POP R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*SORT OBJECTS BY CURRENT Z
*WAIT FOR NEXT INTERRUPT
*
*CLOBBERS
* R0-R4,AR0-AR5,DP,etc.
*CALL BY MAINLINE CODE
*
ZSORTWT:
LDI 1,R0
STI R0,@CLEARRDY ;READY FOR INTERRUPT
ZSORTWL
CLRI R6 ;FLAG FOR SORT (NOTHING SORTED YET)
LDI @OACTIVEI,AR0 ;INSERT TO HEAD OF PROCESS ACTIVE LIST
LDI *AR0,AR1 ;GET FIRST ELEMENT
LDI AR1,R1 ;BOGUS TEST AR REG'S DON'T SET FLAGS
BZ ZSWTX ;NULL LIST
LDI *AR1,AR2 ;GET NEXT ELEMENT
LDI AR2,R1
BZ ZSWTX ;ONLY ONE ELEMENT ON LIST
ZSWTLP
LDI @CLEARRDY,R0 ;DONE WHEN IN SIGNALS FRAME IS DONE
BZD ZSWTXX
LDI *+AR1(ODIST),R0
LDI *+AR2(ODIST),R1
CMPI R1,R0
;------>BNZD ZSWTXX
BGE ZWPRIOK ;PRIORITY IS O.K. (AR1 is further than AR2)
DOSWAP
;SWAP EM DUDES
LDI 1,R6 ;the list has changed
STI AR2,*AR0 ;POINT N-1 TO N+1
LDI *AR2,R1 ;GET N+2
STI R1,*AR1 ;POINT N TO N+2
STI AR1,*AR2 ;POINT N+1 TO N
BNZD ZSWTLP
LDI AR2,AR0 ;NEW PREVIOUS(N-1)
LDI R1,AR2 ;NEW NEXT(N+1)
LDI R1,R1
;----> BNZD ZSWTLP
LDI R6,R6 ;ANY SWAPS?
BZ ZSWTXX ;NO DONE...
B ZSORTWL ;START OVER AT THE BEGINNING
ZWPRIOK
LDI *AR2,R1 ;NEW NEXT LINK
BNZD ZSWTLP
LDI AR1,AR0 ;AR4=PREVIOUS-1 LINK
LDI AR2,AR1 ;AR0=PREVIOUS
LDI R1,AR2
;----> BNZD ZSWTLP
BR ZSORTWL ;START OVER AT THE BEGINNING
ZSWTX
ZSWTXX
LDI @_MODE,R0
AND MHS,R0
RETSNZ ;Don't do player and drones in HIGH SCORE MODE
CALL PLYRDLINK ;DELINK PLAYER
CALL DRONESORT
CALL DEBRIS_SORT
CALL PLYRSORT ;LINK IN PLAYER
CALL SORT_SMOKE
CALL FLAMESORT
RETS
*-----------------------------------------------------------------------------
*-----------------------------------------------------------------------------
*DELINK THE PLAYER --> SO NO INTERFERENCE WITH DRONESORT
*
*PLYRDLINK
*
PLYRDLINK:
LDI @OACTIVEI,AR1 ;GET OBJECT LIST POINTER
PSORTNXT
LDI *AR1,R0
BZD PDLINKX ;NOBODY HOME
LDI AR1,AR0
LDI R0,AR1
LDI *+AR1(OID),R1
;------>BZD PSORTX
PSORTL
CMPI PLYR_C,R1
BNE PSORTNXT
*FOUND THE PLYR, DELINK 'EM
LDI *AR1,R0 ;GET POINTER TO NEXT ELEMENT
STI R0,*AR0 ;LINK AROUND THE DUDE
PDLINKX
STI AR1,@PLYRTEMP ;SAVE THE DUDE
RETS
*-----------------------------------------------------------------------------
.BSS PLYRTEMP,1 ;PLAYER OBJECT STORE
*-----------------------------------------------------------------------------
*SORT PLYR CAR WITH DRONE CARS INTO ROAD WITH PRIORITY
*
*PLAYER INSERTED BEFORE DRONE WITH CLOSER ODIST
*IF NO DRONE CLOSER, INSERT AT END OF LIST
*
PLYRSORT:
LDI @PLYRTEMP,R0 ;GET PLAYER
BZD PSORTX ;NO PLAYER, HANG IT UP...
LDI R0,AR5
LDI *+AR5(ODIST),R2 ;GET PLAYER DISTANCE
LDF *+AR5(OPOSX),R3 ;GET PLAYER X COORD
;-----> BZD PSORTX ;NO PLAYER, HANG IT UP...
LDI 0,R0
STI R0,*AR5 ;ZERO OUT PLAYERS LINK
LDI @OACTIVEI,AR1 ;GET OBJECT LIST POINTER
BR PSRT1NXT
PSRT1L
AND CLASS_M|TYPE_M,R1 ;CHECK FOR A DRONE
CMPI DRONE_C|VEHICLE_T,R1
BNE PSRT1NXT
*FOUND A DRONE, COMPARE ODIST
CMPI *+AR1(ODIST),R2 ;GET DRONE DISTANCE
BLT PSRT1NXT ;DRONE IN BACK, IGNORE HIM
LDF *+AR1(OPOSX),R1
SUBF R3,R1
ABSF R1
FIX R1
CMPI 2000,R1 ;MUST BE WITHIN X LIMIT (NOT OFFSCREEN)
BGT PSRT1NXT ;DRONE IN FRONT, WERE DONE
LDI AR5,AR2
PSRT2A
LDI *AR2,R1 ;DRONE IN FRONT, LINK EM INTO CHAIN
BZ PSRT2
LDI R1,AR2
BR PSRT2A
PSRT2
LDI *AR1,R0 ;REMOVE DRONE FORM OBJECT LIST
STI R0,*AR0
STI AR1,*AR2 ;LINK DRONE TO TEMP PLAYER LIST
STI R1,*AR1 ;ZERO OUT LAST LINK
LDI AR0,AR1
PSRT1NXT
LDI *AR1,R0
BNZD PSRT1L
LDI AR1,AR0 ;AR4=PREVIOUS-1 LINK
LDI R0,AR1
LDI *+AR1(OID),R1
;------>BNZD PSRT1L
*INSERT HIM
STI AR5,*AR0 ;LINK IN PLAYER CHAIN
PSORTX
RETS
*-----------------------------------------------------------------------------
*-----------------------------------------------------------------------------
*SORT DRONE CARS INTO ROAD WITH PRIORITY
*
*FIND CLOSEST ROAD PIECE DRONE IS ON TOP
*THEN ZSORT DRONE CLOSER BASED ON ODIST
*
*USES
* AR4 POINTER TO DRONES
*
DRONESORT:
;PULL LIST OF DRONES OFF OBJECT LIST
BUD DSORTNXT
NOP
; PUSH R2
LDI 0,AR4 ;INIT DRONE LIST HEADER
LDI @OACTIVEI,AR1 ;GET OBJECT LIST POINTER
;------>BD DSORTNXT ;GO GET FIRST ELEMENT
DSORTL
AND CLASS_M,R1
CMPI DRONE_C,R1
BNE DSORTNXT
*FOUND A DRONE, DELINK 'EM
LDI *AR1,R0 ;GET POINTER TO NEXT ELEMENT
STI R0,*AR0
STI AR4,*AR1 ;LINK HIM INTO TEMP LIST
LDI AR1,AR4
LDI AR0,AR1
DSORTNXT
LDI *AR1,R0
BNZD DSORTL
LDI AR1,AR0 ;AR4=PREVIOUS-1 LINK
LDI R0,AR1
LDI *+AR1(OID),R1
;------>BNZD DSORTL
; LDI R0,R0
; BNZ DSORTL
DSORTX
*PROCESS DRONE LIST
*FOR EACH DRONE PUT IT AFTER HIGHEST PRIORITY ROAD SEG INTERSECTED
LDI AR4,R0 ;NULL LIST?
BZ DSORTXX ;YES, QUIT
NXTDRONE
*GET ROAD COLLISION POINTERS
LDI AR4,AR5
LDI *AR4,AR4 ;MOVE TO NEXT DRONE
PUSH AR4
PUSH AR5
LDI *+AR5(OCARBLK),AR0
LDI *+AR0(CARPCOL),AR1 ;ROAD COLL CNT
LDI *+AR0(CARVSIZ+CARPCOL),AR2 ;ROAD COLL RF
LDI *+AR0((2*CARVSIZ)+CARPCOL),AR3 ;ROAD COLL LF
LDI *+AR0((3*CARVSIZ)+CARPCOL),AR4 ;ROAD COLL LR
LDI *+AR0((4*CARVSIZ)+CARPCOL),AR5 ;ROAD COLL RR
LDI *+AR1(ODIST),R1
LDI *+AR2(ODIST),R2
LDI *+AR3(ODIST),R3
LDI *+AR4(ODIST),R4
LDI *+AR5(ODIST),R5
LDI 7FFFH,R6
LSH 16,R6 ;GET +INFINITY
LDI AR1,R0 ;LOAD INFINITY INTO NULL POINTERS
LDIZ R6,R1
LDI AR2,R0
LDIZ R6,R2
LDI AR3,R0
LDIZ R6,R3
LDI AR4,R0
LDIZ R6,R4
LDI AR5,R0
LDIZ R6,R5
CMPI R1,R2
LDIGT AR1,AR2
LDIGT R1,R2
CMPI R2,R3
LDIGT AR2,AR3
LDIGT R2,R3
CMPI R3,R4
LDIGT AR3,AR4
LDIGT R3,R4
CMPI R4,R5
LDIGT AR4,AR5
LDI AR5,AR3
POP AR5
POP AR4
LDI @OACTIVEI,AR1 ;GET OBJECT LIST POINTER
LDI AR3,R3 ;CHECK NULL
BZ DSORTL1X ;NULL DUDE, Z SORT ONLY
DSORTL1
LDI *AR1,R0 ;CHECK END OF LIST
BNZ DSORTL2
DSORTL1X
LDI @OACTIVEI,AR1 ;CANT FIND TRACK PIECE, Z SORT FROM TOP
LDI AR1,R1
BNZ DZSORTUP ;LIST NOT NULL
LDI *AR2,R2
STI R2,*AR3 ;OBJECT LIST IS NULL, PUT CAR AT HEAD
STI AR3,*AR2
DSORTL2
LDI R0,AR1
CMPI R0,R3
BNZ DSORTL1
*
*SORT PAST SHOULDER PIECES
*AR1=OBJECT TO INSERT AFTER IN OBJECT LIST
*AR5=DRONE
*
DZSORTUP
LDI *+AR0(CARPCOL),AR3 ;ON THE ROAD?
LDI *+AR3(OID),R0
CMPI 0300H,R0
BNZ DZSORTUP1 ;NOPE, FORGET SHOULDER JIVE
LDI *+AR5(ODIST),R1 ;GET DRONE DISTANCE
LDI ROAD_C+SHLDR_T,R2 ;GET SOULDER ID
LDI CLASS_M,R3
BU DSL11
DSLP1
BGT DSL000 ;ROAD OR CAR, CHECK IT OUT..
AND R3,R4,R5
CMPI TSIGN_C,R5 ;SIGN OR TREE, NEED TO CHECK PRIORITY ?
BNZ DSL00 ;NOPE, BLOW IT OFF...
DSL000
CMPI *+AR2(ODIST),R1
BGE DSDONE ;PRIORITY IS O.K., WERE DONE WITH DRONE
DSL00
LDI AR2,AR1
DSL11
LDI *AR1,R0
BNZD DSLP1
LDI R0,AR2
LDI *+AR2(OID),R4
CMPI R4,R2
;-----> BNZD DSLP1
B DSDONE
*Z SORT IT UPWARDS
*AR1=OBJECT TO INSERT AFTER IN OBJECT LIST
*AR5=DRONE
DZSORTUP1
LDI *+AR5(ODIST),R1 ;GET DRONE DISTANCE
BU DSL1
DSLP
BGE DSDONE ;PRIORITY IS O.K., WERE DONE WITH DRONE
LDI AR2,AR1
DSL1
LDI *AR1,R0
BNZD DSLP
LDI R0,AR2
CMPI *+AR2(ODIST),R1
NOP
;-----> BNZD DSLP
DSDONE
LDI *AR1,R0 ;WERE DONE... INSERT THE SUCKA
STI AR5,*AR1
STI R0,*AR5
*GET NEXT DRONE DUDES
DSORTLLL
LDI AR4,R0
BNZ NXTDRONE
DSORTXX
RETS ;WE QUIT...
*----------------------------------------------------------------------------
ACTIVEHI1 .word 75000 ;HI LIMIT FOR INACTIVE-ACTIVE
ACTIVEHI .word 80000 ;HI LIMIT FOR ACTIVE-INACTIVE
ACTIVELO .SET -5000 ;LO LIMIT INACTIVE OBJECT LIST
*----------------------------------------------------------------------------
*SCAN ACTIVE LIST
*PUT DISTANT OBJECTS ON INACTIVE LIST
*
OSCAN:
BUD OSCANNXT
LDI @ACTIVEHI,R4 ;GET FAR LIMIT
LDI @IDLE_LISTI,AR5 ;IN SAME PAGE
LDI @OACTIVEI,AR1
;------>BD OSCANNXT ;GO GET FIRST ELEMENT
OSCANL
LDI *+AR1(ODIST),R0 ;ODIST TOO NEGATIVE?
CMPI ACTIVELO,R0
BLE OSCANACT ;YES, BLOW IT OUT
SUBI R4,R0 ;ODIST TOO POSITIVE
BLE OSCANNXT ;NO...
SUBI *+AR1(ORAD),R0 ;CHECK RADIUS TO MAKE SURE
BLE OSCANNXT
NOP
*FOUND DISTANT ELEMENT, XSFER ACTIVE TO INACTIVE
OSCANACT
LDI *AR1,R0 ;GET POINTER TO NEXT ELEMENT
STI R0,*AR6
LDI *+AR1(OFLAGS),R0 ;SWITCH LIST FLAG
XOR O_LIST2+O_LIST1,R0
STI R0,*+AR1(OFLAGS)
LDI *AR5,R0
STI R0,*AR1 ;LINK HIM INTO INACTIVE LIST
STI AR1,*AR5
LDI AR6,AR1
OSCANNXT
LDI *AR1,R0
BNZD OSCANL
LDI AR1,AR6 ;AR6=PREVIOUS-1 LINK
LDI R0,AR1
NOP
;------>BNZD OSCANL
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*SCAN INACTIVE LIST FOR ACTIVES
*PUT DISTANT OBJECTS ON INACTIVE LIST
*IF RADIUS IS CLOSE, ACTIVATE
*IF ANGLE COSINE POSITIVE (+-90 DEGREES), ACTIVATE
*
ISCAN:
FLOAT ACTIVELO,R3 ;GET CLOSE LIMIT
LDI @ACTIVEHI1,R4 ;GET FAR LIMIT
LDI @CAMERAPOSI,AR4 ;POINTER TO CAMERA STRUCT
LDI @IDLE_LISTI,AR1 ;IN SAME PAGE
LDI @OACTIVEI,AR5
LDI @CAMERAMATRIXI,AR3
ADDI 1,AR4 ;POINT TO Y ELEMENT
BUD ISCANNXT
ADDI 7,AR3 ;LAST COLUMN OF MATRIX
LDI OPOSY,IR0
LDI OPOSZ,IR1
;------>BD ISCANNXT ;GO GET FIRST ELEMENT
ISCANL
SUBF *AR4,*+AR1(IR0),R6 ;OYPOS-CAMERAPOSY
SUBF *+AR4(1),*+AR1(IR1),R7 ;OZPOS-CAMERAPOSZ
MPYF *-AR3(1),R5,R0
MPYF *AR3,R6,R1
MPYF *+AR3(1),R7,R2
ADDF R1,R0
ADDF R2,R0
CMPF R3,R0
BLED ISCANNXT
FIX R0,R1
STI R1,*+AR1(ODIST) ;SETUP ODIST
NOP
;------>BLED ISCANNXT
SUBI R4,R1
SUBI *+AR1(ORAD),R1 ;CHECK RADIUS TO MAKE SURE
BGT ISCANNXT
*FOUND CLOSE ELEMENT, XSFER INACTIVE TO ACTIVE
ISCANACT
LDI *AR1,R0 ;GET POINTER TO NEXT ELEMENT
STI R0,*AR6
LDI *+AR1(OFLAGS),R0 ;SWITCH LIST FLAG
XOR O_LIST2+O_LIST1,R0
STI R0,*+AR1(OFLAGS)
LDI *AR5,R0
STI R0,*AR1 ;LINK HIM INTO INACTIVE LIST
STI AR1,*AR5
LDI AR6,AR1
ISCANNXT
LDI *AR1,R0
BNZD ISCANL
LDI AR1,AR6 ;AR6=PREVIOUS-1 LINK
LDI R0,AR1
SUBF *-AR4(1),*+AR1(OPOSX),R5 ;GET LENGTH OF OBJ VECTOR
;------>BNZD ISCANL
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*RESCAN TOTALLY RESCAN ALL OBJECTS ACTIVE AND INACTIVE
* FOR CAMERA VIEW CHANGE
*
*PARAMETERS
* CAMERAPOS AND CAMERAMATRIX WITH NEW VALUES
*
RESCAN:
PUSH AR3
PUSH AR4
PUSH AR5
PUSH AR6
*COMBINE ACTIVE INACTIVE LISTS
LDI @IDLE_LISTI,AR5
LDI @OACTIVEI,AR1
LDI *AR1,R0
BZ RESCAN1 ;ACTIVE LIST NULL, FORGET IT
RESCAN0
LDI R0,AR2
LDI *+AR2(OFLAGS),R0 ;SWITCH LIST FLAG
XOR O_LIST2+O_LIST1,R0
STI R0,*+AR2(OFLAGS)
LDI *AR2,R0
BNZ RESCAN0
LDI *AR5,R0 ;FIRST ELEMENT INACTIVE LIST
STI R0,*AR2 ;LINK TO LAST ELEMENT OF ACTIVE LIST
LDI *AR1,R0
STI R0,*AR5 ;POINT INACTIVE LIST TO ACTIVE LIST
LDI 0,R0 ;CLEAR OUT ACTIVE LIST
STI R0,*AR1
RESCAN1
CALL ISCAN ;FORM NEW ACTIVE INACTIVE LISTS
CALL ZSORTACT ;BUBBLE SORT ACTIVE LIST
POP AR6
POP AR5
POP AR4
POP AR3
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*BUBBLE SORT PRIORITY LIST UNTIL DONE
*
ZSORTPRIOR:
ZSORTA1P
LDI 0,R2 ;CLEAR EXCHANGE FLAG
LDI @OACTIVE_PRIORITYI,AR0
LDI *AR0,AR1 ;GET FIRST ELEMENT
LDI AR1,R1
BZ ZSORTXP ;NULL LIST
LDI *AR1,AR2 ;GET NEXT ELEMENT
LDI AR2,R1
BZ ZSORTXP ;ONLY ONE ELEMENT ON LIST
LDI *+AR1(ODIST),R0
ZSLPP
LDI *+AR2(ODIST),R1
CMPI R1,R0
BGE PRIOKP ;PRIORITY IS O.K.
*SWAP EM DUDES
LDI 1,R2
STI AR2,*AR0 ;POINT N-1 TO N+1
LDI *AR2,R1 ;GET N+2
STI R1,*AR1 ;POINT N TO N+2
STI AR1,*AR2 ;POINT N+1 TO N
LDI AR2,AR0 ;NEW PREVIOUS(N-1)
LDI R1,AR2 ;NEW NEXT(N+1)
LDI R1,R1
BNZ ZSLPP
BR ZSORTXP
PRIOKP
LDI R1,R0
LDI AR1,AR0 ;AR4=PREVIOUS-1 LINK
LDI AR2,AR1 ;AR0=PREVIOUS
LDI *AR2,R1
LDI R1,AR2
BNZ ZSLPP
ZSORTXP LDI R2,R2
BNZ ZSORTA1P
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*BUBBLE SORT ACTIVE LIST UNTIL DONE
*
ZSORTACT:
ZSORTA1
LDI 0,R2 ;CLEAR EXCHANGE FLAG
LDI @OACTIVEI,AR0
LDI *AR0,AR1 ;GET FIRST ELEMENT
LDI AR1,R1
BZ ZSORTX ;NULL LIST
LDI *AR1,AR2 ;GET NEXT ELEMENT
LDI AR2,R1
BZ ZSORTX ;ONLY ONE ELEMENT ON LIST
LDI *+AR1(ODIST),R0
ZSLP
LDI *+AR2(ODIST),R1
CMPI R1,R0
BGE PRIOK ;PRIORITY IS O.K.
*SWAP EM DUDES
LDI 1,R2
STI AR2,*AR0 ;POINT N-1 TO N+1
LDI *AR2,R1 ;GET N+2
STI R1,*AR1 ;POINT N TO N+2
STI AR1,*AR2 ;POINT N+1 TO N
LDI AR2,AR0 ;NEW PREVIOUS(N-1)
LDI R1,AR2 ;NEW NEXT(N+1)
LDI R1,R1
BNZ ZSLP
BR ZSORTX
PRIOK
LDI R1,R0
LDI AR1,AR0 ;AR4=PREVIOUS-1 LINK
LDI AR2,AR1 ;AR0=PREVIOUS
LDI *AR2,R1
LDI R1,AR2
BNZ ZSLP
ZSORTX
LDI R2,R2
BNZ ZSORTA1
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*OBJECTP make_obj(int *rom,int px,int py,int pz,float rx,float ry)
*
*PARAMETERS
* AR2 ROMDATA ^
* RC POS X |
* RS POS Y ignored
* RE POS Z
* R2 RAD Y
*RETURNS
* R0 OBJECT POINTER
*
*
OBJ_MAKE:
CALL OBJ_GET
ERRON C,EC_OBJ|5
RETSC
STI AR2,*+AR0(OROMDATA)
STF R3,*+AR0(ORADY)
FLOAT RC,R2
STF R2,*+AR0(OPOSX)
FLOAT RS,R2
STF R2,*+AR0(OPOSY)
FLOAT RE,R2
STF R2,*+AR0(OPOSZ)
LDF *+AR0(ORADY),R2
LDI AR0,AR2
ADDI OMATRIX,AR2
CALL FIND_YMATRIX
LDI AR0,R0
RETS
*----------------------------------------------------------------------------
*----------------------------------------------------------------------------
*QWICK MAKE OBJ
*
*PARAMETERS
* AR2 ROM POINTER
* R2 POSX
* R3 POSY
* RC POSZ
*
*RETURNS
* AR0 OBJECT
*
OBJ_QMAKE:
CALL OBJ_GET
RETSC
STI AR2,*+AR0(OROMDATA)
FLOAT R2
STF R2,*+AR0(OPOSX)
FLOAT R3
STF R3,*+AR0(OPOSY)
FLOAT RC,R2
STF R2,*+AR0(OPOSZ)
CLRC
RETS
*----------------------------------------------------------------------------
.END