Step 0478: Run rom_smoke with Timeline IME/EI/DI + Real Loop Disasm

← Return to index

Executive Summary

Step 0477 implemented corrected disassembler and IME/EI/DI timeline. Step 0478 runs rom_smoke with these metrics to classify with evidence Case A/B/C/D, identify exact loop I/O, and confirm clean baseline.

Result:✅ Complete execution with 3 ROMs (baseline OFF) and 1 ROM (prefill ON). ✅ Report generated with tables and automatic decision. ✅ Identified case: mario.gbc (Case A - EI never executed), tetris_dx.gbc (Case D/C - EI executed but IE=0x00). ⚠️ This step DOES NOT modify core code (only execution and reporting).

Hardware Concept

Root Cause Classification (Step 0477)

Step 0477 implemented an automatic classifier that identifies 4 possible cases:

  1. Case A:EI never runs (game is stuck before enabling interrupts)
  2. Case B:EI runs but IME does not go up (bug EI delayed enable)
  3. Case C:IME goes up but IE=0 (game doesn't enable IE or doesn't need it)
  4. Case D:IME+IE OK but there is no service (check request generation)

Fountain:Pan Docs - EI instruction, Interrupt Enable Register (IE)

I/O Source Tagging

Step 0475 implemented source tagging to distinguish IF/IE reads from program code vs internal CPU polling. This allows you to identify if the game is doing manual IF/IE polling or if there is only internal polling.

Implementation

Phase A: Clean Baseline (OFF) with CGB ROMs + DMG Control

rom_smoke was run with the following ROMs using a clean baseline (VIBOY_SIM_BOOT_LOGO=0):

  • tetris_dx.gbc- 240 frames
  • mario.gbc- 240 frames
  • tetris.gb(DMG) - 240 frames (control)

Flags used:

export VIBOY_DEBUG_IO=1
export VIBOY_SIM_BOOT_LOGO=0
export VIBOY_DEBUG_INJECTION=0
export VIBOY_AUTOPRESS=0
export VIBOY_FORCE_BGP=0
export VIBOY_FRAMEBUFFER_TRACE=0

Phase B: Contamination Control (ON) Only 1 ROM

Ran rom_smoke withtetris_dx.gbcusing logo prefill ON (VIBOY_SIM_BOOT_LOGO=1) to show that VRAM/tilemap stats change by prefill and not by the game.

Phase C: Report Generation

The report was generated/tmp/report_step0478.mdwith:

  • Tables per ROM (frames 0/60/120/180) with all minimum fields
  • Disasm hotspot window (frame 180) for each CGB ROM
  • Comparison prefill ON vs OFF (tdx only)
  • Final automatic decision (Case A/B/C/D identified with evidence)
  • Next proposed minimum fix (0479) with register + bit + concrete fix

Results

Automatic Sorting

mario.gbc (Frame 180)

  • Case:A (EI never executed)
  • EIcount = 0
  • ime_set_events_count = 0
  • EMI = 0
  • IE = 0x00
  • if_reads_program = 6603703vsif_reads_cpu_poll = 6602862✅ (The game IS polling IF from code)
  • fb_nonzero = 0(No progress)

Analysis:The game never runs EI, it's stuck in a loop waiting for some condition that is never met. The disasm shows a simple loop with no directly visible I/O, but the massive IF polling suggests that it is waiting for IF to change.

tetris_dx.gbc (Frame 180)

  • Case:D with elements of C (EI executed but IE=0x00)
  • EIcount = 2✅ (THE YES was executed)
  • ime_set_events_count = 2✅ (IME WAS enabled)
  • EMI = 0❌ (But IME is 0 in the snapshot)
  • IE = 0x00❌ (IE stays at 0x00)
  • if_reads_program = 8762209vsif_reads_cpu_poll = 8761604✅ (The game IS polling IF from code)
  • fb_nonzero = 6409(Partial progress)

Analysis:EI ran and IME was enabled, but IE remains at 0x00. The game wrote to IE 7 times but IE is still at 0x00. There is partial progress (non-blank framebuffer), which suggests that the game made more progress than mario.gbc, but it is still stuck waiting for interrupts that never arrive because IE=0x00.

tetris.gb (DMG - Control - Frame 180)

  • Case:Works correctly
  • EMI = 1
  • IE=0x09
  • LastIRQVec = 0x0040✅ (IRQs served)
  • VBlankServ = 179

Analysis:tetris.gb (DMG) works correctly, confirming that the problem is specific to CGB or the initialization sequence of these CGB games.

Loop Disasm (Frame 180)

tetris_dx.gbc

PC_hotspot1: 0x1308

0x1308: JR NZ, 0x1302 (-8)
0x130A: RET
0x130B: DB 0x21
0x130C: DB 0x70
0x130D: DB 0x13
0x130E: CALL 0x12C9
0x1311: CALL 0x12FF
0x1314: LDH A,(JOYP) ← Current PC dialed

I/O identified:The loop containsLDH A,(JOYP)at 0x1314. The game is doing millions of IF reads (8.7M from code), probably inside CALL functions.

mario.gbc

PC_hotspot1: 0x12A0

0x12A0: DB 0x0B
0x12A1: DB 0x79
0x12A2: DB 0xB0
0x12A3: JR NZ, 0x129D (-8)
0x12A5: RET
0x12A6: DB 0x21
0x12A7: DB 0xFF
0x12A8: DB 0x9B

I/O identified:The loop is simple with a conditional jump. The code is in a data zone. The game is doing millions of IF reads (6.6M from code) even though it is not directly visible in this fragment.

Next Steps (Step 0479)

For mario.gbc (Case A)

  • The game never runs EI. We need to identify what condition you are waiting for before executing EI.
  • Disassemble the complete code around 0x12A0 to see what condition is being evaluated.
  • Hypothesis:The game is waiting for some I/O register (IF, STAT, LY, or JOYP) to have a specific value before continuing.

For tetris_dx.gbc (Case D/C)

  • EI ran and IME was enabled, but IE remains at 0x00.
  • The game wrote to IE 7 times but IE is still at 0x00.
  • Hypothesis:Writes to IE are being lost or overwritten.
  • Specific fix:
    • Instrument writes to IE with PC and value (we already have IEWritePC and IEWriteVal, but we need to check if those writes persist).
    • Check if there is code that reads IE and then writes it with 0x00.
    • Find patternsLDH A,(0xFFFF)followed byLDH (0xFFFF),Awith A=0x00.

Affected Files

  • /tmp/report_step0478.md- Complete report with tables and automatic decision
  • /tmp/viboy_0478_tdx_off.log- Tetris_dx.gbc log (baseline OFF)
  • /tmp/viboy_0478_mario_off.log- Mario.gbc log (baseline OFF)
  • /tmp/viboy_0478_tetris_off.log- Tetris.gb log (baseline OFF)
  • /tmp/viboy_0478_tdx_on.log- Tetris_dx.gbc log (prefill ON)

⚠️ IMPORTANT:This step DOES NOT modify core code. Just run rom_smoke and generate report based on the metrics implemented in Step 0477.

Tests and Verification

Command executed: python3 tools/rom_smoke_0442.py <ROM> --frames 240

Result:✅ All ROMs completed without crashes. ✅ Snapshots generated correctly in frames 0/60/120/180. ✅ IME/EI/DI timeline metrics available. ✅ Disasm window functional.

Validation:The logs contain snapshots with all the minimum required fields (PC, PC_hotspot1, IME, IE, EIcount, DIcount, if_reads_program, ie_reads_program, disasm_window, etc.).