Alchemy
Loading...
Searching...
No Matches

intro.c

Go to the documentation of this file.
4#include "battle.h"
5#include "keystate.h"
6#include "debug.h"
7#include "field.h"
8#include "game.h"
9#include "graphics.h"
10#include "menu.h"
11#include "minigame.h"
12#include "sound.h"
13#include "system.h"
14#include "mem.h"
15#include "types.h"
16#include "callback_scheduler.h"
17#include "dma.h"
18#include "edition.h"
19#include "io_reg.h"
20#include "io_write_queue.h"
21#include "map_scroll.h"
22#include "ram_buffer.h"
23#include "resource.h"
24#include "resource_ids.h"
25#include "palbuf.h"
26#include "iwram_call.h"
27#include "heap_state.h"
28#include "scene.h"
29#include "global_cells.h"
30#include "frame.h"
31#include "oambuf.h"
32#include "macros.h"
33#include "songs.h"
34
35/// A sprite of the "Press Start" prompt, linked into a render slot each frame:
36/// OAM attributes 0 to 2 with the position split out.
38 u32 next; ///< the render slot link
40 u8 attr0High; ///< shape and mode bits of attribute 0
41 u16 x : 9;
42 u16 attr1High : 7; ///< flip and size bits of attribute 1
44};
45
46/// The title intro's state, in heap slot 43.
47struct IntroWork {
48 s32 backRows; ///< rows of the far background copied in as it scrolls
49 s32 frontRows; ///< rows of the near background copied in
53 s32 rise; ///< how far the sprites have risen
54 union {
55 struct OamShadow objects[120];
56 struct {
57 u8 introObjects[0x68]; ///< objects[0] to [12], still the intro's
58 struct IntroSprite sprites[8];
59 } prompt;
61};
62
63/// The x of each of the six columns of intro sprites
64const u8 gTitle_IntroSpriteColumns[] = {96, 136, 140, 160, 168, 184};
65
66/// The prompt's blend level over its 60-frame pulse
67// clang-format off
69 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
70 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
71 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
72 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
73};
74// clang-format on
75
76#define INTRO_OBJ(i) (work->area.objects[i])
77
78/// Brings `v` into 0..255 by whole turns of 256
79#define WRAP_TO_BYTE(v) \
80 while ((v) > 255) \
81 (v) -= 256; \
82 while ((v) < 0) \
83 (v) += 256
84
85/// Sets x and y to the top left of a sprite of half-width `half` centred on
86/// column `column`, between slopeBaseY at x = 104 and slopeTopY at x = 184.
87#define PLACE_ON_SLOPE(column, half) \
88 x = gTitle_IntroSpriteColumns[column] - (half); \
89 y = (slopeTopY - slopeBaseY) * ((x + (half)) - 104) / 80 + slopeBaseY - \
90 (half); \
91 WRAP_TO_BYTE(y)
92
93/// Writes OAM entries i to i + 3: four sprites of `size` pixels, mirrored into
94/// the four quarters of one picture at (x, y)
95#define MIRRORED_QUAD(i, size, shape, tile) \
96 INTRO_OBJ(i).attr01 = ((x + 4) << 16) | y | ((shape) + 0x00002400); \
97 INTRO_OBJ((i) + 1).attr01 = \
98 ((x + 4 + (size)) << 16) | y | ((shape) + 0x10002400); \
99 INTRO_OBJ((i) + 2).attr01 = \
100 ((x + 4) << 16) | (u8)(y + (size)) | ((shape) + 0x20002400); \
101 INTRO_OBJ((i) + 3).attr01 = \
102 ((x + 4 + (size)) << 16) | (u8)(y + (size)) | ((shape) + 0x30002400); \
103 INTRO_OBJ(i).attr2 = (tile); \
104 INTRO_OBJ((i) + 1).attr2 = (tile); \
105 INTRO_OBJ((i) + 2).attr2 = (tile); \
106 INTRO_OBJ((i) + 3).attr2 = (tile)
107
108/// A VBlank task of the title intro, scheduled by Title_ShowIntro: places the
109/// rising sprites along the slope of the scrolling background, alternating two
110/// sets every other frame so twice as many show, hides the rest and copies the
111/// list to OAM.
113 /* FAKEMATCH: the OAM shadow it builds is struct OamShadow, volatile words
114 * (tag in oambuf.h): without the qualifier differ 205, 471 instructions for
115 * 496. */
116 struct IntroWork *work;
117 u32 spriteCount;
118 s32 slopeBaseY;
119 s32 slopeTopY;
120 s32 x;
121 s32 y;
122 s32 stripY;
123
124 work = Ram_WorkSlot[43];
125 spriteCount = 0;
126 if (gDebugPaused == 0) {
127 if ((++work->tick & 3) == 0)
128 work->rise++;
129 }
130 slopeBaseY = 48 - gBgScroll[1].y;
131 slopeTopY = 144 - work->rise;
132 // Alternating the two groups fits six shapes into twelve OAM entries;
133 // each group is visible every other frame.
134 if (work->frame < 0x118) {
135 if ((work->tick & 1) == 0) {
136 PLACE_ON_SLOPE(0, 16);
137 MIRRORED_QUAD(spriteCount, 16, 0x40000000, 232);
138 spriteCount += 4;
139 PLACE_ON_SLOPE(2, 16);
140 INTRO_OBJ(spriteCount).attr01 = ((x + 4) << 16) | y | 0x80002400;
141 INTRO_OBJ(spriteCount).attr2 = 128;
142 spriteCount++;
143 PLACE_ON_SLOPE(4, 32);
144 MIRRORED_QUAD(spriteCount, 32, 0x80000000, 192);
145 spriteCount += 4;
146 } else {
147 PLACE_ON_SLOPE(1, 16);
148 MIRRORED_QUAD(spriteCount, 16, 0x40000000, 232);
149 spriteCount += 4;
150 PLACE_ON_SLOPE(3, 16);
151 MIRRORED_QUAD(spriteCount, 16, 0x40000000, 224);
152 spriteCount += 4;
153 PLACE_ON_SLOPE(5, 32);
154 MIRRORED_QUAD(spriteCount, 32, 0x80000000, 160);
155 spriteCount += 4;
156 }
157 }
158 for (; spriteCount <= 119; spriteCount++)
159 INTRO_OBJ(spriteCount).attr01 = 0x400020a0;
161 REG_BLDALPHA = BLEND_ALPHA(14, 14);
162 Dma_Set(&INTRO_OBJ(0), OAM, DMA_COPY_WORDS((spriteCount * 8) >> 2), REG_DMA3);
163 // The strip follows the back layer and occupies the first OAM entry
164 // beyond the 120-entry list; it reuses a hidden shadow-buffer entry.
165 stripY = 32 - gBgScroll[1].y;
166 WRAP_TO_BYTE(stripY);
167 INTRO_OBJ(12).attr01 = stripY | 0xc05c2000;
168 INTRO_OBJ(12).attr2 = 0x800;
169 Dma_Set(&INTRO_OBJ(12), (u8 *)OAM + spriteCount * 8, DMA_COPY_WORDS(2),
170 REG_DMA3);
172}
173
174/// Loads the title intro's two scrolling backgrounds and its sprite tiles,
175/// builds their maps and sets the blending and windows. Called by
176/// Title_ShowIntro.
178 struct IntroWork *work;
179 u8 *resourceData;
180 u16 *tilemap;
181 s32 column;
182 s32 row;
183 u16 tileIndex;
184 s32 blankTile;
185
186 work = Ram_WorkSlot[43];
187 REG_DISPCNT = 0;
189 Dma_Set(resourceData, (void *)OBJ_PLTT, DMA_COPY_WORDS(0x80), REG_DMA3);
190 OBJ_PLTT[0] = 0;
191 resourceData += 0x200;
193 Dma_Set(Ram_MapCellBuffer, (void *)OBJ_VRAM0, DMA_ENABLE << 16 | 0xf00,
194 REG_DMA3);
196 Dma_Set(resourceData, (void *)BG_PLTT, DMA_COPY_WORDS(0x80), REG_DMA3);
197 BG_PLTT[0] = 0;
198 resourceData += 0x200;
201 DMA_ENABLE << 16 | 0x2760, REG_DMA3);
202 Dma_Set(Ram_MapCellBuffer + 0xa140, (void *)0x06004ec0,
203 DMA_ENABLE << 16 | 0x4ec0, REG_DMA3);
204
205 blankTile = 0x1ff;
206 tilemap = (u16 *)BG_SCREEN_BLOCK(30);
207 tileIndex = 0x267;
208 for (row = 0; row <= 10; row++) {
209 for (column = 0; column < 30; column++)
210 *tilemap++ = tileIndex++;
211 *tilemap++ = blankTile;
212 *tilemap++ = blankTile;
213 }
214 tileIndex = 0x13b;
215 for (row = 11; row <= 31; row++) {
216 for (column = 0; column < 30; column++)
217 *tilemap++ = tileIndex++;
218 *tilemap++ = blankTile;
219 *tilemap++ = blankTile;
220 }
221 tilemap = (u16 *)BG_SCREEN_BLOCK(31);
222 tileIndex = 300;
223 for (row = 0; row <= 10; row++) {
224 for (column = 0; column < 30; column++)
225 *tilemap++ = tileIndex++;
226 *tilemap++ = blankTile;
227 *tilemap++ = blankTile;
228 }
229 tileIndex = 0;
230 for (row = 11; row <= 31; row++) {
231 for (column = 0; column < 30; column++)
232 *tilemap++ = tileIndex++;
233 *tilemap++ = blankTile;
234 *tilemap++ = blankTile;
235 }
236
239 REG_WIN0H = WIN_RANGE(0, 240);
240 REG_WIN0V = WIN_RANGE(0, 159);
241 REG_WIN1H = WIN_RANGE(0, 240);
242 REG_WIN1V = WIN_RANGE(0, 159);
245 for (row = 0; row < 4; row++) {
246 gBgScroll[row].y = 0;
247 gBgScroll[row].x = 0;
248 }
249 gBgScroll[1].y = 96;
250 gBgScroll[2].y = 96;
251 work->frame = 0;
252 work->backRows = 0;
253 work->frontRows = 0;
254 work->tick = 0;
255 work->rise = 0;
256 work->state = 0;
259 REG_BLDALPHA = BLEND_ALPHA(16, 16);
261}
262
263// The "Press Start" prompt: its tile count, rows and sprites, and where it
264// stands, by edition.
265#if (LANGUAGE == LANGUAGE_GERMAN)
266#define PROMPT_TILES 8
267#else
268#define PROMPT_TILES 5
269#endif
270#if (LANGUAGE == LANGUAGE_GERMAN)
271#define PROMPT_ROWS 2
272#define PROMPT_SPRITES 3
273#define PROMPT_X 80
274#define PROMPT_Y 116
275#elif (LANGUAGE == LANGUAGE_JAPANESE)
276#define PROMPT_SPRITES 5
277#define PROMPT_X 56
278#define PROMPT_Y 126
279#elif (LANGUAGE == LANGUAGE_FRENCH)
280#define PROMPT_SPRITES 5
281#define PROMPT_X 56
282#define PROMPT_Y 124
283#else
284#define PROMPT_SPRITES 3
285#define PROMPT_X 80
286#define PROMPT_Y 124
287#endif
288
289/// Plays the title intro: the backgrounds scroll down and the sprites rise
290/// until frame 278 (A or Start skips ahead), then the screen flashes white
291/// into the title picture. With `prompt` set the "Press Start" prompt pulses
292/// for up to a minute, otherwise the picture stays five seconds. Reached
293/// through the palette far-call table from the title screen. Returns 1 when A
294/// or Start was pressed on the title picture.
296 struct IntroWork *work;
297 s32 result;
298 u8 savedCpuLoadDisplay;
299 u16 clearValue;
300 u8 *resourceData;
301 u16 *tilemap;
302 u32 i;
303 u16 tile;
304 u32 j;
305 u32 holdFrames;
306 s32 blankTile;
307
308 result = 0;
309 blankTile = 0x1ff;
310 savedCpuLoadDisplay = gCpuLoadDisplayEnabled;
311 work = Runtime_AllocateHeapBlock(43, 224);
314 WaitFrames(1);
316 gOamCopyEnabled = result;
317 gCpuLoadDisplayEnabled = result;
321 // This screen supplies its own OAM list in VBlank. Keep the normal OAM
322 // copy disabled until its sprite callback is removed at the white flash.
330
331 for (;;) {
332 s32 frame;
333 s32 nextFrame;
334 s32 tick;
335
336 // A skip retains the final approach to the flash rather than replacing
337 // the animated screen at an arbitrary scroll position.
338 frame = work->frame;
339 if (frame > 20 && frame < 239 &&
340 (gKeysPressed & (KEY_A | KEY_START)) != 0) {
341 work->state = 1;
342 work->frame = 239;
343 frame = 239;
344 }
345 nextFrame = frame + 1;
346 work->frame = nextFrame;
347 if (nextFrame <= 278) {
348 // The back layer (BG1) scrolls a pixel every third tick, the front
349 // (BG2) every other one; each new row of eight pixels copies the next
350 // band of the picture from the decode buffer before it becomes visible.
351 tick = work->tick;
352 if (tick % 3 == 0) {
353 s32 y;
354
355 gBgScroll[1].y--;
356 y = gBgScroll[1].y;
357 if ((y & 7) == 0) {
358 Dma_Set(Ram_MapCellBuffer + 0x2580 - work->backRows * 960,
359 (u8 *)0x06004b00 - work->backRows * 960,
360 DMA_ENABLE << 16 | 0x1e0, REG_DMA3);
361 work->backRows++;
362 tick = work->tick;
363 }
364 }
365 if ((tick & 1) == 0) {
366 s32 y;
367
368 gBgScroll[2].y--;
369 y = gBgScroll[2].y;
370 if ((y & 7) == 0) {
371 if (work->frontRows * 8 <= 24) {
372 Dma_Set(Ram_MapCellBuffer + 0x99c0 - work->frontRows * 1920,
373 (u8 *)0x0600e4c0 - work->frontRows * 1920,
374 DMA_ENABLE << 16 | 0x3c0, REG_DMA3);
375 } else {
376 // Once the finite picture is exhausted, clear incoming bands
377 // so wrapped tile memory cannot expose earlier picture rows.
378 clearValue = 0;
379 Dma_Set(&clearValue,
380 (u8 *)0x06004ec0 + (160 - work->frontRows * 8) % 160 * 240,
381 (DMA_ENABLE | DMA_SRC_FIXED) << 16 | 0x3c0, REG_DMA3);
382 tilemap = (u16 *)0x0600f6c0;
383 for (i = 0; i < 5; i++) {
384 for (j = 0; j < 30; j++)
385 *tilemap++ = 0x13b;
386 *tilemap++ = 0x13b;
387 *tilemap++ = 0x13b;
388 }
389 }
390 work->frontRows++;
391 }
392 }
393 if (work->frame == 239)
394 work->state = 1;
395 } else if (nextFrame == 281) {
396 // The frame-280 branch below exits before these later states can run.
397 work->state = 2;
398 } else if (nextFrame == 289) {
399 work->state = 0;
400 } else if (nextFrame == 280) {
401 // Hide the background replacement behind white, and restore the
402 // normal OAM uploader before drawing the title prompt.
403 Fade_ToWhite(1);
405 gOamCopyEnabled = 1;
406 WaitFrames(1);
409 gBgScroll[2].y = 0;
411 Dma_Set(resourceData, (void *)BG_PLTT, DMA_COPY_WORDS(0x78), REG_DMA3);
412 BG_PLTT[0] = 0;
413 resourceData += 0x200;
416 REG_DMA3);
417 tilemap = (u16 *)BG_SCREEN_BLOCK(6);
418 tile = 0x100;
419 i = 0;
420 break;
421 }
422 WaitFrames(1);
423 }
424 // Blank the two off-screen columns so the 30-tile picture occupies a
425 // complete 32-tile hardware map row.
426 for (; i < 20; i++) {
427 for (j = 0; j < 30; j++)
428 *tilemap++ = tile++;
429 *tilemap++ = blankTile;
430 *tilemap++ = blankTile;
431 }
432
435 if (prompt != 0) {
436 u8 *buffer = Runtime_AllocateBlock(14, 0x400);
437 struct IntroSprite *sprite = work->area.prompt.sprites;
438
440 for (i = 0; i < PROMPT_TILES; i++) {
441 s32 vramBlock =
442 VramCache_Load(Resource_FindFreeEntry(), 128, buffer + (i << 8) / 2);
443 u32 *spriteWords = (u32 *)sprite;
444
445 *spriteWords++ = 0;
446 sprite++;
447 *spriteWords++ = 0x40004000;
448 *spriteWords = vramBlock;
449 }
451 }
452 Fade_FromWhite(30);
453 Fade_Wait();
456 if (prompt != 0)
457 holdFrames = 3600;
458 else
459 holdFrames = 300;
460 for (i = 0; i < holdFrames; i++) {
461 if (prompt != 0) {
462 struct IntroSprite *sprite = work->area.prompt.sprites;
463 u32 level;
464 s32 x;
465#if (LANGUAGE == LANGUAGE_GERMAN)
466 u32 row;
467 s32 y;
468
469 for (row = 0, y = PROMPT_Y; row < PROMPT_ROWS; y += 8, row++) {
470 for (j = 0, x = PROMPT_X; j < PROMPT_SPRITES; j++) {
471 sprite->x = x;
472 sprite->y = y;
473 Runtime_PushSlotEntry(sprite, 0);
474 x += 32;
475 sprite++;
476 }
477 }
478#else
479
480 for (j = 0, x = PROMPT_X; j < PROMPT_SPRITES; j++) {
481 sprite->x = x;
482 sprite->y = PROMPT_Y;
483 Runtime_PushSlotEntry(sprite, 0);
484 x += 32;
485 sprite++;
486 }
487#endif
488 // The prompt pulses once a second: its blend weight over the picture
489 // (written out: as BLEND_ALPHA(level, 16 - level) the bytes differ).
490 level = gTitle_PromptBlendLevels[i % 60];
494 REG_BLDALPHA = (16 - level) * 256 + level;
495 }
496 if ((gKeysPressed & (KEY_A | KEY_START)) != 0) {
497 result = 1;
498 break;
499 }
500 WaitFrames(1);
501 }
502 gCpuLoadDisplayEnabled = savedCpuLoadDisplay;
504 REG_BLDCNT = 0;
505 REG_BLDALPHA = 0;
506 WaitFrames(1);
507 return result;
508}
509
510/// Unused palette entry retained in the far-call table.
512
513/// Shows the Nintendo logo with its jingle. With `mode` 0 it fades in and
514/// holds two seconds; otherwise it waits a second, fades in, holds three
515/// seconds and fades out, faster once skipped. Called by Title_Run. Returns -1
516/// when A or Start skipped it.
518 s32 result;
519 u8 *resourceData;
520 u16 *tilemap;
521 u32 column;
522 u32 rowOrHoldFrame;
523 u16 tileIndex;
524 s32 blankTile;
525 s32 resourceId;
526
528 gOamCopyEnabled = 1;
529 resourceId = (s32)&ResourceId_NintendoLogo;
530 blankTile = 0x1ff;
532 Fade_ToBlack(1);
534 WaitFrames(1);
537 result = 0;
538 gBgScroll[2].y = result;
539 // The resource begins with 224 colours; its packed tiles follow them.
540 resourceData = Resource_GetTableEntry(resourceId);
541 Dma_Set(resourceData, (void *)BG_PLTT, DMA_COPY_WORDS(0x70), REG_DMA3);
542 Resource_DecodeType01(resourceData + 448, Ram_MapCellBuffer);
544 REG_DMA3);
545 // Pad the 30-tile picture to the hardware map's 32-tile row width.
546 tileIndex = 256;
547 tilemap = (u16 *)BG_SCREEN_BLOCK(6);
548 for (rowOrHoldFrame = 0; rowOrHoldFrame < 20; rowOrHoldFrame++) {
549 for (column = 0; column < 30; column++)
550 *tilemap++ = tileIndex++;
551 *tilemap++ = blankTile;
552 *tilemap++ = blankTile;
553 }
554 for (rowOrHoldFrame = 0; rowOrHoldFrame < 4; rowOrHoldFrame++) {
555 gBgScroll[rowOrHoldFrame].y = 0;
556 gBgScroll[rowOrHoldFrame].x = 0;
557 }
563 if (mode == 0) {
565 Fade_Wait();
566 for (rowOrHoldFrame = 0; rowOrHoldFrame < 120; rowOrHoldFrame++) {
567 if (gKeysPressed & (KEY_A | KEY_START)) {
568 result = -1;
569 break;
570 }
571 WaitFrames(1);
572 }
573 return result;
574 }
575 // Otherwise a second of black, a second's fade in, three seconds held and
576 // a second's fade out; a skip shortens each fade to eight frames.
577 for (rowOrHoldFrame = 0; rowOrHoldFrame < 60; rowOrHoldFrame++) {
578 if (gKeysPressed & (KEY_A | KEY_START)) {
579 result = -1;
580 break;
581 }
582 WaitFrames(1);
583 }
584 if (result != 0)
586 else
587 Fade_FromBlack(60);
588 Fade_Wait();
589 if (result == 0) {
590 for (rowOrHoldFrame = 0; rowOrHoldFrame < 180; rowOrHoldFrame++) {
591 if (gKeysPressed & (KEY_A | KEY_START)) {
592 result = -1;
593 break;
594 }
595 WaitFrames(1);
596 }
597 }
598 if (result != 0)
599 Fade_ToBlack(8);
600 else
601 Fade_ToBlack(60);
602 Fade_Wait();
603 return result;
604}
605
606/// Shows the Camelot logo for two seconds, cycling its four frames of tiles.
607/// A or Start ends it early. Reached through the palette far-call table from
608/// the title sequence. Returns 0.
610 s32 result;
611 u32 workIndex;
612 u8 *resourceData;
613 s32 resourceId;
614
615 gOamCopyEnabled = 1;
616 result = 0;
617 resourceId = (s32)&ResourceId_CamelotLogo;
619 Fade_ToBlack(1);
621 WaitFrames(1);
625 gBgScroll[2].y = result;
626 /* FAKEMATCH: needed to match: workIndex carries the decode destination
627 * before counting; a separate pointer is coalesced with resourceData
628 * (31 differ). */
629 workIndex = (u32)Ram_MapCellBuffer;
630 Resource_DecodeType01(Resource_GetTableEntry(resourceId), (u8 *)workIndex);
631 // The decoded resource: 224 colours, the map, the still tiles, then four
632 // animation frames of 0x400 bytes each.
633 resourceData = (u8 *)workIndex;
634 Dma_Set(resourceData, (void *)BG_PLTT, DMA_COPY_WORDS(0x1c0 / 4), REG_DMA3);
635 resourceData += 0x1c0;
636 Dma_Set(resourceData, BG_SCREEN_BLOCK(6), DMA_COPY_WORDS(0x800 / 4),
637 REG_DMA3);
638 resourceData += 0x800;
639 Dma_Set(resourceData, BG_CHAR_BLOCK(1), DMA_COPY_WORDS(0x4000 / 4), REG_DMA3);
640 resourceData += 0x4000;
641 for (workIndex = 0; workIndex < 4; workIndex++) {
642 gBgScroll[workIndex].y = 0;
643 gBgScroll[workIndex].x = 0;
644 }
649 Fade_Wait();
652 // Replace only the animated tiles; the rest of the decoded logo stays
653 // in VRAM while the four animation frames cycle.
654 for (workIndex = 0; workIndex < 120; workIndex++) {
655 Dma_Set(((gFrameCount >> 3) & 3) * 0x400 + resourceData,
656 BG_CHAR_BLOCK(1) + 0x100, DMA_COPY_WORDS(0x340 / 4), REG_DMA3);
657 if (gKeysPressed & (KEY_A | KEY_START))
658 break;
659 WaitFrames(1);
660 }
661 return result;
662}
663
664/// Unused color entry retained in the far-call table.
666
667// The palette fade (struct PaletteFade) keeps the saved palettes, the
668// colour components shown now, the target components and each one's step.
669
670/// Computes each of the 1536 colour components' change per frame from the
671/// current components to the target (nothing when `frames` is not
672/// positive). Called by PaletteFade_Start.
673void PaletteFade_ComputeSteps(s16 *sourceComponents, s16 *targetComponents,
674 s16 *componentSteps, s32 frames) {
675 s32 remaining;
676 s32 sourceValue;
677 s32 targetValue;
678
679 if (frames > 0) {
680 remaining = 3 * 512 - 1;
681 do {
682 sourceValue = *sourceComponents;
683 targetValue = *targetComponents;
684 *componentSteps = Iwram_SignedDivide(targetValue - sourceValue, frames);
685 remaining--;
686 sourceComponents++;
687 targetComponents++;
688 componentSteps++;
689 } while (remaining >= 0);
690 }
691}
692
693/// A task scheduled by PaletteFade_Init: steps the palette fade each frame,
694/// adding the step to every colour component until the fade is done, packs
695/// the components into the spare RGB555 copy of the palettes and queues both
696/// halves for VBlank.
698 struct PaletteFade *work = (struct PaletteFade *)gPaletteBufferWork;
699 u16 *componentSteps = work->delta;
700 u16 *currentComponents;
701 u16 *packedColors;
702 s32 remaining;
703 u16 *paletteBank;
704 s32 blueMask;
705
706 if (work->duration == 0)
707 return;
708 if ((s8)++work->step < work->duration) {
709 currentComponents = work->current;
710 for (remaining = 0; remaining <= 0x5ff; remaining++)
711 *currentComponents++ += *componentSteps++;
712 } else {
713 Dma_Set(work->target, work->current, DMA_COPY_WORDS(0x300), REG_DMA3);
714 work->duration = 0;
715 }
716 // The queued DMA keeps a pointer until VBlank. Build into the spare page
717 // so packing this frame cannot overwrite the last frame's pending colours.
718 packedColors = work->packed[work->page ^ 1];
719 blueMask = 0x7c00;
720 remaining = 512;
721 currentComponents = work->current;
722 for (; remaining != 0; remaining--) {
723 *packedColors++ = (currentComponents[0] & blueMask) |
724 (((s16)currentComponents[1] >> 5) & 0x3e0) |
725 (((s16)currentComponents[2] >> 10) & 0x1f);
726 currentComponents += 3;
727 }
728 work->page ^= 1;
729 paletteBank = work->packed[work->page];
730 {
731 u16 *backgroundColors = paletteBank;
732
733 IO_WRITE_QUEUE_PUSH((u32)BG_PLTT, (u32)backgroundColors,
734 DMA_COPY_WORDS(0x80));
735 }
736 IO_WRITE_QUEUE_PUSH((u32)OBJ_PLTT, (u32)(paletteBank + 256),
737 DMA_COPY_WORDS(0x80));
738}
739
740/// Transforms 512 source colours into destination components (three
741/// per colour, each in the high bits of a halfword). `mode` picks the
742/// transform: a colour below 0x8000 fills every colour with it; 0x8000 takes
743/// that colour from source[0]; 0x10000 to 0x10007 are the whole-palette filters
744/// (plain, grey, sepia and the others); the TINT, BLEND and SPLIT flags carry
745/// a colour in their low bits; anything else is the address of components to
746/// copy. paletteHalf 1 does only the background palettes, 2 only the sprites'.
747/// Called by PaletteFade_Init and the palette fade's setters.
748void Palette_Transform(u32 mode, u16 *source, u16 *destination,
749 s32 paletteHalf) {
750 u32 colorIndex;
751 u32 colorCount = 512;
752 s32 red;
753 s32 blue;
754 u32 colorWork;
755 s32 green;
756
758 mode = *source;
759 if (paletteHalf == 1) {
760 colorCount = 256;
761 } else if (paletteHalf == 2) {
762 destination += 768;
763 source += 256;
764 colorCount = 256;
765 }
766
768 *destination++ = mode & 0x7c00;
769 *destination++ = (mode & 0x03e0) << 5;
770 *destination++ = (mode & 0x001f) << 10;
771 Dma_Set(destination - 3, destination,
772 DMA_ENABLE << 16 | (((colorCount - 1) * 6) >> 1), REG_DMA3);
773 } else if (mode < PALETTE_TRANSFORM_FLAGS) {
774 switch (mode) {
776 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
777 colorWork = *source++;
778 red = ((colorWork << 11) & 0xf800);
779 green = ((colorWork << 7) & 0x1f000);
780 blue = (colorWork & 0x7c00);
781 colorWork = Iwram_SignedDivide(red + green + blue, 7);
782 *destination++ = colorWork;
783 *destination++ = colorWork;
784 *destination++ = colorWork;
785 }
786 break;
788 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
789 colorWork = *source++;
790 red = colorWork & 31;
791 colorWork = Iwram_SignedDivide(
792 red + ((colorWork >> 5) & 31) + ((colorWork >> 10) & 31), 10);
793 red = colorWork * 4 + 5;
794 blue = colorWork * 3 + 5;
795 /* FAKEMATCH: the reversible XOR initialization of green folds late,
796 * keeping blue's add first and its separate lower test; as green =
797 * blue, 4 instructions differ in tbs-en. */
798 green = blue ^ red;
799 green ^= red;
800 if (red < 8)
801 red = 8;
802 if (blue < 8) {
803 green = 8;
804 /* FAKEMATCH: needed to match: green is 8, so this pair changes no
805 * bits. Its late fold retains the separate blue lower test; an
806 * ordinary copy threads past that test and loses two instructions. */
807 blue ^= green;
808 blue ^= 8;
809 }
810 if (blue < 8)
811 blue = 8;
812 if (red > 28)
813 red = 28;
814 if (green > 28)
815 green = 28;
816 if (blue > 28)
817 blue = 28;
818 *destination++ = gPalette_ChannelCurveLight[blue];
819 *destination++ = gPalette_ChannelCurveLight[green];
820 *destination++ = gPalette_ChannelCurveLight[red];
821 }
822 break;
824 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
825 colorWork = *source++;
826 red = colorWork & 31;
827 green = (colorWork >> 5) & 31;
828 blue = (colorWork >> 10) & 31;
829 red -= (u32)red >> 1;
830 green -= green / 3;
831 red += 6;
832 green += 4;
833 blue -= 6;
835 green = Graphics_ClampRgb555Channel(green);
836 blue = Graphics_ClampRgb555Channel(blue);
837 SET_VECTOR(destination, gPalette_ChannelCurveContrast[blue],
840 destination += 3;
841 }
842 break;
844 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
845 colorWork = *source++;
846 red = colorWork & 31;
847 green = (colorWork >> 5) & 31;
848 blue = (colorWork >> 10) & 31;
849 if (red < 10)
850 red = 10;
851 if (green < 16)
852 green = 16;
853 if (blue < 16)
854 blue = 16;
855 if (red > 28)
856 red = 28;
857 if (green > 24)
858 green = 24;
859 if (blue > 26)
860 blue = 26;
861 green += 2;
862 blue += 2;
864 green = Graphics_ClampRgb555Channel(green);
865 blue = Graphics_ClampRgb555Channel(blue);
866 *destination++ = gPalette_ChannelCurve[blue];
867 *destination++ = gPalette_ChannelCurve[green];
868 *destination++ = gPalette_ChannelCurve[red];
869 }
870 break;
872 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
873 s32 mean;
874
875 colorWork = *source++;
876 red = colorWork & 31;
877 green = (colorWork >> 5) & 31;
878 blue = (colorWork >> 10) & 31;
879 mean = Graphics_ClampRgb555Channel((red + green + blue) / 3);
880 red = (red >> 1) + mean;
881 green = (green >> 1) + mean;
882 blue = (blue >> 1) + mean;
884 green = Graphics_ClampRgb555Channel(green);
885 blue = Graphics_ClampRgb555Channel(blue);
886 SET_VECTOR(destination, gPalette_ChannelCurveContrast[blue],
889 destination += 3;
890 }
891 break;
893 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
894 colorWork = *source++;
895 red = colorWork & 31;
896 green = (colorWork >> 5) & 31;
897 blue = (colorWork >> 10) & 31;
898 red += ((green >> 3) + (blue >> 3));
900 green -= green / 3;
901 blue -= blue / 3;
902 SET_VECTOR(destination, gPalette_ChannelCurve[blue],
905 destination += 3;
906 }
907 break;
909 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
910 colorWork = *source++;
911 red = colorWork & 31;
912 green = (colorWork >> 5) & 31;
913 blue = (colorWork >> 10) & 31;
914 red -= (u32)red >> 1;
915 green -= green / 3;
916 red += 6;
917 green += 4;
918 blue -= 6;
920 green = Graphics_ClampRgb555Channel(green);
921 blue = Graphics_ClampRgb555Channel(blue);
922 SET_VECTOR(destination, gPalette_ChannelCurveContrast[blue],
925 destination += 3;
926 }
927 break;
928 default:
929 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
930 colorWork = *source++;
931 destination[colorIndex * 3 + 0] = colorWork & 0x7c00;
932 destination[colorIndex * 3 + 1] = (colorWork & 0x03e0) << 5;
933 destination[colorIndex * 3 + 2] = (colorWork & 0x001f) << 10;
934 }
935 break;
936 }
937 } else if (mode & PALETTE_TRANSFORM_TINT) {
938 u32 tintRed;
939 u32 tintGreen;
940 u32 tintBlue;
941
942 tintRed = mode & 31;
943 tintGreen = (mode >> 5) & 31;
944 tintBlue = (mode >> 10) & 31;
945 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
946 colorWork = *source++;
947 red = ((colorWork << 11) & 0xf800);
948 green = ((colorWork << 7) & 0x1f000);
949 blue = (colorWork & 0x7c00);
950 colorWork = Iwram_SignedDivide(red + green + blue, 96);
951 red = colorWork * tintRed;
952 green = colorWork * tintGreen;
953 blue = colorWork * tintBlue;
955 green = Graphics_ClampRgb555Component(green);
957 SET_VECTOR(destination, blue, green, red);
958 destination += 3;
959 }
960 } else if (mode & PALETTE_TRANSFORM_BLEND) {
961 u32 tintRed;
962 u32 tintGreen;
963 u32 tintBlue;
964
965 tintRed = mode & 31;
966 tintGreen = (mode >> 5) & 31;
967 tintBlue = (mode >> 10) & 31;
968 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
969 colorWork = *source++;
970 red = colorWork & 31;
971 colorWork = Iwram_SignedDivide(
972 (red + ((colorWork >> 5) & 31) + ((colorWork >> 10) & 31)) << 4,
973 tintRed + tintGreen + tintBlue);
974 red = Iwram_MulQ16(((colorWork * tintRed) >> 4) << 16,
975 (s32)(tintRed << 16) >> 4);
976 green = Iwram_MulQ16(((colorWork * tintGreen) >> 4) << 16,
977 (s32)(tintGreen << 16) >> 4);
978 blue = Iwram_MulQ16(((colorWork * tintBlue) >> 4) << 16,
979 (s32)(tintBlue << 16) >> 4);
980 red = Graphics_ClampRgb555Channel((u32)red >> 16);
981 green = Graphics_ClampRgb555Channel((u32)green >> 16);
982 blue = Graphics_ClampRgb555Channel((u32)blue >> 16);
983 *destination++ = gPalette_ChannelCurve[blue];
984 *destination++ = gPalette_ChannelCurve[green];
985 *destination++ = gPalette_ChannelCurve[red];
986 }
987 } else if (mode & PALETTE_TRANSFORM_SPLIT) {
988 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
989 colorWork = *source++;
990 destination[colorIndex * 3 + 0] = colorWork & 0x7c00;
991 destination[colorIndex * 3 + 1] = (colorWork & 0x03e0) << 5;
992 destination[colorIndex * 3 + 2] = (colorWork & 0x001f) << 10;
993 }
994 } else {
995 if (paletteHalf == 2)
996 mode += 0x600;
997 Dma_Set((const void *)mode, destination,
998 DMA_COPY_WORDS((colorCount * 6) >> 2), REG_DMA3);
999 }
1000}
1001
1002/// Allocates the palette fade, saves both hardware palettes in it as the
1003/// starting colours and schedules PaletteFade_Update. Called by
1004/// Title_ShowIntro.
1006 struct PaletteFade *buffer;
1007 s32 callbackPriority;
1008
1009 buffer = Runtime_AllocateBlock(32, sizeof(*buffer));
1010 Dma_Fill32(0, buffer, sizeof(*buffer));
1011 Dma_Set((void *)BG_PLTT, buffer, DMA_COPY_WORDS(0x80), REG_DMA3);
1012 Dma_Set((void *)OBJ_PLTT, &buffer->palette[256], DMA_COPY_WORDS(0x80),
1013 REG_DMA3);
1015 0);
1016 callbackPriority = SCHEDULER_KEY_MAIN_LOOP;
1018}
1019
1020/// Unschedules the palette fade and frees its buffers. Nothing in ☀️ calls
1021/// it.
1025}
1026
1027/// Sets the fade target by transforming the saved background and/or sprite
1028/// palettes through the requested mode. Nothing in ☀️ calls it.
1029UNUSED void PaletteFade_SetTarget(s32 mode, s32 paletteHalf) {
1030 struct PaletteFade *fade = (struct PaletteFade *)gPaletteBufferWork;
1031
1032 if (fade != NULL)
1033 Palette_Transform(mode, fade->palette, fade->target, paletteHalf);
1034}
1035
1036/// Sets the colours shown now by transforming the saved palettes. Called by
1037/// Title_ShowIntro.
1038void PaletteFade_SetCurrent(s32 mode, s32 paletteHalf) {
1039 struct PaletteFade *fade = (struct PaletteFade *)gPaletteBufferWork;
1040
1041 if (fade != NULL)
1042 Palette_Transform(mode, fade->palette, fade->current, paletteHalf);
1043}
1044
1045/// Replaces the first saved colour, the backdrop. Nothing in ☀️ calls it.
1047 struct PaletteFade *fade = (struct PaletteFade *)gPaletteBufferWork;
1048
1049 if (fade != NULL)
1050 fade->palette[0] = color;
1051}
1052
1053/// Starts fading the shown colours to the target over the requested frames.
1054/// Called by Title_ShowIntro for the opening fade from black.
1056 struct PaletteFade *fade = (struct PaletteFade *)gPaletteBufferWork;
1057
1058 if (fade != NULL) {
1059 fade->duration = frames;
1060 fade->step = 0;
1061 PaletteFade_ComputeSteps((s16 *)fade->current, (s16 *)fade->target,
1062 (s16 *)fade->delta, frames);
1063 }
1064}
1065
1066/// Clamps a five-bit colour channel to 0..31. Called by Palette_Transform.
1068 if (value > 31)
1069 return 31;
1070 if (value < 0)
1071 value = 0;
1072 return value;
1073}
1074
1075/// Caps a colour component at 0x7c00, the largest a five-bit channel shifted
1076/// into the high bits reaches. There is no lower bound. Called by
1077/// Palette_Transform.
1079 if (value > 0x7c00)
1080 value = 0x7c00;
1081 return value;
1082}
1083
1084// The response curves of Palette_Transform's filters. Like the
1085// declarations in palbuf.h they are not const: as const the code differs.
1086
1087/// Maps a channel (0..31) to a component (0..31 << 10)
1088// clang-format off
1090 0, 524, 1071, 1643, 2240, 2863, 3513, 4191,
1091 4898, 5635, 6403, 7202, 8035, 8901, 9803, 10740,
1092 11715, 12729, 13783, 14877, 16014, 17195, 18422, 19694,
1093 21015, 22386, 23808, 25283, 26812, 28397, 30041, 31744
1094};
1095
1096/// A brighter curve
1098 0, 613, 1247, 1902, 2580, 3281, 4005, 4753,
1099 5526, 6324, 7148, 7999, 8876, 9782, 10716, 11680,
1100 12674, 13699, 14755, 15843, 16965, 18121, 19312, 20538,
1101 21801, 23101, 24440, 25818, 27237, 28697, 30199, 31744
1102};
1103
1104/// A high-contrast curve (25 and above are full)
1106 0, 360, 759, 1201, 1689, 2226, 2817, 3466,
1107 4178, 4957, 5808, 6738, 7752, 8856, 10058, 11365,
1108 12784, 14325, 15996, 17806, 19767, 21888, 24183, 26662,
1109 29340, 31744, 31744, 31744, 31744, 31744, 31744, 31744
1110};
1111// clang-format on
The battle animation state, render objects and effect entries, and the palette buffer work.
struct BattleEffectBuffers * gPaletteBufferWork
The task scheduler: tasks, their order and the scheduler's state.
#define SCHEDULER_KEY_VBLANK
A task's order: the high byte picks the pass that runs it, the low byte ranks it within the pass (hig...
#define SCHEDULER_KEY_MAIN_LOOP
The engine calls the debug menus import, and their palette swatch tiles.
DMA channel registers, and the DMA and CPU fills.
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
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
Definition dma.h:30
The edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
void Fade_ToBlack(s32 frames)
Fades out to black.
Definition fade.c:76
void Fade_ToWhite(s32 frames)
Fades out to white.
Definition fade.c:82
void Fade_FromWhite(s32 frames)
Fades in from white.
Definition fade.c:85
void Fade_Wait(void)
Waits a frame at a time until the running fade has finished.
Definition fade.c:108
void Fade_FromBlack(s32 frames)
Fades in from black.
Definition fade.c:79
void AudioCommand_PlayFar(s32 id)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
The frame loop's globals: lag counts, the CPU load display and the VBlank flags.
volatile u8 gCpuLoadDisplayEnabled
Debug: WaitFrames measures the CPU load into gCpuLoadPeak when set.
u8 gOamCopyEnabled
The VBlank handler copies the OAM list only while it is set; scenes clear it to keep their own sprite...
u8 gDebugPaused
The debug pause is on.
volatile u32 gFrameCount
Frames WaitFrames has finished.
The work slots of gWorkSlot, read through their own names.
The screen blend's globals and the graphics routines.
const u8 gTitle_PromptTiles[]
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
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
The heap's work slots and HeapState.
#define PROMPT_Y
Definition intro.c:286
UNUSED void Graphics_NoOpColor(void)
Unused color entry retained in the far-call table.
Definition intro.c:665
void Palette_Transform(u32 mode, u16 *source, u16 *destination, s32 paletteHalf)
Transforms 512 source colours into destination components (three per colour, each in the high bits of...
Definition intro.c:748
s32 Title_ShowIntro(s32 prompt)
Plays the title intro: the backgrounds scroll down and the sprites rise until frame 278 (A or Start s...
Definition intro.c:295
UNUSED void PaletteFade_SetBackdrop(s32 color)
Replaces the first saved colour, the backdrop. Nothing in ☀️ calls it.
Definition intro.c:1046
void PaletteFade_Update(void)
A task scheduled by PaletteFade_Init: steps the palette fade each frame, adding the step to every col...
Definition intro.c:697
const u8 gTitle_IntroSpriteColumns[]
The x of each of the six columns of intro sprites.
Definition intro.c:64
#define INTRO_OBJ(i)
Definition intro.c:76
void PaletteFade_SetCurrent(s32 mode, s32 paletteHalf)
Sets the colours shown now by transforming the saved palettes.
Definition intro.c:1038
void PaletteFade_Init(void)
Allocates the palette fade, saves both hardware palettes in it as the starting colours and schedules ...
Definition intro.c:1005
UNUSED void PaletteFade_SetTarget(s32 mode, s32 paletteHalf)
Sets the fade target by transforming the saved background and/or sprite palettes through the requeste...
Definition intro.c:1029
void PaletteFade_Start(s32 frames)
Starts fading the shown colours to the target over the requested frames.
Definition intro.c:1055
#define PROMPT_SPRITES
Definition intro.c:284
u16 gPalette_ChannelCurve[32]
Maps a channel (0..31) to a component (0..31 << 10).
Definition intro.c:1089
#define PROMPT_X
Definition intro.c:285
UNUSED void Title_NoOpPalette(void)
Unused palette entry retained in the far-call table.
Definition intro.c:511
u16 gPalette_ChannelCurveLight[32]
A brighter curve.
Definition intro.c:1097
u16 gPalette_ChannelCurveContrast[32]
A high-contrast curve (25 and above are full).
Definition intro.c:1105
#define MIRRORED_QUAD(i, size, shape, tile)
Writes OAM entries i to i + 3: four sprites of size pixels, mirrored into the four quarters of one pi...
Definition intro.c:95
s32 Title_ShowAnimatedSplash(void)
Shows the Camelot logo for two seconds, cycling its four frames of tiles.
Definition intro.c:609
s32 Graphics_ClampRgb555Channel(s32 value)
Clamps a five-bit colour channel to 0..31. Called by Palette_Transform.
Definition intro.c:1067
#define PLACE_ON_SLOPE(column, half)
Sets x and y to the top left of a sprite of half-width half centred on column column,...
Definition intro.c:87
s32 Graphics_ClampRgb555Component(s32 value)
Caps a colour component at 0x7c00, the largest a five-bit channel shifted into the high bits reaches.
Definition intro.c:1078
#define WRAP_TO_BYTE(v)
Brings v into 0..255 by whole turns of 256.
Definition intro.c:79
#define PROMPT_TILES
Definition intro.c:268
const u8 gTitle_PromptBlendLevels[60]
The prompt's blend level over its 60-frame pulse.
Definition intro.c:68
UNUSED void PaletteFade_Release(void)
Unschedules the palette fade and frees its buffers.
Definition intro.c:1022
void Title_LoadIntroBackgrounds(void)
Loads the title intro's two scrolling backgrounds and its sprite tiles, builds their maps and sets th...
Definition intro.c:177
void PaletteFade_ComputeSteps(s16 *sourceComponents, s16 *targetComponents, s16 *componentSteps, s32 frames)
Computes each of the 1536 colour components' change per frame from the current components to the targ...
Definition intro.c:673
s32 Title_ShowSplashScreen(s32 mode)
Shows the Nintendo logo with its jingle.
Definition intro.c:517
void Title_UpdateIntroSprites(void)
A VBlank task of the title intro, scheduled by Title_ShowIntro: places the rising sprites along the s...
Definition intro.c:112
The hardware's I/O registers and their bits, as pret names them.
#define REG_WIN1H
Definition io_reg.h:75
#define BGCNT_CHAR_BASE(block)
Definition io_reg.h:25
#define REG_WININ
Definition io_reg.h:81
#define BLDCNT_TGT2_BG2
Definition io_reg.h:136
#define OBJ_PLTT
Definition io_reg.h:159
#define BGCNT_256_COLORS
Definition io_reg.h:27
#define BGCNT_PRIORITY(n)
Definition io_reg.h:24
#define WININ_WIN0_BG1
Definition io_reg.h:87
#define BLDCNT_TGT1_OBJ
Definition io_reg.h:127
#define BG_SCREEN_BLOCK(n)
Definition io_reg.h:167
#define REG_BG0HOFS
Definition io_reg.h:149
#define BLDCNT_TGT1_BG2
Definition io_reg.h:125
#define BG_CHAR_BLOCK(n)
Definition io_reg.h:166
#define OAM
Definition io_reg.h:239
#define REG_WIN0H
Definition io_reg.h:74
#define OBJ_VRAM0
Sprite tile memory, as pret names it: the 32 KB from 0x06010000.
Definition io_reg.h:170
@ DISPCNT_OBJ_ON
Definition io_reg.h:44
@ DISPCNT_WIN0_ON
Definition io_reg.h:45
@ DISPCNT_BG0_ON
Definition io_reg.h:40
@ DISPCNT_OBJ_1D_MAP
Definition io_reg.h:39
@ DISPCNT_OBJWIN_ON
Definition io_reg.h:47
@ DISPCNT_WIN1_ON
Definition io_reg.h:46
@ DISPCNT_BG2_ON
Definition io_reg.h:42
@ DISPCNT_BG1_ON
Definition io_reg.h:41
@ KEY_START
Definition io_reg.h:246
@ KEY_A
Definition io_reg.h:243
#define BLDCNT_EFFECT_LIGHTEN
towards white by REG_BLDY
Definition io_reg.h:132
#define REG_DISPCNT
Definition io_reg.h:9
#define BLDCNT_TGT2_BG0
Definition io_reg.h:134
#define BLDCNT_EFFECT_BLEND
weighted by REG_BLDALPHA
Definition io_reg.h:131
#define DMA_SRC_FIXED
Definition io_reg.h:207
#define BLDCNT_TGT2_ALL
Definition io_reg.h:140
#define BLDCNT_TGT2_BG1
Definition io_reg.h:135
#define REG_DMA3
Definition io_reg.h:153
#define BLDCNT_TGT2_BG3
Definition io_reg.h:137
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
Definition io_reg.h:145
#define WININ_WIN0_OBJ
Definition io_reg.h:90
#define BGCNT_SCREEN_BASE(block)
Definition io_reg.h:28
#define REG_BG2CNT
Definition io_reg.h:21
#define DMA_COPY_WORDS(n)
Definition io_reg.h:226
#define REG_BLDALPHA
Definition io_reg.h:142
#define WIN_RANGE(start, end)
A REG_WINxH or REG_WINxV value: the window covers start up to, but not including, end.
Definition io_reg.h:80
#define WININ_WIN1_BG1
Definition io_reg.h:94
#define BG_PLTT
Definition io_reg.h:157
#define BGCNT_MOSAIC
Definition io_reg.h:26
#define WININ_WIN1_OBJ
Definition io_reg.h:97
#define BLDCNT_TGT1_ALL
Definition io_reg.h:129
#define REG_BLDCNT
Definition io_reg.h:119
#define REG_BG1CNT
Definition io_reg.h:20
#define DMA_ENABLE
Definition io_reg.h:217
#define REG_WIN1V
Definition io_reg.h:77
#define BLDCNT_TGT2_BD
Definition io_reg.h:139
#define WININ_WIN1_BG2
Definition io_reg.h:95
#define WININ_WIN0_BG2
Definition io_reg.h:88
#define REG_WIN0V
Definition io_reg.h:76
The register write queue that VBlank carries out after each finished frame.
#define IO_WRITE_16
Writes a halfword.
#define IO_WRITE_QUEUE_PUSH(address, value, control)
Disables interrupts to add one register write or DMA to the queue; a write to a full queue is dropped...
The IWRAM call layer: the routines the game keeps resident in IWRAM, each at its fixed address,...
static s32 Iwram_SignedDivide(s32 dividend, s32 divisor)
Definition iwram_call.h:73
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
The keypad state the VBlank interrupt keeps.
volatile u32 gKeysPressed
Keys that went down this frame.
Small statement macros both games use for positions, velocities and bounds.
#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
The map layers' scroll work and the background scroll values.
struct BgScroll gBgScroll[]
The heaps: allocating and freeing blocks.
void Runtime_ReleaseHeapBlock(s32 slot)
The reel game's title lettering.
OamShadow, a sprite entry a routine builds by hand and DMA copies to OAM.
Palette fades, the battle effect palette buffers and the colour channel curves.
@ PALETTE_TRANSFORM_GREY
grey of brightness (2R + 4G + B) / 7
Definition palbuf.h:73
@ PALETTE_TRANSFORM_MUTED
Definition palbuf.h:76
@ PALETTE_TRANSFORM_BLEND
The brightness R + G + B shared out in the proportions of the colour carried.
Definition palbuf.h:88
@ PALETTE_TRANSFORM_PLAIN
each colour unchanged
Definition palbuf.h:72
@ PALETTE_TRANSFORM_PALE
Definition palbuf.h:77
@ PALETTE_TRANSFORM_FROM_SOURCE
The backdrop colour (palette RAM's first colour) for all.
Definition palbuf.h:71
@ PALETTE_TRANSFORM_WARM
Definition palbuf.h:75
@ PALETTE_TRANSFORM_SEPIA
Definition palbuf.h:74
@ PALETTE_TRANSFORM_SPLIT
each colour unchanged
Definition palbuf.h:89
@ PALETTE_TRANSFORM_WARM2
half R + 6, two thirds G + 4, B - 6
Definition palbuf.h:79
@ PALETTE_TRANSFORM_FLAGS
From here the TINT, BLEND and SPLIT bits are tested, TINT and BLEND carrying an RGB555 colour in the ...
Definition palbuf.h:83
@ PALETTE_TRANSFORM_RED
Definition palbuf.h:78
@ PALETTE_TRANSFORM_TINT
The brightness (2R + 4G + B) times the colour carried.
Definition palbuf.h:85
The work pointers in the gWorkSlot table, by name.
#define Ram_WorkSlot
Definition ram_buffer.h:44
#define Ram_MapCellBuffer
Definition ram_buffer.h:10
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
Resource numbers, named where their contents are known.
char ResourceId_NintendoLogo
char ResourceId_IntroGraphicsA
char ResourceId_IntroGraphicsC
char ResourceId_IntroGraphicsB
char ResourceId_CamelotLogo
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
s32 Resource_DecodeByteLz(const void *source, void *destination)
Decodes a byte-oriented LZ resource and returns its unpacked byte count.
Definition decompress.c:37
FIELD_AT_OFFSET and the entity and camera views older scene code reads.
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
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Definition scheduler.c:146
Song and sound effect ids, indices into gSound_SongTable.
#define SE_110
Definition songs.h:103
#define NULL
Definition bilibin.h:6
u16 y
pixels
Definition map_scroll.h:65
A sprite of the "Press Start" prompt, linked into a render slot each frame: OAM attributes 0 to 2 wit...
Definition intro.c:37
u32 next
the render slot link
Definition intro.c:38
u16 attr1High
flip and size bits of attribute 1
Definition intro.c:42
u16 x
Definition intro.c:41
s32 tile
Definition intro.c:43
u8 attr0High
shape and mode bits of attribute 0
Definition intro.c:40
u8 introObjects[0x68]
objects[0] to [12], still the intro's
The title intro's state, in heap slot 43.
Definition intro.c:47
s32 frontRows
rows of the near background copied in
Definition intro.c:49
s32 frame
Definition intro.c:50
s32 backRows
rows of the far background copied in as it scrolls
Definition intro.c:48
s32 rise
how far the sprites have risen
Definition intro.c:53
s32 state
Definition intro.c:52
s32 tick
Definition intro.c:51
union IntroWork::@371345267344337301352016037371134340173036225143 area
OAM buffer: sprite entries a routine builds by hand and DMA copies to OAM.
Definition oambuf.h:18
A colour buffer for all 512 palette colours: the source palette, the shown and target colour channels...
Definition palbuf.h:14
u16 delta[0x600]
added to each current channel each frame
Definition palbuf.h:21
u8 step
frames
Definition palbuf.h:26
u16 palette[512]
The source palette, RGB555: 256 BG colours, then 256 OBJ colours.
Definition palbuf.h:16
u16 current[0x600]
The shown colours, as B, G and R channels shifted up 10 bits, three a colour.
Definition palbuf.h:19
s8 duration
frames; 0 when the colours are not moving
Definition palbuf.h:25
u16 target[0x600]
the colours current moves toward, as current
Definition palbuf.h:20
u16 packed[2][512]
Two pages of RGB555 colours: one is built while the other is queued.
Definition palbuf.h:23
u8 page
the packed page queued this frame
Definition palbuf.h:24
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
The system's routines and globals: interrupts, BIOS sound bias, random numbers and sleep.
void Ui_LoadWindowGraphics(void)
Loads the window font and frame tiles into BG character block 0, the window palette into BG palette 1...
Definition text.c:180
void DebugText_Clear(void)
Blanks the debug text screen, homes the cursor and points BG0 at it.
Definition text.c:170
The integer types, TRUE, UNUSED and the fixed-address macros.
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
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
struct IntroWork::@371345267344337301352016037371134340173036225143::@040137040231117373311171222275233041277366335161 prompt
struct OamShadow objects[120]
void VramCache_Reset(void)
Frees every block and every cache entry.
Definition vram_cache.c:184
s32 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
Definition vram_cache.c:211
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