Language…
15 users online: deported, Domokun007, eltiolavara9, GiraffeKiller, Golden Yoshi, gothic251, h.carrell, koffe190, Maw, OEO6, OrangeRock57, Raccoon Sam, Rykon-V73, SirGabe, The_Uber_Camper - Guests: 259 - Bots: 363
Users: 64,795 (2,375 active)
Latest user: mathew

$2116 - Background Information

BG Modes
--------

The SNES has 7 background modes, two of which have major variations. The modes
are selected by bits 0-2 of register $2105. The variation of Mode 1 is selected
by bit 3 of $2105, and the variation of Mode 7 is selected by bit 6 of $2133.

Mode # Colors for BG
1 2 3 4
======---=---=---=---=
0 4 4 4 4
1 16 16 4 -
2 16 16 - -
3 256 16 - -
4 256 4 - -
5 16 4 - -
6 16 - - -
7 256 - - -
7EXTBG 256 128 - -

In all modes and for all BGs, color 0 in any palette is considered transparent.


Tile Maps and Character Maps
----------------------------

Each BG has two regions of VRAM associated with it: one for the tilemap, and
one for the character data.

The tilemap address is selected by bits 2-7 of registers $2107-a, and the
tilemap size is selected by bits 0-1 of that same register. All tilemaps are
32x32, bits 0-1 simply select the number of 32x32 tilemaps and how they're
layed out in memory:
00 32x32 AA
AA
01 64x32 AB
AB
10 32x64 AA
BB
11 64x64 AB
CD
Starting at the tilemap address, the first $800 bytes are for tilemap A. Then
come the $800 bytes for B, then C then D. Of course, if only A is required
something else could be stuck in the empty space.

Each entry in the tilemap is 2 bytes, formatted as (high low):
vhopppcc cccccccc

v/h = Vertical/Horizontal flip this tile.
o = Tile priority.
ppp = Tile palette. The number of entries in the palette depends on the Mode
and the BG.
cccccccccc = Tile number.

To find the tilemap word address for a particular tile (X and Y), you'd use a
formula something like this:
(Addr<<9) + ((Y&0x1f)<<5) + (X&0x1f) +
(SY ? ((Y&0x20)<<(SX ? 6 : 5)) : 0) + (SX ? ((X&0x20)<<5) : 0)

The tile character data is stored at the address pointed to by registers
$210b-c, starting at byte address:
(Base<<13) + (TileNumber * 8*NumBitplanes)
Each tile is (normally) 8x8 pixels. The data is stored in bitplanes.
Each row of the tile fills 1 byte, with the leftmost pixel being in bit 7. For
4-color tiles, bitplanes 0 and 1 are stored in the low and high bytes of a
word, with 8 words making up the tile. For a 16-color tile, bitplanes 0 and 1
are stored as for a 4-color tile, followed by bitplanes 2 and 3 in the same
format. A 256-color tile is stored in the same way as 2 4-color tiles.

If the appropriate bit of $2105 is set, each "tile" of the tilemap actually
corresponds to a 16x16 pixel block consisting of Tile, Tile+1, Tile+16, and
Tile+17. In this case, the 32x32 tile tilemap codes for a 512x512 pixel screen
rather than a 256x256 pixel screen as normal. Thus, using both 16x16 tiles and
the 64x64 tilemap each BG can be up to 1024x1024 pixels. There is no wrapping
like there is for 16x16 sprites: if you specify Tile=$2ff, you'll get $2ff,
$300, $30f, and $310 (as opposed to $2ff, $2f0, $20f, and $200 you might
otherwise expect). $3ff goes to $000, of course. Flipping in this mode flips th
whole 16x16 tile, not just the individual 8x8 tiles.


BG Scrolling
------------

Of course, depending on the BG mode and the interlace setting, Modes 0-6 have
an actual display of 256x224 or 256x239 pixels. The BG scroll registers
$210d-$2114 control the offset of the displayed area within that possible
256x256 to 1024x1024 pixel BG.

The display can never fall outside the BG: if that would seem to be the case,
simply wrap around back to 0 (or 'tile' the BG to fill the full 1024x1024,
however you like to think of it).

