01 — The Idea & Foundation

A decompiled ROM, a design on paper, and the first lines cut.


Pokémon Blue was the first game I played through. Decades later — after shipping software in more languages than I care to count — I picked up a small handheld for emulation. Quality-of-life FireRed hacks rekindled something. Not just to play. To change it. Claude handles the GBA-specific C. I handle the design, the lore, and the calls.

The Pitch

What if Pokémon had gear? Not held items — real gear. Randomized loot with prefixes, suffixes, rarity tiers, and quality rolls. Diablo 3 meets Pokémon FireRed.

Every battle would have a chance to drop gear for your Pokémon. An Amulet with +ATK. Armor with +DEF. Rare drops with exotic affixes. Your Pokémon aren’t just leveling through battles — they’re getting kitted out.

The trainer gets one relic slot. A Mentor’s Tome for +50% XP. A Lucky Charm for better shiny odds. A Hunter’s Mark for improved drop rates. Passives that change how you play.

Why a Decompilation?

Two ways to hack a GBA ROM:

  1. Binary ROM hacking: Hex-edit the compiled ROM directly. Tools like HxD, AdvanceMap, PGE. Poke bytes at specific offsets.
  2. Decompilation hacking: Start from pret/pokefirered — a full C decompilation of the game. Write real C code. Compile a new ROM.

Binary hacking is the traditional approach. Most ROM hacks use it. For adding entirely new systems — not tweaking trainers or changing stats, but building new game mechanics — decompilation opens things up. Real C with types, structs, and functions. A build system that produces a byte-identical ROM from source. Compiler errors instead of mysterious crashes.

The tradeoff: the codebase runs ~500K lines of C. The toolchain is arcane — DevKitARM cross-compiler, custom preprocessor for string encoding. The GBA’s constraints are brutal.

Designing the Gear System

The core data structure had to be small. Every Pokémon stores its gear in a u16 field — 2 bytes. The actual gear data lives in a bag in the save file. The gear encoding packs everything into a single u32:

Bits 0-1:   Slot type (Accessory / Armor)
Bits 2-3:   Rarity (Common / Uncommon / Rare / Epic)
Bits 4-7:   Base item (8 types: Amulet, Bracelet, Ring, Crown, Vest, Mail, Cloak, Shield)
Bits 8-11:  Prefix 1 (10 options: Lucky, Stalwart, Fierce, etc.)
Bits 12-15: Prefix 2
Bits 16-19: Suffix 1 (8 options: of Focus, of Power, of the Moon, etc.)
Bits 20-21: Suffix 2
Bits 22-25: Quality (85%-130% effectiveness multiplier)
Bit 26:     Is Legendary
Bits 27-30: Legendary ID

One u32. 4 bytes. The entire identity of a piece of gear.

The GearEncode macro assembles it:

#define GearEncode(slot, rarity, base, p1, p2, s1, s2, quality) \
    ((slot) | ((rarity) << 2) | ((base) << 4) | ...)

The Drop System

After every battle, TryDropGear() runs. It rolls against the base drop rate — modified by the Hunter’s Mark relic if equipped — picks a rarity tier, randomizes affixes, and generates a quality roll. The gear appears in a post-battle notification screen.

Drop rates scale with rarity:

Higher rarity fills more affix slots. Affixes run stronger ranges at higher rarities.

The Relic System

Relics are simpler than gear. One slot on the trainer. Passive effects that apply globally:

Relic Effect
Lucky Charm Increased shiny encounter rate
Mentor’s Tome Bonus XP from battles
Gold Coin Bonus prize money
Hunter’s Mark Improved gear drop rate
Seeker’s Eye Better item find chance
Breeder’s Loop Faster egg hatching
Sprinter’s Boots Walk/run speed boost

Each relic has 4 rarity tiers with scaling effect strength — stored as per-mille values for integer math on the GBA. No floating point on this machine.

The Save File Challenge

GBA save data is fixed-size. FireRed’s SaveBlock1 and SaveBlock2 have specific byte layouts. You can’t append data. You carve space from existing unused filler bytes.

I carved:

Total SaveBlock2 must stay exactly 0xF24 bytes on GBA. Verified obsessively.

First Code

The initial commit added ~420 lines of core gear logic (gear.h + gear.c), hooked drops into the battle system, added stat bonuses to CalculateMonStats(), and created a “GEAR” option in the party menu. The relic system followed immediately — 6 types with hooks scattered across the codebase: XP in the battle controller, money in battle scripts, shiny in wild encounter generation, egg hatch in daycare, item find in field control.

The data layer was solid. There was no way yet to look at any of it. Good problem to have.

That was the UI phase’s job — and it would break before it fixed anything.

By the Numbers

Metric Value
Active ~4 hours
Commits 2
Lines of C added ~6,300
New source files 12
Systems built gear, relic, legendary gear, shards, merchant, chest, altar, scrapper, drop notify
UI screens 7
Save file carved ~500 bytes from filler
Copilot requests 17
Tool executions ~1,270
Sub-agents 8

Next: 02 — The UI Challenge