You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: src/Rendering.md
+30-45
Original file line number
Diff line number
Diff line change
@@ -17,67 +17,52 @@ The following diagram shows how a Game Boy frame is decomposed:
17
17
18
18
</figure>
19
19
20
-
## STAT modes
20
+
TODO: high-level description of the above... and implications ("raster effects")
21
21
22
-
The LCD controller operates on a 2^22 Hz = 4.194 MHz dot clock. An
23
-
entire frame is 154 scanlines = 70224 dots = 16.74 ms. On scanlines 0
22
+
## PPU modes
23
+
24
+
The PPU operates on a 2<sup>22</sup> Hz = 4.194 MHz clock, called the "dot clock".
25
+
An entire frame is 154 scanlines = 70224 dots = 16.74 ms. On scanlines 0
24
26
through 143, the PPU cycles through modes 2, 3, and 0 once
25
27
every 456 dots. Scanlines 144 through 153 are mode 1.
26
28
27
-
The following sequence is typical when the display is enabled:
29
+
While the PPU is accessing some video-related memory, [that memory is inaccessible to the CPU](<#Accessing VRAM and OAM>) (writes are ignored, and reads return garbage values, usually $FF).
2 | Searching for OBJs which overlap this line | 80 dots | VRAM, CGB palettes
34
+
3 | Sending pixels to the LCD | Between 172 and 289 dots, see below | None
35
+
0 | Waiting until the end of the scanline | 376 - mode 3's duration | VRAM, OAM, CGB palettes
36
+
1 | Waiting until the next frame | 4560 dots (10 scanlines) | VRAM, OAM, CGB palettes
35
37
36
-
When the PPU is accessing some video-related memory, that memory is inaccessible
37
-
to the CPU: writes are ignored, and reads return garbage values (usually $FF).
38
+
## Mode 3 length
38
39
39
-
- During modes 2 and 3, the CPU cannot access [OAM](<#VRAM Sprite Attribute Table (OAM)>) ($FE00-FE9F).
40
-
- During mode 3, the CPU cannot access VRAM or [CGB palette data registers](<#LCD Color Palettes (CGB only)>)
41
-
($FF69,$FF6B).
40
+
Unlike most game consoles, the Game Boy does not always output pixels steadily[^crt]: some features cause the rendering process to stall for a couple dots.
41
+
Any extra time spent stalling *lengthens* Mode 3; but since scanlines last for a fixed number of dots, Mode 0 is therefore shortened by that same amount of time.
42
42
43
-
Mode | Action | Duration | Accessible video memory
-**Background scrolling**: At the very beginning of Mode 3, rendering is paused for [`SCX`](<#FF42–FF43 — SCY, SCX: Viewport Y position, X position>) % 8 dots while the same number of pixels are discarded from the leftmost tile.
46
+
-**Window**: After the last non-window pixel is emitted, a 6-dot penalty is incurred while the BG fetcher is being set up for the window.
47
+
-**Objects**: Each object drawn during the scanline (even partially) incurs a 6- to 11-dot penalty ([see below](<#OBJ penalty algorithm>)).
51
48
52
-
Unlike most game consoles, the Game Boy can pause the dot clock briefly,
53
-
making Mode 3 longer and Mode 0 shorter. It routinely takes a 6 to 11 dot
54
-
break to fetch an OBJ's tile between background tile pattern fetches.
55
49
On DMG and GBC in DMG mode, mid-scanline writes to [`BGP`](<#FF47 — BGP (Non-CGB Mode only): BG palette data>)
56
50
allow observing this behavior, as the delay from drawing an OBJ shifts the
57
51
write's effect to the left by that many dots.
58
52
59
-
Three things are known to pause the dot clock:
60
-
61
-
- Background scrolling: If `SCX % 8` is not zero at the start of the scanline, rendering is paused for that many dots while the shifter discards that many pixels from the leftmost tile.
62
-
- Window: An active window pauses for at least 6 dots, as the background fetching mechanism starts over at the left side of the window.
63
-
- Objects: Each object usually pauses for `11 - min(5, (x + SCX) % 8)` dots.
64
-
Because object fetch waits for background fetch to finish, an object's cost depends on its position relative to the left side of the background tile under it. It's greater if an object is directly aligned over the background tile, less if the object is to the right. If the object's left side is over the window, use `255 - WX` instead of `SCX` in this formula.
53
+
### OBJ penalty algorithm
65
54
66
-
::: warning TO BE VERIFIED
55
+
Only the OBJ's leftmost pixel matters here, transparent or not; it is designated as "The Pixel" in the following.
67
56
68
-
The exact pause duration for window start is
69
-
not confirmed; it may have the same background fetch finish delay as
70
-
an object. If two objects' left sides are over the same background or
71
-
window tile, the second may pause for fewer dots.
57
+
1. Determine the tile (background or window) that The Pixel is within. (This is affected by horizontal scrolling and/or the window!)
58
+
2. If that tile has **not** been considered by a previous OBJ yet:
59
+
1. Count how many of that tile's pixels are to the right of The Pixel.
60
+
2. Subtract 3.
61
+
3. Incur this many dots of penalty, or zero if negative (from waiting for the BG fetch to finish).
62
+
3. Incur a flat, 6-dot penalty (from fetching the OBJ's tile).
72
63
73
-
:::
64
+
**Exception**: an OBJ with an OAM X position of 0 (thus, completely off the left side of the screen) always incurs a 11-cycle penalty, regardless of `SCX`.
74
65
75
-
A hardware quirk in the monochrome Game Boy makes the LCD interrupt
76
-
sometimes trigger when writing to STAT (including writing \$00) during
77
-
OAM scan, HBlank, VBlank, or LY=LYC. It behaves as if \$FF were
78
-
written for one cycle, and then the written value were written the next
79
-
cycle. Because the GBC in DMG mode does not have this quirk, two games
80
-
that depend on this quirk (Ocean's *Road Rash* and Vic Tokai's *Xerd
81
-
no Densetsu*) will not run on a GBC.
66
+
TODO: a diagram of some examples would probably help this be much clearer! \>_\<
82
67
83
-
TODO
68
+
[^crt]: The Game Boy can afford to "take pauses", because it writes to a LCD it fully controls; by contrast, home consoles like the NES or SNES are on a schedule imposed by the screen they are hooked up to. Taking pauses arguably simplified the PPU's design while allowing greater flexibility to game developers.
0 commit comments