feat(banim): Extract battle animation assets from baserom into source files#735
Open
laqieer wants to merge 40 commits intoFireEmblemUniverse:masterfrom
Open
feat(banim): Extract battle animation assets from baserom into source files#735laqieer wants to merge 40 commits intoFireEmblemUniverse:masterfrom
laqieer wants to merge 40 commits intoFireEmblemUniverse:masterfrom
Conversation
Agent: OpenClaw Assistant | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
Agent: OpenClaw Assistant | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
Agent: OpenClaw Assistant | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
Agent: OpenClaw Assistant | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
Agent: banim-scribe | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
Agent: banim-scribe | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
This reverts commit 1636d5d.
Agent: banim-migrator | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
Agent: banim-migrator | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
… Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
…odel: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
… Nightfall | Model: github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
…github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
…ub-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
…gpt-5.1-codex | OpenClaw: 2026.2.25
…ilot/gpt-5.1-codex | OpenClaw: 2026.2.25
… github-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
…ub-copilot/gpt-5.1-codex | OpenClaw: 2026.2.25
…ot/gpt-5.1-codex | OpenClaw: 2026.2.25
…github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.26
…tes to actual 4bpp image data\n- Split 006792A4_Pal_086792A4 into palette and TSA components\n- Rebuilt and verified with checksum\n\nAgent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.26
Records the exploration, batch testing, and root-cause analysis revealing that Banim TSAs rely on multi-to-one shared image tilesets, making them incompatible with the current 1-to-1 png tsa_generator toolchain. Concludes that these binaries must be preserved. Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
These PNGs are strictly for visual reference and preview purposes. As documented in Banim_TSA_Preservation_Report.md, the original .tsa and .4bpp files are non-regeneratable due to multi-frame shared tileset architecture, so these PNGs are NOT used in the build process. Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
Added a section detailing the investigation into the pret/pokeemerald repository. It confirms that retaining raw binary tilemaps (.bin/TSA) is the standard practice in GBA decompilations, as their gbagfx tool also lacks the ability to generate tilemaps from PNGs (only decoding is supported). Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
Reverse-engineered the two animscr binary files into labeled assembly source. Key findings: - NaglfarBG4.bin (6156 bytes) contains interleaved data: 26 OAM sprite arrays for NaglfarBG4, an AnimScr script, then 26 more OAM sprite arrays for DarkBreath_Far. DarkBreath_Far.bin (108 bytes) is just the DarkBreath script referencing OAM data inside NaglfarBG4. - OAM entries use both ANIM_SPRITE and ANIM_SPRITE_AFFIN formats (12 bytes each, distinguished by oam1 == 0xFFFF). - All OAM data verified byte-for-byte identical. Script sections require arm_compressing_linker.py for final label resolution. - Created 52 new AnimSprite labels (AnimSpr_NaglfarOBJ_0..24, AnimSpr_DarkBreathOBJ_0..25) for previously unlabeled OAM arrays. - Full exploration documented in docs/AnimScr_Disassembly_Report.md. Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
- Deleted 007219FC_AnimScr_NaglfarBG4.bin and 00723208_AnimScr_DarkBreath_Far.bin - Replaced their .incbin references in data_banim.s with an .include of the decompiled animscr_naglfarbg4_darkbreath.s - Verified byte-for-byte identical build (sha1sum OK) Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
Agent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.25
Agent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.25
Agent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.25
Removed the following files as they are generated dynamically during build: - graphics/banim/assets/img/006671B0_Img_EfxMagdhisEffectBG_LayerB.4bpp.lz - graphics/banim/assets/tsa/005DDAF4_Tsa_085DDAF4.tsa.lz - graphics/banim/assets/tsa/00603F00_Tsa_EfxElfireBG_Clear.tsa.lz Verified standard 'make' regenerates them natively and sha1sum passes. Agent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.25
Deleted banim_asset_process_log.md as it contained Feishu chat logs not relevant to the PR. Translated banim_asset_extraction.md to English. Agent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.25
Agent: Rennac | Model: github-copilot/gemini-3.1-pro-preview | OpenClaw: 2026.2.25
- Removed 799 .tsa.png preview files (4MB, not needed for build) - Removed redundant AnimScr_Disassembly_Report.md (content consolidated in Banim_AnimScr_Decompilation_Report.md) Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
Resolved conflicts in data_banim.s by keeping the extracted asset paths. This ensures the branch stays in sync with upstream changes while maintaining the extracted banim assets. Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
…merge The upstream master reverted a previous banim sourcing PR, which deleted banim_img_rules.mk (with -num_tiles rules), update_banim_img_rules.py, and the reports directory. Without banim_img_rules.mk, the generic %.4bpp: %.png rule produces incorrect tile counts, causing sha1 mismatch. Build verified: sha1sum OK (c25b145e37456171ada4b0d440bf88a19f4d509f) Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25
Contributor
Author
Build Verification LogBranch: SHA1 VerificationBuild Summary
Last 20 lines of build log (sanitized)Full sanitized build log (12,334 lines) available on request. Agent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR extracts battle animation (banim) graphical assets from raw
baserom.gba.incbindirectives indata/data_banim.sinto individual, trackable source files. It also decompiles two animation script binaries into human-readable assembly source usinganimscr.incmacros.Motivation
The original
data/data_banim.scontained hundreds of.incbin "baserom.gba", offset, sizedirectives that embedded raw ROM data directly. This made the graphical assets opaque, untrackable, and impossible to modify without hex editing the base ROM.Changes
Asset Extraction (~1500 files)
graphics/banim/assets/img/) — 4bpp tile graphics converted to editable PNGsgraphics/banim/assets/pal/) —.pal(text) and.agbpal(binary, for edge-case high-bit palettes)graphics/banim/assets/tsa/) — binary tile arrangement data preserved as-is (see rationale below)Animation Script Decompilation
007219FC_AnimScr_NaglfarBG4.binand00723208_AnimScr_DarkBreath_Far.binintodata/banim/animscr_naglfarbg4_darkbreath.sanimscr.incmacros (anim_sprite,ANIMSCR_FORCE_SPRITE,animscr_loop, etc.).sfile because DarkBreath_Far references OAM arrays stored inside the NaglfarBG4 binary block.incbindirectives with.includeindata/data_banim.s.binfilesBuild System Integration
graphics/banim/assets/img/banim_img_rules.mk— auto-generated Makefile rules for PNG → 4bpp conversion with correct width constraintsgraphics/banim/assets/pal/banim_pal_rules.mk— palette conversion rules (.pal→.gbapal).mkrule files and adds pattern rules for.tsa→.tsa.lzcompressionBuild Artifact Cleanup
.lzintermediate files that were accidentally committed (they are auto-generated by the Makefile%.lz: %rule and already covered by.gitignore)Documentation
docs/banim_asset_extraction.md— extraction workflow, conversion rules, and edge casesdocs/Banim_TSA_Preservation_Report.md— rationale for keeping TSA files as binary (multi-frame shared tilesets prevent lossless PNG round-tripping)docs/Banim_AnimScr_Decompilation_Report.md— animation script decompilation process andarm_compressing_linker.pypipeline analysisUtility Scripts
scripts/generate_anim_script.py— disassembles animation script binaries into labeled.sfiles usinganimscr.incmacrosDesign Decisions
Why TSA files remain binary
Multiple animation frames share a single large tileset (
.4bpp), but each frame has its own.tsamapping into that tileset. Converting a TSA+tileset to PNG and back throughtsa_generator.pydiscards the shared tile indices and reorders them, breaking byte-for-byte reproduction. This is consistent with howpokeemeraldhandles its tilemaps (raw.binfiles). Seedocs/Banim_TSA_Preservation_Report.mdfor the full investigation.Why AnimScr files use
.includeinstead ofarm_compressing_linker.pyThe Naglfar/DarkBreath animation scripts were not LZ-compressed in the original ROM (included via plain
.incbinwithout.lzsuffix). Thearm_compressing_linker.pypipeline is only needed for assets requiring LZ compression. Direct.includelets the standard GNU assembler resolve label relocations natively viaR_ARM_ABS32.Build Verification
make clean && make fireemblem8.gbacompletes successfullysha1sum -c checksum.sha1confirms byte-for-byte match with the original ROMInternal Review Notes
During development, the following review feedback from the human developer (@laqieer) was addressed:
.tsa.lzand.4bpp.lzbuild products.tsa.pngpreview files (4MB) that served no build purposegenerate_animscr_s_v2.py,v3.py)AnimScr_Disassembly_Report.mdinto the decompilation reportAgent: Rennac | Model: github-copilot/claude-opus-4.6 | OpenClaw: 2026.2.25