⚠️ Clean-Room / Educational

This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.

Live STAT/LYC Diagnosis

Date:2025-12-18 StepID:0073 State: draft

Summary

Added real-time diagnostic instrumentation to detect LYC and STAT settings, and to identify when the PPU detects active STAT interrupt signals. The goal is to diagnose why games like Pokémon and Tetris freeze on the logo: logs show many interruptions V-Blank (0x0040) but no STAT interrupt (0x0048), suggesting the game expects an interrupt STAT (LY=LYC) to animate the logo but it is not firing.

Hardware Concept

The Game Boy may generate STAT (LCD Status) interrupts when certain related conditions are met. with the status of the PPU. One of these conditions is theLYC=LY match: when registration LY (Current Line) matches the LYC (LY Compare) register, an interrupt may be generated if bit 6 STAT register is active.

Many games use this feature to animate the logo during the intro: they set LYC to a specific value (e.g. line 144 for V-Blank or a visible line for special effects), enable interrupt STAT in IE (bit 1) and in STAT (bit 6), and wait for the interrupt to fire to update the graphics.

If the STAT interrupt is not fired, the game waits indefinitely in a loop, causing the screen freezes on the logo.

Fountain:Pan Docs - LCD Status Register (STAT), LYC Register, STAT Interrupt

Implementation

Diagnostic instrumentation was added at three key points in the system:

1. Instrumentation in MMU (writes to LYC and STAT)

Insrc/memory/mmu.py, added informative logs when the game writes to:

  • LYC (0xFF45):The written value is recorded with the log👁️ LYC SET: {value}
  • STAT (0xFF41):The written value and which interrupt bits are enabled are recorded:
    • Bit 3: H-Blank Interrupt Enable
    • Bit 4: V-Blank Interrupt Enable
    • Bit 5: OAM Search Interrupt Enable
    • Bit 6: LYC=LY Coincidence Interrupt Enable

2. Instrumentation in PPU (active STAT signal detection)

Insrc/gpu/ppu.py, in the method_check_stat_interrupt(), logs were added when An active STAT signal is detected by any of the conditions:

  • LYC Match:When LY == LYC and STAT bit 6 is active
  • H-Blank:When the mode is Mode 0 and STAT bit 3 is active
  • V-Blank:When the mode is Mode 1 and STAT bit 4 is active
  • OAMSearch:When the mode is Mode 2 and STAT bit 5 is active

The log includes complete information: PPU mode, current LY, configured LYC, STAT value, and what condition activated the signal.

3. Interrupt Dispatcher Verification

It was verified that the interrupt dispatcher insrc/cpu/core.pycorrectly check bit 1 of IF for the STAT interrupt and jumps to vector 0x0048. The implementation is correct and follows the priority of hardware interrupts (V-Blank has higher priority than STAT).

Design decisions

Logs were added with levelINFOso that they are visible during normal emulator execution. This allows problems to be diagnosed in real time without the need to activate DEBUG logging, which can be very verbose.

Affected Files

  • src/memory/mmu.py- Added instrumentation for writes to LYC (0xFF45) and STAT (0xFF41)
  • src/gpu/ppu.py- Added instrumentation for detection of active STAT signal in_check_stat_interrupt()

Tests and Verification

This is an implementation ofdiagnosis, not new functionality. The instrumentation was added to help identify why games freeze.

Next steps for verification:

  • Executepython main.py pkmn.gbeitherpython main.py tetris_dx.gbc
  • Search the logs:
    • If it appears👁️LYC SET: The game is setting up LYC
    • If it appears👁️ STAT WRITE: The game is setting STAT
    • If it appears🚨 STAT SIGNAL ACTIVE: The PPU detects the event
    • If the above appears but does NOT appear⚡ INTERRUPT DISPATCHED! Vector: 0048: The fault is in the interrupt dispatcher (CPU)

State: draft- Pending execution and analysis of logs to identify the exact problem.

Sources consulted

Educational Integrity

What I Understand Now

  • STAT Interrupts:The Game Boy can generate interruptions when conditions are met specifics related to the status of the PPU (mode, LYC=LY, etc.).
  • LYC=LY Coincidence:When LY matches LYC, an interrupt can be generated if the STAT bit 6 is active. This is useful for synchronizing graphic updates with specific lines.
  • Rising Edge Detection:STAT interrupts are fired at "rising edge", i.e. only when the condition goes from False to True, not while it remains True.
  • Interrupt Priority:V-Blank has higher priority than STAT. If both are pending, V-Blank is processed first.

What remains to be confirmed

  • Game settings:Is the game setting LYC and STAT correctly? The logs will tell us if the game writes to these logs.
  • Signal detection:Is the PPU detecting the LY==LYC match? The logs will tell us if the STAT signal is activated.
  • Interrupt dispatcher:Is the dispatcher checking IF bit 1 correctly? We've already checked the code and it seems correct, but the logs will confirm if the interrupt is triggered.
  • Enablement in IE:Is the game enabling STAT interrupt in IE (bit 1)? If not enabled in IE, the interrupt will not be processed even if IF has the bit set.

Hypotheses and Assumptions

Main hypothesis:The game is setting LYC and STAT correctly, but the interruption STAT is not firing because:

  • The PPU is not detecting the LY==LYC match (problem in_check_stat_interrupt())
  • The game is not enabling STAT interrupt in IE (bit 1)
  • There is an issue with rising edge detection that prevents it from triggering multiple times

The logs will tell us exactly where the problem is.

Next Steps

  • [ ] Run the emulator with a ROM (pkmn.gb or tetris_dx.gbc) and analyze the logs
  • [ ] Identify if the game configures LYC and STAT (search👁️LYC SETand👁️ STAT WRITE)
  • [ ] Identify if the PPU detects the STAT signal (search🚨 STAT SIGNAL ACTIVE)
  • [ ] Identify if the STAT interrupt is triggered (search⚡ INTERRUPT DISPATCHED! Vector: 0048)
  • [ ] Correct the problem identified in the logs
  • [ ] Verify that the game no longer freezes and progresses correctly