Wikia

ROM Hack City

Comments0

Mario Paint: Where are the sprite tiles?

Kernigh October 18, 2009 User blog:Kernigh

Inside the SNES, the VRAM (for "video RAM") is one of several types of memory. VRAM holds the pixel data (or "character data") for the 8x8 tiles. The SNES uses these 8x8 tiles to draw all backgrounds and sprites. VRAM has its own separate address space, but DMA allows a SNES game to copy tiles from ROM to VRAM.

I have not learned DMA, but I also have not learned which VRAM addresses to use for my tiles. Today, as I explore Mario Paint (JU) for SNES, I might begin to learn. I found this code in Mario Paint:

/*008385 a9 02*/	lda	#$02
/*008387 8d 01 21*/	sta.w	$2101
/*00838a 8d 05 01*/	sta.w	$0105

This puts the value $02 into hardware register $2101, and RAM mirror $000105.

Contents

What is register $2101? Edit

Anomie's Register Doc has this description of register $2101:

2101  wb++?- OBSEL - Object Size and Chr Address
        sssnnbbb

        sss  = Object size:
            000 =  8x8  and 16x16 sprites
            ...
        nn   = Name Select
        bbb  = Name Base Select (Addr>>14)
            See the section "SPRITES" below for details.

The section "SPRITES", subsection "Character table in VRAM", provides the following formula:

The first table is at the address specified by the Name Base bits of $2101, and
the offset of the second is determined by the Name bits of $2101. The word
address in VRAM of a sprite's first tile may be calculated as:
  ((Base<<13) + (cccccccc<<4) + (N ? ((Name+1)<<12) : 0)) & 0x7fff

I want to know how the value $02 in register $2101 affects the VRAM addresses of the sprite tiles.

What are VRAM addresses? Edit

memmap.cpp of snes9x-gtk 74 tells me that VRAM is 0x10000 bytes (equal to 64 kilobytes). However, registers $2116 and $2117 (which set the VRAM address during DMA) expose a word address, not a byte address. Each address holds two bytes, not only one byte. So VRAM addresses have range $0000..$7fff, such that

  • address $0000 has bytes x0000 and x0001,
  • address $0001 has bytes x0002 and x0003,
  • ...
  • address $7ffe has bytes xfffc and xfffd,
  • address $7fff has bytes xfffe and xffff.

Snes9x stores the VRAM as an array of bytes, so we can see how Snes9x doubles the VRAM address to compute the offset into the array. In ppu.cpp, Snes9x puts the VRAM address into PPU.VMA.Address.

                  case 0x2116:
                        // VRAM read/write address (low)
                        PPU.VMA.Address &= 0xFF00;
                        PPU.VMA.Address |= Byte;
                        ...
                  case 0x2117:
                        // VRAM read/write address (high)
                        PPU.VMA.Address &= 0x00FF;
                        PPU.VMA.Address |= Byte << 8;
                        ...

To double the address, Snes9x uses PPU.VMA.Address << 1 (a left shift by one). Here is an example in ppu.h:

        Memory.VRAM[Binary shift]]PU.VMA.Address << 1) & 0xFFFF] = Byte;

The VRAM addresses $8000..$ffff act like mirrors of $0000..$7fff, instead of overflowing the array. In Snes9x, the code & 0xFFFF enforces the mirror and prevents the overflow of the array.

How do I use the formula? Edit

When Mario Paint puts $02 in register $2101, the result is:

$02 == %00000010
        sssnnbbb
  •  %sss = 0, so the SNES draws 8x8 and 16x16 sprites.
  •  %nn = 0.
  •  %bbb = 2.

In anomie's formula, %nn becomes "Name", and %bbb becomes "Base". The other inputs are the formula are the tile number "%cccccccc" and the "%N" bit; these inputs are per sprite and come from OAM.

The first table is at the address specified by the Name Base bits of $2101, and
the offset of the second is determined by the Name bits of $2101. The word
address in VRAM of a sprite's first tile may be calculated as:
  ((Base<<13) + (cccccccc<<4) + (N ? ((Name+1)<<12) : 0)) & 0x7fff

To understand this formula, I vertically write the formula in binary, to show how the binary shift affects each term of the formula.

(when N == 0)   %bbb00000 00000000 == Base<<13
              + %0000cccc cccc0000 == cccccccc<<4
              & %01111111 11111111 == 0x7fff
                ==================
VRAM address == %0bb0cccc cccc0000


(when N == 1)   %bbb00000 00000000 == Base<<13
              + %0000cccc cccc0000 == cccccccc<<4
              + %0iii0000 00000000 == (Name+1)<<12
              & %01111111 11111111 == 0x7fff
                ==================
VRAM address == %0jjicccc cccc0000

I wrote %nn + 1 as %iii. Because %nn is a number from 0 to 3, so %iii is a number from 1 to 4. I also wrote %bb + %ii as %jj. This is the only part of the addition that might cause a carry. (I wonder if the correct formula uses binary-or or binary-xor instead of addition?)

The purpose of %bbb is to set the high 3 bits of the VRAM address; but the highest bit disappears. The purpose of %nn is to choose how bit %N affects the VRAM address.

Also, I must not forget to mention that %0jjicccc cccc0000 is the VRAM address of the first tile. An 8x8 sprite uses only this tile. (If I understand the document, then a 16x16 sprite uses this tile, the 1st next tile, the 16th next tile and the 17th next tile.) Because sprites use 4bpp graphics, and an 8x8 tile has 64 pixels, so each tile occupies 256 bits, equaling 32 bytes, equaling 16 words. The low bits of the VRAM address of the tile are %0000, but this only means that we must align the tiles in memory. Low bits %0000 through %1111 point to each of the 16 words in the tile.

Where are the sprite tiles in Mario Paint? Edit

When Mario Paint puts $02 in register $2101, the result is:

$02 == %00000010
        sssnnbbb
  •  %sss = 0, so the SNES draws 8x8 and 16x16 sprites.
  •  %nn = 0.
  •  %bbb = 2.

I only need to substitute %iii = %nn + 1 = 1 and %bbb = 0 into the formula for VRAM address.

(when N == 0)   %01000000 00000000 == Base<<13
              + %0000cccc cccc0000 == cccccccc<<4
              & %01111111 11111111 == 0x7fff
                ==================
VRAM address == %0100cccc cccc0000


(when N == 1)   %01000000 00000000 == Base<<13
              + %0000cccc cccc0000 == cccccccc<<4
              + %00010000 00000000 == (Name+1)<<12
              & %01111111 11111111 == 0x7fff
                ==================
VRAM address == %0101cccc cccc0000

Therefore, the instant after Mario Paint stores $02 to register $2101, the VRAM address of the first tile of each OAM sprite is %010Ncccc cccc0000.

I am not sure whether Mario Paint can store a value other than $02 to register $2101. Such other values would change the VRAM address.

Advertisement | Your ad here

Photos

Add a Photo
10photos on this wiki
See all photos >

No recent blog posts. Write one now!


What are Wikia Blogs?

Wikia community blogs allow you to contribute a blog post to any wiki's Community Blog.

Blogs are used by wiki communities for fan fiction or original work, news and announcements, questions or recommendations to the community, or reviews or op-eds. Check out Fallout Wiki's News Blog and Lostpedia's Theories Blog to see two examples.

Around Wikia's network

Random Wiki