⚠️ 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.

GPS Monitor (The Navigator)

Date:2025-12-22 StepID:0240 State: VERIFIED

Summary

After overcoming the Echo RAM loop in0x2B30, the emulator runs stable at 60 FPS, but the screen it still shows only the background color (light green). To diagnose the current state of the CPU without overloading the console with massive logs, aGPS monitor (Navigator)that reports periodically the position of the Program Counter (PC), the Stack Pointer (SP), the status of the interrupts (IME, IE, IF) and the video status (LCDC, LY).

The monitor activates every 60 frames (approximately once per second) and displays critical information of system status in a compact format:[GPS] PC:XXXX | SP:XXXX | IME:X | IE:XX IF:XX | LCDC:XX LY:XX. This allows you to identify whether the CPU is stuck in a loop, waiting for interrupts, or executing code normally.

Hardware Concept

Non-Intrusive Diagnosis: In embedded systems and emulators, it is crucial to be able to observe the internal state of the system without modifying its behavior. A periodic monitor (GPS) allows you to track the execution position and the state of critical registers without affecting the timing of the emulator.

Key Records for Diagnosis:

  • PC (Program Counter): Indicates where the CPU is executing code. If the PC is fixed or in a small loop the CPU may be stuck waiting for a condition.
  • SP (Stack Pointer): Indicates the position of the battery. An SP that does not change may indicate that no function calls or interrupts are being made.
  • IME (Interrupt Master Enable): Indicates whether interrupts are enabled globally. If IME=0 and the CPU is HALT, the system may be waiting for an interrupt that will never arrive.
  • IE (Interrupt Enable, 0xFFFF): Indicates which interrupts are enabled (VBlank, LCD STAT, Timer, Serial, Joypad).
  • IF (Interrupt Flag, 0xFF0F): Indicates which interrupts are pending. If an interruption is pending but IME=0, the CPU will not process it.
  • LCDC (LCD Control, 0xFF40): Controls the status of the LCD. If bit 7 is off, the LCD is off and nothing will render.
  • LY (Line Y, 0xFF44): Indicates the current scanline (0-153). If LY is fixed, the PPU can be stuck

Sampling Frequency: Reporting every 60 frames (1 second at 60 FPS) is a balance between get enough information and not clutter the console. This frequency allows fast loops to be detected without generate thousands of log lines.

Fountain: Bread Docs -CPU Registers, Interrupts, LCDC.

Implementation

The GPS monitor is implemented in the methodrun()ofsrc/viboy.py, just after increase offrame_count. It is activated whenframe_count %60 == 0(every 60 frames).

Components created/modified

  • src/viboy.py: Added GPS diagnostic block in methodrun()who reads and shows CPU, interrupt and video status every second.

Design decisions

  • Sampling Rate: 60 frames (1 second) is enough to detect problems without clutter the console. It can be easily adjusted by changing the module.
  • Compact format: The format[GPS] PC:XXXX | SP:XXXX | IME:X | IE:XX IF:XX | LCDC:XX LY:XXIt is easy to read and parse visually.
  • Dual Compatibility: The code supports both the C++ core and the Python fallback, reading logs appropriately depending on the active mode.
  • Non intrusive: The monitor only reads values, it does not modify the system state. This guarantees which does not affect the behavior of the emulator.

Implemented code

