Alchemy
Loading...
Searching...
No Matches

sprite_viewer.c

Go to the documentation of this file.
1/// @file
2/// A debug sprite viewer.
3/// Part of field.c, the field object, compiled only through it.
4
5#include "../field_internal.h"
6
7enum {
12};
13
20};
21
22/// One animation layer the sprite viewer edits.
24 s16 spriteId; ///< metadata record selected for this layer
25 s16 animationIndex; ///< script selected from that metadata
26 u8 enabled; ///< zero hides it by a priority above the drawing range
27 s8 priority; ///< drawing order, 0 to 3
28 s8 colorMode; ///< SpriteColorMode; the viewer cycles through 0 to 15
29};
30
31/// A debug sprite viewer, which never returns. It shows a sprite (with up to
32/// three more animation layers) once for each of its facings, in a ring.
33/// Start with the direction pad moves the ring; otherwise up and down choose
34/// a layer and left and right what to edit: 0 the animation, 1 the sprite
35/// number (ten at a time with Start), 2 the priority, 3 the draw parameter,
36/// changed with L and R. A restarts the animation, or in the other modes
37/// turns a layer on or off. Pressing Start toggles the shadows; B turns the
38/// ring when it is rebuilt with Start held. Select starts over; it passes
39/// a far-call resource set (the alternate one unless B is held) to
40/// RuntimeDispatch_ReturnZero, a stub that ignores it.
41///
42/// It has a bare veneer in the field far-call table, and no caller names it.
43/// Takes heap slot 9 for the ring of ten positions and runs
44/// Battle_PlaceActorsByFormationKind each frame to draw the copies.
47 struct AnimationMetadata *spriteMetadata;
48 struct AnimationObject *sprites;
49 volatile s32 fillWord;
50 s32 spriteId;
51 s32 x;
52 s32 y;
53 u32 editMode;
54 s32 shadowsEnabled;
55 struct SpritePlacement *ring;
56 s32 selectedLayer;
57 u32 spriteSteps;
58 // The selected resource offset becomes its sprite, then its flags address.
59 union {
60 s32 resourceOffset;
61 struct AnimationObject *sprite;
62 u8 *flags;
63 } spriteWork;
64 s32 changed;
65 /* FAKEMATCH(temporary): only gKeysHeld and gKeysRepeat are held, in fp and
66 * r9, read through these pointers; as gKeysHeld and gKeysRepeat directly,
67 * 135 of 672 instructions differ in tbs-en. */
68 volatile u32 *heldKeys;
69 volatile u32 *repeatedKeys;
70 u32 i;
71
72 // The ring's centre, in pixels.
73 x = 144;
74 y = 96;
76 shadowsEnabled = 1;
77 selectedLayer = 0;
79 UI_SPRITE_VIEWER_COPY_COUNT * sizeof(*ring));
81
82 // Only the ring's first word is cleared; Map_BuildProbeRing fills it.
83 Dma_Fill32Cell(fillWord, 0, ring, 4);
84 Dma_Fill32Cell(fillWord, 0, layers, sizeof(layers));
85
86 // All four layers start on the first sprite with an image, animation 1,
87 // priority 1; only layer 0 is shown.
88 spriteId = Ui_FindNextSpriteWithImage(-1, 1);
89 for (i = 0; i < ANIMATION_LAYER_COUNT; i++) {
90 layers[i].animationIndex = 1;
91 layers[i].priority = 1;
92 layers[i].spriteId = spriteId;
93 }
94 layers[0].enabled = 1;
95 gDebugMode = 2;
96 // Only BG0 and the sprites are shown.
98 // A green backdrop (BGR555 green 15).
99 PLTT_BACKDROP = 0x01E0;
102
103 // Rebuilt from here whenever layer 0's sprite changes or Select is
104 // pressed: a fresh heap, task table and VRAM cache each time.
105restart:
109 UI_SPRITE_VIEWER_COPY_COUNT * sizeof(*ring));
112 // With no map loaded, the map cell buffer holds layer 0's frames; a
113 // two-part sprite (draw kind 20) puts its second part in the actor
114 // sprite buffer, as resource slot 1.
115 ResourceSlot_Load(0, (u32 *)Ram_MapCellBuffer, layers[0].spriteId, 0);
116 spriteMetadata = Resource_GetMetadataRecordFar(layers[0].spriteId);
117 if (spriteMetadata->drawKind == 20) {
118 ResourceSlot_Load(1, (u32 *)Ram_ActorSpriteSlots, layers[0].spriteId + 1,
119 0);
120 }
121
122 // Ten copies of the sprite; for a sprite of draw kind 20 every other copy
123 // shows its second part, number + 1, from resource slot 1.
124 for (i = 0; i < UI_SPRITE_VIEWER_COPY_COUNT; i++) {
125 spriteMetadata = Resource_GetMetadataRecordFar(layers[0].spriteId);
126 spriteWork.resourceOffset = 0;
127 if (spriteMetadata->drawKind == 20 && (i & 1) != 0) {
128 spriteWork.resourceOffset = 1;
129 }
130 spriteWork.sprite =
131 ResourceObject_Create(layers[0].spriteId + spriteWork.resourceOffset +
132 (spriteWork.resourceOffset << 12));
133 // Layers 1 to 3 are added to every copy whether shown or not; a hidden
134 // layer is kept out of the drawing by its priority below.
135 ResourceMetadata_Register(spriteWork.sprite, layers[1].spriteId);
136 ResourceMetadata_Register(spriteWork.sprite, layers[2].spriteId);
137 ResourceMetadata_Register(spriteWork.sprite, layers[3].spriteId);
138 /* FAKEMATCH(temporary): the native adds the flags offset to the sprite's
139 * own register (r5) in place; as spriteWork.sprite->flags = shadowsEnabled,
140 * 21 of 672 instructions differ in tbs-en. */
141 spriteWork.flags = &spriteWork.sprite->flags;
142 *spriteWork.flags = shadowsEnabled;
143 }
144
145 // Priority 8 hides a layer: Sprite_ComposeAnimationFrame draws only
146 // priorities 0 to 3.
147 for (i = 0; i < ANIMATION_LAYER_COUNT; i++) {
148 if (layers[i].enabled != 0) {
149 Ui_SetGridColumnPriority(i, layers[i].priority);
150 } else {
152 }
153 Ui_SetGridColumnParameter(i, layers[i].colorMode);
154 Ui_FillGridColumnFromMetadata(i, layers[i].animationIndex);
155 }
156 // The copies are drawn each frame by the task below, from the ring's
157 // positions.
158
159 Map_BuildProbeRing(x, y, ring);
160 // Order 3200 (0xc80), where the field camera runs.
162
163next:
164 WaitFrames(1);
165 heldKeys = &gKeysHeld;
166 repeatedKeys = &gKeysRepeat;
167 for (;;) {
168 // Start held: the direction pad moves the ring a pixel a frame.
169 // Otherwise up and down pick the layer and left and right the mode,
170 // both wrapping at four.
171
172 if ((*heldKeys & KEY_START) != 0) {
173 if ((*heldKeys & KEY_LEFT) != 0) {
174 x--;
175 }
176 if ((*heldKeys & KEY_RIGHT) != 0) {
177 x++;
178 }
179 if ((*heldKeys & KEY_UP) != 0) {
180 y--;
181 }
182 if ((*heldKeys & KEY_DOWN) != 0) {
183 y++;
184 }
185 Map_BuildProbeRing(x, y, ring);
186 } else {
187 (void)gKeysRepeat;
188 if ((*repeatedKeys & KEY_UP) != 0) {
189 selectedLayer = (selectedLayer - 1) & (ANIMATION_LAYER_COUNT - 1);
190 }
191 if ((gKeysRepeat & KEY_DOWN) != 0) {
192 selectedLayer = (selectedLayer + 1) & (ANIMATION_LAYER_COUNT - 1);
193 }
194 if ((gKeysRepeat & KEY_LEFT) != 0) {
195 editMode = (editMode - 1) & (UI_SPRITE_VIEWER_EDIT_COUNT - 1);
196 }
197 if ((gKeysRepeat & KEY_RIGHT) != 0) {
198 editMode++;
199 editMode &= UI_SPRITE_VIEWER_EDIT_COUNT - 1;
200 }
201 }
202
203 // A press of Start also toggles the shadows (sprite flag bit 0) of the
204 // ten copies.
205 if ((gKeysPressed & KEY_START) != 0) {
206 sprites = gSpriteObjects;
207 shadowsEnabled ^= 1;
208 for (i = 0; i < UI_SPRITE_VIEWER_COPY_COUNT; i++) {
209 sprites->flags = shadowsEnabled;
210 sprites++;
211 }
212 }
213
214 switch (editMode) {
215 // Mode 0, the animation: layer 1 follows layer 0's and is not edited on
216 // its own; 0 to 99.
218 if (selectedLayer == 1) {
219 break;
220 }
221 if ((gKeysRepeat & KEY_L) != 0) {
222 layers[selectedLayer].animationIndex--;
223 if (layers[selectedLayer].animationIndex < 0) {
224 layers[selectedLayer].animationIndex = 0;
225 }
226 if (selectedLayer == 0) {
227 layers[1].animationIndex = layers[0].animationIndex;
228 }
229 goto next;
230 }
231 if ((gKeysRepeat & KEY_R) == 0) {
232 break;
233 }
234 layers[selectedLayer].animationIndex++;
235 if (layers[selectedLayer].animationIndex >=
237 layers[selectedLayer].animationIndex =
239 }
240 if (selectedLayer == 0) {
241 layers[1].animationIndex = layers[0].animationIndex;
242 }
243 goto next;
244
245 // Mode 1, the sprite number: one sprite with an image at a time, or ten
246 // with Start held.
248 changed = 0;
249 spriteSteps = 1;
250 if ((*heldKeys & KEY_START) != 0) {
251 spriteSteps = 10;
252 }
253 if ((*repeatedKeys & KEY_L) != 0) {
254 for (i = 0; i < spriteSteps; i++) {
255 layers[selectedLayer].spriteId =
256 Ui_FindNextSpriteWithImage(layers[selectedLayer].spriteId, -1);
257 }
258 changed = 1;
259 }
260 if ((*repeatedKeys & KEY_R) != 0) {
261 for (i = 0; i < spriteSteps; i++) {
262 layers[selectedLayer].spriteId =
263 Ui_FindNextSpriteWithImage(layers[selectedLayer].spriteId, 1);
264 }
265 changed = 1;
266 }
267 if (changed == 0) {
268 break;
269 }
270 // A new sprite on layer 0 changes the ring and the copies: start over.
271 if (selectedLayer == 0) {
272 goto restart;
273 }
274 // A hidden layer only remembers the number until it is shown again.
275 if (layers[selectedLayer].enabled != 0) {
276 Ui_SetGridColumnNumber(selectedLayer, layers[selectedLayer].spriteId);
277 Ui_SetGridColumnPriority(selectedLayer, layers[selectedLayer].priority);
278 Ui_SetGridColumnParameter(selectedLayer,
279 layers[selectedLayer].colorMode);
280 Ui_FillGridColumnFromMetadata(selectedLayer,
281 layers[selectedLayer].animationIndex);
282 }
283 goto next;
284
285 // Mode 2, the layer's draw priority, 0 to 3 and wrapping.
287 changed = 0;
288 if ((*repeatedKeys & KEY_L) != 0) {
289 layers[selectedLayer].priority--;
290 if (layers[selectedLayer].priority < 0) {
291 layers[selectedLayer].priority = 3;
292 }
293 changed = 1;
294 }
295 if ((*repeatedKeys & KEY_R) != 0) {
296 layers[selectedLayer].priority++;
297 if (layers[selectedLayer].priority > 3) {
298 layers[selectedLayer].priority = 0;
299 }
300 changed = 1;
301 }
302 if (changed == 0) {
303 break;
304 }
305 if (layers[selectedLayer].enabled != 0) {
306 Ui_SetGridColumnPriority(selectedLayer, layers[selectedLayer].priority);
307 }
308 goto next;
309
310 // Mode 3, the draw parameter, 0 to 15 and wrapping; 15 is the value
311 // ObjectGroup_SetChildValueUnlessFifteen leaves alone.
313 changed = 0;
314 if ((*repeatedKeys & KEY_L) != 0) {
315 layers[selectedLayer].colorMode--;
316 if (layers[selectedLayer].colorMode < 0) {
317 layers[selectedLayer].colorMode = 15;
318 }
319 changed = 1;
320 }
321 if ((*repeatedKeys & KEY_R) != 0) {
322 layers[selectedLayer].colorMode++;
323 if (layers[selectedLayer].colorMode > 15) {
324 layers[selectedLayer].colorMode = 0;
325 }
326 changed = 1;
327 }
328 if (changed == 0) {
329 break;
330 }
331 if (layers[selectedLayer].enabled != 0) {
332 Ui_SetGridColumnParameter(selectedLayer,
333 layers[selectedLayer].colorMode);
334 }
335 goto next;
336
337 default:
338 break;
339 }
340
341 // A, in mode 0: restart the selected layer's animation (layer 0 also
342 // restarts layer 1, which follows it). In the other modes: show or hide
343 // the layer; layer 0 is always shown.
344 if ((*repeatedKeys & KEY_A) != 0) {
345 if (editMode == UI_SPRITE_VIEWER_EDIT_ANIMATION) {
346 if (selectedLayer != 1) {
347 if (layers[selectedLayer].enabled != 0) {
348 Ui_FillGridColumnFromMetadata(selectedLayer,
349 layers[selectedLayer].animationIndex);
350 if (selectedLayer == 0) {
351 Ui_FillGridColumnFromMetadata(1, layers[1].animationIndex);
352 }
353 }
354 goto next;
355 }
356 } else if (selectedLayer != 0) {
357 layers[selectedLayer].enabled ^= 1;
358 Ui_SetGridColumnPriority(selectedLayer,
359 layers[selectedLayer].enabled != 0
360 ? layers[selectedLayer].priority
362 goto next;
363 }
364 }
365
366 // RuntimeDispatch_ReturnZero ignores its arguments, so the resource set
367 // chosen here changes nothing in this build.
368 if ((*repeatedKeys & KEY_SELECT) != 0) {
370 if ((*heldKeys & KEY_B) != 0) {
373 } else {
376 }
377 goto restart;
378 }
379 WaitFrames(1);
380 }
381}
382
383/// Returns the next sprite id after spriteId, stepping by direction (1 or
384/// -1) and wrapping within 0-511, whose metadata has an image (a nonzero
385/// width). Called by Ui_RunIconMonitor.
386s32 Ui_FindNextSpriteWithImage(s32 spriteId, s32 direction) {
387 for (;;) {
388 spriteId += direction;
389 // Past either end, jump to just beyond the other, so the next step
390 // lands on 511 or 0.
391 if (spriteId < 0) {
393 continue;
394 }
395 {
396 /* FAKEMATCH(temporary): the bound in a local compares as cmp against
397 * 0x200 with blt, as native; as spriteId >= 0x200, 3 of 25 instructions
398 * differ in tbs-en. */
400 if (spriteId >= spriteLimit) {
401 spriteId = -1;
402 continue;
403 }
404 }
405 if (Resource_GetMetadataRecordFar(spriteId)->width) {
406 return spriteId;
407 }
408 }
409}
410
411/// Lays out the sprite viewer's ring around pixel (x, z): one position per
412/// facing of the first sprite's facing kind (6, 8, 10 or 4, or two opposite
413/// pairs for kind 20), 56 pixels out (40 for kind 20). B held turns the ring.
414/// Called by Ui_RunIconMonitor when it starts and while Start moves the ring.
415void Map_BuildProbeRing(s32 centerX, s32 centerY,
416 struct SpritePlacement *positions) {
417 struct SpritePlacement *pairedPositions;
418 s32 angle;
419 s32 facingIndex;
420 u16 initialHeading;
421 u8 facingKind;
422
423 angle = 0;
424 // Select the viewer sprite's formation; headings wrap as 16-bit turns.
425 facingKind = gSpriteObjects->entries[0]->kind;
426 // With B held the ring starts at an angle that turns with the frame
427 // counter, a full turn every 256 frames.
428 if ((gKeysHeld & KEY_B) != 0)
429 angle = (s16)(gFrameTick << 8);
430 // 0x2aaa, 0x2000, 0x1999 and 0x4000 are a sixth, an eighth, a tenth and
431 // a quarter of a turn; 0x380000 is 56 pixels. Unused positions of the ten
432 // are skipped.
433 switch ((u32)facingKind) {
434 case 3:
435 for (facingIndex = 0; facingIndex < 6; facingIndex++) {
436 angle = (u32)angle << 16;
437 positions->x = centerX << 16;
438 angle = (u32)angle >> 16;
439 positions->height = 0;
440 positions->y = centerY << 16;
441 Vector_AddPolarOffset(0x380000, (u16)angle,
442 SpritePlacement_Values(positions));
443 positions++;
444 angle = (s16)(angle + 0x2aaa);
445 }
446 for (; facingIndex < UI_SPRITE_VIEWER_COPY_COUNT; facingIndex++)
447 positions++;
448 break;
449 case 5:
450 case 8:
451 case 44:
452 case 88:
453 for (facingIndex = 0; facingIndex < 8; facingIndex++) {
454 angle = (u32)angle << 16;
455 positions->x = centerX << 16;
456 angle = (u32)angle >> 16;
457 positions->height = 0;
458 positions->y = centerY << 16;
459 Vector_AddPolarOffset(0x380000, (u16)angle,
460 SpritePlacement_Values(positions));
461 positions++;
462 angle = (s16)(angle + 0x2000);
463 }
464 for (; facingIndex < UI_SPRITE_VIEWER_COPY_COUNT; facingIndex++)
465 positions++;
466 break;
467 case 4:
468 case 6:
469 for (facingIndex = 0; facingIndex < UI_SPRITE_VIEWER_COPY_COUNT;
470 facingIndex++) {
471 angle = (u32)angle << 16;
472 positions->x = centerX << 16;
473 angle = (u32)angle >> 16;
474 positions->height = 0;
475 positions->y = centerY << 16;
476 Vector_AddPolarOffset(0x380000, (u16)angle,
477 SpritePlacement_Values(positions));
478 positions++;
479 angle = (s16)(angle + 0x1999);
480 }
481 break;
482 // Draw kind 20: two places 40 pixels out, a quarter turn round and then
483 // opposite it, each holding both of the sprite's parts.
484 case 20:
485 initialHeading = angle;
486 angle = (s16)(initialHeading + 0x4000);
487 facingIndex = 0;
488 pairedPositions = positions;
489 while (facingIndex < 2) {
490 pairedPositions[facingIndex * 2].x = centerX << 16;
491 pairedPositions[facingIndex * 2].height = 0;
492 pairedPositions[facingIndex * 2].y = centerY << 16;
493 angle = (u32)angle << 16;
494 angle = (u32)angle >> 16;
495 Vector_AddPolarOffset(0x280000, angle,
496 SpritePlacement_Values(&positions[0]));
497 pairedPositions[facingIndex * 2 + 1].x = centerX << 16;
498 {
499 s32 *point = SpritePlacement_Values(&positions[1]);
500 pairedPositions[facingIndex * 2 + 1].height = 0;
501 pairedPositions[facingIndex * 2 + 1].y = centerY << 16;
502 Vector_AddPolarOffset(0x280000, (u16)angle, point);
503 }
504 angle = ((u32)angle + 0x8000) << 16;
505 facingIndex++;
506 positions += 2;
507 angle >>= 16;
508 }
509 break;
510 // Any other kind: four places, starting an eighth of a turn round.
511 default:
512 angle = (s32)(((u32)angle << 16) + 0x20000000) >> 16;
513 for (facingIndex = 0; facingIndex < 4; facingIndex++) {
514 angle = (u32)angle << 16;
515 angle = (u32)angle >> 16;
516 positions->x = centerX << 16;
517 positions->height = 0;
518 positions->y = centerY << 16;
519 Vector_AddPolarOffset(0x380000, (u16)angle,
520 SpritePlacement_Values(positions));
521 positions++;
522 angle = (s16)(angle + 0x4000);
523 }
524 for (facingIndex = 4; facingIndex < UI_SPRITE_VIEWER_COPY_COUNT;
525 facingIndex++)
526 positions++;
527 break;
528 }
529}
530
531/// Defines name(slot, value), which sets field of entry slot (0-3) in each of
532/// the first ten sprites to value.
533#define UI_DEFINE_SET_GRID_COLUMN(name, field) \
534 void name(s32 layerIndex, s32 value) { \
535 struct AnimationObject *spriteGroup = gSpriteObjects; \
536 s32 spriteIndex; \
537 \
538 layerIndex &= ANIMATION_LAYER_COUNT - 1; \
539 for (spriteIndex = 0; spriteIndex < UI_SPRITE_VIEWER_COPY_COUNT; \
540 spriteIndex++) { \
541 spriteGroup->entries[layerIndex]->field = value; \
542 spriteGroup++; \
543 } \
544 }
545
546/// Sets the draw parameter or the priority of one layer of the viewer's ten
547/// sprites.
550
551/// Starts animationIndex on layerIndex of each of the viewer's ten sprites,
552/// each one a frame (16 timer units) behind the last, so the copies are
553/// staggered. Also sets each copy's offsetY and clears its rotation.
554/// Called by Ui_RunIconMonitor.
555void Ui_FillGridColumnFromMetadata(s32 layerIndex, s32 animationIndex) {
556 s32 spriteIndex;
557 struct AnimationObject *spriteGroup;
558
559 spriteGroup = gSpriteObjects;
560 spriteIndex = 0;
561 do {
562 struct AnimationEntry *entry =
563 spriteGroup->entries[layerIndex & (ANIMATION_LAYER_COUNT - 1)];
564 struct AnimationMetadata *metadata;
565 s32 initialFrame = 0;
566
567 if (entry->scripts != 0) {
568 metadata = Resource_GetMetadataRecordFar(entry->animId);
569 if (animationIndex < metadata->animationCount) {
570 // Copy n starts n frames (16 timer units each) late, at normal
571 // speed, with no frame drawn yet.
572 entry->kind = metadata->drawKind;
573 entry->script = entry->scripts[animationIndex];
574 entry->timer = spriteIndex * ANIMATION_NORMAL_STEP;
576 entry->pos = initialFrame;
577 entry->frameBase = initialFrame;
578 entry->frame = 0xff;
579 }
580 spriteGroup->offsetY = metadata->adjustY;
581 spriteGroup->rotation = initialFrame;
582 }
583 spriteIndex++;
584 spriteGroup++;
585 } while (spriteIndex < UI_SPRITE_VIEWER_COPY_COUNT);
586}
587
588/// Sets spriteId on layerIndex of each of the viewer's ten sprites.
589/// Resets each layer from its new metadata. Called by Ui_RunIconMonitor when
590/// a layer other than 0 gets a new sprite.
591void Ui_SetGridColumnNumber(s32 layerIndex, s32 spriteId) {
592 struct AnimationObject *spriteGroup = gSpriteObjects;
593 s32 spriteIndex;
594
595 // The ROM looks the metadata up here and drops the result.
597 layerIndex &= ANIMATION_LAYER_COUNT - 1;
598 for (spriteIndex = 0; spriteIndex < UI_SPRITE_VIEWER_COPY_COUNT;
599 spriteIndex++) {
600 struct AnimationEntry *entry = spriteGroup->entries[layerIndex];
601
602 entry->animId = spriteId;
604 spriteGroup++;
605 }
606}
607
608/// Each frame in the sprite viewer: places each copy of the sprite at its
609/// ring position, facing the way that position stands for.
610/// Despite its name it belongs to the sprite viewer, which schedules it; its
611/// ring is the placements in heap slot 9 (HEAP_SLOT_BATTLE) and its sprites
612/// the pool in heap slot 4.
614 struct AnimationObject *sprite = WORK_SLOT(4);
615 u32 facingKind = sprite->entries[0]->kind;
616 struct SpriteScale scale;
617 struct SpritePlacement *facingPositions;
618 u16 angle;
619 u16 step;
620 u16 pairedFacingStep = 0;
621 u32 count;
622 u32 spriteIndex;
623
625 facingPositions = WORK_SLOT(HEAP_SLOT_BATTLE);
626
627 switch (facingKind) {
628 case 3:
629 angle = 0;
630 step = 0x2aaa;
631 count = 6;
632 break;
633 case 5:
634 case 8:
635 case 44:
636 case 88:
637 angle = 0;
638 step = 0x2000;
639 count = 8;
640 break;
641 case 4:
642 case 6:
643 angle = 0;
644 step = 0x1999;
645 count = 10;
646 break;
647 // The two parts at each place face the same way; the second place faces
648 // half a turn from the first.
649 case 20:
650 angle = 0;
651 step = 0;
652 pairedFacingStep = 0x8000;
653 count = 4;
654 break;
655 // The eighth-turn start matches Map_BuildProbeRing's default ring.
656 default:
657 angle = 0x2000;
658 step = 0x4000;
659 count = 4;
660 break;
661 }
662
663 // Copy n faces n steps round, the way its ring position lies.
664 for (spriteIndex = 0; spriteIndex < count; spriteIndex++) {
665 Render_ApplyProjectedPlacement(sprite, &facingPositions[spriteIndex],
666 &scale, angle);
667 sprite++;
668 angle += step;
669 if (spriteIndex & 1)
670 angle += pairedFacingStep;
671 }
672}
673
674#undef UI_DEFINE_SET_GRID_COLUMN
s32 ResourceSlot_Load(u32 slot, u32 *buffer, s32 number, u32 variant)
Loads the frames of animation id number into resource slot slot's buffer: the resource listed for it ...
Definition animation.c:34
s32 ResourceMetadata_Register(struct AnimationObject *sprite, s32 id)
Adds a layer of animation id to a sprite, in its first free layer of four.
Definition animation.c:191
void Animation_InitWorkFromMetadata(struct AnimationEntry *layer)
Resets one animation layer from its animation's metadata, as Animation_InitializeObjects does for eac...
Definition animation.c:160
struct AnimationObject * ResourceObject_Create(s32 id)
Creates a sprite for animation id, taking one of the 64 free sprites and a VRAM cache entry for its t...
Definition animation.c:512
#define Dma_Fill32Cell(cell, value, destination, size)
Dma_Fill32 through the caller's own volatile word cell, so a function that fills several blocks keeps...
Definition dma.h:42
void Fade_FromBlack(s32 frames)
Fades in from black.
Definition fade.c:79
struct AnimationMetadata * Resource_GetMetadataRecordFar(u32 number)
void ObjectSystem_Initialize(s32 controlMode)
Sets up the object system: allocates and zeroes the 64 objects and registers the per-frame updates.
Definition objects.c:157
What every part of the field object shares: its includes and the few names more than one part uses.
@ ANIMATION_LAYER_COUNT
@ ANIMATION_NORMAL_STEP
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
u32 gFrameTick
Counted up by every VBlank.
u8 gDebugMode
Debug builds: Start+Select pauses the frame loop.
const u8 FarCall_ResourceTable[]
u8 gDecodeFillByte
struct AnimationObject * gSpriteObjects
const struct SpriteScale gBattle_FormationPlacementScale
The sprite viewer's (x, y) sprite scale, 1.0 each (Q16), which Battle_PlaceActorsByFormationKind read...
Definition griddata.c:7
void Runtime_InitializeHeap(void)
Empties the heap: clears the 64 words of gWorkSlot (both pool pointers and every named slot) and sets...
Definition heap.c:15
void * Runtime_AllocateBlock(s32 kind, s32 size)
As Runtime_AllocateHeapBlock, but tries EWRAM first, for blocks that need room more than speed: the b...
Definition heap.c:80
@ HEAP_SLOT_BATTLE
Definition heap_state.h:37
#define WORK_SLOT(n)
Reads slots through their own addresses; adjacent slots are reached by offsets.
Definition heap_state.h:14
@ DISPCNT_OBJ_ON
Definition io_reg.h:44
@ DISPCNT_BG0_ON
Definition io_reg.h:40
@ DISPCNT_OBJ_1D_MAP
Definition io_reg.h:39
@ KEY_UP
Definition io_reg.h:249
@ KEY_B
Definition io_reg.h:244
@ KEY_SELECT
Definition io_reg.h:245
@ KEY_LEFT
Definition io_reg.h:248
@ KEY_START
Definition io_reg.h:246
@ KEY_RIGHT
Definition io_reg.h:247
@ KEY_R
Definition io_reg.h:251
@ KEY_A
Definition io_reg.h:243
@ KEY_DOWN
Definition io_reg.h:250
@ KEY_L
Definition io_reg.h:252
#define REG_DISPCNT
Definition io_reg.h:9
#define PLTT_BACKDROP
Definition io_reg.h:155
#define BLDCNT_EFFECT_BLEND
weighted by REG_BLDALPHA
Definition io_reg.h:131
#define BLDCNT_TGT2_ALL
Definition io_reg.h:140
#define BLDCNT_TGT1_BG1
Definition io_reg.h:124
#define REG_BLDCNT
Definition io_reg.h:119
volatile u32 gKeysHeld
Keys down now.
volatile u32 gKeysPressed
Keys that went down this frame.
volatile u32 gKeysRepeat
Pressed keys, repeating while held: after 19 frames, then every 6.
void Vector_AddPolarOffset(s32 radius, s32 angle, void *position)
Moves the point position by radius in direction angle on the ground plane: x by the cosine,...
Definition math.c:23
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
#define Ram_ActorSpriteSlots
Definition ram_buffer.h:16
static s32 * SpritePlacement_Values(struct SpritePlacement *placement)
Returns the placement's values as a writable array.
char ResourceId_ResourceFarCalls
char ResourceId_ResourceFarCallsAlternate
s32 Scheduler_AddOrUpdateCallback(SchedulerCallback callback, s32 order)
Schedules callback with order, or gives a task already running it the new order, and re-sorts the tab...
Definition scheduler.c:102
void Scheduler_ResetTaskTable(void)
Empties the task table: every slot gets no routine, order 0xffff (sorted last) and no flags.
Definition scheduler.c:19
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.
s32 Ui_FindNextSpriteWithImage(s32 spriteId, s32 direction)
Returns the next sprite id after spriteId, stepping by direction (1 or -1) and wrapping within 0-511,...
void Ui_SetGridColumnPriority(s32 layerIndex, s32 value)
void Ui_RunIconMonitor(void)
A debug sprite viewer, which never returns.
UiSpriteViewerEditMode
@ UI_SPRITE_VIEWER_EDIT_PRIORITY
@ UI_SPRITE_VIEWER_EDIT_COLOR
@ UI_SPRITE_VIEWER_EDIT_ANIMATION
@ UI_SPRITE_VIEWER_EDIT_SPRITE
@ UI_SPRITE_VIEWER_EDIT_COUNT
@ UI_SPRITE_VIEWER_COPY_COUNT
@ UI_SPRITE_VIEWER_ANIMATION_LIMIT
@ UI_SPRITE_VIEWER_SPRITE_LIMIT
@ UI_SPRITE_VIEWER_HIDDEN_PRIORITY
void Ui_FillGridColumnFromMetadata(s32 layerIndex, s32 animationIndex)
Starts animationIndex on layerIndex of each of the viewer's ten sprites, each one a frame (16 timer u...
void Map_BuildProbeRing(s32 centerX, s32 centerY, struct SpritePlacement *positions)
Lays out the sprite viewer's ring around pixel (x, z): one position per facing of the first sprite's ...
void Battle_PlaceActorsByFormationKind(void)
Each frame in the sprite viewer: places each copy of the sprite at its ring position,...
void Ui_SetGridColumnParameter(s32 layerIndex, s32 value)
Sets the draw parameter or the priority of one layer of the viewer's ten sprites.
void Ui_SetGridColumnNumber(s32 layerIndex, s32 spriteId)
Sets spriteId on layerIndex of each of the viewer's ten sprites.
#define UI_DEFINE_SET_GRID_COLUMN(name, field)
Defines name(slot, value), which sets field of entry slot (0-3) in each of the first ten sprites to v...
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 pos
byte offset of the next command in script
Definition animspr.h:51
u8 ** scripts
the metadata's command scripts, one per animation number
Definition animspr.h:49
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
s16 animId
the sprite id whose metadata and frames it uses
Definition animspr.h:38
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 animation's metadata: the sprite's size, scale and offsets, how its frames are drawn and decoded,...
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
Definition animspr.h:108
s8 offsetY
pixels
Definition animspr.h:122
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
struct AnimationEntry * entries[4]
its layers; empty ones null
Definition animspr.h:130
A sprite's screen position and its two vertical offsets, in 16.16 pixels.
s32 x
screen x of the sprite's centre
s32 y
screen y at the ground; sets the depth slot
s32 height
how far the image is raised above y
Horizontal and vertical sprite scale; 0x10000 is the original size.
One animation layer the sprite viewer edits.
s8 colorMode
SpriteColorMode; the viewer cycles through 0 to 15.
s16 spriteId
metadata record selected for this layer
s16 animationIndex
script selected from that metadata
u8 enabled
zero hides it by a priority above the drawing range
s8 priority
drawing order, 0 to 3
s32 RuntimeDispatch_ReturnZero(s32 unused0, const u8 *unused1)
An exported stub that ignores its arguments and reports 0.
Definition system.c:124
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed char s8
Definition types.h:10
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11
void VramCache_Reset(void)
Frees every block and every cache entry.
Definition vram_cache.c:184