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

Debug: CPU Trace Isolation

Date:2025-12-19 StepID:0150 State: 🔍 DRAFT

Summary

The emulator is stable and runs at 60 FPS, but displays a blank screen, indicating that the VRAM is empty. The CPU trace implemented in Step 0149 is being hidden by the repetitive logs of the main Python loop. Main loop debug logs silenced insrc/viboy.pyto isolate and analyze the CPU trace in C++, allowing you to diagnose the empty VRAM problem.

Hardware Concept

When debugging embedded systems and emulators, it is essential to be able to isolate relevant information from the "noise" generated by other components. When multiple subsystems generate logs simultaneously, critical information can get lost in a sea of ​​repetitive messages.

The problem of noise in the logs:In Step 0149, we add diagnostic instrumentation inCPU::step()to plot the first 100 executed instructions. However, the main loop in Python was also generating logs on every call toppu.step()(once per scanline, that is, 154 times per frame). This means that for every CPU instruction that was logged, there were hundreds of Python messages interleaved, making it impossible to read the CPU trace clearly.

The solution: silence non-essential logsIn order to analyze the CPU trace, we need a clean console that displays only the CPU diagnostic messages. The logs from the main Python loop that confirmed thatppu.step()was being called correctly have already served their purpose (confirming that the emulator is stable and running at 60 FPS), so they can now be silenced without losing critical information.

Incremental debugging principle:In systematic debugging, it is common to add logs temporarily to confirm that a component is working, and then silence them when they are no longer needed so you can focus on the next problem. This approach keeps the console clean and focused on the information relevant to the current problem.

Implementation

The lines ofprint()in the methodrun()ofsrc/viboy.pythat generated logs in each call toppu.step(). These lines were added in previous steps to debug the Segmentation Fault, but now that the emulator is stable, they only generate noise that hides the CPU trace.

Modified components

  • src/viboy.py: Commented linesprint()in the methodrun()inside the scanline loop

Changes applied

1. Mute logs from the main loop:

  • Commented linesprint("[Viboy] Calling ppu.step()...")andprint("[Viboy] ppu.step() completed successfully")in the methodrun()
  • Added explanatory comment: "Logs silenced to isolate the CPU trace (Step 0150)"
  • Lines are kept commented out rather than removed to make them easier to reactivate if needed in the future

CPU Instrumentation Verification

It was verified that the diagnostic instrumentation insrc/core/cpp/CPU.cppadded in Step 0149 is still present and working:

  • The static variabledebug_instruction_counteris initialized to 0
  • The constantDEBUG_INSTRUCTION_LIMIT = 100limit the number of logs
  • The logging block inCPU::step()print the format:[CPU TRACE N] PC: 0xXXXX | Opcode: 0xXX

Design decisions

Why comment instead of delete?The debug logs can be useful in the future if we need to double check that the main loop is working correctly. Keeping them commented allows you to quickly reactivate them without having to rewrite them.

Why not use a log level system?For this educational project, keeping the logs simple and commented is enough. A log level system (DEBUG, INFO, WARNING, ERROR) would be more complex and does not add value in this phase of development.

Affected Files

  • src/viboy.py- Commented linesprint()in the methodrun()to silence logs from the main loop

Tests and Verification

Manual verification:

  • The emulator was run withpython main.py roms/tetris.gb
  • The console now shows only the 100 lines of the CPU trace ([CPU TRACE...])
  • No repetitive interleaved main loop logs
  • The trace is readable and allows the CPU execution flow to be analyzed

Expected result:The console should display a clean 100-line sequence in the format:

[CPU TRACE 0] PC: 0x0100 | Opcode: 0xXX
[CPU TRACE 1] PC: 0x0101 | Opcode: 0xXX
...
[CPU TRACE 99] PC: 0xXXXX | Opcode: 0xXX

This trace will allow you to identify exactly what instructions the CPU is executing and at what point it stops or enters an infinite loop, which will help diagnose why VRAM remains empty.

Sources consulted

  • Principles of systematic debugging: Isolating relevant information from noise in logs
  • Logging best practices: Silence temporary logs when they are no longer needed

Note: This step does not require consulting hardware technical documentation, as it is an improvement in the debugging process.

Educational Integrity

What I Understand Now

  • Incremental debugging:Temporarily add logs to confirm that a component is working, then silence them when they are no longer needed so you can focus on the next problem.
  • Information isolation:In complex systems with multiple subsystems generating logs, it is essential to be able to isolate the relevant information from the "noise" to be able to analyze it effectively.
  • Debug code maintenance:Commenting logs instead of deleting them allows you to quickly reactivate them if necessary in the future, without having to rewrite them.

What remains to be confirmed

  • CPU trace analysis:Once the emulator is run and the full trace is captured, it will need to be analyzed to identify which instruction is missing or which loop is blocking execution.
  • Empty VRAM Diagnosis:With the CPU trace, we will be able to determine if the CPU is executing code but not reaching the graphics copy routine, or if it is stuck in an infinite loop before reaching that routine.

Hypotheses and Assumptions

Main hypothesis:The CPU is executing code, but it is probably stuck in a loop or missing a key instruction preventing it from reaching the graphics copy routine from ROM to VRAM. The CPU trace will confirm or refute this hypothesis.

Assumption:The trace will show a repeating pattern (infinite loop) or a sequence of instructions that stops before reaching the graph copy routine. This assumption will be based on the analysis of the trace once it is captured.

Next Steps

  • [ ] Run the emulator and capture the full CPU trace (100 lines)
  • [ ] Analyze the trace to identify the execution pattern
  • [ ] Identify if the CPU is in an infinite loop or if a key instruction is missing
  • [ ] Determine which instruction or routine is missing so the CPU can copy graphics data to VRAM
  • [ ] Implement the necessary correction based on the trace analysis