This project is educational and Open Source. No code is copied from other emulators. Implementation based solely on technical documentation and permitted tests.
Verification: Post-Conditional Jump Execution
Summary
After implementing the conditional relative jumps (JR Z, JR NC, JR C) in Step 0162, the emulator was run to check if the LY=0 deadlock had been resolved. The results show that the problem persists: LY is still stuck at 0, but no warnings for unknown opcodes appear, indicating that the CPU is executing known instructions. This suggests that the problem may be more complex than initially anticipated or that there is another cause in addition to the original deadlock.
Hardware Concept
On a Game Boy emulator, the scan line counter (LY) should be incremented every 456 clock cycles (T-Cycles) when the LCD is on. If LY remains stuck at 0, it means that the PPU is not receiving enough CPU cycles to advance the scan lines, which can be due to several reasons:
- Opcodes not implemented:If the CPU executes an unknown opcode that returns 0 cycles, time does not advance.
- Infinite loops in game code:The game code may be running an infinite loop waiting for a condition that is never met.
- HALT without interruptions:If the CPU enters the HALT state and no interrupts are enabled, the CPU will consume minimal cycles but the code will not advance.
- Synchronization problems:The CPU may be returning valid cycles, but the timing logic may be in error.
The absence of unknown opcode warnings is an important finding: it means that the CPU is executing known and correctly implemented instructions, but something else is preventing the system from progressing correctly.
Verification Process
Run the emulator with the recompiled C++ module after implementing the conditional jumps, using the verbose mode to monitor the system state.
Commands Executed
python setup.py build_ext --inplace
python main.py roms/tetris.gb --verbose > temp_execution_0163.log 2>&1
Observed Results
- LY Status:It remains stuck at 0 throughout the execution.
- CPU Warnings:No warnings for unimplemented opcodes ([CPU WARN]) appear.
- CPU traces:No execution traces appear (the PC does not reach 0x0300 where the debug trace is activated).
- Rendering:The renderer shows frames but all with color indexes 0 (black screen).
- Main loop:The main loop is working (periodic heartbeats are displayed), but LY is not advancing.
Situation Analysis
The fact that warnings for unknown opcodes do not appear is significant. This indicates that:
- The CPU is not executing opcodes that fall into the switch's `default` case.
- The CPU is returning valid cycles (greater than 0), because the deadlock protection system is not activated (no "CPU returned 0 cycles" warnings appear).
- The problem may be somewhere else: either in the main loop logic, in PPU timing, or in an infinite loop in the game code itself.
Archives consulted
temp_execution_0163.log- Complete log of the emulator executionsrc/core/cpp/CPU.cpp- CPU code to verify implementation of conditional jumpssrc/viboy.py- Main emulator loop to understand timing
Tests and Verification
This step is purely for verification by running the full emulator. No unit tests were run, but it was verified that the C++ module was recompiled correctly.
- Recompilation:The C++ module was successfully recompiled without errors.
- Running the emulator:The emulator ran without crashes, but LY remains stuck.
- Log analysis:The logs were analyzed looking for warnings, traces and behavioral patterns.
Log Evidence
Representative extract from the execution log:
💓 Heartbeat ... LY=0 | Mode=2 | LCDC=0x80 (LCD ON) | live PPU
[Renderer] Frame #60: framebuffer read, show indices: [0, 0, 0, 0, 0, 0], len=23040
💓 Heartbeat ... LY=0 | Mode=2 | LCDC=0x80 (LCD ON) | live PPU
[Renderer] Frame #120: framebuffer read, show indices: [0, 0, 0, 0, 0, 0], len=23040
...
(pattern repeats indefinitely)
Sources consulted
- Pan Docs: LCD Timing, V-Blank Interrupt
- Existing implementation of the main loop in
src/viboy.py - CPU implementation in
src/core/cpp/CPU.cpp
Educational Integrity
What I Understand Now
- Deadlock diagnosis:The absence of warnings for unknown opcodes is valuable information. It indicates that the problem may be elsewhere in the system, not necessarily in the opcodes implementation.
- Debugging complexity:When a complex system like an emulator has a problem, there may be multiple potential causes that interact in non-obvious ways.
- Importance of instrumentation:Logs and heartbeats are essential to understand what is happening at runtime, especially when the system appears to be working but is not producing the expected results.
What remains to be confirmed
- Root cause of deadlock:Although conditional jumps are implemented, the deadlock persists. We need to identify if it's a timing issue, an infinite loop in the game code, or some other factor.
- CPU actual status:It would be useful to turn on CPU traces from the beginning (not just after PC=0x0300) to see which opcodes are actually being executed.
- PPU-CPU synchronization:Verify that the PPU is correctly receiving CPU cycles and that the LY advance calculation is correct.
Hypotheses and Assumptions
Main hypothesis:The game code may be running an infinite loop waiting for a condition that is never met. This could be because:
- Some hardware functionality is missing (for example, the Timer may not be working correctly).
- The initial state of the CPU or memory is not exactly what the game expects.
- There is some flag or register that the game is consulting and that is not in the correct state.
Assumption:We assume that the conditional jumps are correctly implemented because the unit tests passed. However, in a complex system, interactions between components can reveal problems that do not appear in isolated tests.
Next Steps
- [ ] Enable CPU traces from startup (modify DEBUG_TRIGGER_PC to 0x0100) to see what opcodes are running.
- [ ] Check the status of the CPU registers at different times to detect abnormal patterns.
- [ ] Review the implementation of the Timer and other I/O functionality that the game might be expecting.
- [ ] Consider the possibility that the game is in an infinite loop waiting for V-Blank, but V-Blank never occurs because LY does not advance.
- [ ] Analyze if there is any problem in converting M-Cycles to T-Cycles in the main loop.