Alchemy
Loading...
Searching...
No Matches

scene.c

Go to the documentation of this file.
1/// @file
2/// Scene changes: exits, returns from battle, the main loop, entering.
3/// Part of object.c, the field object, compiled only through it.
4
6
7// The scene overlay's exit table: a header word holding a scene id, then that
8// scene's exits, one packed word each (and a flag word after it when
9// EXIT_HAS_FLAG is set). Scene id EXIT_TABLE_END ends the exits of a scene and
10// the whole table.
11#define EXIT_SCENE_MASK 0xfff
12#define EXIT_ENTRANCE(word) (((word) & 0xff000) >> 12)
13#define EXIT_KIND(word) (((word) & 0x0ff00000) >> 20)
14#define EXIT_HAS_FLAG 0x10000000
15#define EXIT_TABLE_END 0x1ff
16#define EXIT_KIND_ANY 0xff
17
18/// Chooses the scene and entrance to go to when the party leaves the current
19/// scene. exitKind is the kind of exit Field_RunScene ended on; the scene's
20/// exit table gives the first exit of that kind (or of any kind) whose flag, if
21/// it has one, is not set. An exit of kind 0 or the end of the scene's exits
22/// falls back to the scene of its first exit. Called by Game_ResetForNewGame
23/// with Field_RunScene's result; sets gGameState.scene and .entrance, and
24/// leaves them alone for EXIT_NONE or a scene with no header in the table.
25void Scene_TakeExit(s32 exitKind) {
26 s16 currentScene;
27 const u32 *exitTable;
28 const u32 *firstExit;
29 u32 word;
30 s32 scene;
31 s32 nextScene;
32 s32 nextEntrance;
33 s32 entrance;
34 s32 kind;
35 s32 flag;
36
37 currentScene = gGameState.scene;
38 exitTable = gOverlayArea.exits();
39 nextScene = EXIT_NONE;
40 nextEntrance = 0;
41 if (exitKind == EXIT_NONE)
42 return;
43
44 for (;;) {
45 // Find the header of the current scene: exit words have high bits set.
46 scene = *exitTable++;
47 if (scene & ~EXIT_SCENE_MASK)
48 continue;
49 scene &= EXIT_SCENE_MASK;
50 if (scene == EXIT_TABLE_END)
51 break;
52 if (scene != currentScene)
53 continue;
54
55 firstExit = exitTable;
56 for (;;) {
57 word = *exitTable++;
58 scene = word & EXIT_SCENE_MASK;
59 entrance = EXIT_ENTRANCE(word);
60 kind = EXIT_KIND(word);
61 flag = word & EXIT_HAS_FLAG;
62 if (flag)
63 flag = *exitTable++;
64 if (scene == EXIT_TABLE_END || kind == 0) {
65 nextScene = *firstExit & 0x1ff; // only 9 bits, unlike EXIT_SCENE_MASK
66 break;
67 }
68 if (kind == EXIT_KIND_ANY || kind == exitKind) {
69 if (flag == 0 || GameFlag_TestFar(flag) == 0) {
70 nextScene = scene;
71 nextEntrance = entrance;
72 break;
73 }
74 }
75 }
76 break;
77 }
78
79 // Commit the chosen exit only after a matching scene header was found.
80 if (nextScene != EXIT_NONE) {
81 gGameState.scene = nextScene;
82 gGameState.entrance = nextEntrance;
83 }
84}
85
86/// Chooses where the game continues after a battle or another scene that is
87/// not a field map (see Game_ResetForNewGame). result is that scene's result:
88/// -1 when the party was defeated, which revives the leader with 1 HP (and,
89/// with FLAG_CHILDHOOD, fully heals the first two characters) and returns to
90/// the defeat point, or to the last saved point when none is set. Any other
91/// result goes to the next scene the event set, or to the default scene with
92/// the party keeping its position (FLAG_KEEP_PARTY_POSITION). Called by
93/// Game_ResetForNewGame after each scene above SCENE_BLANK; stores result in
94/// gGameState.sceneChangeReason and sets gGameState.scene and .entrance.
96 struct BattleUnit *unit;
97 s32 i;
98 s32 scene;
99 s32 entrance;
100
102 if (result == -1) {
103 // Revive the leader before choosing the defeat return point.
105 if (unit->hp == 0) {
106 unit->hp = 1;
107 Unit_UpdateGauges(unit);
108 }
110 for (i = 0; i < 2; i++) {
111 unit = UnitGetFar(i);
112 unit->hp = unit->maxHp;
113 unit->pp = unit->maxPp;
114 Unit_UpdateGauges(unit);
115 }
116 }
117 scene = gGameState.defeatScene;
118 entrance = gGameState.defeatEntrance;
119 if (scene == -1 && entrance == -1) {
122 } else {
123 if (scene != -1)
124 gGameState.scene = scene;
125 else
127 if (entrance != -1)
128 gGameState.entrance = entrance;
129 else
131 }
132 } else {
133 // An explicit event destination overrides the scene's default return.
134 scene = gGameState.nextScene;
135 entrance = gGameState.nextEntrance;
136 if (scene != -1 || entrance != -1) {
137 if (scene != -1)
138 gGameState.scene = scene;
139 else
141 if (entrance != -1)
142 gGameState.entrance = entrance;
143 else
145 } else {
149 }
150 }
151}
152
153/// Returns the group scene belongs to. The scenes of one place share a group,
154/// which selects their music, area name and the flags kept while inside it.
155/// Called by Scene_ResolveInteractionResult.
157 return gField_SceneTable[scene].group;
158}
159
160/// The minigames borrow the final two 16-colour background palettes.
162
163/// Runs the Lucky Dice minigame, preserving BG palettes 14 and 15.
164static __inline__ s32 RunLuckyDice(s32 entrance) {
165 void *palette = (void *)&BG_PLTT_COLOR(MINIGAME_PALETTE_FIRST, 0);
166 void *saved = MemAlloc(MINIGAME_PALETTE_BYTES);
167 s32 result;
168
169 Dma_Set(palette, saved,
171 REG_DMA3);
172 result = Runtime_BlankDisplayAndRunFar(entrance);
173 Dma_Set(saved, palette,
175 REG_DMA3);
176 MemFree(saved);
177 return result;
178}
179
180/// Runs the slot machine, preserving BG palettes 14 and 15.
181static __inline__ s32 RunReelGame(s32 entrance) {
182 void *palette = (void *)&BG_PLTT_COLOR(MINIGAME_PALETTE_FIRST, 0);
183 void *saved = MemAlloc(MINIGAME_PALETTE_BYTES);
184 s32 result;
185
186 Dma_Set(palette, saved,
188 REG_DMA3);
189 result = ReelGame_StartFar(entrance);
190 Dma_Set(saved, palette,
192 REG_DMA3);
193 MemFree(saved);
194 return result;
195}
196
197/// The game's main loop, which never returns. mode chooses the first scene: 0
198/// starts at the title screen with a fresh game state; in debug mode, 1 starts
199/// in Isaac's home in Vale and 2 at the clear screen. Each pass resets the
200/// runtime, then either runs a battle or minigame and picks the scene to return
201/// to, or loads a field scene's code, starts its music and runs it until the
202/// party takes an exit. Called with mode 0 through Game_ResetForNewGameFar by
203/// System_Initialize at power-on and by Game_Restart.
205 const struct SceneRecord *table;
206 const struct SceneRecord *record;
207 s32 entrance;
208
209 table = gField_SceneTable;
210 // Choose the first scene before initializing the per-scene runtime.
211 if (gDebugMode && mode == 1) {
213 gGameState.entrance = mode;
214 } else if (gDebugMode && mode == 2) {
217 } else {
221 }
226 for (;;) {
227 // Flag 0x101 skips SE_288 for one scene change, then clears itself.
228 if (GameFlag_TestFar(0x101))
230 else
232 record = &table[gGameState.scene];
233 entrance = gGameState.entrance;
234
235 // Stop DMA 0, which a scene may have left running for an HBlank effect.
236 {
237 volatile u16 *dma0 = REG_DMA0;
238
240 dma0[5] &= ~DMA_ENABLE;
241 dma0[5];
242 }
244 Runtime_SetIrqHandler(1, 0, 0);
245 Runtime_SetIrqHandler(2, 0, 0);
249 // A battle or minigame returns a result, not an exit: the return scene is
250 // chosen from the game state, and no overlay is loaded.
252 switch (gGameState.scene) {
253 case SCENE_BATTLE:
254 entrance = Battle_RunEncounterFar(entrance);
255 break;
256 case SCENE_LUCKY_DICE:
257 entrance = RunLuckyDice(entrance);
258 break;
259 case SCENE_REEL_GAME:
260 entrance = RunReelGame(entrance);
261 break;
262 case SCENE_BLANK:
263 entrance = 0;
264 break;
265 }
266 Scene_ReturnFromBattle(entrance);
267 continue;
268 }
269
270 // A field scene: set its flags and music, load its code and run it.
275 // Flags 0x11a and 0x11b keep the music that is playing.
279 else
281 } else if (gGameState.returnCue != -1) {
283 } else {
285 }
286 gGameState.map = record->mapIndex;
289 }
290}
291
292/// Loads the current scene's overlay code (its resource) into gOverlayArea.
293/// Called by Game_ResetForNewGame before Field_RunScene.
294void Scene_LoadOverlay(s32 unused) {
295 const struct SceneRecord *table;
296
297 table = gField_SceneTable;
299}
300
301#define SCENE_RECORD(id) (&gField_SceneTable[id])
302
303/// Updates the flags and state that last for one scene or one group of scenes,
304/// on entering the current scene. Unless keep is set (the party returns to
305/// where it was, as after a battle), the flags of the last scene are cleared,
306/// and on entering a new group so are the group's flags and step counters, the
307/// location name is shown and the entrance becomes the point Retreat returns
308/// to. Then the group's visited flag (0x180 + group) is set. Called by
309/// Game_ResetForNewGame before each field scene, with keep from
310/// FLAG_KEEP_PARTY_POSITION; sets gGameState.sceneGroup and .sceneVariant.
311void Scene_ResetFlagsOnEnter(s32 unused, s32 keep) {
313 s32 flag;
314
315 if (keep == 0) {
316 // Local puzzle flags expire on every normal scene entrance.
317 for (flag = 0x200; flag <= 0x2ff; flag++)
319 if (group != gGameState.sceneGroup) {
320 // Group state and Retreat's destination survive moves within a place.
321 for (flag = 0x300; flag <= 0x3ff; flag++)
332 }
333 // Flags 0x80 to 0xdf last for one scene, even within a group.
334 for (flag = 0x80; flag <= 0xdf; flag++)
342 }
344 GameFlag_SetBitFar((group & 0x7f) + 0x180);
345 // Flag 0x123 marks scenes of variant 2.
347 if (gGameState.sceneVariant == 2)
348 GameFlag_SetBitFar(0x123);
350}
351
352/// Starts the current scene's field music, chosen by
353/// Scene_ResolveInteractionResult. Called by Game_ResetForNewGame, and by
354/// 34 scene overlays through Audio_PlayCueFromEventWorkFar.
356
357#undef EXIT_SCENE_MASK
358#undef EXIT_ENTRANCE
359#undef EXIT_KIND
360#undef EXIT_HAS_FLAG
361#undef EXIT_TABLE_END
362#undef EXIT_KIND_ANY
363#undef SCENE_RECORD
#define Unit_UpdateGauges(unit)
Recalculates HP and PP gauges, keeping at least one when any points remain.
s32 ReelGame_StartFar()
s32 Runtime_BlankDisplayAndRunFar()
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
s32 Battle_RunEncounterFar(s32 enemyGroup)
struct BattleUnit * UnitGetFar(u32 owner)
s32 GameFlag_TestFar(s32 flag)
s32 GameFlag_SetBitFar(s32 flag)
void GameFlag_RefreshLureCapFar(void)
void GameFlag_ClearBitFar(s32 flag)
void GameState_InitDefaultsFar(void)
void AudioCommand_PlayFar(s32 id)
void PaletteGlow_UpdateFar(s32 phase, s32 brightness)
const struct SceneRecord gField_SceneTable[]
struct SceneEntries gOverlayArea
#define FLAG_SHOW_LOCATION_NAME
Definition flags.h:94
#define FLAG_MERCURY_LIGHTHOUSE_LIT
Definition flags.h:30
#define FLAG_VENUS_LIGHTHOUSE_LIT
Definition flags.h:29
#define FLAG_KEEP_MUSIC
The next scene keeps the music that is playing; scene.c clears FLAG_KEEP_MUSIC as it does,...
Definition flags.h:35
#define FLAG_MARS_LIGHTHOUSE_LIT
Definition flags.h:31
#define FLAG_RETREAT_BLOCKED
Retreat is blocked, from Psynergy or an item.
Definition flags.h:55
#define FLAG_LINK_BATTLE
Definition flags.h:68
#define FLAG_KEEP_PARTY_POSITION
Definition flags.h:93
#define FLAG_JUPITER_LIGHTHOUSE_LIT
Definition flags.h:32
#define FLAG_CHILDHOOD
the prologue: Isaac and Garet are children
Definition flags.h:10
#define FLAG_KEEP_MUSIC_HELD
Definition flags.h:36
#define FLAG_NOT_ON_MAP
the current place is not on the world map
Definition flags.h:37
void Runtime_SetIrqHandler(u32 irq, s32 vcount, InterruptHandler handler)
Installs handler for interrupt irq and enables that interrupt, or with a null handler disables it and...
Definition frame.c:37
u8 gDebugMode
Debug builds: Start+Select pauses the frame loop.
struct GameState gGameState
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 * MemAlloc(s32 size)
Allocates size bytes (rounded up to words) with no slot, from IWRAM when they fit and EWRAM otherwise...
Definition heap.c:115
#define REG_DMA0
Definition io_reg.h:151
#define DMA_START_TIMING_DRQ_REPEAT
A DMA control's start timing (bits 12 and 13), cartridge request (bit 11) and repeat (bit 9): the bit...
Definition io_reg.h:220
#define DMA_32BIT
Definition io_reg.h:210
#define REG_DMA3
Definition io_reg.h:153
#define BG_PLTT_COLOR(palette, color)
Definition io_reg.h:158
#define DMA_ENABLE
Definition io_reg.h:217
void MemFree(void *buffer)
void Scene_ResolveInteractionResult(void)
Chooses the current scene's field music (gGameState.cue) from the first rule matching the scene or it...
Definition encounter.c:279
What every part of object.c shares: its includes and the macros and types more than one part uses.
@ SCENE_REEL_GAME
@ SCENE_BATTLE
@ SCENE_BLANK
@ SCENE_LUCKY_DICE
#define EXIT_NONE
Field_RunScene's result when the scene was not left (scene.c, run_scene.c).
s32 Field_RunScene(s32 entrance)
Runs the current field scene, which the party entered by entrance, until it leaves; returns the exit ...
Definition run_scene.c:26
#define SCENE_RECORD(id)
Definition scene.c:301
#define EXIT_KIND(word)
Definition scene.c:13
void Audio_PlayCueFromEventWork(void)
Starts the current scene's field music, chosen by Scene_ResolveInteractionResult.
Definition scene.c:355
static __inline__ s32 RunReelGame(s32 entrance)
Runs the slot machine, preserving BG palettes 14 and 15.
Definition scene.c:181
s32 BattleFx_GetResourceGroup(s32 scene)
Returns the group scene belongs to.
Definition scene.c:156
#define EXIT_SCENE_MASK
Definition scene.c:11
@ MINIGAME_PALETTE_FIRST
Definition scene.c:161
@ MINIGAME_PALETTE_BYTES
Definition scene.c:161
#define EXIT_TABLE_END
Definition scene.c:15
void Scene_TakeExit(s32 exitKind)
Chooses the scene and entrance to go to when the party leaves the current scene.
Definition scene.c:25
void Scene_ResetFlagsOnEnter(s32 unused, s32 keep)
Updates the flags and state that last for one scene or one group of scenes, on entering the current s...
Definition scene.c:311
void Game_ResetForNewGame(s32 mode)
The game's main loop, which never returns.
Definition scene.c:204
#define EXIT_ENTRANCE(word)
Definition scene.c:12
#define EXIT_KIND_ANY
Definition scene.c:16
void Scene_LoadOverlay(s32 unused)
Loads the current scene's overlay code (its resource) into gOverlayArea.
Definition scene.c:294
void Scene_ReturnFromBattle(s32 result)
Chooses where the game continues after a battle or another scene that is not a field map (see Game_Re...
Definition scene.c:95
#define EXIT_HAS_FLAG
Definition scene.c:14
static __inline__ s32 RunLuckyDice(s32 entrance)
Runs the Lucky Dice minigame, preserving BG palettes 14 and 15.
Definition scene.c:164
char SceneId_Title
char SceneId_Clear
char SceneId_ValeHome
void Scheduler_ResetTaskTable(void)
Empties the task table: every slot gets no routine, order 0xffff (sorted last) and no flags.
Definition scheduler.c:19
#define SE_288
Definition songs.h:281
A unit in battle: a party member's or an enemy's stats, Psynergy, items, Djinn and ailments.
s16 maxPp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
s16 hp
current HP, 0 when downed
s16 pp
current PP
s16 maxHp
0 to 1999 for a character, 9999 for an enemy (UnitCalc)
s16 nextScene
where the event sends the party next; -1 for none
Definition game_state.h:43
u8 paletteGlow[2]
window hue (0 to 24), brightness
Definition game_state.h:62
s16 nextEntrance
where the event sends the party next; -1 for none
Definition game_state.h:44
s16 map
the scene's map; SceneId_Clear for the world map
Definition game_state.h:49
s16 sceneGroup
the current scene's group; a new group resets its flags
Definition game_state.h:42
s16 defaultEntrance
the entrance it was entered by
Definition game_state.h:41
s16 hazardSteps
reset on entering a new scene group
Definition game_state.h:99
s32 encounterSteps
the encounter count, reset with a new group
Definition game_state.h:105
s16 defeatEntrance
where a defeat returns to; -1 for none
Definition game_state.h:46
s16 sceneChangeReason
the last battle's result; -1 for a defeat
Definition game_state.h:104
s16 retreatEntrance
where Retreat goes; the group's first entrance
Definition game_state.h:109
s16 defeatScene
where a defeat returns to; -1 for none
Definition game_state.h:45
s16 retreatScene
where Retreat goes; the group's first entrance
Definition game_state.h:108
s16 defaultScene
the scene being run, kept as it starts
Definition game_state.h:40
s16 sceneVariant
the current scene's variant from its record
Definition game_state.h:107
s16 entrance
Definition game_state.h:37
s32 selectedActor
the leader: its unit and its actor
Definition game_state.h:59
s16 savedScene
where a defeat returns to without a defeat point
Definition game_state.h:38
s16 cue
the current scene's field music
Definition game_state.h:56
s16 returnCue
music playing when the field left; -1 for none
Definition game_state.h:82
s16 savedEntrance
where a defeat returns to without a defeat point
Definition game_state.h:39
const u32 *(*) exits(void)
An actor's animation object, seen for the flags and rotation that lay a wounded soldier in his bed.
void Resource_LoadCode(u32 index, void *destination)
Decodes the compressed code resource index to destination and resolves its long branches there,...
Definition system.c:228
void DebugText_Clear(void)
Blanks the debug text screen, homes the cursor and points BG0 at it.
Definition text.c:170
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
signed short s16
Definition types.h:12
unsigned short u16
Definition types.h:13
void VramCache_Reset(void)
Frees every block and every cache entry.
Definition vram_cache.c:184