# --- Step 0240: GPS Monitor (Navigator) ---
# Reports CPU position and hardware status every second (60 frames)
if self.frame_count % 60 == 0:
    if self._use_cpp and self._regs is not None and self._cpu is not None and self._mmu is not None:
        # Read CPU registers
        pc = self._regs.pc
        sp = self._regs.sp
        ime = self._cpu.get_ime()
        
        # Read interrupt logs
        ie = self._mmu.read(0xFFFF) # Interrupt Enable
        if_register = self._mmu.read(0xFF0F) # Interrupt Flag
        
        # Read video logs
        lcdc = self._mmu.read(0xFF40) # LCD Control
        ly = self._ppu.ly if self._ppu is not None else self._mmu.read(0xFF44) # LY (current scanline)
        
        # Format: [GPS] PC:XXXX | SP:XXXX | IME:X | IE:XX IF:XX | LCDC:XX LY:XX
        print(f"[GPS] PC:{pc:04X} | SP:{sp:04X} | IME:{ime} | IE:{ie:02X} IF:{if_register:02X} | LCDC:{lcdc:02X} LY:{ly:02X}")
    elif not self._use_cpp and self._cpu is not None and self._mmu is not None:
        # Fallback for Python mode
        pc = self._cpu.registers.get_pc()
        sp = self._cpu.registers.get_sp()
        ime = 1 if self._cpu.ime else 0
        
        ie = self._mmu.read(0xFFFF)
        if_register = self._mmu.read(0xFF0F)
        
        lcdc = self._mmu.read(0xFF40)
        ly = self._ppu.ly if self._ppu is not None else self._mmu.read(0xFF44)
        
        print(f"[GPS] PC:{pc:04X} | SP:{sp:04X} | IME:{ime} | IE:{ie:02X} IF:{if_register:02X} | LCDC:{lcdc:02X} LY:{ly:02X}")
# -------------------------------------------------

Affected Files

  • src/viboy.py- Added GPS monitor block in methodrun()(lines 942-970)
  • docs/bitacora/entries/2025-12-22__0240__monitor-gps-navegador.html- Log entry
  • REPORT_PHASE_2.md- Update with Step 0240
  • docs/bitacora/index.html- Added entry to index

Tests and Verification

The implementation was validated by running the emulator with Tetris and observing the GPS logs:

  • Manual execution: python main.py roms/tetris.gb
  • Expected result: Lines[GPS]appearing every second on the console with system status information.
  • Validation: The displayed values ​​must be consistent:
    • PC must be in a valid range (0x0100-0xFFFF for game code, 0x0000-0x00FF for interrupts).
    • SP must be in a valid range (typically 0xC000-0xDFFF for WRAM or 0xFFFE-0xFFFF for HRAM).
    • LCDC bit 7 must be set (0x80 or higher) for the LCD to be on.
    • LY should change between 0-153 if the PPU is working.

Interpretation of logs:

  • If the PC is set to a small value (ex:0x02xx), the game may be in initialization.
  • If the PC is in0xFFxx(HRAM), may be running a high-speed (DMA) routine.
  • If the PC jumps between different values ​​a lot, the game is executing code normally.
  • If LCDC bit 7 is disabled (value< 0x80), el LCD está apagado y no se renderizará nada.

Sources consulted

Educational Integrity

What I Understand Now

  • Non-intrusive diagnosis: A periodic monitor allows you to observe the status of the system without modifying its behavior, which is crucial for debugging emulators without introducing side effects.
  • Critical records: PC, SP, IME, IE, IF, LCDC and LY are sufficient to determine whether the system is working properly or stuck in a loop.
  • Sampling Rate: Reporting every second (60 frames) is a balance between obtain enough information and not saturate the console with massive logs.

What remains to be confirmed

  • CPU actual status: GPS logs will reveal if the CPU is executing code usually waiting for interruptions, or stuck in a loop.
  • LCD status: If LCDC bit 7 is off, the LCD is off and will not render nothing, which would explain the green screen.
  • Interruptions: If there are pending interrupts (IF) but IME is disabled, the CPU may be waiting for interrupts to fire.

Hypotheses and Assumptions

We assume that the GPS monitor does not affect the timing of the emulator because it only reads values ​​and does not modify the state. If the logs reveal that the PC is stuck or in a small loop, we will investigate what condition it is waiting for. the CPU.

Next Steps

  • [ ] Run the emulator with Tetris and observe the GPS logs.
  • [ ] Analyze PC values ​​to determine if the CPU is executing code normally or is stuck.
  • [ ] Check the LCDC status to confirm whether the LCD is on.
  • [ ] If the PC is fixed, investigate what condition the CPU is waiting for (interrupts, state changes, etc.).
  • [ ] If the LCD is off (LCDC bit 7 = 0), investigate why the game does not turn it on.