| name | match-bss-segment |
| description | Match a segments bss data by replacing extern declarations with the appropriate definitions. Use when asked to match, add, split, or fix a .bss segment, especially after checksum failures from bss symbol layout, shifted VRAM labels, queue/stack buffers, or unresolved bss externs. |
Match BSS Segment
Core Rule
Match .bss by reproducing the original VRAM layout exactly. A successful local compile is not enough; the full ROM checksum must match.
Use symbol_addrs.txt as the main layout source. Use code references to infer types and sizes, but let the expected VRAM addresses decide ordering, padding, arrays, and segment boundaries.
Workflow
-
Identify the target range.
- Find the target symbols in
symbol_addrs.txt.
- Note the first symbol address, each following symbol address, and the first symbol after the target file's range.
- Check
snowboardkids2.yaml for the current unsplit bss segment covering that range.
-
Split snowboardkids2.yaml.
- Add a
.bss subsegment for the C file at the first target symbol VRAM.
- Preserve the remaining unknown range by adding or keeping a trailing plain
bss segment at the next unclaimed VRAM.
- Keep later known
.bss or lib .bss entries at their original VRAMs.
Example:
- { type: .bss, vram: 0x800A35D0, name: system/thread_manager }
- { type: .bss, vram: 0x800A4460, name: audio/audio_manager }
-
Replace externs in the C file.
- Convert only symbols that belong to the target file's
.bss range from extern declarations to definitions.
- Add
__attribute__((section(".bss"))) to each definition.
- Use explicit zero initialization so definitions are emitted in source order instead of as reorderable common symbols, e.g.
s32 foo __attribute__((section(".bss"))) = 0; or u8 buffer[0x10] __attribute__((section(".bss"))) = { 0 };.
- Order definitions by expected VRAM address, not by where the old externs happened to appear.
- Use
static only when the symbol is file-local and not referenced externally.
- Keep unrelated externs as externs.
-
Infer sizes from address deltas and use sites.
- For adjacent symbols, subtract addresses to infer object sizes.
- For stacks, define the full stack array and pass
stack + sizeof(stack) to osCreateThread.
- For
OSMesgQueue buffers, define arrays sized to the queue depth passed to osCreateMesgQueue; pass the array base, not &array.
- For gaps that are not understood, add a named or static padding array only when needed to preserve layout.
- Prefer real structs and arrays over
u8 padding[] when usage reveals the type.
- Check whether autogenerated asm labels fall inside a larger real object. If a struct's size spans those labels, let the struct own that range and do not add standalone padding for labels inside it.
-
Fix shifted label names caused by newly split earlier bss.
- Matching an earlier
.bss range can change autogenerated suffixes such as D_800A6468_A7068 to D_800A6468_A7058.
- Search the whole project for old shifted names and update references consistently.
- Do not create duplicate declarations under old and new names.
-
Build and compare layout.
- Run
./tools/build-and-verify.sh.
- If the checksum fails, inspect generated addresses:
mips-linux-gnu-nm -n build/snowboardkids2.elf | rg "symbolA|symbolB|target_file"
- Compare against
symbol_addrs.txt. If one symbol is correct and all later symbols are too early or late, the preceding symbol's size is wrong.
- If symbols appear reordered by alignment rather than source order, check for tentative definitions without explicit zero initialization.
- Re-check array lengths, implicit alignment, struct size, and missing padding before changing YAML addresses.
- Finish only after full verification.
./tools/build-and-verify.sh must finish with build/snowboardkids2.z64: OK.
- If the user requested a commit, commit only the scoped YAML and source changes after the verifier passes.
- If the build script explicitly says to stop, stop immediately and report the best known state rather than attempting another change.
Common Patterns
Single cached object
OutputStruct_19E80 gCachedSpriteTextureEntry __attribute__((section(".bss")));
Queue backing buffer
OSMesgQueue displayQueue __attribute__((section(".bss")));
OSMesg displayQueueMsgs[0x20] __attribute__((section(".bss")));
osCreateMesgQueue(&displayQueue, displayQueueMsgs, 0x20);
Thread stack
OSThread audioThread __attribute__((section(".bss")));
char audioThreadStack[0x180] __attribute__((section(".bss")));
osCreateThread(&audioThread, 9, audioThreadEntry, 0, audioThreadStack + sizeof(audioThreadStack), 7);
Quality Checks
- Do not use manual pointer arithmetic to fake struct fields.
- Do not make unclear symbols
void * when code usage reveals a real type.
- Keep macro definitions, structs, globals, declarations, and implementations in project order.
- Search
src/ and include/ for duplicate or stale declarations before final verification.
- Update
DECOMPILATION_LEARNINGS.md only when matching reveals a reusable compiler or project-specific insight.