nesdev.com
http://forums.nesdev.com/

Questions about SNES programming
http://forums.nesdev.com/viewtopic.php?f=12&t=19147
Page 1 of 2

Author:  SusiKette [ Mon Jul 29, 2019 11:16 am ]
Post subject:  Questions about SNES programming

I was thinking of trying SNES programming, but there are a few things that I need to ask about before I can start.

The first thing is to understand how the SNES uses the available memory. As far as I know, RAM and registers are at $xx:0000 - $xx:7FFF and ROM is at $xx:8000 - $xx:FFFF. xx is the value at Program Bank or Data Bank register depending on whether its accessed by read/write instruction or instruction fetch. Do reads/writes at $0000 - $7FFF care what value xx is?

Now, PPU memory is a bit more of a mystery to me. How do you assign pattern tables and how many tiles can they hold at once? Can parts of the pattern table be swapped or are you limited to certain minimum sizes you can swap at once? Or can you swap individual tiles kinda like CHR RAM on some NES mappers? What about nametables and attributes?

Author:  lidnariq [ Mon Jul 29, 2019 11:36 am ]
Post subject:  Re: Questions about SNES programming

SusiKette wrote:
The first thing is to understand how the SNES uses the available memory.
There are multiple different ways that cartridges work. What you described is "Mode 20h", mostly, or "LoROM".

Divide the 24-bit address of the SNES's CPU into three eight-bit quantities. In order, call those the "bank", "page", and ... nothing.

The SNES itself only imposes a few limits:
  • 8K of RAM can be accessed in banks $00-$3F, $7E, and $80-$BF, across pages $00-$1F.
  • 128K of RAM can be accessed in banks $7E and $7F, across all pages, not redundant.
  • registers to configure how everything operates can be accessed in banks $00-$3F and $80-$BF, in pages $21 and $40-$43.

But "bank" is misleading: the SNES's CPU provides the ability to natively specify the full 24-bit address without using bankswitching.

The SNES hardware makes specific memory layouts easier. It provides a specific signal on the connection to the cartridge that lets the cart know when ("bank" is $40-$7D or $C0-$FF) or ("bank" is $00-$3F or $80-$BF and "page" is $80-$FF).

Quote:
How do you assign pattern tables and how many tiles can they hold at once? Can parts of the pattern table be swapped or are you limited to certain minimum sizes you can swap at once? Or can you swap individual tiles kinda like CHR RAM on some NES mappers? What about nametables and attributes?
In the SNES, 64KB of RAM is available to hold everything to be drawn. Unlike the NES, this cannot be changed by the cartridge. Also unlike the NES, there's a wide variety of ways to interpret the data. There is no attribute table; nametable entries are always 16 bits wide. Up to four background layers plus a layer of sprites can be drawn, each from their own location in memory. Each background layer has its own nametable, each nametable can be any of the four combinations of 32 or 64 tiles wide and tall; each nametable entry can represent an 8x8 (or 16x8 in specific cases) or a 16x16 pixel region.

I'd suggest using some SNES emulator with a debugger—NO$SNS, bsnes-plus, or Mesen-S—and looking at what's going on.

Author:  SusiKette [ Mon Jul 29, 2019 3:12 pm ]
Post subject:  Re: Questions about SNES programming

lidnariq wrote:
In the SNES, 64KB of RAM is available to hold everything to be drawn. Unlike the NES, this cannot be changed by the cartridge. Also unlike the NES, there's a wide variety of ways to interpret the data. There is no attribute table; nametable entries are always 16 bits wide. Up to four background layers plus a layer of sprites can be drawn, each from their own location in memory. Each background layer has its own nametable, each nametable can be any of the four combinations of 32 or 64 tiles wide and tall; each nametable entry can represent an 8x8 (or 16x8 in specific cases) or a 16x16 pixel region.


So in other words, the programmer defines where each data is located in VRAM? Still I don't know how you define sprite graphics location, or is it fixed?

Author:  dougeff [ Mon Jul 29, 2019 3:28 pm ]
Post subject:  Re: Questions about SNES programming

