10#define SAVE_FILE_COUNT 3
11#define SAVE_RECORD_BYTES 0x1000
12#define SAVE_NO_FREE_FILE 999
15#define SAVE_ERROR_READ -2
17#define SAVE_ERROR_WRITE -3
18#define SAVE_ERROR_ERASE -4
19#define SAVE_ERROR_NO_FILE -5
21#define SAVE_ERROR_NO_MEMORY -9
34 totalMinutes = (
u32)frames / (60 * 60);
35 if (totalMinutes > 999 * 60 + 59)
36 totalMinutes = 999 * 60 + 59;
38 hours = totalMinutes / 60;
39 minutes = totalMinutes % 60;
45 *textCursor = *digitsCursor;
47 *textCursor = digitsCursor[1];
55 *textCursor = digitsCursor[0];
57 *textCursor = digitsCursor[1];
71 if (summary->
level == 0)
89 if (excludeSent != 0) {
102#define SUMMARY_DISTANCE(from, to) \
103 ((u32)&((struct SaveSummary *)0)->to - (u32)&((struct SaveSummary *)0)->from)
147 if (fileCount != 0 && sentCount == fileCount) {
148 return fileCount + 100;
180 destination = summary->
name;
181 source = leader->
name;
182 for (i = 11; i >= 0; i--)
183 *destination++ = *source++;
196 for (i = 0; i <= 3 && members[i] != 255; i++)
197 summary->
party[i] = members[i];
198 summary->
party[i] = -1;
203 for (i = 48; i <= 127; i++) {
467#if LANGUAGE != LANGUAGE_JAPANESE
475 volatile u16 *palette;
486 sine =
Trig_Sin((((
u32)*tick + i * 8U) * 0x300U) & 0xffffU);
488 sine =
Trig_Sin((*tick + i * 8) * 0x300);
490 colour = sine / 16384;
494 u32 red = (
u32)colour << 1;
496 u32 red = colour << 1;
545 sum = y + (window)->y;
562 if (width > 0 && height > 0) {
564 s32 yOffset = y << 6;
565 s32 xOffset = x << 1;
566 s32 offset = yOffset + xOffset;
568 s32 remaining = width;
569 u16 *cell = (
u16 *)(offset + (
s32)tilemap);
570 if (remaining != 0) {
574 }
while (remaining != 0);
578 }
while (height != 0);
588#define SAVE_MENU_SPRITE_SPACING 3
590#define SAVE_MENU_SPRITE_PRIORITY (200 << 4)
601 for (i = 0; i < 4 && summary->
party[i] != -1; i++) {
606 if (sprite !=
NULL) {
630 for (i = 0; i < 4; i++) {
654 position.
height = 500 << 16;
655 position.
y = (menu->
partyMemberY[index] << 16) + (500 << 16);
673 if (window !=
NULL) {
674 for (i = 0; i < 4; i++) {
678 if (sprite !=
NULL) {
701 for (i = 0; i < 4; i++) {
721 if (sprite !=
NULL) {
734 }
while (index <= 3);
744 if (window !=
NULL) {
745 for (i = 0; i < 4; i++)
752#if (LANGUAGE == LANGUAGE_SPANISH)
753#define SUMMARY_LEVEL_X 64
754#define SUMMARY_COINS_X 56
755#define SUMMARY_DRAW_LEVEL UiText_DrawStringAtOffset
756#elif (LANGUAGE == LANGUAGE_FRENCH)
757#define SUMMARY_LEVEL_X 59
758#define SUMMARY_COINS_X 56
759#define SUMMARY_DRAW_LEVEL UiText_DrawStringAtOffset
761#define SUMMARY_LEVEL_X 72
762#define SUMMARY_COINS_X 48
763#define SUMMARY_DRAW_LEVEL UiText_DrawStringInWindow
799#if (LANGUAGE == LANGUAGE_FRENCH)
801 if (summary->
coins > 1)
824#define SAVE_MENU_NO_FILE -2
832#if TBS_PATCH_1 || LANGUAGE == LANGUAGE_JAPANESE
873 summaryWindow =
NULL;
880 if (selectedFile < 0)
936 Dma_Fill32(0, spriteWork,
sizeof(*spriteWork));
942 if (summary->
level == 0) {
944 }
else if (summary->
frames < buildStamp) {
1013 Dma_Fill32(0, spriteWork,
sizeof(*spriteWork));
1041 y = selectedFile * 16 + 4;
1044 cursorSprite->
active = 1;
1045 fileCursor.
anchor = cursorSprite;
1053 if (summaryDirty != 0) {
1058 if (summaryWindow ==
NULL)
1062 if (partyWindow ==
NULL)
1066 &save->
summary[selectedFile]);
1073 if (djinnWindow ==
NULL)
1093 summaryWindow =
NULL;
1102 x = fileList->
x * 8 - 4;
1103 y = (fileList->
y << 3) + selectedFile * 16 + 12;
1146 result = selectedFile;
What every part of the menu object shares: its includes, edition values, macros and the link round st...
#define OUTPUT_SIZE_16X16
OAM attribute bits a sprite output is created with: the size field of attribute 1 (bits 30-31 of the ...
#define Dma_Fill32(value, destination, size)
Fills size bytes at destination with the word value by DMA3.
s32 AnimationObjects_SelectAnimationFar(struct AnimationObject *state, s32 flags)
struct AnimationObject * ResourceObject_CreateFar(s32 id)
void Object_ApplyProjectedPlacementFar(struct AnimationObject *sprite, const struct SpritePlacement *position, const struct SpriteScale *scale, s32 facing)
Far call to Render_ApplyProjectedPlacement.
void ResourceObject_ReleaseFar(struct AnimationObject *sprite)
struct BattleUnit * UnitGetFar(u32 owner)
s32 Party_ListActiveOwnersFar(s16 *owners)
s32 GameFlag_TestFar(s32 flag)
u32 Runtime_GetBuildStampTimeFar()
s32 Party_SumDjinnCountsFar(s32 index)
s32 Scene_GetAreaNameIndexFar(s32 scene, s32 entrance)
void SaveState_CaptureObjectTableFar(void)
Far call to ObjectTable_Snapshot.
s32 Party_RemapCharacterIdIfEnabledFar(s32 arg0, s32 arg1)
void Shop_SetCursorFar(struct ShopCursor *cursor, s32 targetX, s32 targetY, s32 kind)
void ShopCursor_AdvanceFar(struct ShopCursor *cursor)
void AudioCommand_PlayFar(s32 id)
#define FLAG_CHILDHOOD
the prologue: Isaac and Garet are children
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
u32 gFrameTick
Counted up by every VBlank.
u32 gPlayTimeFrames
The play time clock, in frames.
volatile u16 gIdleFrames
Frames since a key was last held.
volatile u8 gIdleSleepEnabled
Sleep after three idle minutes.
void UiText_ShowPositionedMessageAndWait(s32 message, s32 flags)
Shows a message in a window centred on the screen, waits until it is typed out and closes it.
struct UiWindow * UiText_OpenMessageWindow(s32 message, s32 x, s32 y, u32 packed)
Opens a window sized to a message near tile (x, y) and starts typing the message into it.
s32 UiWork_IsComplete(void)
Returns 1 when every message channel has finished its text (or is idle), and 0 while one is still typ...
struct GameState gGameState
u8 * UiText_FormatNumber(u8 *buffer, s32 input, s32 width)
Writes value as decimal text into buffer (14 bytes) and returns where the text starts.
u8 gResource_FixedBlockBTiles[]
void * Runtime_BumpAllocateAlternatePool(s32 size)
As MemAlloc, but tries EWRAM first.
void * Runtime_AllocateHeapBlock(s32 kind, s32 size)
Returns heap slot kind's block, first allocating size bytes for it (rounded up to words),...
#define BG_PLTT_COLOR(palette, color)
static s32 Iwram_CopyWords(volatile void *destination, const volatile void *source, s32 size)
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 Runtime_ReleaseHeapBlock(s32 slot)
void MemFree(void *buffer)
void PaletteGlow_Update(s32 phase, s32 brightness)
Sets the window colours (BG palette 15, colours 4 to 10) for a window hue (0 to 23) and brightness (0...
struct RenderOutput * RenderOutput_Create(s32 slot, s32 oamFlags, struct UiWindow *window, s32 offsetX, s32 offsetY)
Creates a sprite output for the VRAM cache slot slot and attaches it to window, placed at (offsetX,...
struct RenderOutput * RenderResource_CreatePair(s32 picture, struct UiWindow *window, s32 x, s32 y)
Shows picture picture of gRenderResource_PairSourceTable as two 32x32 sprites side by side at (x,...
void RenderOutput_BobPair(struct RenderOutput *obj)
Bobs the two sprites of a pair (see RenderResource_CreatePair) up and down by gUi_PairBobOffsets,...
u32 SaveState_ReadRecordPayload(s32 recordId, void *destination)
Loads the current copy of record recordId into destination.
s32 SaveState_LoadSummaryRecords(void)
Reads the summary at the start of each of the three save files into summary for the file select scree...
u32 SaveState_ReleaseWorkspace(void)
Removes the flash timer handler and frees the save workspace's heap slot.
u32 SaveState_DeleteRecord(s32 recordId)
Invalidates the current copy of record recordId.
s32 SaveState_WriteRecord(s32 recordId, void *source)
Saves 0xff0 bytes from source as record recordId: writes the new copy with the next sequence number,...
s32 SaveState_InitializeWorkspace(void)
Allocates the save workspace (heap slot HEAP_SLOT_SAVE), installs the flash library's timer 2 handler...
struct SaveWorkspace * gSaveWorkspace
s16 gTitleSendOptionEnabled
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...
s32 Scheduler_RemoveCallback(SchedulerCallback callback)
Unschedules the task running callback: clears its routine and gives it order 0x7fff,...
#define SE_MENU_CURSOR_MOVE
An animated sprite: its image and shadow, scale, rotation, size and up to four animation layers.
struct AnimationSpritePart image
u8 flags
bits: 1 outlined in ObjectSystemWork's edge and fill colours | 0 shadow drawn (set when created)
s32 scale
16.16 fixed point, 0x10000 full size
u16 priority
2 when created
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
u8 name[0x0f]
The name, one byte a character, ending in 0.
u8 classIndex
The character's class, worked out from its Djinn (Unit_UpdateClass); 0 marks an enemy,...
u8 level
1 to 99 for a character
The menu work as the row of four figures reads it: each figure's object, screen position and motion p...
struct AnimationObject * objects[4]
s16 positionsX[4]
screen pixels
s16 positionsY[4]
screen pixels
u8 paletteGlow[2]
window hue (0 to 24), brightness
u32 playTime
frames, copied from gPlayTimeFrames when saving
u32 buildStamp
Runtime_GetBuildStampTime's value when the game was last saved; its low half goes into the file's sum...
u8 unk20f
Set on saving at the end of the game; copied to the file's summary as sendFlag.
u8 idleSleepEnabled
the option, saved from gIdleSleepEnabled
s32 selectedActor
the leader: its unit and its actor
A render output: a sprite in a window's output list (a character, an icon or a portrait),...
s8 active
its UI_SPRITE_ motion; 0 while free
A save file's summary for the file screen: the leader's name, level and class, the area,...
u16 paletteGlow
bits: 15..8 paletteGlowSub | 7..0 paletteGlow
u8 unk38[4]
Filled on reading: the play time from the file's second record.
u8 hasFlag20
FLAG_CHILDHOOD is set; remaps the party's sprites.
u16 frames
Low half of GameState.buildStamp; a file below the current stamp is listed as from an older build.
u32 checksum
the sum of the 968 words from gGameFlagBytes
s8 sendFlag
Copied from GameState.unk20f, which saving at the end of the game sets; the file menu for cleared dat...
u8 djinn[4]
the party's Djinn of each element
u8 level
the leader's; 0 for an empty file
s8 flagCount
how many of game flags 48 to 127 are set
u16 paletteGlowSub
GameState.paletteGlow[1].
u16 area
area name number (Scene_GetAreaNameIndex)
s8 party[5]
up to four party members, ended by -1
The save work: which of the 16 flash sectors hold a record, their record ids and sequence numbers,...
struct SaveSummary summary[3]
each file's, read from its first record
union SaveWorkspace::@331263107057156204162071305274032234046256201132 slot
one sector, read from or written to flash
Cursor that approaches its target, shared by shop, name entry and settings.
u16 x
screen pixels: where the current move started
u16 y
screen pixels: where the current move started
struct RenderOutput * anchor
the cursor's sprite, moved with its OAM
A shop's work: its windows, the party members' icons, the stock, the cursor and its icons,...
s32 partyMemberScale[8]
16.16 fixed point, 0x10000 full size
struct AnimationObject * partyMemberIcons[8]
the party row's sprites
s16 partyMemberY[8]
pixels
s16 partyMemberX[8]
pixels
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 groundHeight
how far the shadow is raised above y
s32 height
how far the image is raised above y
Horizontal and vertical sprite scale; 0x10000 is the original size.
The window system's work: the windows' tilemap, the windows, the three text channels,...
u16 tilemap[640]
the windows' BG tilemap, 32 by 20 tiles
u8 dirty
The tilemap's 4-row bands to upload: bit 0 for all, bit n + 1 for band n.
A window: a framed rectangle of the tilemap with its sprite outputs, its opening or closing animation...
void UiText_DrawStringInWindow(const u8 *text, struct UiWindow *window, u32 x, u32 y)
Draws a byte string into a window's tilemap at pixel (x, y) of its interior, rounded down to tiles.
void UiText_DrawResource(s32 message, struct UiWindow *window, s32 x, s32 y)
Decodes a message and draws it into a text canvas window at pixel (x, y).
void UiText_DrawString(const u8 *text, struct UiWindow *window, s32 x, s32 y)
Draws a byte string into a text canvas window at pixel (x, y).
void UiWindow_DrawDividerLine(struct UiWindow *win, u32 x1, u32 y1, u32 x2, u32 y2)
Draws a straight divider line inside a window from tile (x1, y1) to (x2, y2), horizontal or vertical:...
void UiText_DrawStringAtOffset(const u8 *text, const struct UiWindow *work, s32 offsetX, s32 offsetY)
Draws a byte string as tiles in window work at pixel (offsetX, offsetY) of its interior.
void UiText_DrawNumberInWindow(s32 value, s32 width, struct UiWindow *window, s32 x, s32 y)
Draws a number (width as UiText_FormatNumber) into a window's tilemap at pixel (x,...
void UiText_DrawNumberAtOffset(s32 value, s32 width, const struct UiWindow *window, s32 x, s32 y)
Draws a number (width as UiText_FormatNumber) as tiles in a window at pixel (x, y) of its interior.
void UiText_DrawCharacterAtOffset(s32 message, const struct UiWindow *window, u32 offsetX, u32 offsetY)
Decodes a message and draws it as tiles in a window at pixel (offsetX, offsetY) of its interior.
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.
#define SAVE_ERROR_READ
a record could not be read
s32 Save_WriteSelectedSlot(void)
The Save command: lets the player choose a file (the current one first), asks whether to save over it...
#define SAVE_MENU_NO_FILE
SaveMenu_SelectSlot's result when no file can be chosen in its mode.
#define SAVE_RECORD_BYTES
s32 SaveState_DeleteSelectedSlot(void)
The file menu's Erase: lets the player choose a file, asks whether to erase it and on Yes deletes bot...
#define SUMMARY_DRAW_LEVEL
void UiWindow_FillTilemapRect(struct UiWindow *window, s32 x, s32 y, s32 width, s32 height)
Fills the width x height tile rectangle at (x, y) inside window, clipped to the screen as UiWindow_Se...
s32 SaveState_WriteSlotPair(s32 file)
Writes both halves of the save buffer, as they are, to save file file.
void SaveMenu_ShowDjinnSprites(struct UiWindow *window, s32 x, s32 y)
Shows the four Djinn sprites, one for each element, in a row from tile (x, y) inside window,...
#define SAVE_ERROR_NO_FILE
no empty file to copy into
u32 SaveState_BuildSummaryHeader(void)
Prepares the save buffer for writing: stamps the game state with the time and options,...
s32 SaveMenu_SelectSlot(s32 selectedFile, s32 menuMode)
#define SAVE_MENU_SPRITE_SPACING
The save file menu shows the chosen file's party as walking sprites in a row, and four Djinn sprites,...
void SaveMenu_HidePartySprites(void)
Stops placing the party sprites of the save file menu and releases them.
UNUSED s32 SaveState_ConfirmAndProcessSelectedSlot(void)
Asks whether to save over the current file and, on Yes, writes the save stamp into it (SaveState_Proc...
s32 SaveState_CopySlotPair(void)
The file menu's Copy: lets the player choose a file, reads both of its records into the save buffer a...
void SaveMenu_DrawFileSummary(struct UiWindow *window, struct SaveSummary *summary)
Draws the summary of save file summary into window: the leader's name, level and class,...
void PaletteGlow_UpdateSine(void)
A scheduler callback that makes colours 8-11 of BG palette 14 glow: each follows a sine wave of the f...
#define SAVE_MENU_SPRITE_PRIORITY
Scheduler priority of the callbacks that place the sprites every frame.
void PaletteGlow_Start(void)
Starts the palette glow (PaletteGlow_UpdateSine) in the scheduler.
u32 SaveState_FindFreeSummarySlot(void)
Returns the first save file whose summary shows it empty (level 0), or SAVE_NO_FREE_FILE when all thr...
void SaveMenu_DrawDjinnCounts(struct UiWindow *window, struct SaveSummary *summary)
Draws the Djinn counts of save file summary, one for each element, two digits each,...
void SaveMenu_HideDjinnSprites(void)
Stops placing the Djinn sprites of the save file menu and releases them.
s32 Resource_LoadFixedBlockBIntoFreeSlot(void)
Loads the pointing hand cursor's tiles (gResource_FixedBlockBTiles, 128 bytes) into a free VRAM slot ...
void PaletteGlow_Stop(void)
s16 SaveState_WriteCurrentSlotPair(void)
Saves the game to the current file (gSaveSlot): builds the summary and writes both halves of the save...
#define SAVE_NO_FREE_FILE
s32 SaveState_CountRecordsExcludingFlagged(s32 excludeSent)
Returns how many save files there are, leaving out those whose summary has its send flag set when exc...
s32 SaveState_LoadRecordIntoWork(s32 mode)
Lets the player choose a file in save menu mode (see SaveMenuMode) and loads it into the save buffer ...
s32 SaveState_ProcessSelectedSlot(void)
Writes the 64-byte save stamp (gSaveStamp, which lies in the first half of the save buffer) into the ...
s32 SaveState_ScanRecordFlags(void)
Loads the save file summaries for the title menu and returns how many files there are: plus 100 when ...
SaveMenuMode
What the save file menu is choosing a file for, which decides the files the cursor may stop on.
@ SAVE_MENU_CLEARED
cleared files only
@ SAVE_MENU_SAVE
saving: any file, empty ones too
@ SAVE_MENU_CONTINUE
continuing: files not yet cleared
@ SAVE_MENU_COPY
copying: any file with data
@ SAVE_MENU_EXTRA
files with any of game flags 48-127 set
@ SAVE_MENU_ERASE
erasing: any file with data
void SaveMenu_PlaceDjinnSprites(void)
A scheduler callback: draws each Djinn sprite of the save file menu at its place, at scale 1....
#define SAVE_ERROR_ERASE
erasing failed. "Failed to erase."
void * Text_FormatPlayTime(s32 frames, u8 *out)
Writes the play time frames (at 60 frames a second) into out as hours and minutes,...
#define SAVE_ERROR_NO_MEMORY
No backup memory. "Unable to detect backup memory.".
void SaveMenu_PlacePartySprites(void)
A scheduler callback: draws each party sprite of the save file menu at its place and scale for this f...
#define SUMMARY_DISTANCE(from, to)
The distance in bytes from one field of a save summary to another.
void SaveMenu_ShowPartySprites(struct UiWindow *window, s32 x, s32 y, struct SaveSummary *summary)
Shows the party of save file summary (up to four members) as sprites in a row from tile (x,...
#define SAVE_ERROR_WRITE
Writing failed. "Failed to save." (or "Failed to erase.").
void UiWork_FinalizePendingCore(void)
Closes each message channel's window whose text has ended, then waits ten frames.
void RenderOutput_PrepareForRedraw(struct UiWindow *window)
Clears a window's contents: redraws its empty frame and releases the render outputs it carries.
void UiWork_Finalize(struct UiWindow *window, s32 instant)
Closes a window: clears its contents and remembers its last rectangle.
void RenderOutput_RedrawSavedRect(struct UiWindow *window)
Redraws a window's empty frame at its current rectangle.
struct UiWindow * UiWindow_Create(s32 x, s32 y, s32 width, s32 height, s32 attrs)
Opens a window at tile (x, y) of width by height tiles in the first free window slot,...