Alchemy
Loading...
Searching...
No Matches

system.c

Go to the documentation of this file.
1/// @file
2/// Power-up, the cartridge's language, the build stamp and code loading.
3/// Part of runtime.c, the runtime object, compiled only through it.
4
6
7#if TBS_PATCH_2
8#define SYSTEM_HALT_ON_GAMEPAK_IRQ 1
9#endif
10
11/// Powers the game up: stops any HBlank DMA left running, sets the cartridge
12/// wait states, clears IWRAM, installs the interrupt handlers and the resident
13/// IWRAM code, loads the window graphics and the sound driver, then starts a
14/// new game. It never returns. Called once by System_Entry after it has set
15/// the stacks; it clears the debug switches, enables the OAM copy and sleep,
16/// and clears gCartridgeResetMarker, which a soft reset leaves set.
18 {
19 volatile u16 *dma0 = REG_DMA0;
20
21 // DMA0CNT_H: drop the HBlank repeat timing, then the enable bit
23 dma0[5] &= ~DMA_ENABLE;
24 dma0[5];
25 }
27 // Clear IWRAM up to the heap's end (the stacks above it are in use), then
28 // install the resident runtime before any service can use its work blocks
29 Dma_Fill32(0, (void *)0x03000000, 0x7800);
32 // UB: the count and its pad are cleared with one word store
33#ifdef UBFIX
36#else
37 *(u32 *)&gIoWriteQueue.count = 0;
38#endif
40 gDebugMode = 0;
47#if defined(SYSTEM_HALT_ON_GAMEPAK_IRQ)
49#endif
51 // Start audio and frame services only after the interrupt handlers are ready.
58 WaitFrames(10);
60}
61
62/// Waits out frames forever; the frame loop still runs the scheduled tasks.
63/// Nothing in ☀️ calls it.
65 for (;;) {
66 (void)gKeysPressed;
67 WaitFrames(1);
68 }
69}
70
71#if TBS_PATCH_4
72
73enum CartridgeLanguage {
74 CARTRIDGE_LANGUAGE_ENGLISH,
75 CARTRIDGE_LANGUAGE_GERMAN,
76 CARTRIDGE_LANGUAGE_FRENCH,
77 CARTRIDGE_LANGUAGE_SPANISH,
78 CARTRIDGE_LANGUAGE_ITALIAN
79};
80
81/// Returns the language of this cartridge from the header's game code letter:
82/// 0 English, 1 German, 2 French, 3 Spanish, 4 Italian. Called by the battle
83/// target selection and the status screen, which lay text out by language.
85 s32 language;
86
87 switch (gRom_LanguageCode) {
88 case 'D':
89 language = CARTRIDGE_LANGUAGE_GERMAN;
90 break;
91 case 'F':
92 language = CARTRIDGE_LANGUAGE_FRENCH;
93 break;
94 case 'S':
95 language = CARTRIDGE_LANGUAGE_SPANISH;
96 break;
97 case 'I':
98 language = CARTRIDGE_LANGUAGE_ITALIAN;
99 break;
100 default:
101 language = CARTRIDGE_LANGUAGE_ENGLISH;
102 break;
103 }
104 return language;
105}
106#endif
107
108/// Reserved empty export A in the runtime far-call table; no source caller.
110
111/// Reserved empty export B in the runtime far-call table; no source caller.
113
114/// Reserved empty export C in the runtime far-call table; no source caller.
116
117/// Reserved empty export D in the runtime far-call table; no source caller.
119
120/// Reserved empty export E in the runtime far-call table; no source caller.
122
123/// An exported stub that ignores its arguments and reports 0.
124s32 RuntimeDispatch_ReturnZero(s32 unused0, const u8 *unused1) { return 0; }
125
126/// The build stamp's twelve digit characters copied to IWRAM, and a zero word
127/// after them that ends the string.
131};
132
133/// Copies the build stamp resource (twelve digits) into gBuildStamp in high
134/// IWRAM and writes the zero word that ends it. Called by System_Initialize.
136 const void *stamp;
137 struct BuildStampCopy *copy;
138
140 copy = (struct BuildStampCopy *)gBuildStamp;
141 Dma_Set(stamp, copy, DMA_COPY_WORDS(3), REG_DMA3);
142 copy->terminator = 0;
143}
144
145/// An exported stub that does nothing with its argument.
147
148/// Returns the ROM address of resource `index` from the resource directory.
149/// Called throughout the game before decoding a resource.
151 return Resource_DirectoryTable[index];
152}
153
154/// Resolves the Thumb long branches (BL pairs) of a block of code whose branch
155/// offsets are stored from the start of the block. A BL is two halfwords: the
156/// first carries the marker bits 0xf000 and the high eleven bits of the offset,
157/// the second the marker 0xf800 and the low eleven bits of the halfword offset.
158/// Each pair's offset is reduced by the pair's own position in the block, which
159/// turns it into the pc-relative offset the CPU expects; the pairs are
160/// rewritten in place. `byteLength` is the code size. Nothing calls it:
161/// Resource_LoadCode uses the ARM routine that does the same.
162UNUSED void Code_ResolveLongBranches(u16 *entries, s32 byteLength) {
163 s32 entryCount;
164 s32 entryIndex;
165
166 entryCount = byteLength >> 1;
167 entryIndex = 1;
168#ifndef UBFIX
169 entries++;
170#endif
171 if (entryIndex < entryCount) {
172 u32 nextMarkerMask;
173 u32 currentMarkerMask;
174 u32 payloadMask = 0x7ff;
175 nextMarkerMask = 0xf800;
176 currentMarkerMask = 0xf000;
177#ifndef UBFIX
178 // UB: temporarily forms a pointer before the start of the code block.
179 entries -= 2;
180#endif
181 // Only adjacent halfwords with both BL marker patterns are relocated.
182 do {
183 u16 currentEntry;
184 u16 nextEntry;
185 u32 nextMarkerBits;
186 u32 currentMarkerBits;
187
188#ifdef UBFIX
189 nextEntry = entries[1];
190#else
191 nextEntry = entries[2];
192#endif
193 nextMarkerBits = nextEntry & nextMarkerMask;
194#ifndef UBFIX
195 entries++;
196#endif
197 if (nextMarkerBits == nextMarkerMask) {
198 currentEntry = entries[0];
199 currentMarkerBits = currentEntry & nextMarkerBits;
200 if (currentMarkerBits == currentMarkerMask) {
201 u32 packedOffset;
202 u32 adjustedCurrent;
203 u32 adjustedNext;
204
205 packedOffset = (((currentEntry & payloadMask) << 12) |
206 ((nextEntry & payloadMask) * 2)) -
207 (entryIndex * 2);
208 adjustedCurrent =
209 ((packedOffset >> 12) & payloadMask) | currentMarkerBits;
210 adjustedNext = ((packedOffset >> 1) & payloadMask) | nextMarkerBits;
211 entries[0] = adjustedCurrent;
212 entries[1] = adjustedNext;
213 }
214 }
215#ifdef UBFIX
216 entries++;
217#endif
218 entryIndex++;
219 } while (entryIndex < entryCount);
220 }
221}
222
223/// Decodes the compressed code resource `index` to `destination` and resolves
224/// its long branches there, with a RAM copy of the ARM routine that does what
225/// Code_ResolveLongBranches does; the copy is allocated and freed again.
226/// Called by Scene_LoadOverlay for each scene's overlay, and through the
227/// far-call table.
228void Resource_LoadCode(u32 index, void *destination) {
229 void (*patchBranches)(void *, s32);
230 s32 codeSize;
231
232 codeSize = Resource_DecodeType01(Resource_GetTableEntry(index), destination);
235 patchBranches(destination, codeSize);
236 MemFree(patchBranches);
237}
238
239/// The handler of every interrupt nobody has claimed.
241
242/// Copies the resident code to IWRAM, points the BIOS interrupt vector
243/// (gIrqVector) at its dispatcher, installs the default handler table and
244/// enables the VBlank and keypad interrupts (and, outside Japan and England,
245/// the cartridge-removed interrupt, which halts the game). Called by
246/// System_Initialize with IME cleared; it sets IME again at the end.
248 u8 *iwram;
249
250 // Keep interrupts masked while replacing both the dispatcher and its table.
251 Io_Write16(0, &REG_IME);
252 iwram = IwramIrqMain;
253 // 0x1400 bytes of resident code and data
255 gIrqVector = iwram;
257 REG_DMA3);
259 // Disarmed until System_Initialize arms the soft-reset keys
261#if defined(SYSTEM_HALT_ON_GAMEPAK_IRQ)
263#else
265#endif
266 Io_Write16(1, &REG_IME);
267}
268
269#undef SYSTEM_HALT_ON_GAMEPAK_IRQ
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
void Game_ResetForNewGameFar(s32 mode)
void Audio_InitializeRuntimeDefaultsFar(void)
void System_VBlankHandler(void)
The VBlank interrupt handler, installed by System_Initialize.
Definition frame.c:374
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
void WaitFrames(s32 frames)
The game's frame loop: runs frames frames and returns.
Definition frame.c:97
volatile u8 gCpuLoadDisplayEnabled
Debug: WaitFrames measures the CPU load into gCpuLoadPeak when set.
volatile u8 gSleepDisabled
Nonzero: WaitFrames counts no idle time and ignores sleep requests.
u8 gDebugMode
Debug builds: Start+Select pauses the frame loop.
u8 gOamCopyEnabled
The VBlank handler copies the OAM list only while it is set; scenes clear it to keep their own sprite...
u32 gCartridgeResetMarker
Written by the soft reset just before it restarts the cartridge, and cleared by System_Initialize; no...
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
#define REG_KEYCNT
Definition io_reg.h:184
#define KEYCNT_DISARMED
Requires all ten keys together to prevent the reset chord retriggering it.
Definition io_reg.h:313
#define REG_WAITCNT
Definition io_reg.h:307
#define KEYCNT_SOFT_RESET
A, B, Select and Start.
Definition io_reg.h:311
#define REG_IE
Definition io_reg.h:305
#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
@ DISPCNT_BG0_ON
Definition io_reg.h:40
@ DISPCNT_OBJ_1D_MAP
Definition io_reg.h:39
#define REG_DISPCNT
Definition io_reg.h:9
#define REG_IME
Definition io_reg.h:308
#define REG_DMA3
Definition io_reg.h:153
#define REG_DISPSTAT
Definition io_reg.h:10
#define WAITCNT_GAME
Definition io_reg.h:317
#define DMA_COPY_WORDS(n)
Definition io_reg.h:226
#define DMA_ENABLE
Definition io_reg.h:217
struct IoWriteQueue gIoWriteQueue
#define Io_Write16(v, reg)
Writes a value to a 16-bit register or memory location.
Definition iowrite.h:14
InterruptHandler gIrqHandlers[IRQ_COUNT]
The handler the IWRAM dispatcher calls for each interrupt source.
#define INTR_FLAG_GAMEPAK
Definition irq.h:34
u8 IwramIrqMain[]
#define INTR_FLAG_VBLANK
Definition irq.h:30
const u8 IwramRuntime_Rom[]
@ IRQ_VBLANK
Definition irq.h:13
@ IRQ_COUNT
Definition irq.h:27
@ IRQ_GAMEPAK
Definition irq.h:26
const u32 gRuntime_IrqHandlers[IRQ_COUNT]
The handlers installed at power-on, copied into gIrqHandlers.
#define INTR_FLAG_KEYPAD
Definition irq.h:33
void * gIrqVector
volatile u32 gKeysPressed
Keys that went down this frame.
void MemFree(void *buffer)
#define RamCode_Load(to, code, bytes)
Allocates a heap copy; release it with MemFree when finished.
Definition ramcode.h:15
char ResourceId_BuildStamp
s32 Resource_DecodeType01(const void *source, void *destination)
Decodes a type-01 resource and returns its unpacked byte count.
Definition decompress.c:31
What every part of the runtime object shares: its includes and the library call two parts make.
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 gBuildStamp[]
The build stamp System_CopyBuildStamp copies to IWRAM at power-on: twelve digits and a zero word,...
The build stamp's twelve digit characters copied to IWRAM, and a zero word after them that ends the s...
Definition system.c:128
u32 digits[3]
Definition system.c:129
u16 count
Entries waiting, at most 32.
UNUSED void RuntimeDispatch_ReservedNoOpA(void)
Reserved empty export A in the runtime far-call table; no source caller.
Definition system.c:109
void Runtime_IgnoreInterrupt(void)
The handler of every interrupt nobody has claimed.
Definition system.c:240
void System_Initialize(void)
Powers the game up: stops any HBlank DMA left running, sets the cartridge wait states,...
Definition system.c:17
void System_CopyBuildStamp(void)
Copies the build stamp resource (twelve digits) into gBuildStamp in high IWRAM and writes the zero wo...
Definition system.c:135
UNUSED void RuntimeDispatch_ReservedNoOpB(void)
Reserved empty export B in the runtime far-call table; no source caller.
Definition system.c:112
void * Resource_GetTableEntry(s32 index)
Returns the ROM address of resource index from the resource directory.
Definition system.c:150
UNUSED void RuntimeDispatch_ReservedNoOpD(void)
Reserved empty export D in the runtime far-call table; no source caller.
Definition system.c:118
UNUSED void RuntimeDispatch_ReservedNoOpC(void)
Reserved empty export C in the runtime far-call table; no source caller.
Definition system.c:115
void RuntimeDispatch_NoOpHook(s32 unused)
An exported stub that does nothing with its argument.
Definition system.c:146
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
UNUSED void Code_ResolveLongBranches(u16 *entries, s32 byteLength)
Resolves the Thumb long branches (BL pairs) of a block of code whose branch offsets are stored from t...
Definition system.c:162
UNUSED void RuntimeDispatch_ReservedNoOpE(void)
Reserved empty export E in the runtime far-call table; no source caller.
Definition system.c:121
void Runtime_InstallIwramAndIrqs(void)
Copies the resident code to IWRAM, points the BIOS interrupt vector (gIrqVector) at its dispatcher,...
Definition system.c:247
UNUSED void Runtime_IdleForever(void)
Waits out frames forever; the frame loop still runs the scheduled tasks.
Definition system.c:64
s32 RuntimeDispatch_ReturnZero(s32 unused0, const u8 *unused1)
An exported stub that ignores its arguments and reports 0.
Definition system.c:124
const u8 gRom_LanguageCode
void * Resource_DirectoryTable[]
u8 gDebugTextEnabled
u8 Resource_PatchThumbBranchCodeSize[]
const u8 Resource_PatchThumbBranch[]
void IwramHalt(void)
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
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned short u16
Definition types.h:13
#define UNUSED
Definition types.h:22
unsigned char u8
Definition types.h:11
s32 System_GetLanguage(void)
void VramCache_Reset(void)
Frees every block and every cache entry.
Definition vram_cache.c:184