getting started on SNES

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
getting started on SNES
by on (#156133)
I'm having trouble finding good source material for the SNES to start learning from. I found 1 Hello World on github (in German). But, there's no nerdy nights equivalent for the SNES.

I was thinking about using a debugger and going step by step through an actual game, to see how it initializes things and sets everything up. Does anyone have any suggestions for a simple game I can start looking at, or should I just start with SMW since it's so well documented? Did anyone make a Pac-man or Galaga port to the SNES that I can look at (examples of simple games).
Re: getting started on SNES
by on (#156134)
Oh, I see that Frogger, Space Invaders, and Ms. Pacman were. Space invaders might be the easier of them to figure out.
Re: getting started on SNES
by on (#156135)
Superfamicom.org is your friend: http://wiki.superfamicom.org/snes/show/HomePage

You could try looking at bazz's tutorials just like I did, but I'm sure you already know most of that stuff, and they're using WLA... I started off fiddling with the Walker demo in "Neviksti's Starter Kit" under this: http://wiki.superfamicom.org/snes/show/ ... nvironment
Re: getting started on SNES
by on (#156137)
I've got a walker demo for Super NES in ca65 if you're interested.
Re: getting started on SNES
by on (#156141)
Thanks guys.

I don't know if I'm going to make any SNES homebrews, but I've had a few people ask me if I can mod SNES games, and I'd really like to learn it, since SNES was the system I played through high school.

Dumb question... what's the difference between HiROM and LoROM?
Re: getting started on SNES
by on (#156142)
In LoROM (mode $20), CPU A15 isn't connected to the ROM. In HiROM (mode $21), it is. This means in LoROM, data occupies the upper half of each 64 KiB bank, while in HiROM, ROM data occupies the whole bank. LoROM is intended to be accessed through $808000-$80FFFF, $818000-$81FFFF, $828000-$82FFFF, etc., while HiROM just starts at $C00000 and goes up. The reason for LoROM's existence is related to the mirroring of the first 8 KiB of RAM and MMIO registers throughout banks $00-$3F and $80-$BF so that you don't always have to use (slower) long addressing modes to reach MMIO. However, the second half of each bank of HiROM is also mirrored down into $80-$BF, letting you do MMIO with 2-byte addresses from pseudo-LoROM routines stored there.

View more definitions
Re: getting started on SNES
by on (#156145)
Just so I understand...

In either mode, LoROM or HiROM, can I access all banks?

Edit. Oh wait, there are 2 different types of cartridges... One mapped with LoROM and one mapped with HiROM. Do I have that right? And so, its not like switching from Native mode to Emulator mode, or something like that.
Re: getting started on SNES
by on (#156148)
dougeff wrote:
Just so I understand...

In either mode, LoROM or HiROM, can I access all banks?

Edit. Oh wait, there are 2 different types of cartridges... One mapped with LoROM and one mapped with HiROM. Do I have that right? And so, its not like switching from Native mode to Emulator mode, or something like that.


Yeah, it's two types of cartridges that are physically wired differently--a bit like horizontal/vertical CIRAM mirroring on the NES.

There are actually a lot more than two cartridge types, with subtle differences involving which address ranges are mirrored in cartridges with SRAM and/or with multiple physical ROM chips, but you really don't have to worry about them unless you're an emulator developer.
Re: getting started on SNES
by on (#157027)
Ive read every document on SNES that I could find. I have a few questions...just so I know I have it right.

1. The SNES has a VRAM that is divided into 3 parts...Color palette, OAM (sprite attributes), and tilemap...each accessible though different registers...
2121/2122 for palette, 2102-4 OAM, 2116-9 tilemap. Do I have that right?
2. How do I write tile data then (CHR)?
3. Do you usually write to the VRAM with a DMA?
4. Do you have to write to VRAM during V-blank?
5. In mode 1, there are 3 BG layers? If an upper one is mostly color 0, does that work as a mostly transparent layer?

Edit...
6. I'm also slightly confused with joypad reads. There seems to be 2 ways to read the joypads (auto and manual) with a warning somewhere about getting incorrect reads if done at the wrong time. Is there a 'standard' way of doing this?
Re: getting started on SNES
by on (#157028)
dougeff wrote:
1. The SNES has a VRAM that is divided into 3 parts...Color palette, OAM (sprite attributes), and tilemap...each accessible though different registers...

Yes, much as with the NES, except the palette doesn't overlay the last 256 words of VRAM addresses anymore.

Quote:
2. How do I write tile data then (CHR)?

It should be familiar if you've ever used CHR RAM on the NES: write the address, then write the data. Tiles and tile map both go in the main 32 Kword (64 KiB) VRAM.

Quote:
3. Do you usually write to the VRAM with a DMA?

Yes. "Blast Processing" is one advantage the Genesis and Super NES have over the third-gen systems.

Quote:
4. Do you have to write to VRAM during V-blank?

Yes, just as on the NES. Unlike on the Genesis, there's no VRAM write FIFO. Or if you're willing to do a little letterboxing, you can also write during forced blank. This is a lot easier to pull off on the Super NES than on the NES.

Quote:
5. In mode 1, there are 3 BG layers? If an upper one is mostly color 0, does that work as a mostly transparent layer?

Correct.
Re: getting started on SNES
by on (#157030)
Thanks. I was editing (adding another question) while you were typing. Any thoughts on button reads?

And...
7. Do sprites use the same tileset that BGs do in the same area of the VRAM?
Re: getting started on SNES
by on (#157031)
The base address for sprite tiles, each background's tiles, and each background's tile map can be set independently. A 16-color background can address 32K of tiles, but the sprite system can address only 16K at once. You might be able to get away with a layout like this in mode 1:

$0000-$3FFF (32K): 1024 tiles for BG1 and BG2
$4000-$5FFF (16K): 512 sprite tiles
$6000-$67FF (4K): BG1 map
$6800-$6FFF (4K): BG2 map
$7000-$77FF (4K): BG3 map
$6000-$7FFF ($7800-$7FFF used): 256 HUD tiles for BG3

These are word addresses, where $0000 refers to 16 bits, $0001 refers to the next 16 bits, etc.
Re: getting started on SNES
by on (#157033)
dougeff wrote:
Ive read every document on SNES that I could find. I have a few questions...just so I know I have it right.

1. The SNES has a VRAM that is divided into 3 parts...Color palette, OAM (sprite attributes), and tilemap...each accessible though different registers...
2121/2122 for palette, 2102-4 OAM, 2116-9 tilemap. Do I have that right?
2. How do I write tile data then (CHR)?
3. Do you usually write to the VRAM with a DMA?
4. Do you have to write to VRAM during V-blank?
5. In mode 1, there are 3 BG layers? If an upper one is mostly color 0, does that work as a mostly transparent layer?


1. Mostly correct, but CGRAM (the palette) and OAM aren't normally referred to as VRAM.

2. VRAM contains both the name tables (tilemaps) and the pattern tables (CHR data). Unlike the NES, which has the name tables and pattern tables at fixed addresses in the PPU address space, the SNES has registers to specify the addresses where the name table and the pattern table for each layer are located (including the pattern table for sprites).

3. Yes, uploading data to the PPU is almost always done via DMA. Even writing to the scroll registers may be done via DMA.

4. Yes. VRAM can only be accessed during VBlank or forced blank. Unlike the NES, accessing VRAM outside VBlank simply fails (writes go nowhere, reads return 0) with no side effects on the display. CGRAM can be accessed normally during either VBlank or HBlank; some games write to CGRAM during HBlank to produce a color gradient. You can "sort of" access OAM outside VBlank but what you can do with it is very limited; Uniracers is the only game that intentionally does so.

5. Typically the 2bpp layer (BG3) is used as the score/status display and is therefore mostly blank (transparent) tiles. Or it may be multiplexed as both a score/status display and a far BG, using a raster effect to change its scroll position and priority partway down the screen (see e.g. Super Castlevania) Note that doing raster effects on the SNES is much, much easier than on the NES. Both a beam-position IRQ (a real one, not fake like MMC3) and beam-triggered DMA (HDMA) are built into the base system, and there's no voodoo needed for midscreen scroll changes, you just write the new vertical and horizontal positions exactly the same way you would during VBlank.

Quote:
Edit...
6. I'm also slightly confused with joypad reads. There seems to be 2 ways to read the joypads (auto and manual) with a warning somewhere about getting incorrect reads if done at the wrong time. Is there a 'standard' way of doing this?


The standard way to read normal SNES controllers is using the auto read. In VBlank, after doing all the OAM/VRAM/CGRAM uploads you're going to do, wait for bit 0 of $4212 to go to 0 and then read $4218-$421B. Manual reading is only needed for special controllers: mouse, multitap, light guns, etc.
Re: getting started on SNES
by on (#157034)
tepples wrote:
The base address for sprite tiles, each background's tiles, and each background's tile map can be set independently. A 16-color background can address 32K of tiles, but the sprite system can address only 16K at once. You might be able to get away with a layout like this in mode 1:

$0000-$3FFF (32K): 1024 tiles for BG1 and BG2
$4000-$5FFF (16K): 512 sprite tiles
$6000-$67FF (4K): BG1 map
$6800-$6FFF (4K): BG2 map
$7000-$77FF (4K): BG3 map
$6000-$7FFF ($7800-$7FFF used): 256 HUD tiles for BG3

These are word addresses, where $0000 refers to 16 bits, $0001 refers to the next 16 bits, etc.


BGxxNBA have granularity of $1000 words, so I don't see the need to locate the BG3 tiles in such a weird way...
Re: getting started on SNES
by on (#157061)
AWJ wrote:
BGxxNBA have granularity of $1000 words, so I don't see the need to locate the BG3 tiles in such a weird way...

Also possible:
$7000-$77FF (4K): 256 HUD tiles for BG3
$7800-$7FFF (4K): BG3 map

Or
$7000-$7BFF (6K): 384 HUD tiles for BG3
$7C00-$7FFF (2K): BG3 map (not scrolling)
Re: getting started on SNES
by on (#157080)
You can, of course, overlap OBJ tables and BG tile data, and use literally the same tiles for both. But only for 4bpp BG layers; otherwise you get a format mismatch. And of course both sprite tables combined would only cover half of the valid BG data range.
Re: getting started on SNES
by on (#157168)
I need some help. I've been trying to write a "Hello World" SNES program, but so far it's been a total failure. I've modified it to just fill all BG tilemaps with tiles and display 2 sprites (and turn the background green)...

Except I'm getting nothing. Nothing but a blank green screen.

Here's the source files and snes file...I just want it to show ANYTHING at all on the screen. Can anyone explain to me what I'm doing wrong? I want to understand this, but the documents for SNES are hard to understand...especially VRAM writes / registers.

http://dl.dropboxusercontent.com/s/bsl0 ... /Hello.zip

EDIT: DON'T USE THIS CODE. BROKEN. LEFT HERE FOR REFERENCE.

Compiles with ca65.
Re: getting started on SNES
by on (#157183)
Solved...

Apparently I needed to add this at the end...
Code:
lda #$1f
sta $212C ;enable main screen!!!


It only took me about 3 hours to figure out that :P
Re: getting started on SNES
by on (#157185)
There's my lovely little sprites. Yay!
Re: getting started on SNES
by on (#157189)
I'd say I have success. The above link has been updated, if anyone wants to see source code for a working "Hello World" for the SNES.
Re: getting started on SNES
by on (#190154)
I got a Super Everdrive yesterday, tried this file, and none of the sprites appear on screen. (Sprites are letters, BG is numbers). Any ideas?

BTW, my loop is this...

Forever:
Jmp Forever

And my NMI/IRQ is...
Rti

Am I supposed to do something each frame to get sprites to work? I know you have to continually send sprite data on NES. (Or else they all jump to the corner of the screen)
Re: getting started on SNES
by on (#190159)
You should use bsnes(-plus) for testing, rather than Snes9X. It's more accurate, so if it works on there it'll be more likely to work on hardware.

Three guesses (in order from most to least likely):

You're writing data to VRAM during not-vblank

OR

You're relying on uninitialized RAM somehow

OR

Your header data is invalid somehow, causing the Super Everdrive to map it improperly
Re: getting started on SNES
by on (#190171)
I did test with higan/bsnes accuracy. It looks fine.

On hardware, Bg is fine. No sprites.

Tried pushing sprites every frame. No difference.
Re: getting started on SNES
by on (#190181)
OAM persists on SNES. You don't need to resend it.

Also, if you're actually using an interrupt, you need to clear the IRQ flag by reading $4211, or it will keep firing ad infinitum. According to fullsnes you don't actually have to read $4210 in an NMI, but it's good practice anyway (and I'm not sure I'm impressed by his excuse).

Do games work properly on your SNES?
Re: getting started on SNES
by on (#190186)
93143 wrote:
According to fullsnes you don't actually have to read $4210 in an NMI, but it's good practice anyway (and I'm not sure I'm impressed by his excuse).

I'd say that reading $4210 on Super NES is approximately as required as reading $2002 on NES, but at least $2002 clears the PPU's first/second write latch.
Re: getting started on SNES
by on (#190205)
93143 wrote:
and I'm not sure I'm impressed by his excuse

...that sounded really rude, didn't it?

His explanation was that the NMI flag is cleared at the end of VBlank, so unless you're disabling and re-enabling NMI, you shouldn't have to clear it yourself. I'm pretty sure nocash knows more about the SNES than I do, but it's not obvious to me what happens if your NMI routine ends before the flag is cleared.
Re: getting started on SNES
by on (#190206)
Quote:
Do games work properly on your SNES?


Yes.
No problems with games, nor with the Everdrive.

It's a code problem. I just don't know enough SNES programming to understand, or fix.
Re: getting started on SNES
by on (#190218)
Mind posting your code so that we can take a look?
Re: getting started on SNES
by on (#190242)
Are you writing correctly to the second OAM table? It's been a while since my SNES days, but I do seem to recall having a similar problem and it was caused by (IIRC) not correctly writing to the second OAM table that contains the X coordinates MSB and the sprite size.

Also, the way OAM works on the SNES seems weird to me. IIRC, you have the set the sprite number multiplied by either 2 or 4 when you write the OAM address low.
Re: getting started on SNES
by on (#190246)
Quote:
Mind posting your code so that we can take a look?


It's the Dropbox link above...the only thing I've changed from that is the Vectors.

Quote:
Writing to the second OAM table


I don't think so.
CORRECTION - I think I'm filling it with zeros.
Re: getting started on SNES
by on (#190277)
zkip wrote:
Also, the way OAM works on the SNES seems weird to me. IIRC, you have the set the sprite number multiplied by either 2 or 4 when you write the OAM address low.

Not particularly weird considering that the size of each OAM entry is 4 bytes.
Re: getting started on SNES
by on (#190303)
Quote:
Not particularly weird considering that the size of each OAM entry is 4 bytes.

Exactly, so why multiply the address by 2? (I'm recalling now that it was actually 2 because that's what made it seem weird to me.)

By the way, I actually have no right to try to help here. I'm probably confusing you more. It's been 5+ years since I've done anything with the SNES. :oops:
Re: getting started on SNES
by on (#190305)
I'm just frustrated. I just got my running shoes (everdrive) in the mail, and want to go for a jog, and then i spend 4 hours trying to tie my shoes (and failing).
Re: getting started on SNES
by on (#190306)
You seem to be writing sprites in a straight forward way. Maybe try DMAing the sprites from a copy in RAM? Not sure if those "tutorials" have been depreciated yet or not though.
Re: getting started on SNES
by on (#190313)
I got it to work.

I wrote to the low table, but then no follow up to the high table, thus the low table was never updated, my sprites didn't appear.

Ok, I feel better.

Edit, I think I misunderstood the wiki above, but somehow, rewriting the entire OAM (low and high) fixed it, and sprites are showing. Perhaps leaving the OAM address set mid-way screws things up.
Re: getting started on SNES
by on (#190328)
zkip wrote:
Quote:
Not particularly weird considering that the size of each OAM entry is 4 bytes.

Exactly, so why multiply the address by 2? (I'm recalling now that it was actually 2 because that's what made it seem weird to me.)

By the way, I actually have no right to try to help here. I'm probably confusing you more. It's been 5+ years since I've done anything with the SNES. :oops:

Yet you couldn't resist the urge to spread disinformation in the very same post?

Of course you don't multiply by 2 to index into an array of data structures of size 4.
Re: getting started on SNES
by on (#190331)
2 what? 4 what?

To clarify things, I applied dimensional analysis. I searched superfamicom.org's page about MMIO ports for "word address", and it turns out VRAM, OAM, and CGRAM are all addressed in 16-bit units. Such address registers behave as if they multiply the address by 2 bytes per word. Thus accessing data structures of size 4 bytes per element requires multiplying the index by 2 words per element, not 4 bytes per element.

But in practice, it's more common to write to OAM using DMA from a display list in a memory that's byte-addressed, namely WRAM. For this, you do need 4 bytes per element.
Re: getting started on SNES
by on (#190333)
Quote:
Yet you couldn't resist the urge to spread disinformation in the very same post?

At least I tried to help?

No need to be snarky.

BTW, thanks tepples for clearing that up.
Re: getting started on SNES
by on (#190343)
dougeff wrote:
I got it to work!

Quote from the superfamicom wiki

Quote:
the low table of OAM is not affected until the high byte of a word is written


I wrote to the low table, but then no follow up to the high table, thus the low table was never updated, my sprites didn't appear.

Ok, I feel better.

Edit, I think I misunderstood the wiki above, but somehow, rewriting the entire OAM (low and high) fixed it, and sprites are showing. Perhaps leaving the OAM address set mid-way screws things up.

Think of the high table as a separate chip that is only accessed with addresses 512..543. Only the lower table has a latch that buffers writes.

See anomie's regs.txt (e.g. on RHDN) for details.
Re: getting started on SNES
by on (#190353)
I was still having tons of problems, bugs, making me very angry... I think I fixed it... my bad init code says this...

sep #$20 ;a 8
rep #$10 ;i 16
...
lda #$00
tcd

But, TCD transfers low AND high byte of A+B, regardless of processor status, and the value of A is not know at startup, so I was storing a random value for the high byte of the Direct Page Register.

correct init code should be...

rep #$30 ;a 16 i 16
lda #$0000
tcd


Ok, hopefully, I can get this stupid first test program up and running soon.
Re: getting started on SNES
by on (#190355)
Well, or
sep #$20
lda #0
xba
lda #0
tcd

Also, the 65816 datasheet says D is set to 0 on reset (although I suppose it's possible that this is not true for the 5a22?)
Re: getting started on SNES
by on (#190357)
I assume this is still running on the Everdrive, in which case that's probably not a safe assumption.
Re: getting started on SNES
by on (#190360)
Yes, I'm running on an Everdrive.

Here's the code that IS working on the Everdrive. Slight changes, the background auto-scrolls left (during NMI, let's me know that NMI is firing correctly). And, Controller Reads, Up/Down/Left/Right moves one of the sprites (outside of NMI, let's me know program is running outside NMI correctly).

http://dl.dropboxusercontent.com/s/n93a ... ello11.zip

Improvement still needed, pushing unused sprites offscreen. You can see them in the top left corner. I can't seem to find any documentation on this. Perhaps a Y value of $ff would do it?


Hey, should I also do this on INIT?
lda #00
pha
plb ; set the data bank to 0

EDIT: link updated to push unused sprites to Y = $f0.
Re: getting started on SNES
by on (#190366)
zkip wrote:
At least I tried to help?

No need to be snarky..

Yeah, sorry about lashing out a bit there. Especially since you stating "multiplying by either 4 or 2" is technically exactly true depending if you want the word or byte offset. :oops: (Then, of course, not having an OAM shadow buffer in RAM and DMA it during vblank is rather bonkers, so it didn't even cross my mind that you might want to use the word offset.)

Sometimes I just get a bit disillusioned with how SNES homebrew never seems to be able to get out of the ghetto...
Re: getting started on SNES
by on (#190379)
Quote:
pushing unused sprites offscreen

You can use the 9th bit for the X location (located in the second OAM table) of the sprite to move it off-screen. Actually, I'm pretty sure that this is the exact purpose of having this bit there anyway as I see no other reason for it.

Quote:
Sometimes I just get a bit disillusioned with how SNES homebrew never seems to be able to get out of the ghetto...

I agree. There's some sort of jump-start that NESDEV got that SNES didn't.
Re: getting started on SNES
by on (#190381)
zkip wrote:
Actually, I'm pretty sure that this is the exact purpose of having this bit there anyway as I see no other reason for it.

It's necessary for moving sprites partially off the left side of the screen.
Re: getting started on SNES
by on (#190385)
I believe you can also set the Y coordinate to 240 if you don't want to have to touch the high table, as long as your sprites aren't larger than 16x16 (otherwise they'll wrap around and be partially visible at the top of the screen).
Re: getting started on SNES
by on (#190386)
You can't smoothly scroll sprites in from the left side of the screen, with the sprite partially onscreen, without the hioam.

As for dealing with hioam, I always just stored the full x-coordinates and size bits on a separate table, and then afterwards, jump to a routine that builds the hioam all at once.
Re: getting started on SNES
by on (#190449)
zkip wrote:
Quote:
pushing unused sprites offscreen

You can use the 9th bit for the X location (located in the second OAM table) of the sprite to move it off-screen. Actually, I'm pretty sure that this is the exact purpose of having this bit there anyway as I see no other reason for it.

Quote:
Sometimes I just get a bit disillusioned with how SNES homebrew never seems to be able to get out of the ghetto...

I agree. There's some sort of jump-start that NESDEV got that SNES didn't.


One day I am going to make a tutorial on how to make a giant screen filling robot with rotating limbs and body, once I actually make a demo of one. If that doesn't make people want to do SNES homebrew then I don't know what will. The nice thing about rotating sprites is that if you run out of CPU speed and RAM, you can pre-render everything else in ROM.
Re: getting started on SNES
by on (#190536)
Revenant wrote:
I believe you can also set the Y coordinate to 240 if you don't want to have to touch the high table, as long as your sprites aren't larger than 16x16 (otherwise they'll wrap around and be partially visible at the top of the screen).


Thanks. I think this would be the easiest method.