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

Critical Debug: The "Checkerboard Test" to Validate the Data Pipeline

Date:2025-12-20 StepID:0192 State: 🔍 DRAFT

Summary

We have reached a critical point. Despite having a fully synchronized and functional emulation core, the screen remains blank. The main hypothesis is that although the C++ PPU might be rendering correctly to its internal framebuffer, this data is not reaching the Python layer via the Cython bridge (`memoryview`).

This Step implements a "Checkerboard Test": temporarily modify `PPU::render_scanline()` so that it ignores all emulation logic and draws a checkerboard pattern directly into the framebuffer. This will allow us to unambiguously validate whether the C++ → Cython → Python data pipeline is working.

Engineering Concept: Data Pipe Isolation and Testing

When a complex system fails, the best debugging strategy isisolation. Let's isolate the rendering "pipeline" from the rest of the emulator. If we can write data to a `std::vector` in C++ and read it into a `PixelArray` in Python, then the pipeline works. If not, the pipe is broken.

The checkerboard pattern is ideal because it is:

  • Visually unmistakable:A checkerboard is impossible to confuse with any other pattern.
  • Easy to generate mathematically:It does not require access to VRAM, tiles, or any other emulator component.
  • Deterministic:If the pipeline works, we'll see the pattern. If it doesn't work, we will see a white screen.

This test will give us a binary and definitive answer about where the problem is:

  • If we see the checkerboard:The pipe works. The problem is in the VRAM (the CPU is not copying the logo data).
  • If the screen is still blank:The pipe is broken. The problem is in the Cython wrapper or how the framebuffer is exposed.

Implementation

We temporarily modified `PPU::render_scanline()` to replace all rendering logic with a simple checkerboard pattern generator.

Modified components

  • src/core/cpp/PPU.cpp: Methodrender_scanline()replaced with checkerboard logic

Checkerboard Logic

The pattern is generated line by line:

// For each pixel (x, y) on the current line:
bool is_dark = ((ly_ / 8) % 2) == ((x / 8) % 2);
uint8_t color_index = is_dark ? 3 : 0;
framebuffer_[line_start_index + x] = color_index;

This logic divides the screen into blocks of 8x8 pixels. If both the row and column of the block are odd or even, the block is dark (color 3). If one is even and the other odd, the block is light (color 0).

Design decisions

  • Ignore all PPU logic:We do not read LCDC, VRAM, tiles, or any other register. This removes all possible variables except the data pipe.
  • Use colors 0 and 3:Color 0 (white) and color 3 (black) are the extremes of the palette, which makes the pattern more visible.
  • 8x8 pattern:It matches the size of the Game Boy tiles, making the pattern more recognizable to developers familiar with the hardware.

Affected Files

  • src/core/cpp/PPU.cpp- Methodrender_scanline()replaced with checkerboard test
  • docs/bitacora/entries/2025-12-20__0192__debug-critical-test-checkerboard-validate-pipe-data.html- New log entry
  • docs/bitacora/index.html- Updated with new entry
  • REPORT_PHASE_2.md- Updated with Step 0192

Tests and Verification

This test is purely visual. It does not require unit tests, since we are validating the complete integration of the system.

Verification Process

  1. Recompile the C++ module:
    .\rebuild_cpp.ps1
  2. Run the emulator:
    python main.py roms/tetris.gb
  3. Observe the Pygame window:The window should show one of two possible results.

Possible Results

Result 1: We see a Chess Board

Meaning:Data pipeline works! C++ is writing, Cython is exposing, and Python is reading and drawing.

Diagnosis:The problem, then, is 100% that theVRAM is really empty. The CPU, for some reason we don't yet understand, is not copying the logo data.

Next Step:We would re-instrument the CPU to understand why its execution path does not reach the DMA/VRAM copy routine.

Result 2: Screen Still Blank

Meaning:The data pipe is broken! The C++ PPU is generating the pattern, but it never reaches the screen.

Diagnosis:The problem is in our Cython wrapper (ppu.pyx), specifically how we expose the framebuffer pointer and convert it to amemoryview.

Next Step:We would debug the Cython interface, verifying:

  • Framebuffer pointers
  • memoryview data types
  • The life cycle of the memoryview (if it is being invalidated between frames)
  • Synchronization between writing in C++ and reading in Python

C++ Compiled Module Validation

The emulator uses the compiled C++ module (viboy_core), which contains the modified implementation ofPPU::render_scanline()with the checkerboard test.

Sources consulted

  • Cython documentation:Memoryviews vs Zero-Copy
  • Principles of Debugging Complex Systems: Isolation and Integration Testing

Educational Integrity

What I Understand Now

  • Component isolation:When a complex system fails, the best strategy is to isolate each component and test it individually.
  • Data pipeline validation:In a hybrid Python/C++ system, it is critical to validate that data flows correctly across the layers (C++ → Cython → Python).
  • Debugging patterns:A simple, deterministic visual pattern (like a checkerboard) is more valuable for debugging than a complex pattern that could fail for multiple reasons.

What remains to be confirmed

  • Data pipeline status:Is the C++ framebuffer correctly reaching Python via Cython's memoryview?
  • If the pipe works:Why isn't the CPU copying the logo data to VRAM?
  • If the pipe is broken:Where exactly is the connection broken? In the pointer, in the memoryview, or in synchronization?

Hypotheses and Assumptions

Main hypothesis:The problem is in the data pipeline between C++ and Python. Although the PPU might be rendering correctly to its internal framebuffer, this data is not reaching the Python layer.

Assumption:If the checkerboard test works, then we know the pipeline is fine and the problem is with the CPU/VRAM emulation. If it doesn't work, then we know that the problem is with the Cython wrapper.

Next Steps

  • [ ] Run the emulator with the checkerboard test
  • [ ] Observe the visual result (checkerboard or white screen)
  • [ ] If we see checkerboard:Instrument the CPU to understand why it is not copying data to VRAM
  • [ ] If we see white screen:Debug the Cython wrapper and the framebuffer memoryview
  • [ ] Restore the original logicrender_scanline()once the problem is identified