Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- LoadObjects:
- moveq #0,d0
- move.b ObjManager_Routine.w,d0 ; get manager routine
- jmp .indx(pc,d0.w) ; jump to appropriate code
- ; ---------------------------------------------------------------------------
- .indx bra.w .init ; initialization code
- bra.w LoadObjects_Main
- bra.w LoadObjects_Main
- rts
- ; ---------------------------------------------------------------------------
- .init move.l #Sprite_ListingK,d0 ; get S&K sprite listings
- move.b Current_Zone.w,d1 ; get zone ID
- cmpi.b #$16,d1
- bhs.s .sk ; branch if last 2 zones
- cmpi.b #$E,d1
- bhs.s .s3 ; branch if Azure Lake or higher
- cmpi.b #7,d1
- bhs.s .sk ; branch if MHZ or higher
- .s3 move.l #Sprite_Listing3,d0 ; get S3 sprite listings
- .sk move.l d0,Object_index_addr.w ; store the address
- addq.b #4,ObjManager_Routine.w ; use next routine
- tst.b Transport_Flag.w
- bne.s .noclear
- clearRAM Object_respawn_table, Camera_X_Pos_Diff-Object_respawn_table
- .noclear move.w Current_Zone.w,d0 ; get zone ID
- ror.b #1,d0 ; make act ID bit be 7th bit
- lsr.w #5,d0 ; shift right 5 times (each act is in increments of 4)
- lea ObjectLayoutPtrs,a0 ; get object layout position array
- movea.l (a0,d0.w),a0 ; get the appropriate one to a0
- cmpi.w #$1701,Current_Zone.w
- beq.s .0 ; branch if master emerald shrine
- cmpi.b #$16,Current_Zone.w
- bhs.s .normal ; branch if zone $16xx or $1700
- cmpi.b #$14,Current_Zone.w
- beq.s .normal ; branch if Glowing Spheres
- cmpi.b #$13,Current_Zone.w
- bhs.s .0 ; branch if GumBall or higher
- tst.w Multiplayer_Flag.w
- beq.s .normal
- .0 addq.b #8,ObjManager_Routine.w ; this makes the object manager just rts.
- jsr CreateObject(pc) ; attempt to create a new object
- bne.s .camerashit ; if failed, branch
- lea Current_Respawn_Index.w,a3 ; get respawn index
- movea.l Object_index_addr.w,a4 ; get object table
- move.w #$800,d6 ; get max x
- cmpi.w #$1701,Current_Zone.w
- bne.s .notshrine ; branch if not master emerald shrine
- move.w #$1780,d6 ; get max x
- .notshrine cmp.w (a0),d6 ; compare object position against d6
- bls.s .camerashit ; if higher than d6, dont load
- jsr CreateObj_Anyway(pc) ; load the next object
- beq.s .notshrine ; if more can be loaded, keep loading
- .camerashit clr.w Camera_X_Rough.w ; clear camera rough X
- cmpi.w #$1701,Current_Zone.w
- bne.s .rts ; branch if not master emerald shrine
- move.w Camera_X.w,d1 ; get camera x-pos
- subi.w #128,d1 ; sub 128 from it
- andi.w #$FF80,d1 ; keep in proper range
- move.w d1,Camera_X_Rough.w ; and store value
- .rts rts
- ; ---------------------------------------------------------------------------
- .normal move.l a0,ObjMng_AdrRight.w
- move.l a0,ObjMng_AdrLeft.w ; store address of the object layout
- lea Object_respawn_table.w,a3 ; get object respawn table
- cmpi.b #$14,Current_Zone.w
- bne.s .notglow ; branch if not Glowing spheres
- lea Level_layout_main+$3F8.w,a3 ; I just assume this is used as the respawn table in glowing spheres
- moveq #($200/4)-1,d6
- .clr clr.l (a3)+ ; clear next long
- dbf d6,.clr ; loop until done
- lea Level_layout_main+$3F8.w,a3
- ; the following code resets the variables and offsets of the manager so that,
- ; the objects manager will load the objects directly onscreen (and a little offscreen)
- ; and corrects all the variables with relevant values. Also makes sure correct amount of
- ; respawn indexes are skipped to keep enough space for all objects left from the player
- .notglow move.w Camera_X.w,d6 ; get camera X-pos
- subi.w #128,d6 ; sub 128 from it
- bhs.s .noreset ; if higher than 0, branch
- moveq #0,d6 ; reset to 0
- .noreset andi.w #$FF80,d6 ; keep in chunks of 128 pixels
- movea.l ObjMng_AdrRight.w,a0 ; get the address of the objloader
- ; this seems to load the objects from start of the level until the position behind you
- ; these objects will no be loaded to RAM, but rather, just skipped over, counting the address of the last loaded object and its respawn index
- .chkobjsleft cmp.w (a0),d6 ; compare object position against d6
- bls.s .chkdone ; if higher than d6, branch
- addq.w #6,a0 ; next object in list
- addq.w #1,a3 ; next respawn table index
- bra.s .chkobjsleft ; check next
- .chkdone move.l a0,ObjMng_AdrRight.w ; store address to load from
- move.w a3,ObjMng_RespawnRight.w ; and store respawn table
- lea Object_respawn_table.w,a3 ; get respawn index to a3
- cmpi.b #$14,Current_Zone.w
- bne.s .notglow2 ; branch not if Glowing Spheres
- lea Level_layout_main+$3F8.w,a3 ; get the table used by glowing spheres
- .notglow2 movea.l ObjMng_AdrLeft.w,a0
- subi.w #128,d6 ; sub 128 from Camera X again. This is grossly offscreen,
- ; but is done to account for the objects loader later on
- blo.s .chkdone2 ; if this position would be offscreen, it is assumed there are no objects to load
- .chkobjsright cmp.w (a0),d6 ; compare object position against d6
- bls.s .chkdone2 ; if higher than d6, branch
- addq.w #6,a0 ; next object in list
- addq.w #1,a3 ; next respawn table index
- bra.s .chkobjsright ; check next
- .chkdone2 move.l a0,ObjMng_AdrLeft.w ; store address to load from
- move.w a3,ObjMng_RespawnLeft.w ; and store respawn table
- move.w #-1,ObjMgr_Camera_X.w ; reset camera X
- move.w Camera_Y.w,d0 ; get camera y-position
- andi.w #$FF80,d0 ; keep in range
- move.w d0,ObjMgr_Camera_Y.w ; store it so no unnecesary Y-checks shouldnt be done
- ; ---------------------------------------------------------------------------
- LoadObjects_Main:
- move.w Camera_Y.w,d1 ; get camera Y-pos
- subi.w #128,d1 ; sub 128 pixels from it
- andi.w #$FF80,d1 ; keep in range
- move.w d1,Camera_Y_Rough.w ; save this
- move.w Camera_X.w,d1 ; get camera X-pos
- subi.w #128,d1 ; sub 128 pixels from it
- andi.w #$FF80,d1 ; keep in range
- move.w d1,Camera_X_Rough.w ; save this
- movea.l Object_index_addr.w,a4
- tst.w Camera_min_Y.w
- bpl.s .noywrap ; branch if Y-wrapping isnt active
- lea CreateObj_ChkYWrap(pc),a6 ; use check code, that account for Y-wrapping
- move.w Camera_Y.w,d3 ; get camera Y-positon
- andi.w #$FF80,d3 ; keep in range
- move.w d3,d4 ; copy result
- addi.w #512,d4 ; set lower y-boundary
- subi.w #128,d3 ; set upper y-boundary
- bpl.s .setnowrap ; if d3 is positive, branch
- and.w Screen_Y_wrap_value.w,d3 ; wrap d3
- bra.s .common
- .nowrap move.w Screen_Y_wrap_value.w,d0 ; get vertical wrap value
- addq.w #1,d0 ; add 1 to it
- cmp.w d0,d4 ; compare with lower y-boundary
- bls.s .setnowrap ; if no below the level either, branch
- and.w Screen_Y_wrap_value.w,d4 ; wrap this value
- bra.s .common
- ; ---------------------------------------------------------------------------
- .noywrap move.w Camera_Y.w,d3 ; get camera Y-positon
- andi.w #$FF80,d3 ; keep in range
- move.w d3,d4 ; copy result
- addi.w #512,d4 ; set lower y-boundary
- subi.w #128,d3 ; set upper y-boundary
- bpl.s .noywrap ; if still positive, branch
- moveq #0,d3 ; force upper level boundary
- .setnowrap lea CreateObj_ChkNoWrap(pc),a6 ; use check code, that doesnt account for Y-wrapping
- .common move.w #$FFF,d5
- move.w Camera_X.w,d6 ; get camera x-pos
- andi.w #$FF80,d6 ; keep in ramge
- cmp.w ObjMgr_Camera_X.w,d6 ; check against last range
- beq.w LoadObjects_Common ; branch if same
- bge.s LoadObjects_Forward ; if new range is greater than last, branch
- ; ---------------------------------------------------------------------------
- ; else the range is less than.
- move.w d6,ObjMgr_Camera_X.w ; store the new range
- movea.l ObjMng_AdrLeft.w,a0 ; get the current objects left
- movea.w ObjMng_RespawnLeft.w,a3 ; and appropriate respawn list
- subi.w #128,d6 ; sub 128 from the x-pos
- blo.s .endload ; if outside level boundary, branch
- jsr CreateObject(pc) ; attempt to load new object
- bne.s .endload ; branch if failed
- .loadloop cmp.w -6(a0),d6 ; check if the last object is in range
- bge.s .endload ; if not, branch
- subq.w #6,a0 ; get the actual object address
- subq.w #1,a3 ; get the actual respawn table address
- jsr (a6) ; attempt to spawn the object
- bne.s .loadfail ; branch if we could not load object afterall
- subq.w #6,a0
- bra.s .loadloop ; attempt to load new object
- .loadfail addq.w #6,a0 ;
- addq.w #1,a3 ; undo loading an object
- .endload move.l a0,ObjMng_AdrLeft.w ; store the current object
- move.w a3,ObjMng_RespawnLeft.w ; and respawn index
- movea.l ObjMng_AdrRight.w,a0 ; get the current objects right
- movea.w ObjMng_RespawnRight.w,a3 ; and appropriate respawn list
- addi.w #768,d6 ; look two chunks forwards
- ; this counts all the objects that have now moved offscreen
- .chkloop cmp.w -6(a0),d6 ; check if the last object is out of range
- bgt.s .chkdone ; if is, branch
- subq.w #6,a0 ; get object before this
- subq.w #1,a3 ; and its respawn index
- bra.s .chkloop ; check next object
- .chkdone move.l a0,ObjMng_AdrRight.w ; store the current object
- move.w a3,ObjMng_RespawnRight.w ; and respawn index
- bra.s LoadObjects_Common ; and branch away!
- ; ---------------------------------------------------------------------------
- LoadObjects_Forward:
- move.w d6,ObjMgr_Camera_X.w ; store the new range
- movea.l ObjMng_AdrRight.w,a0 ; get the current objects right
- movea.w ObjMng_RespawnRight.w,a3 ; and appropriate respawn list
- addi.w #640,d6 ; look two chunks forwards
- jsr CreateObject(pc) ; attempt to load new object
- bne.s .endload ; branch if failed
- .loadloop cmp.w (a0),d6 ; check if the last object is in range
- bls.s .endload ; if not, branch
- jsr (a6) ; attempt to spawn the object
- addq.w #1,a3 ; get new respawn index (remember this does not modify CCR)
- beq.s .loadloop ; branch if we could load objects
- .endload move.l a0,ObjMng_AdrRight.w ; store the current object
- move.w a3,ObjMng_RespawnRight.w ; and respawn index
- movea.l ObjMng_AdrLeft.w,a0 ; get the current objects left
- movea.w ObjMng_RespawnLeft.w,a3 ; and appropriate respawn list
- subi.w #768,d6 ; check 1 chunk backwards
- blo.s .chkdone ; if outside of level, branch
- ; this counts all the objects that have now moved offscreen
- .chkloop cmp.w (a0),d6 ; check if the last object is out of range
- bls.s .chkdone ; if is, branch
- addq.w #6,a0 ; get object after this
- addq.w #1,a3 ; and its respawn index
- bra.s .chkloop ; check next object
- .chkdone move.l a0,ObjMng_AdrLeft.w ; store the current object
- move.w a3,ObjMng_RespawnLeft.w ; and respawn index
- ; ---------------------------------------------------------------------------
- LoadObjects_Common:
- move.w Camera_Y.w,d6 ; get camera x-pos
- andi.w #$FF80,d6 ; keep in ramge
- move.w d6,d3 ; copy the value
- cmp.w ObjMgr_Camera_Y.w,d6 ; check against last range
- beq.w .loadend ; branch if same
- bge.s .movingdown ; if new range is greater than last, branch
- ; ---------------------------------------------------------------------------
- ; else the range is less than.
- tst.w Camera_min_Y.w
- bpl.s .nowrap ; branch if level does not Y-wrap
- tst.w d6
- bne.s .mvupwrap
- cmpi.w #128,ObjMgr_Camera_Y.w
- bne.s .mvdownwrap
- .mvupwrap subi.w #128,d3 ; look one chunk up
- bpl.s .ycheck ; branch if still positive
- and.w Screen_Y_wrap_value.w,d3 ; wrap y-pos
- bra.s .ycheck
- .nowrap subi.w #128,d3 ; look one chunk up
- bmi.w .loadend
- bra.s .ycheck
- ; ---------------------------------------------------------------------------
- .movingdown tst.w Camera_min_Y.w
- bpl.s .nowrap2 ; branch if level does not Y-wrap
- tst.w ObjMgr_Camera_Y.w
- bne.s .mvdownwrap
- cmpi.w #128,d6
- bne.s .mvupwrap
- .mvdownwrap addi.w #384,d3 ; look one chunk down
- cmp.w Screen_Y_wrap_value.w,d3
- blo.s .ycheck ; if we should now wrap yet
- and.w Screen_Y_wrap_value.w,d3 ; wrap the y-position
- bra.s .ycheck
- .nowrap2 addi.w #384,d3 ; look one chunk down
- cmp.w Screen_Y_wrap_value.w,d3
- bhi.s .loadend
- ; ---------------------------------------------------------------------------
- .ycheck jsr CreateObject(pc) ; attempt to create an object
- bne.s .loadend ; if failed, branch
- move.w d3,d4 ; copy y-pos
- addi.w #128,d4 ; look one chunk down
- move.w #$FFF,d5
- movea.l ObjMng_AdrLeft.w,a0 ; get the current objects left
- movea.w ObjMng_RespawnLeft.w,a3 ; get respawn list left
- move.l ObjMng_AdrRight.w,d7 ; get the current objects right
- sub.l a0,d7 ; sub the left position from right
- beq.s .loadend ; branch if no objects
- addq.w #2,a0 ; align to obj y
- .loadnext tst.b (a3) ; has object been loaded?
- bmi.s .loadfail ; if so, branch
- move.w (a0),d1 ; get objects y-pos
- and.w d5,d1 ; keep it in range of 0-$FFF
- cmp.w d3,d1
- blo.s .loadfail ; branch if out of range in top
- cmp.w d4,d1
- bhi.s .loadfail ; branch if out of range in bottom
- bset #7,(a3) ; mark as loaded
- move.w -2(a0),xpos(a1) ; get x-position
- move.w (a0),d1 ; get y-position
- move.w d1,d2 ; copy it
- and.w d5,d1 ; keep in range
- move.w d1,ypos(a1) ; store it as the new y-pos
- rol.w #3,d2 ; get X & Y flip bits to start of d2
- andi.w #3,d2 ; keep only X & Y flip bits
- move.b d2,render(a1) ; store render flags
- move.b d2,status(a1) ; store status
- move.b 2(a0),d2 ; get ID
- add.w d2,d2
- add.w d2,d2 ; quadruple it
- move.l (a4,d2.w),(a1) ; get the object ID from listings table
- move.b 3(a0),subtype(a1) ; get object subtype
- move.w a3,respawn(a1) ; get the respawn index
- jsr CreateObjFromLoader(pc) ; attempt to load more objects
- bne.s .loadend ; if none could be loaded, branch
- .loadfail addq.w #6,a0 ; next objects address
- addq.w #1,a3 ; next respawn index
- subq.w #6,d7 ; sub the size of the object
- bne.s .loadnext ; if there is object remaining, branch
- .loadend move.w d6,ObjMgr_Camera_Y.w ; store camera Y-pos
- rts
- ; ---------------------------------------------------------------------------
- ; unused/dead code
- bset #7,(a3) ; mark as loaded
- beq.s CreateObj_Anyway ; if wasn't loaded, load
- addq.w #2,a0 ; increment to address of the next object
- moveq #0,d1 ; ensure that upstream code knows to continue loading
- rts
- ; ---------------------------------------------------------------------------
- CreateObj_Anyway:
- move.w (a0)+,xpos(a1) ; copy x-position
- move.w (a0)+,d1 ; get y-position
- move.w d1,d2 ; copy it
- andi.w #$FFF,d1 ; filter out unnecessary bits
- move.w d1,ypos(a1) ; store the new y-pos
- rol.w #3,d2 ; get X & Y flip bits to start of d2
- andi.w #3,d2 ; keep only X & Y flip bits
- move.b d2,render(a1) ; store render flags
- move.b d2,status(a1) ; store status
- move.b (a0)+,d2 ; get object ID
- add.w d2,d2
- add.w d2,d2 ; quadruple it
- move.l (a4,d2.w),(a1) ; get the object ID from listings table
- move.b (a0)+,subtype(a1) ; get object subtype
- move.w a3,respawn(a1) ; get the respawn index
- bra.w CreateObjFromLoader ; attempt to create a new object
- ; ---------------------------------------------------------------------------
- ; subroutine to try and load new objects from object layout files.
- ; has different code for Y-wrapped and non-Y-Wrapped levels.
- ;
- ; input:
- ; d3 = upper boundary
- ; d4 = lower boundary
- ; d5 = Y-position filter bits
- ; a0 = index of object layout file
- ; a1 = target object
- ; a3 = respawn table address
- ; ---------------------------------------------------------------------------
- CreateObj_ChkYWrap:
- tst.b (a3) ; check if the object is already loaded
- bpl.s .notloaded ; if not, branch
- addq.w #6,a0 ; increment to address of the next object
- moveq #0,d1 ; ensure that upstream code knows to continue loading
- rts
- .notloaded move.w (a0)+,d7 ; get x-position
- move.w (a0)+,d1 ; get y-position
- move.w d1,d2 ; copy y-position
- bmi.s .loadnoy ; branch if this object ignore y-checks
- and.w d5,d1 ; keep y-position in range
- cmp.w d3,d1
- bhs.s .spawn ; branch if on range from top(?)
- cmp.w d4,d1
- bls.s .spawn ; branch if on range from bottom
- addq.w #2,a0 ; increment to address of the next object
- moveq #0,d1 ; ensure that upstream code knows to continue loading
- rts
- ; ---------------------------------------------------------------------------
- .loadnoy and.w d5,d1 ; keep y-position in range
- .spawn bset #7,(a3) ; mark as loaded
- move.w d7,xpos(a1) ; store the new x-pos
- move.w d1,ypos(a1) ; store the new y-pos
- rol.w #3,d2 ; get X & Y flip bits to start of d2
- andi.w #3,d2 ; keep only X & Y flip bits
- move.b d2,render(a1) ; store render flags
- move.b d2,status(a1) ; store status
- move.b (a0)+,d2 ; get object ID
- add.w d2,d2
- add.w d2,d2 ; quadruple it
- move.l (a4,d2.w),(a1) ; get the object ID from listings table
- move.b (a0)+,subtype(a1) ; get object subtype
- move.w a3,respawn(a1) ; get the respawn index
- bra.w CreateObjFromLoader ; attempt to create a new object
- ; ---------------------------------------------------------------------------
- CreateObj_ChkNoWrap:
- tst.b (a3) ; check if the object is already loaded
- bpl.s .notloaded ; if not, branch
- addq.w #6,a0 ; increment to address of the next object
- moveq #0,d1 ; ensure that upstream code knows to continue loading
- rts
- .notloaded move.w (a0)+,d7 ; get x-position
- move.w (a0)+,d1 ; get y-position
- move.w d1,d2 ; copy y-position
- bmi.s .loadnoy ; branch if this object ignore y-checks
- and.w d5,d1 ; keep y-position in range
- cmp.w d3,d1
- blo.s .outofrange ; branch if out of range from top
- cmp.w d4,d1
- bls.s .spawn ; branch if on range from bottom
- .outofrange addq.w #2,a0 ; increment to address of the next object
- moveq #0,d1 ; ensure that upstream code knows to continue loading
- rts
- ; ---------------------------------------------------------------------------
- .loadnoy bset #7,(a3) ; mark as loaded
- .spawn move.w d7,xpos(a1) ; store the new x-pos
- move.w d1,ypos(a1) ; store the new y-pos
- rol.w #3,d2 ; get X & Y flip bits to start of d2
- andi.w #3,d2 ; keep only X & Y flip bits
- move.b d2,render(a1) ; store render flags
- move.b d2,status(a1) ; store status
- move.b (a0)+,d2 ; get object ID
- add.w d2,d2
- add.w d2,d2 ; quadruple it
- move.l (a4,d2.w),(a1) ; get the object ID from listings table
- move.b (a0)+,subtype(a1) ; get object subtype
- move.w a3,respawn(a1) ; get the respawn index
- ; ---------------------------------------------------------------------------
- CreateObjFromLoader:
- subq.w #1,d0 ; not sure what d0 is here, but I can just guess
- ; it keeps track of how many objects we have checked
- bmi.s .rts ; if negative, branch
- .chk lea objsize(a1),a1 ; get next object
- tst.l (a1) ; test if there is object here
- dbeq d0,.chk ; if isn't, and more objects are to be done, keep looping.
- .rts rts
- ; ---------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement