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

Restore Rendering Hack for LCDC=0x80

Date:2025-12-18 StepID:0058 State: draft

Summary

Verified and reinforced the "Educational Hack" that allows the background to be drawn even when LCDC Bit 0 is off (LCDC=0x80). This hack is necessary because games like Pokémon Red write LCDC=0x80 waiting for the background to be drawn (CGB behavior), but our emulator acts as strict DMG and would turn it off. A comment was added more explicit confirming that there are no conditions blocking rendering when Bit 0 is off.

Hardware Concept

The LCDC register (LCD Control, 0xFF40) controls the state of the LCD and graphic layers of the Game Boy. Bit 7 controls whether the LCD is on or off, and Bit 0 controls whether the background is enabled.

On Game Boy Classic (DMG), when Bit 0 is off, the background is not drawn. However, on Game Boy Color (CGB), Bit 0 has a different behavior: it does not completely turn off the background, but it changes the priority of sprites vs background. Many CGB games write LCDC=0x80 (LCD ON, BG OFF) waiting for the background to be drawn anyway.

For compatibility with these games, we implemented an "Educational Hack" that ignores Bit 0 and draws the background whenever the LCD is on (Bit 7=1). This hack is temporary and will replace when we implement full CGB mode.

Fountain:Pan Docs - LCD Control Register, Game Boy Color differences

Implementation

It was verified that the educational hack was correctly implemented in the methodrender_frameofsrc/gpu/renderer.py. The hack was already present (documented on lines 281-300), but a more explicit comment was added confirming that there is no condition that blocks rendering when Bit 0 is off.

Changes made

  • Reinforced comment:Added explicit comment (lines 300-304) which confirms that the code continues directly to draw the background without any conditions which locks it when Bit 0 is off.
  • Updated documentation:Updated the hack documentation to specifically mention Pokémon Red as an example of a game that requires this behavior.

Relevant code

The educational hack is implemented insrc/gpu/renderer.py, lines 281-304. The original code that blocked rendering when Bit 0=0 is commented out (lines 294-298), and the code continues directly to draw the background without checking Bit 0.

# EDUCATIONAL HACK: Ignore Bit 0 of LCDC (BG Display)
# On Game Boy Color, Bit 0 does not turn off the background, but rather changes the priority
# of sprites vs background. Pokémon Red and other games write LCDC=0x80 (bit 7=1, bit 0=0)
# waiting for the background to be drawn (CGB behavior), but our emulator acts like
# DMG strict and would turn it off. To unlock the display, we ignore the
# Bit 0 and we draw the background whenever the LCD is on (Bit 7=1).

# CRITICAL: Ensure that the background is drawn whenever LCD is on (Bit 7=1),
# regardless of the state of Bit 0. This hack allows games like Pokémon Red
# that write LCDC=0x80 can display graphics correctly.
# There is no render-blocking condition here - the code continues
# directly to draw the background.

Affected Files

  • src/gpu/renderer.py- Added explicit comment confirming that the hack is correctly implemented (lines 300-304)

Tests and Verification

State:Draft - Pending verification with Pokémon Red

The change is purely documentary (comment added). The educational hack was already implemented correctly. However, if the screen is still blue in Pokémon Red, the problem could be:

  • LCD turns off after writing 0x80:The game could be turning off the LCD after writing it, or there could be a problem with the reading of the LCDC registry.
  • Timing problem:The game could be waiting for an interruption V-Blank before configuring graphics, and our emulator might not be generating these interruptions correctly.
  • VRAM problem:The tilemap or tiles may not be loaded correctly in VRAM, resulting in a white or blue screen even if the background is being drawn.

Next steps for verification:

  • Run Pokémon Red and check if the screen is still blue
  • If still blue, check LCDC register status during execution
  • Verify if V-Blank interrupts are being generated correctly
  • Check VRAM and tilemap contents when trying to render

Sources consulted

Educational Integrity

What I Understand Now

  • Educational Hack:Hack that ignores LCDC Bit 0 is correct implemented. There is no condition that blocks rendering when Bit 0 is set. off. The code continues directly to draw the background as long as the LCD is on (Bit 7=1).
  • CGB vs DMG Behavior:On Game Boy Color, LCDC Bit 0 has a different behavior than in DMG. Many CGB games write LCDC=0x80 waiting let the background be drawn anyway.

What remains to be confirmed

  • Blue screen in Pokémon Red:If the screen remains blue after this change, the problem is not the educational hack (which is already correctly implemented), but something else: the LCD could be turning off after writing it, there could be a problem with V-Blank interrupts, or there could be a problem with the contents of VRAM.
  • Interrupt Timing:We need to check if the interruptions V-Blanks are being generated correctly and if the game is waiting for these interrupts before configuring the graphics.

Hypotheses and Assumptions

Hypothesis:The educational hack is correctly implemented. If the screen is still blue, the problem is that the LCD is turning off after writing 0x80, or there is a problem with V-Blank interrupts or VRAM contents.

Assumption:The educational hack is temporary and will be replaced when we implement full CGB mode. For now, it is necessary so that games like Pokémon Red can show graphics correctly.

Next Steps

  • [ ] Run Pokémon Red and check if the screen is still blue
  • [ ] If still blue, check the status of the LCDC register during execution (temporary registration)
  • [ ] Check if V-Blank interrupts are being generated correctly
  • [ ] Check VRAM and tilemap contents when trying to render
  • [ ] If the problem persists, investigate the timing of the interruptions and the PPU configuration