Alchemy
Loading...
Searching...
No Matches

sprite_draw.c

Go to the documentation of this file.
1/// @file
2/// Drawing sprites: composing their layers and placing them on screen.
3/// Part of field.c, the field object, compiled only through it.
4
5#include "../field_internal.h"
6
7/// Draws one layer's frame into a sprite's pixel buffer (Render_DecodeFrame,
8/// run from RAM).
9typedef void (*SpriteDrawFn)(const void *src, void *dst, s32 param);
10/// Uploads a finished sprite buffer to sprite VRAM (Tile_CopyStrided).
11typedef void (*SpriteUploadFn)(const void *src, u32 w, u32 h, void *vram);
12
13/// Advances a sprite's animation layers by one frame, picks each layer's frame
14/// for the facing dir, and when any frame changed redraws the sprite: the
15/// layers composed by priority into one pixel buffer, an optional outline,
16/// and the result uploaded to the sprite's VRAM tiles. Returns 1 when layer
17/// 0's frame for this facing is drawn mirrored.
18///
19/// Called for each sprite drawn, every frame, by Render_ApplyProjectedPlacement
20/// and Render_PlaceProjectedSprite. Writes the layers' script position,
21/// timer and frame, the sprite's dirty flag and tile, its tiles in OBJ VRAM,
22/// and the ObjectSystemWork's count of bytes composed; takes heap slot
23/// HEAP_SLOT_FRAME_SCRATCH for the decoder when no caller holds it, and frees
24/// it again.
26 s32 mirrored;
27 u32 size;
28 struct ObjectSystemWork *system;
29 SpriteDrawFn decodeFrame;
30 s32 decoderWasLoaded;
31 struct AnimationEntry *layer;
32 void *code;
33 u8 *pixels;
34 u8 *unpacked;
35 void *decoded;
36 u16 drawOrder[ANIMATION_LAYER_COUNT];
37 s32 i;
38 s32 k;
39 s32 drawCount;
40 u32 key;
41 s32 arg;
42 s32 frame;
43 u32 facing;
44 s32 tile;
45
46 // The object system's work and the frame decoder sit in the heap slot
47 // table; load the decoder into RAM for this call if no one else has.
48 mirrored = 0;
49 system = gMenuCtrlWork;
50 decoderWasLoaded = 1;
51 // UB: gMenuCtrlWork is one pointer, not an array reaching the decoder cell.
52 // The native form derives both cell addresses from this one base; using
53 // WORK_SLOT directly changes allocation and adds a literal-pool entry.
54#ifdef UBFIX
56#else
57 decodeFrame =
60#endif
61 if (decodeFrame == 0) {
66 (DMA_ENABLE | DMA_32BIT) << 16,
67 REG_DMA3);
68#ifdef UBFIX
70#else
71 decodeFrame =
74#endif
75 decoderWasLoaded = 0;
76 }
77
78 // Step each layer's script: read commands until one shows a frame for a
79 // while, else count the current frame's time down.
80 for (i = 0; i < obj->count; i++) {
81 layer = obj->entries[i];
82 if (layer == 0) {
83 continue;
84 }
85 if (layer->script == 0) {
86 continue;
87 }
88 // The command loop is written with goto: as while ((s16)layer->timer <= 0),
89 // 33 of 544 instructions differ in tbs-en.
90 read_command:
91 if ((s16)layer->timer <= 0) {
92 frame = layer->script[layer->pos++];
93 arg = layer->script[layer->pos++];
94 switch (frame) {
95 case ANIM_CMD_PLAY:
96 Animation_SetWorkEntry(layer, arg);
97 obj->lastNo = arg;
98 break;
99 case ANIM_CMD_JUMP:
100 layer->pos = arg;
101 break;
102 case ANIM_CMD_WAIT:
103 layer->timer += arg << 4;
104 break;
105 case ANIM_CMD_HOLD:
106 layer->pos -= 2;
107 goto framed;
109 layer->kind = arg;
110 break;
111 case ANIM_CMD_BLANK:
112 layer->frameBase = 255;
113 frame = 255;
114 layer->timer += arg << 4;
115 goto select_direction;
116 case ANIM_CMD_END:
117 layer->frameBase = 255;
118 layer->script = 0;
119 frame = 255;
120 // XXX: ending any layer lowers the sprite's layer count, so the last
121 // layer stops being stepped and drawn even when another one ended; a
122 // sprite whose layer other than the last ends would show whether that
123 // is a bug.
124 obj->count--;
125 goto select_direction;
126 // Unused commands, skipped. 251 is not among them: it shows as a frame.
127 case 242:
128 case 243:
129 case 244:
130 case 246:
131 case 247:
132 case 248:
133 case 249:
134 case 250:
135 case 252:
136 break;
137 default:
138 layer->frameBase = frame;
139 layer->timer += arg << 4;
140 goto select_direction;
141 }
142 goto read_command;
143 }
144 // Time is left on this frame: count it down by the layer's step (16, the
145 // normal speed, takes a frame off each frame).
146 layer->timer = layer->timer - layer->step;
147 framed:
148 frame = layer->frameBase;
149 select_direction:
150 // The facing table of the layer's kind gives an offset from the base
151 // frame (low three bits) and whether to mirror it (bit 7).
152 // The facing is cut into 8 (kinds 1, 2, 20, 22, 8 and 88), 16 (3, 5) or
153 // 64 (4, 6) sectors; kinds 8 and 88 centre theirs on the directions.
154 switch (layer->kind) {
155 case 1:
156 facing = gAnimationFacing_Kind1[dir >> 13];
157 break;
158 case 2:
159 case 20:
160 facing = gAnimationFacing_Kind2[dir >> 13];
161 break;
162 case 22:
163 facing = gAnimationFacing_Kind22[dir >> 13];
164 break;
165 case 3:
166 facing = gAnimationFacing_Kind3[dir >> 12];
167 break;
168 case 4:
169 facing = gAnimationFacing_Kind4[dir >> 10];
170 break;
171 case 5:
172 facing = gAnimationFacing_Kind5[dir >> 12];
173 break;
174 case 6:
175 facing = gAnimationFacing_Kind6[dir >> 10];
176 break;
177 case 8:
178 facing = gAnimationFacing_Kind8[((u32)(dir << 16) + 0x10000000) >> 29];
179 break;
180 case 88:
181 facing = gAnimationFacing_Kind88[((u32)(dir << 16) + 0x10000000) >> 29];
182 break;
183 default:
184 facing = 0;
185 break;
186 }
187 frame += facing & 7;
188 if (i == 0 && (facing >> 7) != 0) {
189 mirrored = 1;
190 }
191 if (layer->frame != frame) {
192 layer->frame = frame;
193 obj->dirty = 1;
194 }
195 }
196
197 if (obj->dirty != 0) {
198 size = obj->width * obj->height;
199 pixels = MemAlloc(size);
200 Iwram_ClearWords(pixels, size);
201
202 // Sort the visible layers by priority (0-3), then by index, with an
203 // insertion sort on keys of (priority << 8) | index.
204 drawCount = -1;
205 for (i = obj->count - 1; i >= 0; i--) {
206 layer = obj->entries[i];
207 if (layer == 0) {
208 continue;
209 }
210 if (layer->frames == 0) {
211 continue;
212 }
213 if (layer->frame == 255) {
214 continue;
215 }
216 key = layer->priority;
217 if (key > 3) {
218 continue;
219 }
220 key = (key << 8) | i;
221 // The scan leaves by goto, which keeps it unrotated with its step at the
222 // top: as a for loop that shifts while drawOrder[k] > key, 156 of 544
223 // instructions differ in tbs-en, and with one break test 91.
224 k = drawCount;
225 if (k >= 0 && drawOrder[k] > key) {
226 drawOrder[k + 1] = drawOrder[k];
227 for (;;) {
228 k--;
229 if (k < 0)
230 goto insert;
231 if (drawOrder[k] <= key)
232 goto insert;
233 drawOrder[k + 1] = drawOrder[k];
234 }
235 }
236 insert:
237 drawOrder[k + 1] = key;
238 drawCount++;
239 }
240 drawCount++;
241
242 // Draw the layers in that order. A layer's frames are stored by its
243 // codec: 1 is the type-01 format, 3 LZ (unpacked first, or drawn
244 // through a scratch buffer when the layer has a draw parameter), and
245 // anything else raw for the decoder.
246 for (i = 0; i < drawCount; i++) {
247 layer = obj->entries[*(u8 *)&drawOrder[i]];
248 if (layer->mode == 1) {
249 Resource_DecodeType01(layer->frames[layer->frame], pixels);
250 } else if (layer->mode == 3) {
251 if (layer->param != 0) {
252 unpacked = MemAlloc(0x400);
253 decodeFrame(
254 Resource_DecompressLz(layer->frames[layer->frame], unpacked),
255 pixels, layer->param);
256 MemFree(unpacked);
257 } else {
258 decoded = Iwram_Decompress(layer->frames[layer->frame], pixels);
259 if (decoded != 0) {
260 decodeFrame(decoded, pixels, 0);
261 }
262 }
263 } else {
264 decodeFrame(layer->frames[layer->frame], pixels, layer->param);
265 }
266 }
267
268 // Outline: a pixel whose four neighbours are all drawn becomes the fill
269 // colour, and any other drawn pixel the edge colour.
270 if ((obj->flags & 2) != 0) {
271 u8 *inside;
272 u8 edge;
273 u8 fill;
274 u32 w;
275 u32 h;
276 u8 *src;
277 u8 *dst;
278
279 inside = MemAlloc(size);
280 w = obj->width;
281 h = obj->height;
282 edge = system->edge;
283 fill = system->fill;
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) {
290 *dst = 1;
291 }
292 dst++;
293 src++;
294 }
295 dst += 2;
296 src += 2;
297 }
298 src = pixels;
299 dst = inside;
300 for (i = 0; i < size; i++) {
301 if (*dst != 0) {
302 *src = fill;
303 } else if (*src != 0) {
304 *src = edge;
305 }
306 dst++;
307 src++;
308 }
309 MemFree(inside);
310 }
311
312 // Upload the pixels to the sprite's tiles in VRAM.
313 // The tile number counts 32-byte tiles.
314 tile = VramCache_Load(obj->slot, size, 0);
315 {
316 void *vram = (void *)(OBJ_VRAM0 + (tile << 5));
318 obj->height, vram);
319 }
320 obj->image.tile = tile;
321 obj->dirty = 0;
322 system->used += size;
323 MemFree(pixels);
324 }
325
326 if (decoderWasLoaded == 0) {
328 }
329 return mirrored;
330}
331
332/// Positions a sprite's image (part 0) and shadow (part 1) on the screen: the
333/// image centred on screenX and raised height above screenY, the shadow at
334/// groundHeight. scale is the sprite's (x, y) scale (16.16); above 1.0 both
335/// parts use the double-size affine mode. It has a bare veneer in the field
336/// far-call table, and no caller names it.
337void Render_PlaceSpritePartPair(struct AnimationObject *sprite, s32 screenX,
338 s32 height, s32 screenY, s32 groundHeight,
339 s32 *scale) {
340 u32 halfWidth = sprite->width >> 1;
341 u32 halfHeight = sprite->height >> 1;
342 s32 marginX = 8;
343 s32 marginY = 4;
344 s32 affine = 1;
345 s32 scaleX = *scale++;
346 s32 scaleY = *scale;
347 s32 x;
348 s32 y;
349 struct AnimationSpritePart *shadow;
350
351 // Double-size affine sprites need enlarged image bounds and shadow margins.
352 if (scaleX > 0x10000 || scaleY > 0x10000) {
353 affine = 3;
354 marginX = 16;
355 marginY = 8;
356 halfWidth <<= 1;
357 halfHeight <<= 1;
358 }
359 x = (screenX >> 16) - halfWidth;
360 y = ((screenY - height) >> 16) - halfHeight -
361 ((((sprite->height >> 1) - sprite->offsetY) * scaleY + 0xffff) >> 16);
362 sprite->image.affine = affine;
363 sprite->image.x = x;
364 sprite->image.y = y;
365 // Place the shadow at ground height independently of the raised image.
366 x = (screenX >> 16) - marginX;
367 y = ((screenY - groundHeight) >> 16) - marginY;
368 shadow = &sprite->shadow;
369 shadow->affine = affine;
370 shadow->x = x;
371 shadow->y = y;
372}
373
374/// Places a sprite for the scrolling camera and queues it for drawing. Position
375/// holds screen x, height, screen y and ground height in 16.16 pixels; scale
376/// holds its x/y factors and facing its angle. Builds an affine matrix when the
377/// sprite is mirrored, scaled or rotated, queues the shadow (when the sprite
378/// has one) and then the image in a draw slot by depth; an object 100 pixels
379/// or more below the ground takes slot 1 instead, its shadow slot 0.
380///
381/// Called by ObjectSystem_UpdateCamera for each one-sprite object on a
382/// layered map, by the sprite viewer, and as Object_ApplyProjectedPlacementFar
383/// by the battle effects, the Psynergy effects and the menus.
385 const struct SpritePlacement *position,
386 const struct SpriteScale *scale,
387 s32 facing) {
388 const s32 *pos = SpritePlacement_ReadValues(position);
389 const s32 *scaleValues = scale->values;
390 s32 matrix;
391 u32 halfWidth = sprite->width >> 1;
392 u32 halfHeight = sprite->height >> 1;
393 s32 shadowHalfWidth = 8;
394 s32 shadowHalfHeight = 4;
395 s32 affine;
396 s32 scaleX = *scaleValues++;
397 s32 screenX = *pos++;
398 s32 scaleY = *scaleValues;
399 s32 height = *pos++;
400 s32 screenY = *pos++;
401 s32 groundHeight = *pos;
402 s32 slot;
403 /* FAKEMATCH(dead): two unused arrays for 24 bytes of the native 68-byte
404 * frame; without them, 2 of 250 instructions differ in tbs-en. */
405 UNUSED s32 ground[3];
406 UNUSED s32 screen[3];
407 struct AffineTransform effect;
408 s32 flip;
409 s32 x;
410 s32 y;
411 s32 depth;
412 struct AnimationSpritePart *part;
413
414 // Reuse an untransformed sprite when mirroring, scale and rotation allow it.
415 flip = Sprite_ComposeAnimationFrame(sprite, facing);
416 if (flip == 0 && scaleX == 0x10000 && scaleY == scaleX &&
417 sprite->rotation == 0) {
418 affine = 0;
419 matrix = 0;
420 } else {
421 affine = 1;
422 effect.angle = sprite->rotation;
423 effect.scaleX = scaleX >> 8;
424 effect.scaleY = scaleY >> 8;
425 if (flip != 0)
426 effect.scaleX = -effect.scaleX;
427 matrix = AffineMatrix_BuildForEffect(&effect);
428 }
429 if (scaleX > 0x10000 || scaleY > 0x10000) {
430 affine = 3;
431 halfWidth <<= 1;
432 halfHeight <<= 1;
433 shadowHalfWidth = 16;
434 shadowHalfHeight = 8;
435 }
436 // Draw slot by screen row, one slot per two rows from slot 10.
437 if (height <= -0x640000) {
438 slot = 1;
439 depth = 0;
440 } else {
441 slot = (screenY >> 17) + 10;
442 depth = 2;
443 }
444 // Queue the shadow at ground height before the raised image.
445 y = ((screenY - groundHeight) >> 16) - shadowHalfHeight;
446 if (sprite->flags & 1) {
447 if (y < 160) {
448 part = &sprite->shadow;
449 part->affine = affine;
450 part->affineIndex = matrix;
451 part->x = (screenX >> 16) - shadowHalfWidth;
452 part->y = y;
453 Runtime_PushSlotEntry(part, depth);
454 }
455 }
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);
459 // Only the right and bottom edges are tested; OAM wraps a negative
460 // position.
461 if (x < 240 && y < 160) {
462 part = &sprite->image;
463 part->x = x;
464 part->y = y;
465 part->affine = affine;
466 part->affineIndex = matrix;
467 Runtime_PushSlotEntry(part, slot);
468 }
469}
470
471/// Places a sprite at 3D point for the fixed camera and queues it for drawing:
472/// projected to the screen and scaled by its distance (unless useOwnScale
473/// keeps its own scale), with an affine matrix as needed and its shadow on
474/// the ground below. depth 0 sorts it by distance; any other value is its draw
475/// slot. A sprite off screen gives up its VRAM cache entry unless
476/// retainCacheEntry holds it.
477///
478/// Called by ObjectSystem_UpdateCameraFixed for each object on the world map
479/// and in the battle; while a menu suspends projection
480/// (ObjectSystemWork.suspended) every sprite is treated as off screen.
482 s32 *scale, s32 facing, s32 depth) {
483 s32 flip;
484 u32 halfHeight;
485 u32 size;
486 s32 affine;
487 s32 halfWidth;
488 s32 ground[3];
489 s32 screen[3];
490 struct AffineTransform effect;
491 s32 z;
492 s32 roundedScale;
493 s32 scaleX;
494 s32 scaleY;
495 s32 offsetX;
496 s32 offsetY;
497 s32 slot;
498
499 // Project first, then discard sprites beyond the padded screen bounds.
500 affine = 1;
501 if (gMenuCtrlWork->suspended == 0) {
502 z = Render_ProjectPoint(point, screen);
503 if (screen[2] != 0 && screen[0] >= -32 && screen[0] <= 272 &&
504 screen[1] >= -32 && screen[1] <= 208) {
505 if (sprite->useOwnScale)
506 z = sprite->scale;
507 else
508 z = Iwram_MulQ16(z, sprite->scale);
509 halfWidth = sprite->width >> 1;
510 halfHeight = sprite->height >> 1;
511 size = 8;
512 flip = Sprite_ComposeAnimationFrame(sprite, facing);
513 // Quantize the perspective scale before combining it with local scale.
514 roundedScale = (z + 0x400) & -0x800;
515 scaleX = Iwram_MulQ16(roundedScale, *scale++);
516 scaleY = Iwram_MulQ16(roundedScale, *scale);
517 if (scaleX > 0x1f7ff)
518 scaleX = 0x1f800;
519 if (scaleY > 0x1f7ff)
520 scaleY = 0x1f800;
521 offsetX = Iwram_MulQ16(sprite->offsetX, scaleX);
522 offsetY = -Iwram_MulQ16((sprite->height >> 1) - sprite->offsetY, scaleY);
523 if (scaleX > 0x10000 || scaleY > 0x10000) {
524 affine = 3;
525 halfWidth <<= 1;
526 halfHeight <<= 1;
527 size = 16;
528 } else if (scaleX == 0x10000 && sprite->rotation == 0 &&
529 scaleY == scaleX) {
530 affine = 0;
531 }
532 // Mirroring uses negative affine scale when a matrix is needed.
533 if (affine != 0) {
534 effect.angle = sprite->rotation;
535 effect.scaleX = scaleX >> 8;
536 if (flip != 0) {
537 effect.scaleX = -effect.scaleX;
538 offsetX = -offsetX;
539 }
540 effect.scaleY = scaleY >> 8;
541 z = AffineMatrix_BuildForEffect(&effect);
542 } else if (flip != 0) {
543 z = 8;
544 offsetX = -offsetX;
545 } else {
546 z = 0;
547 }
548 {
549 struct AnimationSpritePart *image = &sprite->image;
550
551 image->x = screen[0] - halfWidth + offsetX;
552 image->y = screen[1] - halfHeight + offsetY;
553 image->affine = affine;
554 image->affineIndex = z;
555 }
556 // The slot falls as the projected depth screen[2] rises, and stays at
557 // 1 or above: slot 0 is the shadows'.
558 if (depth == 0) {
559 slot = (0x200 - screen[2]) / 2 + 128;
560 if (slot <= 0)
561 slot = 1;
562 Runtime_PushSlotEntry(sprite, slot);
563 } else {
564 Runtime_PushSlotEntry(sprite, depth);
565 }
566 // Project the ground point separately so jumping does not lift the
567 // shadow.
568 if (sprite->flags & 1) {
569 struct AnimationSpritePart *shadow;
570
571 SET_VECTOR(ground, point[0], 0, point[2]);
572 Render_ProjectPoint(ground, screen);
573 shadow = &sprite->shadow;
574 shadow->x = screen[0] - size;
575 shadow->y = screen[1] - (size >> 1) + 2;
576 shadow->affine = affine;
577 shadow->affineIndex = z;
578 if (depth == 0)
579 Runtime_PushSlotEntry(shadow, 0);
580 else
581 Runtime_PushSlotEntry(shadow, depth);
582 }
583 return;
584 }
585 }
586 // Invisible sprites release cached tiles unless their display flags hold
587 // them.
588 if (!sprite->retainCacheEntry) {
590 sprite->dirty = 1;
591 }
592}
593
594/// Sets the draw parameter of each of a sprite's layers to value, except
595/// layers whose parameter is 15, and marks the sprite for redrawing.
596/// Called by Animation_ApplyChildValues and, as
597/// ObjectGroup_SetChildValueUnlessFifteenFar, by the Psynergy effects, the
598/// Sanctum and the Altmiller Cave scene.
599void ObjectGroup_SetChildValueUnlessFifteen(void *rawSprite, u32 value) {
600 struct AnimationObject *sprite = rawSprite;
601 if (sprite != 0) {
602 u32 count = sprite->count;
603
604 if (count != 0) {
605 struct AnimationEntry **entry = sprite->entries;
606 u32 remaining = count;
607 do {
608 struct AnimationEntry *layer = *entry++;
609 if (layer->param != 15)
610 layer->param = value;
611 remaining--;
612 } while (remaining != 0);
613 }
614 sprite->dirty = 1;
615 }
616}
void Animation_SetWorkEntry(struct AnimationEntry *layer, s32 animation)
Starts the indexed animation on a layer when its metadata contains it.
Definition animation.c:289
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...
Definition dma.h:62
const u8 gAnimationFacing_Kind88[8]
Definition facing.c:40
const u8 gAnimationFacing_Kind3[16]
Definition facing.c:26
const u8 gAnimationFacing_Kind2[8]
Definition facing.c:22
const u8 gAnimationFacing_Kind1[16]
Facing tables: for each animation kind, the frame to draw for each sector of the facing angle.
Definition facing.c:13
const u8 gAnimationFacing_Kind6[64]
Definition facing.c:55
const u8 gAnimationFacing_Kind22[8]
Definition facing.c:18
const u8 gAnimationFacing_Kind5[16]
Definition facing.c:31
const u8 gAnimationFacing_Kind4[64]
Definition facing.c:44
const u8 gAnimationFacing_Kind8[8]
Definition facing.c:36
u8 * Resource_DecompressLz(const u8 *source, u8 *destination)
Decompresses an LZ stream from source into destination and returns destination.
Definition decompress.c:17
u8 Render_DecodeFrameCodeSize[]
u8 Render_DecodeFrame[]
What every part of the field object shares: its includes and the few names more than one part uses.
@ ANIMATION_LAYER_COUNT
@ 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...
Definition heap.c:115
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
Definition heap.c:47
@ HEAP_SLOT_MENU_CONTROL
Definition heap_state.h:35
@ HEAP_SLOT_FRAME_UPLOADER
Definition heap_state.h:54
@ HEAP_SLOT_FRAME_SCRATCH
Lives for one frame: WaitFrames builds the OAM list in it, and the field sprite decoder keeps its cod...
Definition heap_state.h:53
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
#define OBJ_VRAM0
Sprite tile memory, as pret names it: the 32 KB from 0x06010000.
Definition io_reg.h:170
#define DMA_32BIT
Definition io_reg.h:210
#define REG_DMA3
Definition io_reg.h:153
#define DMA_ENABLE
Definition io_reg.h:217
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
static void * Iwram_Decompress(const void *source, void *destination)
Definition iwram_call.h:81
#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,...
Definition macros.h:12
void Runtime_ReleaseHeapBlock(s32 slot)
void MemFree(void *buffer)
struct ObjectSystemWork * gMenuCtrlWork
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...
Definition render.c:27
void Runtime_PushSlotEntry(void *slotEntry, s32 slot)
Links a sprite entry into depth slot slot (clamped to 0..255) for this frame.
Definition render.c:79
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.
Definition decompress.c:31
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,...
Definition sprite_draw.c:25
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).
Definition sprite_draw.c:9
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).
Definition sprite_draw.c:11
void * gWorkSlot[]
A sprite's rotation and scale: scales in 8.8 fixed point (0x100 is full size), the angle in 1/65536 t...
Definition affine.h:13
u16 angle
1/65536 turns
Definition affine.h:16
u16 scaleY
8.8 fixed point, read signed
Definition affine.h:15
u16 scaleX
8.8 fixed point, read signed: negative mirrors the sprite
Definition affine.h:14
One animation layer of a sprite: its animation id, frames, running script and timer.
Definition animspr.h:37
u8 frameBase
frame the script chose, before facing; 255 blank
Definition animspr.h:54
u8 param
SpriteColorMode its pixels are drawn with; 0 when taken.
Definition animspr.h:45
u8 pos
byte offset of the next command in script
Definition animspr.h:51
u8 step
taken off timer each frame; 16 is normal speed
Definition animspr.h:52
u8 * script
the running script; null when stopped (ANIM_CMD_END)
Definition animspr.h:50
u8 kind
The facing table its frames follow (from the metadata, or ANIM_CMD_SET_KIND); zero marks a free layer...
Definition animspr.h:44
u8 mode
frame codec: 1 type-01, 3 LZ, anything else raw
Definition animspr.h:47
void ** frames
frame pointers, from the metadata or a resource slot
Definition animspr.h:48
u16 timer
Time left on the current frame in sixteenths of a frame, read signed: each timed command adds its arg...
Definition animspr.h:41
u8 frame
frame shown, frameBase plus the facing offset; 255 none
Definition animspr.h:53
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
struct AnimationSpritePart shadow
Definition animspr.h:110
s8 offsetX
pixels
Definition animspr.h:121
s8 offsetY
pixels
Definition animspr.h:122
struct AnimationSpritePart image
Definition animspr.h:109
u16 rotation
1/65536 turns
Definition animspr.h:118
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
Definition animspr.h:128
u8 width
pixels; zero marks a free sprite
Definition animspr.h:119
u8 height
pixels
Definition animspr.h:120
u8 lastNo
The animation number last selected, which selecting again skips.
Definition animspr.h:124
u8 slot
VRAM cache entry holding its tiles.
Definition animspr.h:112
struct AnimationEntry * entries[4]
its layers; empty ones null
Definition animspr.h:130
u8 count
layers in use, up to the last one present
Definition animspr.h:129
u8 useOwnScale
Drawn at its own scale, not scaled by distance (fixed camera).
Definition animspr.h:116
s32 scale
16.16 fixed point, 0x10000 full size
Definition animspr.h:111
u8 retainCacheEntry
Keeps the VRAM cache entry when it is released or off screen.
Definition animspr.h:114
u8 dirty
nonzero redraws its pixels into VRAM when next drawn
Definition animspr.h:125
The hardware sprite attributes one part of an animated sprite (its image or its shadow) is drawn with...
Definition animspr.h:84
u16 y
The OAM entry's attributes 0 to 2.
Definition animspr.h:90
u16 x
screen pixels
Definition animspr.h:96
u16 affine
0 plain, 1 affine, 3 affine at double size
Definition animspr.h:91
u16 affineIndex
affine matrix, or 8 for a mirrored plain sprite
Definition animspr.h:97
The object system's work: the flag that suspends sprite projection, the outline's edge and fill colou...
Definition animspr.h:66
s16 suspended
nonzero while a menu has suspended sprite projection
Definition animspr.h:69
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 Render_ProjectPoint(const void *point, s32 *screen)
Reads three word-aligned coordinates from point, transforms them by gTransform and projects them to t...
Definition transform.c:364
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
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...
Definition vram_cache.c:122
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.
Definition vram_cache.c:143