Skip to content

Commit a66900f

Browse files
committed
Create a new chapter for the Window
1 parent 3d397e3 commit a66900f

File tree

4 files changed

+41
-45
lines changed

4 files changed

+41
-45
lines changed

src/LCDC.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,8 @@ This bit controls whether the window shall be displayed or not.
5757
This bit is overridden on DMG by [bit 0](<#LCDC.0 — BG and Window enable/priority>)
5858
if that bit is clear.
5959

60-
Changing the value of this register mid-frame triggers a more complex behaviour:
61-
[see further below](<#FF4A–FF4B — WY, WX: Window Y position, X position plus 7>).
62-
63-
Note that on CGB models, setting this bit to 0 then back to 1 mid-frame
64-
may cause the second write to be ignored. (TODO: test this.)
60+
Changing the value of this register mid-frame triggers several more complex behaviours:
61+
[see the corresponding chapter](<#Window mid-frame behavior>).
6562

6663
### LCDC.4 — BG and Window tile data area
6764

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- [Tile Maps](./Tile_Maps.md)
1919
- [OAM](./OAM.md)
2020
- [OAM DMA Transfer](./OAM_DMA_Transfer.md)
21+
- [Window](./Window.md)
2122
- [LCD Control](./LCDC.md)
2223
- [LCD Status Registers](./STAT.md)
2324
- [Scrolling](./Scrolling.md)

src/Scrolling.md

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
2-
# LCD Position and Scrolling
1+
# Viewport Position (Scrolling)
32

43
These registers can be accessed even during Mode 3, but modifications may not take
54
effect immediately (see further below).
@@ -22,46 +21,8 @@ Example from the homebrew game *Mindy's Hike*:
2221

2322
</figure>
2423

25-
## FF4A–FF4B — WY, WX: Window Y position, X position plus 7
26-
27-
These two registers specify the on-screen coordinates of [the Window](#Window)'s top-left pixel.
28-
29-
The Window is visible (if enabled) when both coordinates are in the ranges
30-
WX=0..166, WY=0..143 respectively. Values WX=7, WY=0 place the Window at the
31-
top left of the screen, completely covering the background.
32-
33-
:::warning Warning
34-
35-
WX values 0 and 166 are unreliable due to hardware bugs.
36-
37-
If WX is set to 0, the window will "stutter" horizontally when SCX changes
38-
(depending on SCX % 8).
39-
40-
If WX is set to 166, the window will span the entirety of the following
41-
scanline.
42-
43-
:::
44-
4524
## Mid-frame behavior
4625

47-
### Scrolling
48-
4926
The scroll registers are re-read on each [tile fetch](<#Get Tile>), except for the low 3 bits of SCX, which are only read at the beginning of the scanline (for the initial shifting of pixels).
5027

5128
All models before the CGB-D read the Y coordinate once for each bitplane (so a very precisely timed SCY write allows "desyncing" them), but CGB-D and later use the same Y coordinate for both no matter what.
52-
53-
### Window
54-
55-
While the Window should work as just mentioned, writing to WX, WY etc. mid-frame shows a more articulated behavior.
56-
57-
For the window to be displayed on a scanline, the following conditions must be met:
58-
59-
- **WY condition was triggered**: i.e. at some point in this frame the value of WY was equal to LY (checked at the start of Mode 2 only)
60-
- **WX condition was triggered**: i.e. the current X coordinate being rendered + 7 was equal to WX
61-
- Window enable bit in LCDC is set
62-
63-
If the WY condition has already been triggered and at the start of a row the window enable bit was set,
64-
then resetting that bit before the WX condition gets triggered on that row yields a nice window glitch pixel where the window would have been activated.
65-
66-
The way the Window selects which line of its tilemap to render may be surprising: the Y position is selected by an internal counter, which is reset to 0 during VBlank and **only** incremented when the Window starts being rendered on a given scanline.
67-
In particular, this means that hiding the Window mid-frame in any way (via either `WX` or `LCDC`, usually to display a status bar at the top *and* bottom of the screen) will also inhibit incrementing that Y-position counter.

src/Window.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Window
2+
3+
## FF4A–FF4B — WY, WX: Window Y position, X position plus 7
4+
5+
These two registers specify the on-screen coordinates of [the Window](#Window)'s top-left pixel.
6+
7+
The Window is visible (if enabled) when both coordinates are in the ranges
8+
WX=0..166, WY=0..143 respectively. Values WX=7, WY=0 place the Window at the
9+
top left of the screen, completely covering the background.
10+
11+
:::warning Warning
12+
13+
WX values 0 and 166 are unreliable due to hardware bugs.
14+
15+
If WX is set to 0, the window will "stutter" horizontally when SCX changes
16+
(depending on SCX % 8).
17+
18+
If WX is set to 166, the window will span the entirety of the following
19+
scanline.
20+
21+
:::
22+
23+
## Window mid-frame behavior
24+
25+
While the Window should work as just mentioned, writing to WX, WY etc. mid-frame shows a more articulated behavior.
26+
27+
For the window to be displayed on a scanline, the following conditions must be met:
28+
29+
- **WY condition was triggered**: i.e. at some point in this frame the value of WY was equal to LY (checked at the start of Mode 2 only)
30+
- **WX condition was triggered**: i.e. the current X coordinate being rendered + 7 was equal to WX
31+
- Window enable bit in LCDC is set
32+
33+
If the WY condition has already been triggered and at the start of a row the window enable bit was set,
34+
then resetting that bit before the WX condition gets triggered on that row yields a nice window glitch pixel where the window would have been activated.
35+
36+
The way the Window selects which line of its tilemap to render may be surprising: the Y position is selected by an internal counter, which is reset to 0 during VBlank and **only** incremented when the Window starts being rendered on a given scanline.
37+
In particular, this means that hiding the Window mid-frame in any way (via either `WX` or `LCDC`, usually to display a status bar at the top *and* bottom of the screen) will also inhibit incrementing that Y-position counter.

0 commit comments

Comments
 (0)