This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Hard Rebuild and Cycle Diagnosis
Summary
The user reported that he was still seeing the "Red Dot" (old code from step 116) and that LY remained at 0, even though the source code was already updated. Diagnostics indicated that the `.pyd` binary had not been updated correctly on Windows, possibly because Python had the file loaded in memory. A radical solution was implemented: adding a temporary log in C++ to confirm that new code is executed, improving diagnostics in Python to show loops and LCDC, and providing commands to force recompilation on Windows.
Hardware Concept
On Windows, when Python imports a compiled module (`.pyd`), the operating system loads the file into memory. If you try to recompile the module while Python still has the file loaded, Windows may:
- Block writing:The file is in use and cannot be overwritten.
- Allow writing but keep the old version in memory:Python still uses the old version you already loaded.
- Fail silently:The build appears successful, but the file is not updated.
To force the update, you need to:
- Close all Python instancesthat may have the module loaded.
- Rename or delete the old `.pyd` filebefore recompiling.
- Recompile from scratchwith `python setup.py build_ext --inplace`.
Additionally, to diagnose whether the new code is running, we add a temporary log that is printed the first time `PPU::step()` is called. If this log appears, we confirm that the binary was updated correctly.
Implementation
Three main changes were implemented:
1. Temporal Log in PPU C++
Added a temporary log in `PPU::step()` that is printed the first time the method is called. This log confirms that the new code is running:
// TEMPORARY DIAGNOSIS: Confirm that new code is executed
static bool first_call = true;
if (first_call) {
printf("[PPU C++] STEP LIVE - Code updated successfully\n");
first_call = false;
}
Note:This log is temporary and should be deleted after verifying that it works.
2. Cycle Diagnosis in Python
Added a warning to the scanline loop to detect if `line_cycles` is 0, which would indicate that the CPU is not executing instructions:
# DIAGNOSIS: Verify cycles executed on the scanline
if line_cycles == 0:
logger.warning(f"⚠️ WARNING: line_cycles=0 on scanline. CPU may be stopped.")
3. Diagnosis of LCDC in Heartbeat
Improved heartbeat to show the LCDC value (register 0xFF40) and whether the LCD is on or off:
logger.info(
f"💓 Heartbeat ... LY={ly_value} | LCDC=0x{lcdc_value:02X} "
f"(LCD {'ON' if (lcdc_value & 0x80) != 0 else 'OFF'}) "
f"| PPU {'live' if ly_value > 0 or frame_count > 60 else 'initializing'}"
)
This allows you to diagnose if the LCD is off (LCDC=0x00) or if there is another problem.
Commands to Force Recompile in Windows
Commands were provided to force recompilation:
- Close all Python instances(terminals, IDEs, background processes).
- Rename the old `.pyd` file:
ren build\lib.win-amd64-cpython-313\viboy_core.cp313-win_amd64.pyd viboy_core_OLD.pyd - Clean compiled files:
python setup.py clean --all - Recompile:
python setup.py build_ext --inplace
Affected Files
src/core/cpp/PPU.cpp- Added temporary log to confirm execution of new codesrc/viboy.py- Added cycle diagnostics and LCDC in the main loop
Tests and Verification
Verification is done by running the emulator and observing:
- Confirmation log:If `[PPU C++] STEP LIVE - Code updated successfully` appears in the console, the binary was updated successfully.
- White screen:If the framebuffer is correctly initialized to `0xFFFFFFFF`, the screen should be white (no red dot).
- LY moving forward:If LY changes from 0 to higher values, the PPU is working.
- LCDC changing:If LCDC changes from 0x00 to 0x91 (or similar), the game is initializing the LCD.
Test command:
python main.py roms/tetris.gb
Expected validation:
- Log `[PPU C++] STEP LIVE` appears at startup.
- White screen (without red dot).
- Heartbeat shows `LY` moving forward and `LCDC` changing.
Sources consulted
- Windows Documentation: Behavior of DLL/PDY Files in Use
- Pan Docs: LCDC Register (0xFF40) and LCD Control
Educational Integrity
What I Understand Now
- Windows and compiled modules:Windows locks `.pyd` files when they are in use by Python. To update the module, you need to close all Python instances or rename the file before rebuilding.
- New code diagnosis:Adding a temporary log that is printed the first time a method is executed is an effective way to confirm that the binary was updated correctly.
- LCDC and LCD status:The LCDC register (0xFF40) controls whether the LCD is on (bit 7). If the LCD is off, the PPU stops and LY remains at 0.
What remains to be confirmed
- Behavior in other systems:Do Linux and macOS have the same problem with `.so` files in use?
- Build strategy:Should we add a build script that automatically closes Python processes and renames files before building?
Hypotheses and Assumptions
We assume that the problem is that Windows does not allow overwriting `.pyd` files in use. If the problem persists after following these steps, there may be another problem (for example, the compiler is not generating the file in the correct location).
Next Steps
- [ ] Verify that the `[PPU C++] STEP LIVE` log appears when running the emulator
- [ ] Confirm that the screen is white (no red dot)
- [ ] Verify that LY advances correctly
- [ ] Delete the temporary log after confirming that it works
- [ ] Consider adding an automated build script for Windows