The registers $210d-$2114 are all write-twice to set the 16-bit value. The way
this works, the last write to any of these registers is stored in a buffer.
When a new byte is written to any register, the current register value, the
previous byte written to any of the 6 registers, and the new byte written
are combined as follows:
For BGnHOFS: (NewByte<<8) | (PrevByte&~7) | ((CurrentValue>>8)&7)
For BGnVOFS: (NewByte<<8) | PrevByte
For the most part, the details don't really matter as most games always write
two bytes to one of these registers. However, some games write only one byte,
or they do other odd things.

Thus, the tilemap entry for a particular X and Y position on the screen may be
calculated as follows:
Size = 8 or 16 depending on the appropriate bit of $2105
TileX = (X + BGnHOFS)/Size
TileY = (Y + BGnVOFS)/Size
Look up the tile at TileX and TileY as described above.

Note that many games will set their vertical scroll values to -1 rather than 0.
This is because the SNES loads OBJ data for each scanline during the previous
scanline. The very first line, though, wouldn't have any OBJ data loaded! So
the SNES doesn't actually output scanline 0, although it does everything to
render it. These games want the first line of their tilemap to be the first
line output, so they set their VOFS registers in this manner. Note that an
interlace screen needs -2 rather than -1 to properly correct for the missing
line 0 (and an emulator would need to add 2 instead of 1 to account for this).


Direct Color Mode
-----------------

For the 256-color BGs of Modes 3, 4, and 7, $2130 bit 0 when set enables direct
color mode. In this mode, instead of ignoring ppp and using the character data
as the palette index, you treat the character data as expressing a color
BBGGGRRR, and use the 3 bits of ppp as bgr to make the color
Red=RRRr0, Green=GGGg0, Blue=BBb00

In direct color mode you cannot have a black pixel, since any pixel with
character data = 0 is still considered transparent. Use one of the almost-black
colors instead (01, 08 or 09 are good choices).


Mode 0
------

