Skip to content

Commit 5ff8ccd

Browse files
ISSOtmAntonio Vivace
andcommitted
Apply misc. graphics-related fixups
Co-authored-by: Antonio Vivace <[email protected]>
1 parent a96fcc5 commit 5ff8ccd

File tree

5 files changed

+124
-101
lines changed

5 files changed

+124
-101
lines changed

src/Palettes.md

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -22,72 +22,82 @@ Value | Color
2222
2 | Dark gray
2323
3 | Black
2424

25-
In CGB Mode the Color Palettes are taken from [CGB Palette Memory](<#LCD Color Palettes (CGB only)>)
25+
In CGB Mode the color palettes are taken from [CGB palette memory](<#LCD Color Palettes (CGB only)>)
2626
instead.
2727

28-
### FF48 - OBP0 (Object Palette 0 Data) (R/W) - Non CGB Mode Only
28+
### FF48 - OBP0 (OBJ Palette 0 Data) (R/W), FF49 - OBP1 (OBJ Palette 1 Data) (R/W) - Both Non CGB Mode Only
2929

30-
This register assigns gray shades to the color indexes of the OBJs that use this palette. It works exactly
31-
like BGP (FF47), except that the lower two bits are ignored because
32-
sprite index 00 means transparent.
33-
34-
### FF49 - OBP1 (Object Palette 1 Data) (R/W) - Non CGB Mode Only
35-
36-
This register assigns gray shades to the color indexes of the OBJs that use this palette. It works exactly
37-
like BGP (FF47), except that the lower two bits are ignored because
38-
sprite index 00 means transparent.
30+
These registers assigns gray shades to the color indexes of the OBJs that use the corresponding palette.
31+
They work exactly like BGP, except that the lower two bits are ignored because color index 0 is transparent for OBJs.
3932

4033
## LCD Color Palettes (CGB only)
4134

35+
The CGB has a small amount of RAM used to store its color palettes. Unlike most
36+
of the hardware interface, palette RAM (or *CRAM* for *Color RAM*) is not
37+
accessed directly, but instead through the following registers:
38+
4239
### FF68 - BCPS/BGPI (Background Color Palette Specification or Background Palette Index) - CGB Mode Only
4340

44-
This register is used to address a byte in the CGBs Background Palette
45-
Memory. Each two byte in that memory define a color value. The first 8
46-
bytes define Color 0-3 of Palette 0 (BGP0), and so on for BGP1-7.
41+
This register is used to address a byte in the CGB's background palette RAM.
42+
Since there are 8 palettes, 8 palettes × 4 colors/palette × 2 bytes/color = 64 bytes
43+
can be addressed.
4744

4845
```
4946
Bit 7 Auto Increment (0=Disabled, 1=Increment after Writing)
50-
Bit 5-0 Index (00-3F)
47+
Bit 5-0 Address ($00-3F)
5148
```
5249

53-
Data can be read/written to/from the specified index address through
54-
Register FF69. When the Auto Increment bit is set then the index is
55-
automatically incremented after each **write** to FF69. Auto Increment has
56-
no effect when **reading** from FF69, so the index must be manually
57-
incremented in that case. Writing to FF69 during rendering still causes
58-
auto-increment to occur.
50+
First comes BGP0 color number 0, then BGP0 color number 1, BGP0 color number 2, BGP0 color number 3,
51+
BGP1 color number 0, and so on. Thus, address $03 allows accessing the second (upper)
52+
byte of BGP0 color #1 via BCPD, which contains the color's blue and upper green bits.
5953

60-
Unlike the following, this register can be accessed outside VBlank and
61-
HBlank.
54+
Data can be read from or written to the specified CRAM address through
55+
BCPD/BGPD. If the Auto Increment bit is set, the index gets
56+
incremented after each **write** to BCPD. Auto Increment has
57+
no effect when **reading** from BCPD, so the index must be manually
58+
incremented in that case. Writing to BCPD during rendering still causes
59+
auto-increment to occur, despite the write being blocked.
60+
61+
Unlike BCPD, this register can be accessed outside VBlank and HBlank.
6262

6363
### FF69 - BCPD/BGPD (Background Color Palette Data or Background Palette Data) - CGB Mode Only
6464

65-
This register allows to read/write data to the CGBs Background Palette
66-
Memory, addressed through Register FF68. Each color is defined by two
67-
bytes (Bit 0-7 in first byte).
65+
This register allows to read/write data to the CGBs background palette memory,
66+
addressed through BCPS/BGPI. Each color is stored as little-endian RGB555:
6867

6968
```
70-
Bit 0-4 Red Intensity (00-1F)
71-
Bit 5-9 Green Intensity (00-1F)
72-
Bit 10-14 Blue Intensity (00-1F)
69+
Bit 0-4 Red Intensity ($00-1F)
70+
Bit 5-9 Green Intensity ($00-1F)
71+
Bit 10-14 Blue Intensity ($00-1F)
7372
```
7473

75-
Much like VRAM, data in Palette Memory cannot be read/written during the
76-
time when the LCD Controller is reading from it. (That is when the STAT
77-
register indicates Mode 3). Note: All background colors are initialized
78-
as white by the boot ROM, but it's a good idea to initialize at least
79-
one color yourself (for example if you include a soft-reset mechanic).
74+
Much like VRAM, data in palette memory cannot be read or written during the time
75+
when the PPU is reading from it, that is, [Mode 3](<#LCD Status Register>).
76+
77+
::: tip NOTE
78+
79+
All background colors are initialized as white by the boot ROM, however it is a
80+
good idea to initialize all colors yourself, e.g. if implementing
81+
a soft-reset mechanic.
8082

81-
### FF6A - OCPS/OBPI (Object Color Palette Specification or Sprite Palette Index), FF6B - OCPD/OBPD (Object Color Palette Data or Sprite Palette Data) - Both CGB Mode Only
83+
:::
8284

83-
These registers are used to initialize the Sprite Palettes OBP0-7,
84-
identically as described above for Background Palettes. Note that four
85-
colors may be defined for each OBP Palettes - but only Color 1-3 of each
86-
Sprite Palette can be displayed, Color 0 is always transparent, and can
87-
be initialized to a don't care value or plain never initialized.
85+
### FF6A - OCPS/OBPI (OBJ Color Palette Specification / OBJ Palette Index), FF6B - OCPD/OBPD (OBJ Color Palette Data / OBJ Palette Data) - Both CGB Mode Only
8886

89-
Note: All sprite colors are left uninitialized by the boot ROM, and are
90-
somewhat random.
87+
These registers function exactly like BCPS and BCPD respectively; the 64 bytes
88+
of OBJ palette memory are entirely separate from Background palette memory, but
89+
function the same.
90+
91+
Note that while 4 colors are stored per OBJ palette, color #0 is never used, as
92+
it's always transparent. It's thus fine to write garbage values, or even leave
93+
color #0 uninitialized.
94+
95+
::: tip NOTE
96+
97+
The boot ROM leaves all object colors uninitialized (and thus somewhat random),
98+
aside from setting the first byte of OBJ0 color #0 to $00, which is unused.
99+
100+
:::
91101

92102
### RGB Translation by CGBs
93103

@@ -96,14 +106,14 @@ somewhat random.
96106
When developing graphics on PCs, note that the RGB values will have
97107
different appearance on CGB displays as on VGA/HDMI monitors calibrated
98108
to sRGB color. Because the GBC is not lit, the highest intensity will
99-
produce Light Gray color rather than White. The intensities are not
100-
linear; the values 10h-1Fh will all appear very bright, while medium and
101-
darker colors are ranged at 00h-0Fh.
109+
produce light gray rather than white. The intensities are not
110+
linear; the values $10-$1F will all appear very bright, while medium and
111+
darker colors are ranged at $00-0F.
102112

103113
The CGB display's pigments aren't perfectly saturated. This means the
104-
colors mix quite oddly; increasing intensity of only one R,G,B color
105-
will also influence the other two R,G,B colors. For example, a color
106-
setting of 03EFh (Blue=0, Green=1Fh, Red=0Fh) will appear as Neon Green
114+
colors mix quite oddly: increasing the intensity of only one R/G/B color
115+
will also influence the other two R/G/B colors. For example, a color
116+
setting of $03EF (Blue=$00, Green=$1F, Red=$0F) will appear as Neon Green
107117
on VGA displays, but on the CGB it'll produce a decently washed out
108118
Yellow. See the image above.
109119

@@ -113,21 +123,25 @@ Even though GBA is described to be compatible to CGB games, most CGB
113123
games are completely unplayable on older GBAs because most colors are
114124
invisible (black). Of course, colors such like Black and White will
115125
appear the same on both CGB and GBA, but medium intensities are arranged
116-
completely different. Intensities in range 00h..07h are invisible/black
126+
completely different. Intensities in range $00–07 are invisible/black
117127
(unless eventually under best sunlight circumstances, and when gazing at
118128
the screen under obscure viewing angles), unfortunately, these
119129
intensities are regularly used by most existing CGB games for medium and
120130
darker colors.
121131

132+
::: tip WORKAROUND
133+
122134
Newer CGB games may avoid this effect by changing palette data when
123-
detecting GBA hardware ([see
124-
how](<#Detecting CGB (and GBA) functions>)).
125-
Based on measurement of GBC and GBA palettes using the [144p Test
126-
Suite](https://github.com/pinobatch/240p-test-mini/tree/master/gameboy) ROM, a fairly close approximation is GBA = GBC \* 3/4 + 8h for
127-
each R,G,B intensity. The result isn't quite perfect, and it may turn
135+
detecting GBA hardware ([see how](<#Detecting CGB (and GBA) functions>)).
136+
Based on measurements of GBC and GBA palettes using the
137+
[144p Test Suite](https://github.com/pinobatch/240p-test-mini/tree/master/gameboy),
138+
a fairly close approximation is `GBA = GBC × 3/4 + $08` for each R/G/B
139+
component. The result isn't quite perfect, and it may turn
128140
out that the color mixing is different also; anyways, it'd be still
129141
ways better than no conversion.
130142

143+
:::
144+
131145
This problem with low brightness levels does not affect later GBA SP
132146
units and Game Boy Player. Thus ideally, the player should have control
133147
of this brightness correction.

src/Power_Up_Sequence.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,8 @@ The table above was obtained from Mooneye-GB tests [`acceptance/boot_hwio-dmg0`]
376376
[`LYC`]: <#FF45 - LYC (LY Compare) (R/W)>
377377
[`DMA`]: <#FF46 - DMA (DMA Transfer and Start Address) (R/W)>
378378
[`BGP`]: <#FF47 - BGP (BG Palette Data) (R/W) - Non CGB Mode Only>
379-
[`OBP0`]: <#FF48 - OBP0 (Object Palette 0 Data) (R/W) - Non CGB Mode Only>
380-
[`OBP1`]: <#FF49 - OBP1 (Object Palette 1 Data) (R/W) - Non CGB Mode Only>
379+
[`OBP0`]: <#FF48 - OBP0 (OBJ Palette 0 Data) (R/W), FF49 - OBP1 (OBJ Palette 1 Data) (R/W) - Both Non CGB Mode Only>
380+
[`OBP1`]: <#FF48 - OBP0 (OBJ Palette 0 Data) (R/W), FF49 - OBP1 (OBJ Palette 1 Data) (R/W) - Both Non CGB Mode Only>
381381
[`WY`]: <#FF4A - WY (Window Y Position) (R/W), FF4B - WX (Window X Position + 7) (R/W)>
382382
[`WX`]: <#FF4A - WY (Window Y Position) (R/W), FF4B - WX (Window X Position + 7) (R/W)>
383383
[`KEY1`]: <#FF4D - KEY1 - CGB Mode Only - Prepare Speed Switch>
@@ -390,8 +390,8 @@ The table above was obtained from Mooneye-GB tests [`acceptance/boot_hwio-dmg0`]
390390
[`RP`]: <#FF56 - RP - CGB Mode Only - Infrared Communications Port>
391391
[`BCPS`]: <#FF68 - BCPS/BGPI (Background Color Palette Specification or Background Palette Index) - CGB Mode Only>
392392
[`BCPD`]: <#FF69 - BCPD/BGPD (Background Color Palette Data or Background Palette Data) - CGB Mode Only>
393-
[`OCPS`]: <#FF6A - OCPS/OBPI (Object Color Palette Specification or Sprite Palette Index), FF6B - OCPD/OBPD (Object Color Palette Data or Sprite Palette Data) - Both CGB Mode Only>
394-
[`OCPD`]: <#FF6A - OCPS/OBPI (Object Color Palette Specification or Sprite Palette Index), FF6B - OCPD/OBPD (Object Color Palette Data or Sprite Palette Data) - Both CGB Mode Only>
393+
[`OCPS`]: <#FF6A - OCPS/OBPI (OBJ Color Palette Specification / OBJ Palette Index), FF6B - OCPD/OBPD (OBJ Color Palette Data / OBJ Palette Data) - Both CGB Mode Only>
394+
[`OCPD`]: <#FF6A - OCPS/OBPI (OBJ Color Palette Specification / OBJ Palette Index), FF6B - OCPD/OBPD (OBJ Color Palette Data / OBJ Palette Data) - Both CGB Mode Only>
395395
[`OPRI`]: <#FF6C - OPRI - CGB Mode Only - Object Priority Mode>
396396
[`SVBK`]: <#FF70 - SVBK - CGB Mode Only - WRAM Bank>
397397
[FF72]: <#FF72 - Bits 0-7 (Read/Write), FF73 - Bits 0-7 (Read/Write)>

src/STAT.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ Bit 4 - Mode 1 VBlank STAT Interrupt source (1=Enable) (Read/Write)
1515
Bit 3 - Mode 0 HBlank STAT Interrupt source (1=Enable) (Read/Write)
1616
Bit 2 - LYC=LY Flag (0=Different, 1=Equal) (Read Only)
1717
Bit 1-0 - Mode Flag (Mode 0-3, see below) (Read Only)
18-
0: In HBlank
19-
1: In VBlank
18+
0: HBlank
19+
1: VBlank
2020
2: Searching OAM
2121
3: Transferring Data to LCD Controller
2222
```
@@ -29,7 +29,7 @@ It is constantly updated.
2929
Bits 3-6 select which sources are used for [the STAT interrupt](<#INT 48 - STAT Interrupt>).
3030

3131
The LCD controller operates on a 2^22 Hz = 4.194 MHz dot clock. An
32-
entire frame is 154 scanlines, 70224 dots, or 16.74 ms. On scanlines 0
32+
entire frame is 154 scanlines = 70224 dots = 16.74 ms. On scanlines 0
3333
through 143, the PPU cycles through modes 2, 3, and 0 once
3434
every 456 dots. Scanlines 144 through 153 are mode 1.
3535

@@ -42,34 +42,34 @@ Mode 0 ___000___000___000___000___000___000________________000
4242
Mode 1 ____________________________________11111111111111_____
4343
```
4444

45-
When the PPU is reading a particular part of video memory,
46-
that memory is inaccessible to the CPU.
45+
When the PPU is accessing some video-related memory, that memory is inaccessible
46+
to the CPU: writes are ignored, and reads return garbage values (usually $FF).
4747

48-
- During modes 2 and 3, the CPU cannot access OAM (FE00h-FE9Fh).
49-
- During mode 3, the CPU cannot access VRAM or CGB Palette Data
50-
(FF69,FF6B).
48+
- During modes 2 and 3, the CPU cannot access [OAM](<#VRAM Sprite Attribute Table (OAM)>) ($FE00-FE9F).
49+
- During mode 3, the CPU cannot access VRAM or [CGB palette data registers](<#FF69 - BCPD/BGPD (Background Color Palette Data or Background Palette Data) - CGB Mode Only>)
50+
($FF69,$FF6B).
5151

52-
Mode | Action | Duration | Accessible video memory
52+
Mode | Action | Duration | Accessible video memory
5353
-----|------------------------------------------------------------------|--------------------------------------------------------------------|-------------------------
54-
2 | Searching OAM for OBJs whose (X,Y) coordinates overlap this line | 80 dots (19 µs) | VRAM, CGB palettes
55-
3 | Reading OAM and VRAM to generate the picture | 168 to 291 dots (40 to 60 µs) depending on sprite count | None
56-
0 | Horizontal blanking | 85 to 208 dots (20 to 49 µs) depending on previous mode 3 duration | VRAM, OAM, CGB palettes
57-
1 | Vertical blanking | 4560 dots (1087 µs, 10 scanlines) | VRAM, OAM, CGB palettes
54+
2 | Searching OAM for OBJs whose Y coordinate overlap this line | 80 dots (19 µs) | VRAM, CGB palettes
55+
3 | Reading OAM and VRAM to generate the picture | 168 to 291 dots (40 to 60 µs) depending on sprite count | None
56+
0 | Nothing (HBlank) | 85 to 208 dots (20 to 49 µs) depending on previous mode 3 duration | VRAM, OAM, CGB palettes
57+
1 | Nothing (VBlank) | 4560 dots (1087 µs, 10 scanlines) | VRAM, OAM, CGB palettes
5858

5959
## Properties of STAT modes
6060

6161
Unlike most game consoles, the Game Boy can pause the dot clock briefly,
62-
adding dots to mode 3's duration. It routinely takes a 6 to 11 dot
63-
break to fetch sprite patterns between background tile pattern fetches.
62+
making Mode 3 longer and Mode 0 shorter. It routinely takes a 6 to 11 dot
63+
break to fetch an OBJ's tile between background tile pattern fetches.
6464
On DMG and GBC in DMG mode, mid-scanline writes to [`BGP`](<#FF47 - BGP (BG Palette Data) (R/W) - Non CGB Mode Only>)
65-
allow observing this behavior, as a sprite delay shifts the effect of a
66-
write to the left by that many dots.
65+
allow observing this behavior, as the delay from drawing an OBJ shifts the
66+
write's effect to the left by that many dots.
6767

6868
Three things are known to pause the dot clock:
6969

70-
- Background scrolling: If `SCX mod 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.
70+
- 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.
7171
- Window: An active window pauses for at least 6 dots, as the background fetching mechanism starts over at the left side of the window.
72-
- Sprites: Each sprite usually pauses for `11 - min(5, (x + SCX) mod 8)` dots. Because sprite fetch waits for background fetch to finish, a sprite's cost depends on its position relative to the left side of the background tile under it. It's greater if a sprite is directly aligned over the background tile, less if the sprite is to the right. If the sprite's left side is over the window, use `255 - WX` for `SCX` in this formula.
72+
- Sprites: Each sprite usually pauses for `11 - min(5, (x + SCX) % 8)` dots. Because sprite fetch waits for background fetch to finish, a sprite's cost depends on its position relative to the left side of the background tile under it. It's greater if a sprite is directly aligned over the background tile, less if the sprite is to the right. If the sprite's left side is over the window, use `255 - WX` instead of `SCX` in this formula.
7373

7474
::: warning TO BE VERIFIED
7575

0 commit comments

Comments
 (0)