61 if (decodeFrame == 0) {
80 for (i = 0; i < obj->
count; i++) {
103 layer->
timer += arg << 4;
114 layer->
timer += arg << 4;
115 goto select_direction;
125 goto select_direction;
139 layer->
timer += arg << 4;
140 goto select_direction;
154 switch (layer->
kind) {
188 if (i == 0 && (facing >> 7) != 0) {
192 layer->frame = frame;
197 if (obj->
dirty != 0) {
198 size = obj->width * obj->height;
199 pixels = MemAlloc(size);
200 Iwram_ClearWords(pixels, size);
205 for (i = obj->count - 1; i >= 0; i--) {
206 layer = obj->entries[i];
210 if (layer->frames == 0) {
213 if (layer->frame == 255) {
216 key = layer->priority;
220 key = (key << 8) | i;
225 if (k >= 0 && drawOrder[k] > key) {
226 drawOrder[k + 1] = drawOrder[k];
231 if (drawOrder[k] <= key)
233 drawOrder[k + 1] = drawOrder[k];
237 drawOrder[k + 1] = key;
246 for (i = 0; i < drawCount; i++) {
247 layer = obj->
entries[*(
u8 *)&drawOrder[i]];
248 if (layer->
mode == 1) {
250 }
else if (layer->
mode == 3) {
251 if (layer->
param != 0) {
255 pixels, layer->
param);
260 decodeFrame(decoded, pixels, 0);
270 if ((obj->
flags & 2) != 0) {
279 inside = MemAlloc(size);
284 Iwram_ClearWords(inside, size);
285 src = pixels + w + 1;
286 dst = inside + w + 1;
287 for (i = 1; i < h - 1; i++) {
288 for (k = 1; k < w - 1; k++) {
289 if (src[-1] != 0 && src[1] != 0 && *(src - w) != 0 && src[w] != 0) {
300 for (i = 0; i < size; i++) {
303 }
else if (*src != 0) {
316 void *vram = (
void *)(
OBJ_VRAM0 + (tile << 5));
320 obj->image.tile = tile;
322 system->used += size;
326 if (decoderWasLoaded == 0) {
338 s32 height,
s32 screenY,
s32 groundHeight,
345 s32 scaleX = *scale++;
352 if (scaleX > 0x10000 || scaleY > 0x10000) {
359 x = (screenX >> 16) - halfWidth;
360 y = ((screenY - height) >> 16) - halfHeight -
361 ((((sprite->
height >> 1) - sprite->
offsetY) * scaleY + 0xffff) >> 16);
366 x = (screenX >> 16) - marginX;
367 y = ((screenY - groundHeight) >> 16) - marginY;
389 const s32 *scaleValues = scale->values;
393 s32 shadowHalfWidth = 8;
394 s32 shadowHalfHeight = 4;
396 s32 scaleX = *scaleValues++;
397 s32 screenX = *pos++;
398 s32 scaleY = *scaleValues;
400 s32 screenY = *pos++;
401 s32 groundHeight = *pos;
416 if (flip == 0 && scaleX == 0x10000 && scaleY == scaleX &&
423 effect.
scaleX = scaleX >> 8;
424 effect.
scaleY = scaleY >> 8;
429 if (scaleX > 0x10000 || scaleY > 0x10000) {
433 shadowHalfWidth = 16;
434 shadowHalfHeight = 8;
437 if (height <= -0x640000) {
441 slot = (screenY >> 17) + 10;
445 y = ((screenY - groundHeight) >> 16) - shadowHalfHeight;
446 if (sprite->
flags & 1) {
451 part->
x = (screenX >> 16) - shadowHalfWidth;
456 x = (screenX >> 16) - halfWidth + ((sprite->
offsetX * scaleX + 0xffff) >> 16);
457 y = ((screenY - height) >> 16) - halfHeight -
458 ((scaleY * ((sprite->
height >> 1) - sprite->
offsetY) + 0xffff) >> 16);
461 if (
x < 240 &&
y < 160) {
462 part = &sprite->
image;
503 if (screen[2] != 0 && screen[0] >= -32 && screen[0] <= 272 &&
504 screen[1] >= -32 && screen[1] <= 208) {
509 halfWidth = sprite->
width >> 1;
510 halfHeight = sprite->
height >> 1;
514 roundedScale = (z + 0x400) & -0x800;
542 }
else if (flip != 0) {
551 image->
x = screen[0] - halfWidth + offsetX;
552 image->
y = screen[1] - halfHeight + offsetY;
559 slot = (0x200 - screen[2]) / 2 + 128;
568 if (sprite->
flags & 1) {
574 shadow->
x = screen[0] -
size;
575 shadow->
y = screen[1] - (
size >> 1) + 2;
606 u32 remaining = count;
609 if (layer->
param != 15)
610 layer->
param = value;
612 }
while (remaining != 0);
void Animation_SetWorkEntry(struct AnimationEntry *layer, s32 animation)
Starts the indexed animation on a layer when its metadata contains it.
static __inline__ void Dma_Set(const volatile void *source, volatile void *destination, u32 control, volatile u32 *channel)
Starts a DMA transfer: stores the source, destination and control words into channel's registers with...
const u8 gAnimationFacing_Kind88[8]
const u8 gAnimationFacing_Kind3[16]
const u8 gAnimationFacing_Kind2[8]
const u8 gAnimationFacing_Kind1[16]
Facing tables: for each animation kind, the frame to draw for each sector of the facing angle.
const u8 gAnimationFacing_Kind6[64]
const u8 gAnimationFacing_Kind22[8]
const u8 gAnimationFacing_Kind5[16]
const u8 gAnimationFacing_Kind4[64]
const u8 gAnimationFacing_Kind8[8]
u8 * Resource_DecompressLz(const u8 *source, u8 *destination)
Decompresses an LZ stream from source into destination and returns destination.
u8 Render_DecodeFrameCodeSize[]
What every part of the field object shares: its includes and the few names more than one part uses.
@ ANIM_CMD_JUMP
continue at script position arg
@ ANIM_CMD_WAIT
keep the current frame arg frames longer
@ ANIM_CMD_BLANK
show nothing for arg
@ ANIM_CMD_END
blank the layer and stop its script
@ ANIM_CMD_SET_KIND
use facing table arg
@ ANIM_CMD_PLAY
switch to animation arg
@ ANIM_CMD_HOLD
stay on this command and frame for good
const u8 gRender_DecodeFrameBuffer[]
void * MemAlloc(s32 size)
Allocates size bytes (rounded up to words) with no slot, from IWRAM when they fit and EWRAM otherwise...
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
@ HEAP_SLOT_FRAME_UPLOADER
@ HEAP_SLOT_FRAME_SCRATCH
Lives for one frame: WaitFrames builds the OAM list in it, and the field sprite decoder keeps its cod...
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
#define OBJ_VRAM0
Sprite tile memory, as pret names it: the 32 KB from 0x06010000.
#define Iwram_MulQ16(left, right)
static void * Iwram_Decompress(const void *source, void *destination)
#define SET_VECTOR(v, x, y, z)
Sets the x, y and z of a three-part vector: a position about to be projected, a per-frame step,...
void Runtime_ReleaseHeapBlock(s32 slot)
void MemFree(void *buffer)
s32 AffineMatrix_BuildForEffect(struct AffineTransform *source)
Hands out the next OAM affine matrix for a sprite drawn with source's scale and rotation and fills it...
void Runtime_PushSlotEntry(void *slotEntry, s32 slot)
Links a sprite entry into depth slot slot (clamped to 0..255) for this frame.
static const s32 * SpritePlacement_ReadValues(const struct SpritePlacement *placement)
Returns the placement's values as an array.
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
s32 Sprite_ComposeAnimationFrame(struct AnimationObject *obj, u16 dir)
Advances a sprite's animation layers by one frame, picks each layer's frame for the facing dir,...
void Render_ApplyProjectedPlacement(struct AnimationObject *sprite, const struct SpritePlacement *position, const struct SpriteScale *scale, s32 facing)
Places a sprite for the scrolling camera and queues it for drawing.
void Render_PlaceSpritePartPair(struct AnimationObject *sprite, s32 screenX, s32 height, s32 screenY, s32 groundHeight, s32 *scale)
Positions a sprite's image (part 0) and shadow (part 1) on the screen: the image centred on screenX a...
void(*) SpriteDrawFn(const void *src, void *dst, s32 param)
Draws one layer's frame into a sprite's pixel buffer (Render_DecodeFrame, run from RAM).
void Render_PlaceProjectedSprite(struct AnimationObject *sprite, s32 *point, s32 *scale, s32 facing, s32 depth)
Places a sprite at 3D point for the fixed camera and queues it for drawing: projected to the screen a...
void ObjectGroup_SetChildValueUnlessFifteen(void *rawSprite, u32 value)
Sets the draw parameter of each of a sprite's layers to value, except layers whose parameter is 15,...
void(*) SpriteUploadFn(const void *src, u32 w, u32 h, void *vram)
Uploads a finished sprite buffer to sprite VRAM (Tile_CopyStrided).
One animation layer of a sprite: its animation id, frames, running script and timer.
u8 frameBase
frame the script chose, before facing; 255 blank
u8 param
SpriteColorMode its pixels are drawn with; 0 when taken.
u8 pos
byte offset of the next command in script
u8 step
taken off timer each frame; 16 is normal speed
u8 * script
the running script; null when stopped (ANIM_CMD_END)
u8 kind
The facing table its frames follow (from the metadata, or ANIM_CMD_SET_KIND); zero marks a free layer...
u8 mode
frame codec: 1 type-01, 3 LZ, anything else raw
void ** frames
frame pointers, from the metadata or a resource slot
u16 timer
Time left on the current frame in sixteenths of a frame, read signed: each timed command adds its arg...
u8 frame
frame shown, frameBase plus the facing offset; 255 none
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
struct AnimationSpritePart shadow
struct AnimationSpritePart image
u16 rotation
1/65536 turns
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
u8 width
pixels; zero marks a free sprite
u8 lastNo
The animation number last selected, which selecting again skips.
u8 slot
VRAM cache entry holding its tiles.
struct AnimationEntry * entries[4]
its layers; empty ones null
u8 count
layers in use, up to the last one present
u8 useOwnScale
Drawn at its own scale, not scaled by distance (fixed camera).
s32 scale
16.16 fixed point, 0x10000 full size
u8 retainCacheEntry
Keeps the VRAM cache entry when it is released or off screen.
u8 dirty
nonzero redraws its pixels into VRAM when next drawn
The hardware sprite attributes one part of an animated sprite (its image or its shadow) is drawn with...
u16 y
The OAM entry's attributes 0 to 2.
u16 affine
0 plain, 1 affine, 3 affine at double size
u16 affineIndex
affine matrix, or 8 for a mirrored plain sprite
The object system's work: the flag that suspends sprite projection, the outline's edge and fill colou...
s16 suspended
nonzero while a menu has suspended sprite projection
A sprite's screen position and its two vertical offsets, in 16.16 pixels.
Horizontal and vertical sprite scale; 0x10000 is the original size.
s32 VramCache_ReleaseVram(u32 no)
Gives back entry no's blocks but keeps the entry taken, with size 1, so a later VramCache_Load can re...
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.