Register 2101, Name Base Select is the last 3 bits... actually the last 2 bits, the 3rd one is unused.

So sprite graphics can be at $0000, $2000, $4000 or $6000 in the VRAM.

Author:  Pokun [ Mon Jul 29, 2019 3:32 pm ]
Post subject:  Re: Questions about SNES programming

Quote:
So in other words, the programmer defines where each data is located in VRAM? Still I don't know how you define sprite graphics location
Exactly! You set the base address in VRAM for each "SC" (tilemap nametable) for each background layer, the "BG CHR name" (pattern table for background characters) and the "OBJ CHR name" (pattern table for sprites) using hardware registers. For example the SC base addresses are set by writing the addresses to registers $2107-$210A. Depending what modes, formats and sizes you use, you have to plan and set up VRAM accordingly.

The Color Generator (palette) and OBJ attributes (sprite attributes) however have their own fixed memory and are not set in VRAM. The palette is set into CGRAM and sprite attributes are in OAM like for NES.

Author:  koitsu [ Mon Jul 29, 2019 6:10 pm ]
Post subject:  Re: Questions about SNES programming

In short: yes, you choose where things in PPU RAM end up. You get to manage/define the 64KByte of space yourself.

Be aware, however:

1. There are alignment requirements for each "type" of data:

a) Background nametable (officially called "BG-SC" or "SC" data) base address is 2KByte / 1KWord aligned; see MMIO registers $2107-210A
b) Background CHR (officially called "BG character data") base address is 8KByte / 4KWord aligned; see MMIO registers $210B-210C
c) Sprites/OAM are more complicated; there is an 16KByte / 8KWord alignment; see MMIO register $2101. Sprite alignment in PPU RAM is somewhat complicated; refer to other docs
d) Palette is stored independently elsewhere (i.e. not in PPU RAM), and specific MMIO registers are used to interface with it

All backgrounds/sprites/everything share the same PPU RAM, and with higher bit depths on the SNES than the NES, it can be very easy to run out of PPU RAM (considering alignments, etc.).

Mirroring/etc. is controlled via MMIO registers as well (commonly called "SC size"), with native support for 1x1, 1x2, 2x1, and 2x2 (i.e. 4-screen). Larger sizes require more PPU RAM, obviously.

2. How the data is used/accessed/utilised depends on video mode (MMIO register $2105) and background number. For example, mode 1 has 3 backgrounds, 2 of which are 4 bits per pixel, with the 3rd BG being 2bpp.

3. SNES documentation and MMIO registers often refer to things/offsets __in words__, not bytes. As such, you'll become extremely reliant on macros to do the byte-to-word conversions, and will often spend time debugging problems relating to this when using PPU RAM viewers and so on (some show things in "raw values the PPU has", others show things in bytes, some intermix both). Here are 4 ca65 macros I use, and some equates, with some examples, for mode 1 (I chose not to include details about BG3):

Code:
.define ppuaddr(addr)             (addr / 2)
.define bgmap(addr, size)         ((((addr / 2) & $FC00) >> 8) | size)
.define bg12chr(bg1addr, bg2addr) (((bg2addr / 2) >> 8) | ((bg1addr / 2) >> 12))
.define bg34chr(bg3addr, bg4addr) (((bg4addr / 2) >> 8) | ((bg3addr / 2) >> 12))
SC_SIZE_32X32         = %00
SC_SIZE_64X32         = %01
SC_SIZE_32X64         = %10
SC_SIZE_64X64         = %11

bg1mapaddr  = $0000          ; $0000-0FFF: BG1 map, 2 horizontal screens
bg2mapaddr  = $1000          ; $1000-17FF: BG2 map, single screen
bg1chraddr  = $2000          ; $2000-xxxx: BG1 CHR data
bg2chraddr  = $6000          ; $6000-xxxx: BG2 CHR data

sep #$30    ; 8-bit A/X/Y
rep #$10    ; 16-bit X/Y

