Once every frame, the object processor walks through object RAM, which begins at address $B000 and holds a total of 110 SSTs. For each object slot, the base address of its SST is loaded into the a0 register, and the object's code pointer is retrieved. If the pointer is set to zero, the slot is considered empty, and is not processed. Otherwise, control jumps to the address stored in the pointer, and the object begins executing its own code.
Process_Sprites: tst.b (Teleport_active_flag).w bne.s locret_1AB0C lea (Object_RAM).w,a0 ... moveq #$6D,d7 sub_1AAFC: move.l (a0),d0 beq.s loc_1AB04 movea.l d0,a1 jsr (a1) loc_1AB04: lea next_object(a0),a0 dbf d7,sub_1AAFC locret_1AB0C: rtsThis brings us to our first convention: the a0 register starts off pointing at the object's own SST, and the object can use it to read from and write to its own attributes. For instance, when an object is first loaded from the layout, its subtype is copied to offset $2C of its SST. Later, when the object executes, it can fetch its own subtype by reading from $2C(a0).
Obj_14_2: move.b $2C(a0),d0 andi.w #$7F,d0 lsl.w #3,d0 move.w d0,$36(a0) addi.w #$10,d0 move.w d0,$38(a0) move.l #loc_3FBAC,(a0) loc_3FBAC: moveq #0,d2 lea (Player_1).w,a1 bsr.w sub_3FBC4 lea (Player_2).w,a1 bsr.w sub_3FBC4 jmp (Delete_Sprite_If_Not_In_Range).lFurthermore, most functions called by objects assume a0 is pointing to the SST of the calling object, so as a general rule, objects never write to a0. In the event the object needs to call a function which expects something else in a0, the current value of a0 is backed up before the function call and restored immediately after.