Tuesday, October 31, 2017

Dynamic pattern load cues, part 1

Let's do a recap of how most objects get their graphics on screen. First, on level load, the stage's pattern load cues are processed and the object's art is queued for decompression. In case of the Tulipon enemy, the art pointers are included as part of Angel Island Zone's KosM PLC:
PLCKosM_AIZ:    dc.w 2
                dc.l ArtKosM_AIZ_MonkeyDude
                dc.w $A900
                dc.l ArtKosM_AIZ_Tulipon
                dc.w $A540
                dc.l ArtKosM_AIZ_CaterkillerJr
                dc.w $ABE0
After the KosM queue finishes processing, VRAM address $A540 will contain the art for the Tulipon enemy:


Okay, it doesn't look like much yet. But when a Tulipon object is spawned, it will call the SetUp_ObjAttributes function to initialize its SST to the following values:
ObjDat3_86E12:  dc.l Map_Tulipon
                dc.w $252A
                dc.w $200
                dc.b $C
                dc.b $18
                dc.b 0
                dc.b $23
Specifically, its art_tile attribute is set to $252A, which being a VDP pattern index of the form PCCYXAAAAAAAAAAA, indicates a base tile of $52A using palette line 1, otherwise known as the enemy palette. Each tile is $20 bytes long, so tile $52A begins at VRAM offset $52A * $20 = $A540, which lines up with where the art was decompressed to.

Additionally, the object's mappings attribute is set to Map_Tulipon, which points to sprite mapping data for the Tulipon enemy. This data can be found in the Map - Tulipon.asm file, and it assembles the enemy's graphics into more familiar frames of animation:

Let's look at the sprite definition for the first frame:
Frame_3616CA:   dc.w  6
                dc.b  $EA,   6,   0,   7, $FF, $F0
                dc.b  $EA,   6,   8,   7,   0,   0
                dc.b    8,   0,   0,   0, $FF, $E8
                dc.b    0,   6,   0,   1, $FF, $F0
                dc.b    0,   6,   8,   1,   0,   0
                dc.b    8,   0,   8,   0,   0, $10
This is kind of overwhelming, but bear with me. The first frame contains six sprite pieces, three of which are horizontal mirrors of the other three. You can see this by looking at the middle two bytes for each sprite definition, which make up another VDP pattern index. The mirrored sprite pieces are the ones with their third byte set to 8; this indicates the X bit on the pattern index is set.

On the other hand, the fourth byte is composed entirely of A bits, essentially making it the base tile for that sprite piece. Meanwhile, the low nybble of the second byte defines the piece's shape, out of the 16 possible shapes:


Okay so, the third and sixth pieces, with shape 0 and base tile 0, produce a single tile: these are the spikes sticking out from either side of the enemy. The fourth and fifth pieces, with shape 6 and base tile 1, produce six tiles arranged into a 2x3 rectangle using tiles 1 through 6: these are the enemy's spiky stalk. Finally, the first and second sprites, with shape 6 and base tile 7, produce the same rectangle using tiles 7 through $C: these are the enemy's red bulb.

As such, the first frame makes use of every tile from 0 through $C:


Now let's look at the definition for the second frame:
Frame_3616F0:   dc.w  6
                dc.b  $EA,   6,   0,  $D, $FF, $F0
                dc.b  $EA,   6,   8,  $D,   0,   0
                dc.b    8,   0,   0,   0, $FF, $E8
                dc.b    0,   6,   0,   1, $FF, $F0
                dc.b    0,   6,   8,   1,   0,   0
                dc.b    8,   0,   8,   0,   0, $10
Immediately, we can see that pieces 3 through 6 are identical to those of the previous frame. As for the first two pieces, although they have the same 2x3 shape as before, this time the base tile is $D, which means they use tiles $D through $12 instead. Thus, the tile usage is as follows:


Although the second mapping frame reuses the stalk from the first frame, it supplies its own bulb by simply bumping up the base tile to a value past the last tile of the previous frame.


Man, this post is getting way longer than I originally anticipated. Check back tomorrow when I hopefully get to the point.

No comments:

Post a Comment