⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qsnesdoc.html

📁 SNES game emulator. C and asm files.
💻 HTML
📖 第 1 页 / 共 5 页
字号:
VRAM, it would have to be stored like this:
<PRE>Offset&nbsp; Y-coord. Tile Coord
0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0-7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (0, 0) (8, 0) (16, 0) (24, 0) &lt;Unused--room for 12 more tiles>
512&nbsp;&nbsp;&nbsp;&nbsp; 8-15&nbsp;&nbsp;&nbsp;&nbsp; (0, 8) (8, 8) (16, 8) (24, 8) &lt;Unused--room for 12 more tiles>
1024&nbsp;&nbsp;&nbsp; 16-23&nbsp;&nbsp;&nbsp; (0,16) (8,16) (16,16) (24,16) &lt;Unused--room for 12 more tiles>
1536&nbsp;&nbsp;&nbsp; 24-31&nbsp;&nbsp;&nbsp; (0,24) (8,24) (16,24) (24,24) &lt;Unused></PRE>
In practice, the sprites are interleaved.&nbsp; In other words, when using
32x32 tiles, there would be 3 more sprites stored in that "unused" space.&nbsp;
If the first sprite, shown in the above table, started at offset 0, the
next sprite would start at offset 128 (the <A HREF="#SpriteBasics_CharNum">Character
Number</A>, in <A HREF="#PPUMemoryTypes">OAM</A>, would be 4); the third
sprite would start at offset 256 (Character #8), and the fourth sprite
would start at offset 384 (Character #12).&nbsp; If a fifth sprite was
desired, the pattern would repeat and it would be located at offset 2048
(Character #64).

<P>Similarly, when using 16x16 sprites, there will be 8 sprites interleaved,
and the ninth sprite will have to start after them at offset 1024.&nbsp;
Finally, 64x64 sprites have only two sprites interleaved.&nbsp; It is also
possible to format it such that larger sprites can be interleaved with
smaller sprites, but that is somewhat confusing to try to explain.

<P>In OAM there are two tables which control the position, size, mirroring,
palette, and priority of sprites.&nbsp; This table has room for 128 entries;
thus, the SNES can display up to 128 sprites on the screen at once (although
I think a real SNES will overload and screw up its display when there are
too many large sprites.)&nbsp; The first table has four bytes per sprite,
and is formatted like this:
<PRE>Byte 1&nbsp;&nbsp;&nbsp; xxxxxxxx&nbsp;&nbsp;&nbsp; x: X coordinate
Byte 2&nbsp;&nbsp;&nbsp; yyyyyyyy&nbsp;&nbsp;&nbsp; y: Y coordinate
Byte 3&nbsp;&nbsp;&nbsp; cccccccc&nbsp;&nbsp;&nbsp; c: starting character (tile) number&nbsp;&nbsp;&nbsp; p: palette number
Byte 4&nbsp;&nbsp;&nbsp; vhoopppc&nbsp;&nbsp;&nbsp; v: vertical flip&nbsp;&nbsp; h: horizontal flip&nbsp; o: priority bits
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Note: the 'c' in byte 4 is the MOST significant bit in the 9-bit char #.</PRE>
The second table is 32 bytes and has 2 bits for each sprite (each byte
contains information for 4 sprites.)&nbsp; The lowest significant bits
hold the information for the lower object numbers (for example, the least
significant two bits of the first byte are for object #0.)&nbsp; Bit 0
(and 2, 4, 6) is the size toggle bit (see bits 5-7 of <A HREF="#Reg2101">register
$2101</A>) and bit 1 (3, 5, 7) is the most ignificant bit of the X coordinate.

<P>The vertical and horizontal flips work similarly to flips in the BGs;
the entire sprite is flipped so that the leftmost pixel is swapped with
the rightmost pixel, etc.&nbsp; To see the effect of the priority bits,
see the description of <A HREF="#Reg2105">register $2105</A>.&nbsp; The
palettes start at CG entry 128, so that palette 0 is colors 128 to 143,
and palette 1 consists of colors 144 to 159.

<P><A NAME="SpriteBasics_CharNum"></A>The character number indexes into
an array of 8x8 tiles starting at a base VRAM location selected by bits
0-2 of <A HREF="#Reg2101">register $2101</A>. The byte address in VRAM
where the character data starts can be found using the following calculation:
<BR>&nbsp;&nbsp;&nbsp; address_of_character = (base_location_bits &lt;&lt;
14) + (32 * character_number);
<BR>For example, if base location 1 is selected, and character number 1
is selected, the address will be 16384+32*1 = 16416.&nbsp; Note that the
word address entered into the <A HREF="#Reg2116">VRAM address register</A>
will be half of that, or 8208.

<P>Notice that two or more sprites in the OAM table may have the same character
number; if this is the case, they will look the same except that they can
be mirrored independently and have different palettes.

<P><A NAME="ColorPalettes"></A><FONT SIZE=+1>Color palettes</FONT>

<P>Once the final color value is derived from the character data and 'palette
number' for the sprite or <A HREF="#Terminology">BG</A>, it is indexed
into the <A HREF="#PPUMemoryTypes">CGRAM</A> color palette array.&nbsp;
There are 512 bytes of CGRAM, with each of the 256 colors using two bytes.&nbsp;
Each of the palette entries is formatted like this:
<PRE>?bbbbbgg gggrrrrr&nbsp;&nbsp;&nbsp; ?: Unused and ignored&nbsp; b: Blue intensity
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; g: Green intensity&nbsp;&nbsp;&nbsp;&nbsp; r: Red intensity</PRE>
(Notice this is backwards to the conventional RGB format.)&nbsp; To upload
palette entries to CGRAM, select the color with register $2121, and then
begin sending the bytes to <A HREF="#Reg2122">register $2122</A>.
<BR>&nbsp;
<CENTER><A NAME="GraphicsFormat"></A><FONT SIZE=+3>The SNES Graphics Format</FONT></CENTER>


<P>All SNES graphics (except in <A HREF="#Terminology">BG</A>1 of Mode
7) are made up of <A HREF="#Terminology">Tiles</A>, also called character
data.&nbsp; The basic tile is 8x8 in size, and larger bitmaps are stored
in the form of two-dimensional arrays of these small tiles.&nbsp; On most
computers, bitmaps are stored in a packed format: the color bits are grouped
together in the same byte (or word, or dword, for high-color displays.)&nbsp;
However, SNES graphics are planar; that is, the each of the color bits
are stored separately.&nbsp; Each color plane of the tile is stored like
this:
<PRE>byte 0:&nbsp;&nbsp; top scanline&nbsp;&nbsp; 01234567
byte 2:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 01234567&nbsp;&nbsp;&nbsp;&nbsp; right
byte 4:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; left&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 01234567&nbsp;&nbsp;&nbsp;&nbsp; side
byte 6:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; side&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 01234567&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of
byte 8:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; of&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 01234567&nbsp;&nbsp;&nbsp;&nbsp; tile
byte 10:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tile&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 01234567&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
byte 12:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 01234567&nbsp; Note that left/right and top/bottom can
byte 14: bottom scanline 01234567&nbsp; be reversed using the BG/sprite flip bits.</PRE>
Planes 0 and 1 are stored first, followed by planes 2 and 3, etc.&nbsp;
As you can see, the bytes in each plane are two bytes apart; the byte "in
between" is the following plane.&nbsp; In other words, byte 0 stores the
first eight pixels of plane 0 and byte 1 stores the first eight pixels
of plane 1.&nbsp; If using more than 4 colors, the pattern repeats; byte
16 stores the first eight pixels of plane 2 and byte 17 stores the first
eight pixels of plane 3.

<P>When the tile is to be displayed on the screen, a bit is taken from
each of the planes to form a 2-, 4-, or 8-bit value to index into the <A HREF="#ColorPalettes">color
palette</A>.&nbsp; The first tile (plane 0) contains the least significant
bit of the color, and the last tile contains the most significant bit.

<P><A NAME="Mode7GrFormat"></A><FONT SIZE=+1>Mode 7 Graphics Representation</FONT>

<P>In Mode 7, both the tile map and the tiles themselves are stored differently.&nbsp;
In fact, the tile data and the graphic data are interleaved.&nbsp; The
first byte (low byte) is an element of the tile map, and the second byte
(high byte) is the color value of a pixel.
<PRE>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; First Byte&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Second Byte
Bits&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 7&nbsp; 6&nbsp; 5&nbsp; 4&nbsp; 3&nbsp; 2&nbsp; 1&nbsp; 0&nbsp; 15 14 13 12 11 10 9&nbsp; 8
Contains&nbsp; Tile Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Graphics data</PRE>
The Mode 7 screen data occupies all of the first 32 KB of VRAM: 16K is
for graphics data, and 16K is for the tile numbers.&nbsp; The tile map
format is simply the tile number with no other information, and takes one
byte.&nbsp; The dimensions of the tile map are 128x128 (=16384 bytes).&nbsp;
Unlike all other screen modes, the graphics data is a packed, linear format
and each color value directly indexes into CGRAM.&nbsp; The tiles are still
8x8 pixels, and thus take 64 bytes per tile.&nbsp; There are 256 characters
in total.&nbsp; The calculation to find which character to display is simply
64 * Tile_Number.

<P>A variation of Mode 7, EXTBG (see bit 6 of register $2133), cuts the
colors down to 128 and uses the most significant color bit as a priority
bit.
<CENTER><A NAME="RegisterReference"></A><FONT SIZE=+3>Register Reference</FONT></CENTER>


<P>This section may not be quite accurate.&nbsp; Please tell me if you
find an error.&nbsp; W means writeable; R means readable.&nbsp; 2b means
the register is one word in size;&nbsp; Db means that it is a one-byte
register that must be written or read twice.&nbsp; In contrast to the Y0shi
Doc, auto-incrementing registers such as <A HREF="#Reg2122">$2122</A> are
not considered Db registers, because they can be written any number of
times (writing one byte will work just as well as writing two, or writing
a hundred.)

<P>Can anyone tell me what is supposed to happen when you read from a write
register?
<CENTER>&nbsp;</CENTER>

<CENTER><A NAME="RegOAM"></A><FONT SIZE=+2>OAM Registers</FONT></CENTER>


<P><A NAME="Reg2101"></A><B><FONT FACE="Lucida Console">Register $2101:
OAM Size (1b/W)</FONT></B>
<PRE>sssnnbbb&nbsp;&nbsp; s: Object size&nbsp; n: name selection&nbsp; b: base selection
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Size bit in OAM table:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0&nbsp;&nbsp;&nbsp;&nbsp; 1
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Bits of object size:&nbsp;&nbsp;&nbsp; 000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8x8&nbsp;&nbsp; 16x16
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 001&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8x8&nbsp;&nbsp; 32x32
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 010&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 8x8&nbsp;&nbsp; 64x64
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 011&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16x16 32x32
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 100&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 16x16 64x64
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 101&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 32x32 64x64
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 110,111&nbsp; Unknown behavior</PRE>
This register selects the location in VRAM where the character data is
stored, and the size of sprites on the screen.&nbsp; The byte location
of the character data can be found by shifting the b (base selection) bits
left by 14.&nbsp; Note that this allows only four different locations in
VRAM to put the sprite data; the high bit of the base selection should
always be zero since only 64K of VRAM can be addressed.

<P>I have no information on the name selection bits.

<P><A NAME="Reg2102"></A><B><FONT FACE="Lucida Console">Register $2102/$2103:
Address for accessing OAM (2b/W)</FONT></B>
<PRE>aaaaaaaa r??????m&nbsp; a: low byte of OAM address
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r: OAM priority rotation&nbsp; m: OAM address MSB</PRE>
This register selects the byte location to begin uploading (or downloading)
data to OAM.

<P>I'm sorta guessing, but I think that the priority rotation thing is
applied by SNES games to keep sprites on the screen.&nbsp; That is, when
there are too many sprites on the screen at once I believe the SNES will
turn certain sprites off in order to reduce the load on the PPU.&nbsp;
So I think the SNES takes the "a" bits, shifts them right one and the result
is which sprite to re-activate.&nbsp; In the process another sprite gets
turned off.&nbsp; Another possibility is that it doesn't matter what address
you select, it simply picks any sprite that is off and turns it on, perhaps
simultaneously turning off a sprite that has been on for a while.

<P><A NAME="Reg2104"></A><B><FONT FACE="Lucida Console">Register $2104:
Data write to OAM (1b/W)</FONT></B>
<PRE>dddddddd&nbsp; d: byte to write to VRAM</PRE>
This register writes a byte to OAM.&nbsp; After the byte is stored, the
OAM address is incremented so that the next write or read will be to the
following address.

<P><A NAME="Reg2138"></A><B><FONT FACE="Lucida Console">Register $2138:
Data read from OAM (1b/R)</FONT></B>
<PRE>dddddddd&nbsp; d: byte that was read from OAM</PRE>
After the byte is read, the OAM address is incremented so that the next
write or read will be to the following byte.
<CENTER>&nbsp;</CENTER>

<CENTER><A NAME="RegColor"></A><FONT SIZE=+2>Color Registers</FONT></CENTER>


<P><A NAME="Reg2121"></A><B><FONT FACE="Lucida Console">Register $2121:
Address for accessing CGRAM (1b/W)</FONT></B>
<PRE>aaaaaaaa a: CGRAM word address</PRE>
This register selects the&nbsp; word location (byte address * 2) to begin
uploading (or downloading) data to CGRAM. Click <A HREF="#ColorPalettes">HERE</A>
for more information on color palettes.

<P><A NAME="Reg2122"></A><B><FONT FACE="Lucida Console">Register $2122:
Data write to CGRAM (1b/W)</FONT></B>
<PRE>dddddddd&nbsp; d: byte to write to CGRAM</PRE>
This register writes a byte to CGRAM.&nbsp; After the byte is stored, the
CGRAM address is incremented so that the next write or read will be to
the following byte.

<P><A NAME="Reg213B"></A><B><FONT FACE="Lucida Console">Register $213B:
Data read from CGRAM (1b/R)</FONT></B>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -