25回失敗してもBank 0が溢れた。rpg568→594の19時間
GBDK開発発掘記 / 「あと少し削れば通る」を何度も繰り返したBank 0との長期戦
短い修正で抜けられるBank overflowもあれば、何をしてもなかなか抜けられない時期もあります。
rpg568からrpg594までのbuild jobを時系列で並べると、最初のfailedからsuccessまで19時間24分38秒。その間に残っているfailed buildは25回、22個の異なるrpg番号にまたがっています。
警告の中心は同じです。「Warning: Possible overflow from Bank 0 into Bank 1」。target名を見ると、smooth camera、wrapper、world movement、actor描画、enemy names、field overlay、battle UIと、対象を変えながらBank 0を軽くしようとした痕跡が続きます。
最初の記録はrpg568、16:50:03。targetは `rpg568_smooth_chunk_camera_compile_fix.gbc` でした。そこから569 `smooth_camera_bank0_trim`、570 `bank0_edge_call_trim`、571 `bank0_wrapper_trim`、572 `remove_snap_wrapper`、573 `snap_call_fix_bank0_tiny_trim` と続きます。
それでもBank 0→1 overflowは消えません。
build job一覧にはrpg574のjobがなく、次に確認できる575以降もfailedが続きます。575は同じsource snapshotで5秒差の2試行、588と590にも同一targetの複数試行があります。つまり「25回」は版番号の数ではなく、実際に残ったbuild attemptの数です。
この系列はtarget名を読むだけでも、触っていた場所が移っていく様子が見えます。ただし名前だけから修正効果を断定はしません。ここでは「その名前のbuild jobが実在した」という証拠として扱います。
575〜580付近では `world_start_move_extern_fix`、`world_movement_update_bank29`、`update_player_movement_bank29`、`world_area_macro_inline` が並びます。
582〜585では `fix_remaining_world16_refs`、`draw_all_actors_bank29`、`enemy_names_bank31`、`final_tiny_debug_trim`。587以降は `battle_start_noop_fix`、`final_overflow_trim`、`remove_refresh_actor_wrapper`、`remove_field_overlay_show`、`remove_field_overlay_hide`、`remove_battle_ui_wrappers` と続きます。
名前に「final」や「tiny」が入っていても、実際にはまだ終わっていません。588の `final_overflow_trim` もfailedでした。
この区間には、build job一覧上で574、581、586、593がありません。別資料に番号への言及が残るものはありますが、今回の記事では「568から594まで全番号が連続してビルドされた」とは書きません。
確定しているのは、救出したjob群の中に25回のfailed buildがあり、22個のrpg番号に対応していること。そしてその先でrpg594がsuccessになっていることです。
直接比較できる失敗→成功チェーンとして、incident diff集にはrpg592→594が残っています。
rpg592のtargetは `rpg592_remove_battle_ui_wrappers.gbc`。12:05:50にBank 0→1 overflowでfailed。rpg594は12:14:41に `rpg594_actor_visible_macro_fix.gbc` としてsuccessです。
差分サマリでは `main.c` が +4 / -87、`smooth_camera_runtime.c` が +87 / -6。`set_player_frame()`、`move_player_sprite_px()`、`set_actor_frame()`、`move_actor_sprite()`、`hide_actor_sprite()` といった処理がmain.c側から消え、smooth_camera_runtime.c側にstatic関数として入っています。
さらにsuccess側では `actor_visible_in_current_area()` がsmooth_camera_runtime.cに追加され、main.c側には同名用途のmacroが追加されています。diffにはほかの変更も含まれるため、「この5関数を移しただけで直った」とは断定しません。
ただ、実diffとして「main.cから87行規模が減り、smooth_camera_runtime.c側へ87行規模が増えた」ことと、その差分を含むrpg594がsuccessしたことは確認できます。
A078のrpg434はBank 4のmap dataを27へ移しました。A079のrpg443はchest stateの受け渡しを変えました。
rpg568〜594は、それらより長いです。target名にはBank29、Bank31、wrapper removal、macro inline、tiny trimといった別々の試行が並び、最後の直接diffではmain.cからsmooth camera関連処理がまとまって外へ移っています。
完成したrpg594だけを見ると、こうした経過は見えません。25回の失敗jobが残っているからこそ、「Bank 0が限界に近い状態で、機能を別Bankやruntimeへ押し出し続けていた時期」として読めます。
ただしこの表現も、各target名とdiffから観察できる範囲のまとめです。未取得の中間diffについて、具体的な実装内容を想像で補いません。
rpg594はsource ZIP、build log、generated ROM recordまでつながったsuccess jobです。しかし、今回救出したhistorical ROM実体には該当ファイルがありません。
そのため、この記事の3枚も実ROM画面ではありません。25回のbuild timeline、実target名の推移、rpg592→594の実source diffを整理した技術図解です。
このシリーズでは「画像が欲しいから再現画面を歴史ROM扱いする」ことはしません。再現ビルドを行うなら、rebuildとして別管理します。
この履歴を見ると、Bank overflowが出た瞬間だけ記録しても遅いと感じます。
今なら各build jobごとにBank別使用量をCSVへ出し、Bank 0の使用率が一定値を超えた時点で警告します。さらに、どのsource fileがBank 0へ入っているか、前jobから何byte増えたかまで記録します。
そうすれば「final_tiny_trim」と名前を付けながらまだoverflowしている、という状況になる前に、構造的な移動を検討できます。
開発中には嬉しくないログでも、後から見ると非常に価値があります。
rpg568から594まで、同じoverflow警告を抱えながらtarget名とsource snapshotが変わり続け、最後にsuccessへ到達した。この連続性は、完成ROMだけでは復元できません。
失敗を消さずに救出したことで、「何が完成したか」だけでなく「どれだけ通らなかったか」まで開発史として残せました。
Bank overflowは資料が多く記事にしやすい一方、このアーカイブにはlink error、syntax error、duplicate definition、MAKE_BUILD_FAILUREなど別系統の事故もあります。
次はBank地獄から少し離れて、「コードを書いたのにリンクできない」「文法エラー1個でROMが生まれない」といった、より小さくて身近な失敗を拾うとシリーズに変化が出ます。
対象範囲: rpg568〜594の救出build jobs
failed build attempts: 25
failedに対応するunique rpg番号: 22
最初のfailed: rpg568 / 16:50:03
success: rpg594 / 12:14:41
経過: 19時間24分38秒
共通する主要エラー: Warning: Possible overflow from Bank 0 into Bank 1
rpg592→594 diff: smooth_camera_runtime.c +87/-6 / main.c +4/-87
rpg594: generated ROM recordあり / rescued historical ROM実体なし
図版: 実build log・target名・実source diffを基にした技術図解。実ROM画面ではない
編集状態: 初稿 / Technical Review前