Thursday, June 15, 2017

Sprite Status Tables, part 3

As you may have gathered, given that the term "sprite status table" refers to the structure that records the status of an object, the two terms are mostly interchangeable. This is because objects are the game's main way of drawing sprites, although several objects do stuff in the background without any visual representation.

In order for an object to be rendered as a sprite, it must explicitly request so by calling the Draw_Sprite function once per frame, which is typically the last step of an object's execution. This will add the object's SST to the list of sprites to be rendered during that frame.
loc_81E3C:
    moveq   #0,d0
    move.b  5(a0),d0
    move.w  off_81E50(pc,d0.w),d1
    jsr     off_81E50(pc,d1.w)
    jmp     (Draw_Sprite).l
; ---------------------------------------------------------------------------
off_81E50:
    dc.w loc_81E54-off_81E50
    dc.w loc_81E72-off_81E50
; ---------------------------------------------------------------------------

loc_81E54:
    lea     ObjDat3_831CC(pc),a1
    jsr     SetUp_ObjAttributes(pc)
    ...
Later, when the sprite processor walks through the list, it looks at a bunch of attributes on the SST to figure out how to draw the object. Two of these attributes are the object's X and Y coordinates, which are loaded to $10(a0) and $14(a0) when the object is first loaded from the layout.

Since setting the rest of the attributes is such a common procedure, several objects call a function that initializes them to values from an "object data" structure loaded to register a1:
SetUp_ObjAttributes:
    move.l  (a1)+,$C(a0)    ; Mappings location
    move.w  (a1)+,$A(a0)    ; VRAM offset
    move.w  (a1)+,8(a0)     ; Priority
    move.b  (a1)+,7(a0)     ; Width
    move.b  (a1)+,6(a0)     ; Height
    move.b  (a1)+,$22(a0)   ; Mappings frame
    move.b  (a1)+,$28(a0)   ; Collision Number
    bset    #2,4(a0)        ; Object uses world coordinates
    addq.b  #2,5(a0)        ; Increase routine counter
    rts
Here's a quick rundown:
  • $C(a0) is the object's mappings. This is a pointer to a list of sprite mappings, each of which defines a set of sprite pieces and assembles them into the sprite's final shape.
  • $22(a0) is the current mapping frame. This acts as an index to the above list, and can be changed to pick which of the sprite mappings to display.
  • $A(a0) is the art tile. This is a VDP pattern index of the form PCCYXAAAAAAAAAAA and defines the base priority flag, color palette, X/Y flip and VRAM offset for each sprite piece in the mappings.
  • 8(a0) is the object's priority value, set in increments of $80. Objects with a lower value are drawn on top of ones with a higher value.
  • 6(a0) and 7(a0) are the object's height and width in pixels. These are used along with the object's X and Y coordinates to decide whether the object is on screen. If the object is off-screen, it is not rendered.
  • 4(a0) are the object's render flags. This is a set of flags which, appropriately enough, affect how the object is rendered:
    • Bits 0 and 1 are the horizontal/vertical flip flags. These are automatically set when the object is first loaded from the layout, and flip the entire mapping frame on itself.
    • Bit 2 is the coordinate system flag. If set, the object's X and Y coordinates define the object's position within the level, otherwise they define its position on the screen.
    • Bit 5 is the static mappings flag. If set, the object's mappings point directly to a single mapping rather than a list, and the mapping frame is not used.
    • Bit 6 is the multi-sprite flag. If set, the object is rendered as mutliple sprites, with the mapping frame and X/Y coordinates for the additional sprites pulled from elsewhere in the SST.
    • Bit 7 is the on-screen flag. This will be set or cleared depending on whether the object was on-screen, and thus rendered, during the previous frame.

The sonic3k.constants.asm file in the current disassembly defines human-friendly names for almost every attribute in an object's SST. However, very few objects in the disassembly have actually been refactored to make use of them, so it's always good to know the more common ones by heart.

No comments:

Post a Comment