Tuesday, June 13, 2017

Sprite Status Tables, part 1

A sprite status table, or SST, is a data structure which records all the information about an object's state. It is 74 bytes long, of which 70 bytes are effectively a blank canvas the object can use to store all sorts of data. The first longword in an SST, however, stores the object's code pointer, which is typically the ROM address where the object's code starts.

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:
    rts
This 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).l
Furthermore, 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.

2 comments:

  1. This sounds like there could be a way to do arbitrary code execution. Are there any such glitches in Sonic 3K?

    ReplyDelete
    Replies
    1. None than I know of, but it's definitely not beyond the realms of possibility.

      Delete