Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change most uses of "sprite" to "object" #484

Merged
merged 4 commits into from
Jun 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Accessing_VRAM_and_OAM.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
::: warning Warning

When the PPU is drawing the screen it is directly reading
from Video Memory (VRAM) and from the Sprite Attribute Table (OAM).
from Video Memory (VRAM) and from the Object Attribute Memory (OAM).
During these periods the Game Boy CPU may not access VRAM and OAM.
That means that any attempts to write to VRAM or OAM are ignored (data
remains unchanged). And any attempts to read from VRAM or OAM will return
Expand Down
2 changes: 1 addition & 1 deletion src/CGB_Registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ executed. During this time, the CPU is in a strange state. `DIV` does not tick,
different results depending on the [STAT mode](<#STAT modes>) it's started in:

- HBlank / VBlank (Mode 0 / Mode 1): The PPU cannot access any video memory, and produces black pixels
- OAM scan (Mode 2): The PPU can access VRAM just fine, but not OAM, leading to rendering background, but not sprites
- OAM scan (Mode 2): The PPU can access VRAM just fine, but not OAM, leading to rendering background, but not objects (sprites)
- Rendering (Mode 3): The PPU can access everything correctly, and so rendering is not affected

TODO: confirm whether interrupts can occur (just the joypad one?) during the pause, and consequences if so
Expand Down
3 changes: 2 additions & 1 deletion src/GBC_Approval_Process.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Game Boy Color hardware applies automatic colorization to monochrome
games, with one 4-color palette for backgrounds and two 3-color
palettes for sprites. Because of past under utilization of Super Game Boy
palettes for objects (sprites).
Because of past under-utilization of Super Game Boy
features even in first-party games (as explained in an article by
Christine Love), Nintendo required Game Boy Color games to appear
more colorful than this automatic colorization. Thus, Nintendo
Expand Down
4 changes: 2 additions & 2 deletions src/Interrupt_Sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ dynamically controlling the SCX/SCY registers ($FF43/$FF42) to [perform
special video effects](https://github.com/gb-archive/DeadCScroll).

Example application: set LYC to WY, enable LY=LYC interrupt, and have
the handler disable sprites. This can be used if you use the window for
a text box (at the bottom of the screen), and you want sprites to be
the handler disable objects. This can be used if you use the window for
a text box (at the bottom of the screen), and you want objects (sprites) to be
hidden by the text box.

## INT $50 — Timer interrupt
Expand Down
34 changes: 18 additions & 16 deletions src/LCDC.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Bit | Name | Usage notes
5 | Window enable | 0=Off, 1=On
4 | BG and Window tile data area | 0=8800-97FF, 1=8000-8FFF
3 | BG tile map area | 0=9800-9BFF, 1=9C00-9FFF
2 | OBJ size | 0=8x8, 1=8x16
2 | OBJ size | 0=8×8, 1=8×16
1 | OBJ enable | 0=Off, 1=On
0 | BG and Window enable/priority | 0=Off, 1=On

Expand Down Expand Up @@ -45,14 +45,14 @@ but the screen will stay blank during the first frame.
### LCDC.6 — Window tile map area

This bit controls which background map the Window uses for rendering.
When it's reset, the \$9800 tilemap is used, otherwise it's the \$9C00
When it's clear (0), the \$9800 tilemap is used, otherwise it's the \$9C00
one.

### LCDC.5 — Window enable

This bit controls whether the window shall be displayed or not.
This bit is overridden on DMG by [bit 0](<#LCDC.0 — BG and Window enable/priority>)
if that bit is reset.
if that bit is clear.

Changing the value of this register mid-frame triggers a more complex behaviour:
[see further below](<#FF4A–FF4B — WY, WX: Window Y position, X position plus 7>).
Expand All @@ -66,28 +66,30 @@ This bit controls which [addressing
mode](<#VRAM Tile Data>) the BG and Window use to
pick tiles.

Sprites aren't affected by this, and will always use \$8000 addressing
mode.
Objects (sprites) aren't affected by this, and will always use the \$8000 addressing mode.

### LCDC.3 — BG tile map area

This bit works similarly to [LCDC bit 6](<#LCDC.6 — Window tile map area>):
if the bit is reset, the BG uses tilemap $9800, otherwise tilemap $9C00.
if the bit is clear (0), the BG uses tilemap $9800, otherwise tilemap $9C00.


### LCDC.2 — OBJ size

This bit controls the sprite size (1 tile or 2 stacked vertically).
This bit controls the size of all objects (1 tile or 2 stacked vertically).

Be cautious when changing this mid-frame from 8x8 to 8x16: "remnants"
of the sprites intended for 8x8 could "leak" into the 8x16 zone and
Be cautious when changing object size mid-frame.
Changing from 8×8 to 8×16 pixels mid-frame within 8 scanlines of the bottom of an object
causes the object's second tile to be visible for the rest of those 8 lines.
If the size is changed during mode 2 or 3,
remnants of objects in range could "leak" into the other tile and
cause artifacts.

### LCDC.1 — OBJ enable

This bit toggles whether sprites are displayed or not.
This bit toggles whether objects are displayed or not.

This can be toggled mid-frame, for example to avoid sprites being
This can be toggled mid-frame, for example to avoid objects being
displayed on top of a status bar or text box.

(Note: toggling mid-scanline might have funky results on DMG?
Expand All @@ -101,13 +103,13 @@ LCDC.0 has different meanings depending on Game Boy type and Mode:

When Bit 0 is cleared, both background and window become blank (white),
and the [Window Display Bit](<#LCDC.5 — Window enable>)
is ignored in that case. Only Sprites may still be displayed (if enabled
is ignored in that case. Only objects may still be displayed (if enabled
in Bit 1).

#### CGB Mode: BG and Window master priority

When Bit 0 is cleared, the background and window lose their priority -
the sprites will be always displayed on top of background and window,
the objects will be always displayed on top of background and window,
independently of the priority flags in OAM and BG Map attributes.

When Bit 0 is set, pixel priority is resolved [as described here](<#BG-to-OBJ Priority in CGB Mode>).
Expand All @@ -122,13 +124,13 @@ locks it. It's thus possible to modify it mid-scanline!

## Faux-layer textbox/status bar

A problem often seen especially in NES games is sprites rendering on top
A problem often seen in 8-bit games is objects rendering on top
of the textbox/status bar. It's possible to prevent this using LCDC if
the textbox/status bar is "alone" on its scanlines:

- Set LCDC.1 to 1 for gameplay scanlines
- Set LCDC.1 to 0 for textbox/status bar scanlines

Usually, these bars are either at the top or bottom of the screen, so
the bit can be set by the VBlank handler.

the bit can be set by the VBlank and/or STAT handlers.
Hiding objects behind a right-side window is more challenging.
4 changes: 2 additions & 2 deletions src/Memory_Map.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ A000 | BFFF | 8 KiB External RAM
C000 | CFFF | 4 KiB Work RAM (WRAM) |
D000 | DFFF | 4 KiB Work RAM (WRAM) | In CGB mode, switchable bank 1\~7
E000 | FDFF | Mirror of C000\~DDFF (ECHO RAM) | Nintendo says use of this area is prohibited.
FE00 | FE9F | [Sprite attribute table (OAM)](<#VRAM Sprite Attribute Table (OAM)>) |
FE00 | FE9F | [Object attribute memory (OAM)](<#VRAM Sprite Attribute Table (OAM)>) |
FEA0 | FEFF | Not Usable | Nintendo says use of this area is prohibited
FF00 | FF7F | [I/O Registers](<#I/O Ranges>) |
FF80 | FFFE | High RAM (HRAM) |
FFFF | FFFF | [Interrupt](#Interrupts) Enable register (IE) |
FFFF | FFFF | [Interrupt](#Interrupts) Enable register (IE) |

## Jump Vectors in first ROM bank

Expand Down
62 changes: 33 additions & 29 deletions src/OAM.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,51 @@

# VRAM Sprite Attribute Table (OAM)
# Object Attribute Memory (OAM)

The Game Boy PPU can display up to 40 sprites either in 8x8 or
in 8x16 pixels. Because of a limitation of hardware, only ten sprites
can be displayed per scan line. Sprite tiles have the same format as
BG tiles, but they are taken from the Sprite Tiles Table located at
The Game Boy PPU can display up to 40 movable objects (or sprites), each 8×8 or
8×16 pixels. Because of a limitation of hardware, only ten objects
can be displayed per scanline. Object tiles have the same format as
BG tiles, but they are taken from tile blocks 0 and 1 located at
$8000-8FFF and have unsigned numbering.

Sprite attributes reside in the Sprite Attribute Table (OAM: Object
Attribute Memory) at \$FE00-FE9F. Each of the 40 entries consists of
Object attributes reside in the object attribute memory (OAM) at \$FE00-FE9F.
(This corresponds to the sprite attribute table on a TMS9918 VDP.)
ISSOtm marked this conversation as resolved.
Show resolved Hide resolved
Each of the 40 entries consists of
four bytes with the following meanings:

## Byte 0 — Y Position

Y = Sprite's vertical position on the screen + 16. So for example,
Y=0 hides a sprite,
Y=2 hides an 8×8 sprite but displays the last two rows of an 8×16 sprite,
Y=16 displays a sprite at the top of the screen,
Y=144 displays an 8×16 sprite aligned with the bottom of the screen,
Y=152 displays an 8×8 sprite aligned with the bottom of the screen,
Y=154 displays the first six rows of a sprite at the bottom of the screen,
Y=160 hides a sprite.
![Interpretation of object Y coordinates](imgs/Objects_vertical_position.png)

Y = Object's vertical position on the screen + 16. So for example:

- Y=0 hides an object,
- Y=2 hides an 8×8 object but displays the last two rows of an 8×16 object,
- Y=16 displays an object at the top of the screen,
- Y=144 displays an 8×16 object aligned with the bottom of the screen,
- Y=152 displays an 8×8 object aligned with the bottom of the screen,
- Y=154 displays the first six rows of an object at the bottom of the screen,
- Y=160 hides an object.

## Byte 1 — X Position

X = Sprite's horizontal position on the screen + 8. This works similarly
to the examples above, except that the width of a sprite is always 8. An
off-screen value (X=0 or X\>=168) hides the sprite, but the sprite still
affects the priority ordering, thus other sprites with lower priority may be
left out due to the ten sprites limit per scan-line.
A better way to hide a sprite is to set its Y-coordinate off-screen.
X = Object's horizontal position on the screen + 8. This works similarly
to the examples above, except that the width of an object is always 8. An
off-screen value (X=0 or X\>=168) hides the object, but the object still
contributes to the limit of ten objects per scanline.
This can cause objects later in OAM not to be drawn on that line.
A better way to hide an object is to set its Y-coordinate off-screen.

## Byte 2 — Tile Index

In 8x8 mode (LCDC bit 2 = 0), this byte specifies the sprite's only tile index ($00-$FF).
This unsigned value selects a tile from the memory area at $8000-$8FFF.
In 8×8 mode (LCDC bit 2 = 0), this byte specifies the object's only tile index (\$00-\$FF).
This unsigned value selects a tile from the memory area at \$8000-\$8FFF.
In CGB Mode this could be either in
VRAM bank 0 or 1, depending on bit 3 of the following byte.
In 8x16 mode (LCDC bit 2 = 1), the memory area at $8000-$8FFF is still interpreted
as a series of 8x8 tiles, where every 2 tiles form a sprite. In this mode, this byte
specifies the index of the first (top) tile of the sprite. This is enforced by the
hardware: the least significant bit of the tile index is ignored; that is, the top 8x8
tile is "NN & $FE", and the bottom 8x8 tile is "NN | $01".
In 8×16 mode (LCDC bit 2 = 1), the memory area at \$8000-\$8FFF is still interpreted
as a series of 8×8 tiles, where every 2 tiles form an object. In this mode, this byte
specifies the index of the first (top) tile of the object. This is enforced by the
hardware: the least significant bit of the tile index is ignored; that is, the top 8×8
tile is "NN & \$FE", and the bottom 8×8 tile is "NN | \$01".

## Byte 3 — Attributes/Flags

Expand Down Expand Up @@ -87,7 +91,7 @@ limit, possibly causing another object later in OAM not
to be drawn. To keep off-screen objects from affecting on-screen ones, make
sure to set their Y coordinate to Y&nbsp;=&nbsp;0 or Y&nbsp;≥&nbsp;160
(144&nbsp;+&nbsp;16).
(Y&nbsp;≤&nbsp;8 also works if [object size](<#LCDC.2 — OBJ size>) is set to 8x8.)
(Y&nbsp;≤&nbsp;8 also works if [object size](<#LCDC.2 — OBJ size>) is set to 8×8.)

### Drawing priority

Expand Down
15 changes: 9 additions & 6 deletions src/OAM_Corruption_Bug.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# OAM Corruption Bug

There is a flaw in the Game Boy hardware that causes rubbish data to be written
to OAM RAM if the following instructions are used while their 16-bit content
to object attribute memory (OAM) if the following instructions are used while their 16-bit content
(before the operation) is in the range $FE00&ndash;$FEFF and the PPU is in mode 2:

```rgbasm
Expand All @@ -10,7 +10,7 @@ to OAM RAM if the following instructions are used while their 16-bit content
ld [hli], a ld [hld], a
```

Sprites 1 & 2 ($FE00 & $FE04) are not affected by this bug.
Objects 0 and 1 ($FE00 & $FE04) are not affected by this bug.

Game Boy Color and Advance are not affected by this bug, even when
running monochrome software.
Expand All @@ -20,11 +20,14 @@ running monochrome software.
The OAM Corruption Bug (or OAM Bug) actually consists of two different bugs:

- Attempting to read or write from OAM (Including the $FEA0-$FEFF
region) while the PPU is in mode 2 (OAM mode) will corrupt it.
region) while the PPU is in mode 2 (OAM scan) will corrupt it.
- Performing an increase or decrease operation on any 16-bit register
(BC, DE, HL, SP or PC) while that register is in the OAM range
($FE00 - $FEFF) will trigger a memory write to OAM, causing a
corruption.
($FE00–$FEFF) will trigger an access to OAM, causing a corruption.
This happens because the CPU's increment and decrement unit (IDU)
for 16-bit numbers is directly tied to the address bus.
During IDU operation, the value is output as an address,
even if a read or write is not asserted.

## Affected Operations

Expand Down Expand Up @@ -66,7 +69,7 @@ operations are on 16-bit words.

A "write corruption" corrupts the currently access row in the following
manner, as long as it's not the first row (containing the first two
sprites):
objects):

- The first word in the row is replaced with this bitwise expression:
`((a ^ c) & (b ^ c)) ^ c`, where `a` is the original value of that
Expand Down
8 changes: 4 additions & 4 deletions src/Rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ and some others to higher abstractions concepts.

Similarly to other retro systems, pixels are not manipulated
individually, as this would be expensive CPU-wise. Instead, pixels are grouped
in 8x8 squares, called _tiles_ (or sometimes "patterns"), often considered as
in 8x8 squares, called _tiles_ (or sometimes "patterns" or "characters"), often considered as
the base unit in Game Boy graphics.

A tile does not encode color information. Instead, a tile assigns a
_color ID_ to each of its pixels, ranging from 0 to 3. For this reason,
Game Boy graphics are also called _2bpp_ (2 bits per pixel). When a tile is used
in the Background or Window, these color IDs are associated with a _palette_. When
a tile is used in an OBJ, the IDs 1 to 3 are associated with a palette, but
a tile is used in an object, the IDs 1 to 3 are associated with a palette, but
ID 0 means transparent.

## Palettes
Expand Down Expand Up @@ -59,7 +59,7 @@ It is fairly limited: it has no transparency, it's always a
rectangle and only the position of the top-left pixel can be controlled.

Possible usage include a fixed status bar in an otherwise scrolling game (e.g.
_Super Mario Bros. 3_).
_Super Mario Land 2_).

### Objects

Expand All @@ -82,4 +82,4 @@ To summarise:

- **Tile**, an 8x8-pixel chunk of graphics.
- **Object**, an entry in object attribute memory, composed of 1 or 2
tiles. Independent of the background.
tiles. Can be moved independently of the background.