Cite as
Coaltergeist/goldensun-decomp
Original
https://github.com/Coaltergeist/goldensun-decomp
Pinned
Coaltergeist/goldensun-decomp @ 2e5c504c7d0af54c28830917aec78fbb8bdda01a
Accessed
2026-10-22
Licence
None stated: no LICENSE file, and ATTRIBUTION.md says it "does not replace component notices or introduce a project-wide license". The game code it rebuilds is Nintendo's and Camelot's.
Credit
Coaltergeist and the goldensun-decomp contributors. The README credits gsret for the original disassembly, FutureFractal for Ghidra annotations and function and global names, Tarpman for compiler reproduction, and Karathan for compiler flags. Every function name, field name, and comment quoted in golden-sun claims is theirs.
Notes
Builds a byte-identical ROM; goldensun.sha1 gives 5c4695205413df7db52b9a184815a07783999971, the SHA-1 of "Golden Sun (USA, Europe)" (No-Intro), the North American and European release. Functions not yet decompiled stay as INCLUDE_ASM stubs inside each C file, and parked unfinished C lives apart under src/non_matching/, so every C function in a src/<module>/ file is part of the matching build. decomp.dev reported 30.1% of code matched (2026-10-14, docs/notes/next-decomp-jobs.md). At the pinned commit the battle damage, critical, and Psynergy formulas are all still assembly or unnamed.

Cited on

Claims (2)

In the matching C of the North American and European release, eight unnamed functions (Func_80bf250 to Func_80bf484) each count down one of a unit's turn counters by 1 per call: the attack, defense, and resist modifiers (attackModTurns, defenseModTurns, resistModTurns, field names from the decompilers' struct Unit), and delude, confuse, charm, stun, and sleep. A counter that reaches 0 ends the effect, and for a modifier also zeroes the modifier. Otherwise the unnamed Func_80bf208 rolls for an early end, with the turns left T and a base B per counter: 30 for an attack modifier, 20 for defense and resist, 30 for delude, 60 for confuse, 70 for charm, 40 for stun, 50 for sleep. A modifier rolls only while it is negative (a lowered stat), so a raised stat lasts its full count. The roll happens only when T is 5 or less, and succeeds when (3 × the unit's luck − 5T + B) × 655 is at least a 16-bit RPGRandom result, so a check succeeds about (3 × Luck − 5T + B)% of the time (computed: 655 is about 1% of 65,536; the comparison is signed, so a negative sum never succeeds, and a sum over 100 always does). Success zeroes the counter, and a modifier's value too. Func_80bf208 calls _GetUnit with no argument, so the unit it reads is whatever its first argument left in r0, the unit being checked (the atlas's reading of the matching build). Which routines call these eight, and how often, is still assembly.src/battle/mechanics.c L416–429src/battle/mechanics.c L431–457src/battle/mechanics.c L459–513src/battle/mechanics.c L515–587include/rpg.h L30include/rpg.h L50–60include/macros.inc L62–64exports/rpg/exports.s L58src/rpg/random.c L5–9Code
Golden Sun's RPGRandom is a linear congruential generator, x←1103515245x+12345(mod232) (0x41C64E6D and 0x3039; the state sRPGRNGState is a 32-bit unsigned int on the GBA), returning state >> 8 as an unsigned short: bits 8 to 23 of the state. RPGRandom2 scales one result to 0 to 99, as RPGRandom × 100 >> 16 (computed). These are the constants of the C standard's example rand, which returns bits 16 to 30 instead. Pokémon Emerald's Random keeps the multiplier but adds 24691 and returns the top 16 bits; pret's random.h defines a second step, ISO_RANDOMIZE2, with Golden Sun's 12345.src/rpg/random.c L3–15Code