lda #bgmap(bg1mapaddr, SC_SIZE_64X32)
sta $2107
lda #bgmap(bg2mapaddr, SC_SIZE_32X32)
sta $2108

lda #bg12chr(bg1chraddr, bg2chraddr)
sta $210B

ldx #ppuaddr(bg1mapaddr)
stx $2116
...

ldx #ppuaddr(bg1chraddr)
stx $2116
...

The model used on the SNES is that since ROM can be so large, and native DMA transfers between CPU addressing space (e.g. ROM) and PPU are available, don't be afraid to use ROM space for all your stuff. You have a lot more breathing room that on the NES.

Author:  SusiKette [ Mon Jul 29, 2019 10:20 pm ]
Post subject:  Re: Questions about SNES programming

Okay, I think I now understand how the SNES memory space works. I also found a text document that has memory maps for both LoROM and HiROM. I need probably need to refer to it in the future.

Author:  lidnariq [ Mon Jul 29, 2019 10:40 pm ]
Post subject:  Re: Questions about SNES programming

I would strongly recommend using tepples's memory map diagrams because we've had problems with some of the other depictions of this being confusing, or wrong, or both.

Author:  93143 [ Mon Jul 29, 2019 10:46 pm ]
Post subject:  Re: Questions about SNES programming

If I could recommend a few sources...

https://wiki.superfamicom.org/tags/reference

In particular,
https://wiki.superfamicom.org/memory-mapping
https://wiki.superfamicom.org/registers
https://wiki.superfamicom.org/backgrounds
https://wiki.superfamicom.org/sprites
https://wiki.superfamicom.org/dma-and-hdma
and
https://wiki.superfamicom.org/65816-reference
if you need it.

Lots of great information on there. A lot of it is based on anomie's docs, but there are some original contributions.

Also: https://problemkaputt.de/fullsnes.htm is nocash's doc, which is more recent than anomie's stuff and contains (IIRC) some info that isn't in the above. I find it harder to navigate, but maybe that's just me.

If you already know about these, great.

Author:  SusiKette [ Tue Jul 30, 2019 10:34 am ]
Post subject:  Re: Questions about SNES programming

By the way, since portion of the RAM is called "Low RAM", does it differ in any way from the rest of the RAM available?

Author:  tepples [ Tue Jul 30, 2019 10:49 am ]
Post subject:  Re: Questions about SNES programming

No. Low RAM is just the 8K mirror of $7E0000-$7E1FFF that appears in banks $00-$3F and $80-$BF. It has the same "slow" (8 master clocks) speed as banks $7E and $7F.

Author:  lidnariq [ Tue Jul 30, 2019 10:50 am ]
Post subject:  Re: Questions about SNES programming

It's available in multiple difference places because several instructions can only access things in bank 0, and many instructions can only access things within the same program ("K") or data ("B") bank.

Author:  dougeff [ Tue Jul 30, 2019 12:25 pm ]
Post subject:  Re: Questions about SNES programming

Do you have to put the stack and direct page in the lowRAM?

Author:  tepples [ Tue Jul 30, 2019 12:28 pm ]
Post subject:  Re: Questions about SNES programming

You can place them anywhere in bank $00. But on the Super NES, under the standard cartridge memory mapping, the most useful place for the stack is low RAM, and the most useful places for the direct page are low RAM and the DMA registers.

Author:  93143 [ Tue Jul 30, 2019 1:17 pm ]
Post subject:  Re: Questions about SNES programming

And the PPU registers, depending on what you're doing. If you happen to need fast access to a data table in ROM, you can use direct page for that too, as long as the cart mapping puts the data you want in bank $00.

The great part about direct page is that it's fairly quick and painless to move it, so you don't have to settle on one setting and leave it there for the whole game. In fact you can use it almost as a third index register, which then provides the ability to do nested free indexing because most direct-page instructions have indexed variants. You just have to get in the habit of pushing and pulling D in interrupts.

But yeah, the stack should probably go in RAM...

Page 1 of 2 All times are UTC - 7 hours
Powered by phpBB® Forum Software © phpBB Group
http://www.phpbb.com/