In Mode 0, you have 4 BGs of 4 colors each. To calculate the starting palette
entry for a particular tile, you calculate:
ppp*4 + (BG#-1)*32

The background priority is (from 'front' to 'back'):
Sprites with priority 3
BG1 tiles with priority 1
BG2 tiles with priority 1
Sprites with priority 2
BG1 tiles with priority 0
BG2 tiles with priority 0
Sprites with priority 1
BG3 tiles with priority 1
BG4 tiles with priority 1
Sprites with priority 0
BG3 tiles with priority 0
BG4 tiles with priority 0


Mode 1
------

In Mode 1, you have 2 BGs of 16 colors and 1 BG of 4 colors. To calculate the
starting palette entry, calculate:
ppp*ncolors

The background priority varies depending on the setting of bit 3 of $2105.
The priority is (from 'front' to 'back'):
BG3 tiles with priority 1 if bit 3 of $2105 is set
Sprites with priority 3
BG1 tiles with priority 1
BG2 tiles with priority 1
Sprites with priority 2
BG1 tiles with priority 0
BG2 tiles with priority 0
Sprites with priority 1
BG3 tiles with priority 1 if bit 3 of $2105 is clear
Sprites with priority 0
BG3 tiles with priority 0


Mode 2
------

In Mode 2, you have 2 BGs of 16 colors each. To calculate the starting palette
index, calculate:
ppp*16

The priority is (from 'front' to 'back'):
Sprites with priority 3
BG1 tiles with priority 1
Sprites with priority 2
BG2 tiles with priority 1
Sprites with priority 1
BG1 tiles with priority 0
Sprites with priority 0
BG2 tiles with priority 0

Note the change from Modes 0 and 1.

Mode 2 is the first of the Offset-Per-Tile Modes. In this mode, the 'tile
data' for BG3 actually encodes a (possible) replacement HOffset and/or
VOffset value for each tile of BG1 and/or BG2.

Consider a visible scanline. Normally, you'd get the pixels something like
this:

HOFS = X + BGnHOFS
VOFS = Y + BGnVOFS
Pixel[X,Y] = GetPixel(GetTile(BGn, HOFS, VOFS), HOFS, VOFS)

With offset-per-tile, the formula is a little more complicated:

HOFS = X + BGnHOFS
VOFS = Y + BGnVOFS
ValidBit = 0x2000 for BG1, or 0x4000 for BG2
if (!IsFirst8x8Tile(BGn, HOFS)) {
/* Hopefully these calculations are right... */
Hval = GetTile(BG3, (HOFS&7)|(((X-8)&~7)+(BG3HOFS&~7)), BG3VOFS)
Vval = GetTile(BG3, (HOFS&7)|(((X-8)&~7)+(BG3HOFS&~7)), BG3VOFS + 8)
if (Hval&ValidBit) HOFS = (HOFS&7) | ((X&~7) + (Hval&~7))
if (Vval&ValidBit) VOFS = Y + Vval
}
Pixel[X,Y] = GetPixel(Get8x8Tile(BGn, HOFS, VOFS), HOFS, VOFS)

In other words, number the visible tiles in BGn from 0-32, and the 'visible'
tiles in BG3 the same way. BGn tile 0 is offset as normal, then for 1<=T<33
BGn tile T gets the offset data from BG3 tile T-1. It doesn't matter whether
or not the tiles actually align in any way.

Note that the leftmost visible tile is done as normal in all cases (although
as little as 1 pixel may be visible, and if that still bothers you then use
a clip window to hide it), and the next tile uses the tilemap entry for what
would be BG3's leftmost tile. Note also that the 'new' offset completely
overrides the BGnVOFS register, but the lower 3 bits of the BGnHOFS offset
are still used. And note that the current Y position on the screen does not
affect which row of the BG3 tilemap to reference, it's as if Y were always 0.

On the other hand, note that even if BGn is 16x16 tiles, BG3 can specify the
offset for each 8x8 subtile. And if BG3 is 16x16, the offsets will apply to
all the corresponding 8x8 subtiles on BGn. Also note that if BG3 is 16x16, we
may end up using the same tile for Hval and Vval.


Mode 3
------

In Mode 3, you have one 256-color BG and one 16-color BG. To calculate the
starting palette index, calculate:
BG1: 0
BG2: ppp*16

The priority is (from 'front' to 'back'):
Sprites with priority 3
BG1 tiles with priority 1
Sprites with priority 2
BG2 tiles with priority 1
Sprites with priority 1
BG1 tiles with priority 0
Sprites with priority 0
BG2 tiles with priority 0

Note that register $2130 may enable Direct Color Mode on BG1.


Mode 4
------

In Mode 4, you have one 256-color BG and one 4-color BG. To calculate the
starting palette index, calculate:
BG1: 0
BG2: ppp*4

The priority is (from 'front' to 'back'):
Sprites with priority 3
BG1 tiles with priority 1
Sprites with priority 2
BG2 tiles with priority 1
Sprites with priority 1
BG1 tiles with priority 0
Sprites with priority 0
BG2 tiles with priority 0

Note that register $2130 may enable Direct Color Mode on BG1.

Mode 4 is the second of the Offset-Per-Tile Modes. It operates much like
Mode 2, however the SNES doesn't have time to load two offset values.
Instead, it does this:
Val = GetTile(BG3, ...)
if (Val&0x8000) {
Hval = 0
Vval = Val
} else {
Hval = Val
Vval = 0
}


Mode 5
------

In Mode 5, you have one 16-color BG and one 4-color BG. To calculate the
starting palette index, calculate:
ppp*ncolors

The priority is (from 'front' to 'back'):
Sprites with priority 3
BG1 tiles with priority 1
Sprites with priority 2
BG2 tiles with priority 1
Sprites with priority 1
BG1 tiles with priority 0
Sprites with priority 0
BG2 tiles with priority 0

Mode 5 is rather different from the previous modes. Instead of using an 8/16
pixel wide tile as normal, it always takes a 16 pixel wide tile (the height
may still be 8 or 16) and only uses half the pixels (zero-based, the even
pixels for subscreen tiles and the odd pixels for mainscreen tiles). Then it
forces pseudo-hires on to render a 512-pixel wide scanline. Also, if
Interlace mode is on (see bit 0 of $2133), the screen is 448 or 478
half-lines high instead of 224 or 239. Either the odd half-lines or the even
half-lines are drawn each frame, as indicated by bit 7 of $213f.

Note that this means you must set $212c and $212d to the same value to get the
'expected' display.


Mode 6
------

In Mode 6, you have only one 16-color BG. To calculate the starting palette
index, calculate:
ppp*ncolors

The priority is (from 'front' to 'back'):
Sprites with priority 3
BG1 tiles with priority 1
Sprites with priority 2
Sprites with priority 1
BG1 tiles with priority 0
Sprites with priority 0

Mode 6 has the same oddities as Mode 5. In addition, it is an offset per tile
mode! That part works just like as Mode 2. However, remember that Mode 6 always
uses 8 pixel (16 half-pixel) wide tiles, this applies to BG3 as well as BG1.
You can't apply the offset to an 8-half-pixel tile nor to a 16-pixel wide area
(except by using two offset values for the two 8-pixel areas).


Mode 7
------

Mode 7 is extremely different from all the modes before. You have one BG of 256
colors. However, the tilemap and character map are laid out completely
differently.

The tilemap and charactermap are interleaved, with the character data being in
the high byte of each word and the tilemap data being in the low byte (note
that in hardware, VRAM is set up such that odd bytes are in one RAM chip and
even in another, and each RAM chip has a separate address bus. The Mode 7
renderer probably accesses the two chips independantly). The tilemap is 128x128
entries of one byte each, with that one byte being simply a character map
index. The character data is stored packed pixel rather than bitplaned, with
one pixel per byte. Thus, to calculate the tilemap entry byte address for an X
and Y position in the playing field, you'd calculate: (((Y&~7)<<4) + (X>>3))<<1

To find the byte address of the pixel, you'd calculate:
(((TileData<<6) + ((Y&7)<<3) + (X&7))<<1) + 1

Note that bits 4-7 of $2105 are ignored, as are $2107-$210c. They can be
considered to be always 0.

The next odd thing about Mode 7 is that you have full matrix transformation
abilities. With creative use of HDMA, you can even change the matrix per
scanline. See registers $211b-$2120 for details on the matrix transformation
formula. The entire screen can be flipped with bits 0-1 of $211a.

And finally, the playing field can actually be made larger than the tilemap. If
bit 7 of $211a is set, bit 6 of $211a controls what is seen filling the space
surrounding the map.

The background priorities are:
Sprites with priority 3
Sprites with priority 2
Sprites with priority 1
BG1
Sprites with priority 0

When bit 6 of $2133 is set, you get a related mode known as Mode 7 EXTBG. In
this mode, you get a BG2 with 128 colors, which uses the same tilemap and
character data as BG1 but interprets the high bit of the pixel as a priority
bit. The priority map is:
Sprites with priority 3
Sprites with priority 2
BG2 pixels with priority 1
Sprites with priority 1
BG1
Sprites with priority 0
BG2 pixels with priority 0

Note that the BG1 pixels (if BG1 is enabled) will usually completely obscure
the low-priority BG2 pixels.

BG2 uses the Mode 7 scrolling registers ($210d-e) rather than the 'normal' BG2
ones ($210f-10). Subscreen, pseudo-hires, math, and clip windows work as
normal; keep in mind OBJ and that you can do things like enable BG1 on main and
BG2 on sub if you so desire. Mosaic is somewhat weird, see the section on
Mosaic below.

Note that BG1, being a 256-color BG, can do Direct Color mode (in this case, of
course, there is no palette value so you're limited to 256 colors instead of
2048). BG2 does not do direct color mode, since it is only 7-bit.


Rendering the BGs
-----------------

Rendering a BG is simple.

1) Get your H and V offsets (either by reading the appropriate registers or by
doing the offset-per-tile calculation).
2) Use those to translate the screen X and Y into playing field X and Y
- Note this is rather complicated for Mode 7
3) Look up the tilemap for those coordinates
4) Use that to find the character data
5) If necessary, de-bitplane it and stick it in a buffer.

See the section "RENDERING THE SCREEN" below for more details.

Unresolved Issues
-----------------

1) What happens to the very first pixel on the scanline in Hires Math?
2) Various registers still need to know when writing to them is effective.