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
76#define INTRO_OBJ(i) (work->area.objects[i])
79#define WRAP_TO_BYTE(v) \
87#define PLACE_ON_SLOPE(column, half) \
88 x = gTitle_IntroSpriteColumns[column] - (half); \
89 y = (slopeTopY - slopeBaseY) * ((x + (half)) - 104) / 80 + slopeBaseY - \
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)
127 if ((++work->
tick & 3) == 0)
131 slopeTopY = 144 - work->
rise;
134 if (work->
frame < 0x118) {
135 if ((work->
tick & 1) == 0) {
140 INTRO_OBJ(spriteCount).attr01 = ((x + 4) << 16) | y | 0x80002400;
158 for (; spriteCount <= 119; spriteCount++)
159 INTRO_OBJ(spriteCount).attr01 = 0x400020a0;
167 INTRO_OBJ(12).attr01 = stripY | 0xc05c2000;
191 resourceData += 0x200;
198 resourceData += 0x200;
208 for (row = 0; row <= 10; row++) {
209 for (column = 0; column < 30; column++)
210 *tilemap++ = tileIndex++;
211 *tilemap++ = blankTile;
212 *tilemap++ = blankTile;
215 for (row = 11; row <= 31; row++) {
216 for (column = 0; column < 30; column++)
217 *tilemap++ = tileIndex++;
218 *tilemap++ = blankTile;
219 *tilemap++ = blankTile;
223 for (row = 0; row <= 10; row++) {
224 for (column = 0; column < 30; column++)
225 *tilemap++ = tileIndex++;
226 *tilemap++ = blankTile;
227 *tilemap++ = blankTile;
230 for (row = 11; row <= 31; row++) {
231 for (column = 0; column < 30; column++)
232 *tilemap++ = tileIndex++;
233 *tilemap++ = blankTile;
234 *tilemap++ = blankTile;
245 for (row = 0; row < 4; row++) {
265#if (LANGUAGE == LANGUAGE_GERMAN)
266#define PROMPT_TILES 8
268#define PROMPT_TILES 5
270#if (LANGUAGE == LANGUAGE_GERMAN)
272#define PROMPT_SPRITES 3
275#elif (LANGUAGE == LANGUAGE_JAPANESE)
276#define PROMPT_SPRITES 5
279#elif (LANGUAGE == LANGUAGE_FRENCH)
280#define PROMPT_SPRITES 5
284#define PROMPT_SPRITES 3
298 u8 savedCpuLoadDisplay;
345 nextFrame =
frame + 1;
346 work->
frame = nextFrame;
347 if (nextFrame <= 278) {
365 if ((
tick & 1) == 0) {
380 (
u8 *)0x06004ec0 + (160 - work->
frontRows * 8) % 160 * 240,
382 tilemap = (
u16 *)0x0600f6c0;
383 for (i = 0; i < 5; i++) {
384 for (j = 0; j < 30; j++)
393 if (work->
frame == 239)
395 }
else if (nextFrame == 281) {
398 }
else if (nextFrame == 289) {
400 }
else if (nextFrame == 280) {
413 resourceData += 0x200;
426 for (; i < 20; i++) {
427 for (j = 0; j < 30; j++)
429 *tilemap++ = blankTile;
430 *tilemap++ = blankTile;
443 u32 *spriteWords = (
u32 *)sprite;
447 *spriteWords++ = 0x40004000;
448 *spriteWords = vramBlock;
460 for (i = 0; i < holdFrames; i++) {
465#if (LANGUAGE == LANGUAGE_GERMAN)
469 for (row = 0,
y =
PROMPT_Y; row < PROMPT_ROWS;
y += 8, row++) {
548 for (rowOrHoldFrame = 0; rowOrHoldFrame < 20; rowOrHoldFrame++) {
549 for (column = 0; column < 30; column++)
550 *tilemap++ = tileIndex++;
551 *tilemap++ = blankTile;
552 *tilemap++ = blankTile;
554 for (rowOrHoldFrame = 0; rowOrHoldFrame < 4; rowOrHoldFrame++) {
566 for (rowOrHoldFrame = 0; rowOrHoldFrame < 120; rowOrHoldFrame++) {
577 for (rowOrHoldFrame = 0; rowOrHoldFrame < 60; rowOrHoldFrame++) {
590 for (rowOrHoldFrame = 0; rowOrHoldFrame < 180; rowOrHoldFrame++) {
633 resourceData = (
u8 *)workIndex;
635 resourceData += 0x1c0;
638 resourceData += 0x800;
640 resourceData += 0x4000;
641 for (workIndex = 0; workIndex < 4; workIndex++) {
654 for (workIndex = 0; workIndex < 120; workIndex++) {
674 s16 *componentSteps,
s32 frames) {
680 remaining = 3 * 512 - 1;
682 sourceValue = *sourceComponents;
683 targetValue = *targetComponents;
689 }
while (remaining >= 0);
700 u16 *currentComponents;
709 currentComponents = work->
current;
710 for (remaining = 0; remaining <= 0x5ff; remaining++)
711 *currentComponents++ += *componentSteps++;
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;
731 u16 *backgroundColors = paletteBank;
751 u32 colorCount = 512;
759 if (paletteHalf == 1) {
761 }
else if (paletteHalf == 2) {
768 *destination++ = mode & 0x7c00;
769 *destination++ = (mode & 0x03e0) << 5;
770 *destination++ = (mode & 0x001f) << 10;
771 Dma_Set(destination - 3, destination,
776 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
777 colorWork = *source++;
778 red = ((colorWork << 11) & 0xf800);
779 green = ((colorWork << 7) & 0x1f000);
780 blue = (colorWork & 0x7c00);
782 *destination++ = colorWork;
783 *destination++ = colorWork;
784 *destination++ = colorWork;
788 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
789 colorWork = *source++;
790 red = colorWork & 31;
792 red + ((colorWork >> 5) & 31) + ((colorWork >> 10) & 31), 10);
793 red = colorWork * 4 + 5;
794 blue = colorWork * 3 + 5;
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;
844 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
845 colorWork = *source++;
846 red = colorWork & 31;
847 green = (colorWork >> 5) & 31;
848 blue = (colorWork >> 10) & 31;
872 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
875 colorWork = *source++;
876 red = colorWork & 31;
877 green = (colorWork >> 5) & 31;
878 blue = (colorWork >> 10) & 31;
880 red = (red >> 1) + mean;
881 green = (green >> 1) + mean;
882 blue = (blue >> 1) + mean;
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));
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;
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;
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);
951 red = colorWork * tintRed;
952 green = colorWork * tintGreen;
953 blue = colorWork * tintBlue;
966 tintGreen = (mode >> 5) & 31;
967 tintBlue = (mode >> 10) & 31;
968 for (colorIndex = 0; colorIndex < colorCount; colorIndex++) {
969 colorWork = *source++;
970 red = colorWork & 31;
972 (red + ((colorWork >> 5) & 31) + ((colorWork >> 10) & 31)) << 4,
973 tintRed + tintGreen + tintBlue);
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);
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;
995 if (paletteHalf == 2)
997 Dma_Set((
const void *)mode, destination,
1007 s32 callbackPriority;
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
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
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
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...
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
The edition's language, for C to compare (LANGUAGE == LANGUAGE_GERMAN).
void Fade_ToBlack(s32 frames)
Fades out to black.
void Fade_ToWhite(s32 frames)
Fades out to white.
void Fade_FromWhite(s32 frames)
Fades in from white.
void Fade_Wait(void)
Waits a frame at a time until the running fade has finished.
void Fade_FromBlack(s32 frames)
Fades in from black.
void AudioCommand_PlayFar(s32 id)
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
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...
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
The heap's work slots and HeapState.
UNUSED void Graphics_NoOpColor(void)
Unused color entry retained in the far-call table.
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...
s32 Title_ShowIntro(s32 prompt)
Plays the title intro: the backgrounds scroll down and the sprites rise until frame 278 (A or Start s...
UNUSED void PaletteFade_SetBackdrop(s32 color)
Replaces the first saved colour, the backdrop. Nothing in ☀️ calls it.
void PaletteFade_Update(void)
A task scheduled by PaletteFade_Init: steps the palette fade each frame, adding the step to every col...
const u8 gTitle_IntroSpriteColumns[]
The x of each of the six columns of intro sprites.
void PaletteFade_SetCurrent(s32 mode, s32 paletteHalf)
Sets the colours shown now by transforming the saved palettes.
void PaletteFade_Init(void)
Allocates the palette fade, saves both hardware palettes in it as the starting colours and schedules ...
UNUSED void PaletteFade_SetTarget(s32 mode, s32 paletteHalf)
Sets the fade target by transforming the saved background and/or sprite palettes through the requeste...
void PaletteFade_Start(s32 frames)
Starts fading the shown colours to the target over the requested frames.
u16 gPalette_ChannelCurve[32]
Maps a channel (0..31) to a component (0..31 << 10).
UNUSED void Title_NoOpPalette(void)
Unused palette entry retained in the far-call table.
u16 gPalette_ChannelCurveLight[32]
A brighter curve.
u16 gPalette_ChannelCurveContrast[32]
A high-contrast curve (25 and above are full).
#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...
s32 Title_ShowAnimatedSplash(void)
Shows the Camelot logo for two seconds, cycling its four frames of tiles.
s32 Graphics_ClampRgb555Channel(s32 value)
Clamps a five-bit colour channel to 0..31. Called by Palette_Transform.
#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,...
s32 Graphics_ClampRgb555Component(s32 value)
Caps a colour component at 0x7c00, the largest a five-bit channel shifted into the high bits reaches.
#define WRAP_TO_BYTE(v)
Brings v into 0..255 by whole turns of 256.
const u8 gTitle_PromptBlendLevels[60]
The prompt's blend level over its 60-frame pulse.
UNUSED void PaletteFade_Release(void)
Unschedules the palette fade and frees its buffers.
void Title_LoadIntroBackgrounds(void)
Loads the title intro's two scrolling backgrounds and its sprite tiles, builds their maps and sets th...
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...
s32 Title_ShowSplashScreen(s32 mode)
Shows the Nintendo logo with its jingle.
void Title_UpdateIntroSprites(void)
A VBlank task of the title intro, scheduled by Title_ShowIntro: places the rising sprites along the s...
The hardware's I/O registers and their bits, as pret names them.
#define BGCNT_CHAR_BASE(block)
#define BGCNT_PRIORITY(n)
#define BG_SCREEN_BLOCK(n)
#define OBJ_VRAM0
Sprite tile memory, as pret names it: the 32 KB from 0x06010000.
#define BLDCNT_EFFECT_LIGHTEN
towards white by REG_BLDY
#define BLDCNT_EFFECT_BLEND
weighted by REG_BLDALPHA
#define BLEND_ALPHA(top, bottom)
A REG_BLDALPHA value: top and bottom are the two targets' weights, out of 16.
#define BGCNT_SCREEN_BASE(block)
#define DMA_COPY_WORDS(n)
#define WIN_RANGE(start, end)
A REG_WINxH or REG_WINxV value: the window covers start up to, but not including, end.
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)
#define Iwram_MulQ16(left, right)
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,...
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
@ PALETTE_TRANSFORM_MUTED
@ PALETTE_TRANSFORM_BLEND
The brightness R + G + B shared out in the proportions of the colour carried.
@ PALETTE_TRANSFORM_PLAIN
each colour unchanged
@ PALETTE_TRANSFORM_FROM_SOURCE
The backdrop colour (palette RAM's first colour) for all.
@ PALETTE_TRANSFORM_SEPIA
@ PALETTE_TRANSFORM_SPLIT
each colour unchanged
@ PALETTE_TRANSFORM_WARM2
half R + 6, two thirds G + 4, B - 6
@ PALETTE_TRANSFORM_FLAGS
From here the TINT, BLEND and SPLIT bits are tested, TINT and BLEND carrying an RGB555 colour in the ...
@ PALETTE_TRANSFORM_TINT
The brightness (2R + 4G + B) times the colour carried.
The work pointers in the gWorkSlot table, by name.
#define Ram_MapCellBuffer
void Runtime_PushSlotEntry(void *slotEntry, s32 slot)
Links a sprite entry into depth slot slot (clamped to 0..255) for this frame.
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.
s32 Resource_DecodeByteLz(const void *source, void *destination)
Decodes a byte-oriented LZ resource and returns its unpacked byte count.
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...
void Scheduler_ResetTaskTable(void)
Empties the task table: every slot gets no routine, order 0xffff (sorted last) and no flags.
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
Song and sound effect ids, indices into gSound_SongTable.
A sprite of the "Press Start" prompt, linked into a render slot each frame: OAM attributes 0 to 2 wit...
u32 next
the render slot link
u16 attr1High
flip and size bits of attribute 1
u8 attr0High
shape and mode bits of attribute 0
struct IntroSprite sprites[8]
u8 introObjects[0x68]
objects[0] to [12], still the intro's
The title intro's state, in heap slot 43.
s32 frontRows
rows of the near background copied in
s32 backRows
rows of the far background copied in as it scrolls
s32 rise
how far the sprites have risen
union IntroWork::@371345267344337301352016037371134340173036225143 area
OAM buffer: sprite entries a routine builds by hand and DMA copies to OAM.
A colour buffer for all 512 palette colours: the source palette, the shown and target colour channels...
u16 delta[0x600]
added to each current channel each frame
u16 palette[512]
The source palette, RGB555: 256 BG colours, then 256 OBJ colours.
u16 current[0x600]
The shown colours, as B, G and R channels shifted up 10 bits, three a colour.
s8 duration
frames; 0 when the colours are not moving
u16 target[0x600]
the colours current moves toward, as current
u16 packed[2][512]
Two pages of RGB555 colours: one is built while the other is queued.
u8 page
the packed page queued this frame
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
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...
void DebugText_Clear(void)
Blanks the debug text screen, homes the cursor and points BG0 at it.
The integer types, TRUE, UNUSED and the fixed-address macros.
struct IntroWork::@371345267344337301352016037371134340173036225143::@040137040231117373311171222275233041277366335161 prompt
struct OamShadow objects[120]
void VramCache_Reset(void)
Frees every block and every cache entry.
s32 Resource_FindFreeEntry(void)
Returns the number of the first free cache entry, or VRAM_CACHE_ENTRY_COUNT when all are taken.
s32 VramCache_Load(u32 no, u32 size, const void *src)
Gives cache entry no size bytes of sprite VRAM and copies src there.