Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

LCD-on → First WODU

The path from the CPU's LCD-enabling write to the first H-Blank has a measured end-to-end length. It depends on SCX and not on the instruction stream that precedes the write. This chapter walks that path stage by stage, then maps it onto CPU-observable timing (scanline and frame timing).

At a glance

  • The first WODU↑ lands 251.536 + (SCX & 7) dots after the LCD-enabling write's ff40_d7↑ (dmg-sim measurement; no sprites, no window).
  • The instruction stream between the write and the first WODU is irrelevant to the PPU cascade: both dot-of-M-cycle phases are CPU-prelude-invariant.
  • The first-scanline Mode 2 measures ~78.5 dots from the write — the dot-0 reference shifted, not a Mode 2 shortening.
  • The whole SCX & 7 shift lands in the startup pipeline; every other stage is SCX-invariant to picosecond precision (measured at SCX ∈ {0,1,2,3,7}).
  • At first-WODU phases 2.556 and 3.556 the dispatch slips one M-cycle, raising the handler-entry A by one (canonical prelude).

The end-to-end path

The stages below walk the full path from ff40_d7↑ (the LCD-enabling write's effect) to the first H-Blank condition on the first scanline. All figures are for SCX=0, no sprites, and no window (dmg-sim measurement):

StageΔ from ff40_d7↑ (dots)
→ XODO↓ (VID_RST deasserts)+0.001
→ first XUPY↑ (scan counter starts)+0.480
→ first AVAP↑ (Mode 2 → 3)+78.491
→ first SACU↑+85.5 (= AVAP + 7.026)
→ first WODU↑+251.536 (= AVAP + 173.045)

Two dot-of-M-cycle invariants accompany that path. The write's ff40_d7↑ lands at +2.020 dots into its M-cycle (the CUPA position). The first WODU↑ lands at +1.556 dots into its M-cycle. Both phases are CPU-prelude-invariant: they are ps-identical across five LCD-on events in three radically different instruction streams — quickboot's mid-boot enable, a test ROM's own enable, and post-HALT interrupt-handler enables. The instruction stream between the write and the first WODU is therefore irrelevant to the PPU cascade.

The first-scanline Mode 2 measured from the write spans ~78.5 dots rather than 80. That short span is not a Mode 2 shortening. It is the dot-0 reference shifted by the write phase (+2.020) and divider startup (+0.480). Each subsequent Mode 2 is exactly 80 dots.

SCX extension (measured at SCX ∈ {0,1,2,3,7}): the entire +1-dot-per- SCX&7 shift lands in the startup pipeline. Every other stage is SCX-invariant to picosecond precision, across the same SCX set. The total is 251.536 + (SCX & 7) dots. That total gives a first-WODU M-cycle phase of (1.556 + (SCX & 7)) mod 4.

Mapping to CPU observables

For the canonical LDH (LCDC),a; xor a; inc a; inc a; … prelude, walking the wall-clock M-cells from the write pins everything. The write's M-cycle and WODU's are separated by 63 CLK9 edges. That places the first WODU at dot 1.556 of cell M65, with inc#61 in flight. Handler-entry A is therefore 61, matching the hardware-verified ROM expectation.

Pitfall: the fetch-overlap cell

A walk that charges 4 dots per instruction after the write's M3 comes out 4 dots short. The cause: the cell after a memory write hosts the writer's internal M4 and the next instruction's fetch. That is the SM83 fetch overlap.

One further mechanism joins the in-flight instruction: a one-M-cycle dispatch slip. The slip happens when the WODU-driven int_pending settles past the dispatch-trigger setup boundary. That is at first-WODU phases 2.556/3.556 (see interrupt dispatch). Per SCX, the in-flight instruction and the dispatch slip combine into the hardware-verified expectations:

SCXWODU M-cyclephasein-flightsliphandler A
0M651.556inc#61no61
1M652.556inc#61+162
2M653.556inc#61+162
3M660.556inc#62no62
4M661.556inc#62no62
5M662.556inc#62+163
6M663.556inc#62+163
7M670.556inc#63no63

Skip-boot note

For implementors

The first-scanline shortening happens once, in the first frame after the boot ROM's LCD-on. By PC=0x0100, hundreds of frames later, it is baked into the machine's phase. Skip-boot emulators must adopt the post-boot state values jointly: LX=98 with the divider states as given. They must not synthesise a "pre-shortening" LX and re-apply the shortening at a boot-ROM LCD-on edge. That edge never happens on the skip-boot path.