Cite as
zeldaret/tmc
Original
https://github.com/zeldaret/tmc
Pinned
zeldaret/tmc @ 6fb6dfb4a7efbe24d0fd1dda5097af6131faacde
Accessed
2026-10-22
Licence
none stated (no LICENSE file); the game is Nintendo's
Credit
The Zelda Reverse Engineering Team's (zeldaret) C decompilation of The Minish Cap for Game Boy Advance; see https://github.com/zeldaret/tmc/graphs/contributors. Function names, field names, and comments quoted in tmc claims are theirs.
Notes
The README calls it a work-in-progress decompilation and lists five target ROMs: tmc.gba (USA, SHA-1 b4bd50e4131b027c334547b4524e2dbbd4227130), Japan, Europe, and two demos; it holds no assets, which a build extracts from a copy of the game. The default build is the USA ROM, and GBA.mk checks it against tmc.sha1. At the pinned commit no function in src/ is wrapped in NONMATCH or ASM_FUNC, so the C compiles to the game's bytes. Some routines are still assembly in asm/src/, among them Random, the drop-weight sums, GetRandomByWeight, the iframe countdown sub_080028E0, and the collision loop in intr.s; their mnemonics and comments are the decompilers'. Tables the code reads by address (the collision matrix gCollisionMtx, the fusers' data) are binaries extracted from the ROM, so claims cite those bytes in the US ROM. The player, item, enemy, drop, and Kinstone code read here is all C or that assembly; `#ifdef EU` blocks are not in the US build.

Cited on

Claims (5)

The Minish Cap counts Link's health in eighths of a heart, as A Link to the Past does and as the zladx annotators' comment on Link's Awakening's health byte says ("$08 = 1 heart"); a new file starts him at 24, three hearts. When Link holds up a Piece of Heart, the code refills his health to its maximum and adds 1 to the piece count. The fourth piece resets the count to 0 and then does what a Heart Container does: it adds 8 to the maximum, capped at 160 (20 hearts, A Link to the Past's cap), and refills his health again. Both earlier games also make a container from every fourth piece.src/object/linkHoldingItem.c L131–150src/gameUtils.c L204–216src/fileselect.c L1688–1689src/fileselect.c L776–797Code
The Minish Cap takes a touch's effects from a collision matrix: the entry at the toucher's hit type × 34 + the touched one's hurt type. For an Octorok or a Leever (hit type 25) touching Link in his normal state (hurt type 0), the US ROM's entry gives Link 30 invincibility frames, a knockback duration of 8, and 2 damage, a quarter heart. The collision loop skips a pair while either has a nonzero iframe count, unless either has bit 7 of its collision flags set, and Link's count steps one toward 0 each frame his update runs, so the protection lasts 30 frames. Link's Awakening sets its count to 80 and A Link to the Past to 58.asm/src/intr.s L436–452asm/src/intr.s L329–335src/collision.c L729–737src/collision.c L224–236src/player.c L424src/enemyUtils.c L87src/enemy.c L239–240src/enemy.c L185–186src/interrupts.c L224–228src/interrupts.c L322–335asm/src/code_08001A7C.s L1167–1177Code
While Link's knockback duration is nonzero, a routine that his normal state calls each frame counts it one step toward 0 and, if it's still nonzero, moves him 0x280 along the knockback direction; the code's walking speed kWalkSpeed is Q_8_8(1.25), 0x140, so the atlas reads the push as twice walking speed, though the move routine wasn't read. His normal state skips the code that reads the d-pad while the duration is nonzero, so the player can't steer. The collision loop stores the direction for both parties, Link's the reverse of the toucher's. Among the cancels: a jump, a dash, a roll, a fall, swimming (a swim state above 1), a held object (states 1–4), and climbing unless the push is south. After an Octorok's touch (duration 8) that's 7 moves (computed). Link's Awakening's push runs a 16-frame countdown.src/playerUtils.c L1889–1923src/player.c L37src/player.c L498src/player.c L522–543src/player.c L564–569asm/src/intr.s L475–478src/collision.c L735Code
When a monster dies, its death effect calls the drop routine with the monster's drop table: 6 for Octoroks, ChuChus, Leevers, and Peahats. Unless the room disables random drops, the routine adds the table's 16 weights to an active Picolyte's row, then adds 5 to the heart weight at 8 health (one heart) or less, 3 to bombs with none carried, 3 to arrows with none, and 1 to the 5-rupee weight at 10 rupees or fewer; a weight below 0 (the tables rule an entry out with −999) counts as 0. One Random() value then picks the entry: its bits 24–27 choose where to start, and the value modulo the weights' sum walks the 16 entries from there. Table 6 weighs nothing 73, a green rupee 25, a heart 5, bombs 1, and arrows 1, so with no Picolyte and no need bonus an Octorok drops nothing about 70% of the time (computed). Bombs and arrows drop only once Link has the bag or the bow. A Link to the Past instead steps each prize pack through 8 prizes in order.src/object/deathFx.c L123–127src/object/deathFx.c L237–238src/itemUtils.c L427–432src/itemUtils.c L456–480src/itemUtils.c L495–510asm/src/code_08000F10.s L29–47asm/src/code_08000E44.s L18–27src/droptables.c L112–129src/itemUtils.c L526–536Code
Each Kinstone fuser in The Minish Cap has a data entry whose second byte, which the decompilers call its stability, is the percent chance it offers a fusion: GetFusionToOffer returns no fusion when that byte is at most Random() % 100, none before Link has the Kinstone Bag, and none before the story's progress reaches the entry's first byte. The one call the atlas read is in the Blade Brothers' first action, which sets them up. An entry of 0xFF in a fuser's list stands for a shared fusion: from a random start among 18, the first not yet fused. In the US ROM's table, of the 119 fusers after entry 0, 77 have 100, 20 have 50, 21 have 30, and one has 60 (computed).src/common.c L1235–1239src/common.c L1257–1259src/common.c L1274–1278src/common.c L1943–1958include/kinstone.h L154src/npc/bladeBrothers.c L314–317asm/src/code_08001A7C.s L307–309Code