I'm now getting the desire to get serious with learning to write for the snes. But I have a few questions as to understanding how the RAM/ROM works.

I know 6502, I've hacked many games which a lot of people know, and I've now written 2 games from scratch for the NES. Just wanted to give that brief background on my coding/writing history.

1. Is the snes ram really $0-$1FFF? I ask because, I know the NES ram is $0-$7FF. Also, commercially, the sprite dma is in $200-$2FF of the nes ram, so, is the sprite dma for the snes also placed within the snes ram?

2. Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

3. I know in the nes, the region $FFFA-$FFFF contains the pointers to the NMI/RESET/IRQ, does the snes use the exact same region?

4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

Also, commercially, the sprite dma is in $200-$2FF of the nes ram, so, is the sprite dma for the snes also placed within the snes ram?

Sprite data is in OAM (Object Attribute Memory), which is accessed via a set of PPU registers.

infidelity wrote:

2. Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

Graphics are either stored uncompressed in ROM and transferred to VRAM, or are decoded into WRAM and transferred to VRAM, or decoded directly to VRAM.

infidelity wrote:

3. I know in the nes, the region $FFFA-$FFFF contains the pointers to the NMI/RESET/IRQ, does the snes use the exact same region?

The CPU loads the 16-bit reset vector from $00:$FFFC, which is in cartridge address space. The memory mapper or address bus wiring may route that to any ROM location, but it mostly goes to either $FFFC or $7FFC.

infidelity wrote:

4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

RAM on the Super NES is $7E0000-$7FFFFF. The $7E0000-$7E1FFF region gets mirrored to $0000-$1FFF of banks $00-$3F and $80-$BF.

infidelity wrote:

Also, commercially, the sprite dma is in $200-$2FF of the nes ram, so, is the sprite dma for the snes also placed within the snes ram?

Shadow OAM can be placed anywhere in $7E0000-$7FFFFF. Because DMA on Super NES is much more flexible than DMA on NES, there is no need for alignment to a 256-byte page, though it cannot cross a 65536-byte bank.

infidelity wrote:

2. Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

Like the Game Boy and Genesis, the Super NES uses CHR RAM. The only consoles I know of that use CHR ROM are NES and Neo Geo. (Atari 7800 is a borderline example; if you're interested, ask in Other Retro Dev.)

infidelity wrote:

3. I know in the nes, the region $FFFA-$FFFF contains the pointers to the NMI/RESET/IRQ, does the snes use the exact same region?

Super NES uses $FFE4-$FFFF, as it has separate sets of vectors for 6502 emulation mode (not used much past the boot sequence) and native mode.

infidelity wrote:

4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

The internal header goes immediately prior to the vectors, based on whatever offset in the ROM image corresponds to $00FFB0-$00FFDF in the CPU address space. In mode $20/$30 ("LoROM"), it goes at $007FB0-$007FDF in the ROM image. In mode $21/$31 ("HiROM"), it goes at $00FFB0-$00FFDF in the ROM image.

Do snes games utilize chr-rom, or are the graphics embedded within the rom as chr-ram?

No. The S-PPU can't access the cartridge. All graphics data needs to be transferred to the 64 KB VRAM (which the CPU can access only via a port, as it is not on the A bus) before it can be used. As said, DMA is far more flexible on the SNES, and far more bandwidth is available, so this isn't as onerous as it would be on the NES.

VRAM and OAM can be targeted with DMA at any point during VBlank (which is bigger than on NES, at least for NTSC, because the useless overscan has been trimmed and NMI fires after just 224 lines by default) or forced blank (which can be used to extend VBlank like in Star Fox, which can comfortably update its 224x192 4bpp framebuffer in three frames and could probably do it in two if it had to, or to create a black bar on the screen like in Mario Kart, which uploads OAM data in between the top and bottom halves of the display). CGRAM can be addressed during VBlank, forced blank, or HBlank, and is (like most other PPU registers) a great target for HDMA.

Also, the SNES has a raster IRQ that can be set to trigger at a horizontal position every line, at a vertical position every frame, or at a horizontal position on a particular line every frame. HDMA is better for a lot of things, but the IRQ can be very useful too. The use of forced blank described above is a good example, because the NMI can't be moved except by switching overscan on and off.

Quote:

I'm a little fuzzy on header/no header.

That's got nothing to do with the official Nintendo header. A "headered" ROM is one that has a Super Magicom (or other?) copier header before the actual copy of the ROM, and is thus slightly larger than the actual game; by convention the extension for a ROM with a Super Magicom header is .smc. An "unheadered" ROM has no copier header and is thus the correct size; the correct extension for an unheadered ROM is .sfc. These file extension conventions are not universal and should not be relied on. If the ROM is a multiple of 32 KB, it's unheadered. Modern emulators and flash carts do not use the copier headers, so there's no point including one unless you're going to be using a Super Magicom or something to run it.

Last edited by 93143 on Mon Apr 02, 2018 4:01 pm, edited 2 times in total.

That's got nothing to do with the official Nintendo header. A "headered" ROM is one that has a Super Magicom (or other?) copier header before the actual copy of the ROM, and is thus slightly larger than the actual game; by convention the extension for a ROM with a Super Magicom header is .smc. An "unheadered" ROM has no copier header and is thus the correct size; the correct extension for an unheadered ROM is .sfc. These file extension conventions are not universal and should not be relied on. If the ROM is a multiple of 32 kB, it's unheadered.

I think he's talking about $FFB0 through $FFDF ("ROM Registration Data", using official Nintendo terminology). People colloquially call this a "header" or "cartridge header". Quoting him again, emphasis mine:

infidelity wrote:

4. I'm a little fuzzy on header/no header. Right now I'm using bsnes for trying out writing. If I want to create a header, where I'm the rom does it start? I know it's near the end of the rom. So for example, let's say I have a snes rom file that's empty, starts at $0, and goes all the way to $FFFF. Where would I begin to put the header?

Talking to the OP again: 93143 is talking about the 512-byte SMC header (for files ending in .swc or .smc) for Super Magicom / Super Wild Card copiers, which is at the start of the file (i.e. 512 byte header followed by the actual ROM). You don't need this to make a ROM. Stick to just the raw data and name your ROM with a .sfc file extension and you should be fine. If the assembler you're using forces you to make a file with an SMC header, then that file format is documented -- just ask if/when you get there.

Also, re: "goes from 0 to $FFFF": don't make a 64KByte ROM (or smaller like we used to do back in the day). You'll get publicly chastised by some emulator authors for doing so, usually authors who weren't around doing snesdev using copiers and floppy disks. ;-) Make your ROM 512KBytes (4mbits), even if you use way less space than that. Unused space will compress well with .zip or other formats.

Given the wording of "header/no header", I figured he might be confused about the distinction between copier headers and ROM registration data. I was when I started - I deliberately used .smc on my first attempts because I wasn't sure which "header" Neviksti's starter kit was constructing and including. (It was the ROM registration data, of course. You have to go back a fair ways to find example code that includes a copier header; the Anthrox mode split demo is an example.)

It may be worth noting that while some emulators and flash carts do rely on the ROM registration data, the SNES itself does not. The only header data the SNES cares about is the vectors.

don't make a 64KByte ROM (or smaller like we used to do back in the day). You'll get publicly chastised by some emulator authors for doing so

To the contrary, I think 32/64/128/256kb ROMs are fine if that's the only space you actually need; I'm not aware of any current emulators that would have problems with that. 512kb is reasonable for e.g. an actual gamedev project though, since it's hard to predict how much stuff you'll be throwing in there over the course of development and it's easy to just give yourself a decent amount of space right off the bat.

I've even made working ROMs as small as 256 bytes that loaded and ran just fine in bsnes/higan (other emulators needed some padding), although there is virtually no realistic scenario where anyone would actually have a reason to attempt to do this

To the contrary, I think 32/64/128/256kb ROMs are fine if that's the only space you actually need; I'm not aware of any current emulators that would have problems with that. 512kb is reasonable for e.g. an actual gamedev project though, since it's hard to predict how much stuff you'll be throwing in there over the course of development and it's easy to just give yourself a decent amount of space right off the bat.

I was doing some testing with the JML & JSL, very cool! I learned how to correctly set the desired address, and the bank number, and was able to return properly with the RTL, again that's so cool how that works! And also a first, I wanted to clear all of the $0000-$1FFF snes ram. So I set X & Y as 16 bit values, while A was at 8 bit. I then loaded 00 into A, then I loaded Y as #$1FFF, then I did STA'Y to $0000 (which at the start, stores 00 into $1FFF, then I DEY, and BNE back to my STA'Y. Using bsnes, I stepped through a couple times to make sure it was working, then when I clicked Run, the code worked! Y was down to 0000, and all the ram was wiped!

Very fun stuff!

However I got lazy and didn't read up on what snes address does ppu rendering, (nes uses $2000) so I was unable to have my NMI fire up, my reset vector I had to deliberately insert a brk, to trip the NMI. :-/

All I'm doing is testing commands right now, to get a feel of the system.

Oh, am I wiping the stack with my code? I don't know where the stack is in the snes.

1: Are you able to set the desired CGRAM address via $2121, by writing to it twice like you would on the NES for $2006?

No. $2121 (CGADD) is essentially an "index" register into CGRAM. You write a single 8-bit value (0 to 255), depending on what colour index you wish to start at. The address (internally) auto-increments when you've written to $2122 twice (keep reading). This is a write-only register.

$2122 (CGDATA) is a double-write register, similar to how the NES's $2006 works (but for a different purpose). It's a 15-bit value, but you write the lower 8 bits first, followed by the upper 7. The order of the data is (when represented by a 15-bit value): 0BBBBBGGGGGRRRRR (B = blue, G = green, R = red). You can only write to this during VBlank, HBlank, or if forced blanking is set. How this data is used depends on what BG mode you're using ($2105). This is a write-only register. Example which would store a bright purple colour (%0111110000011111) in CG-RAM location 6, assuming mode 0:

2: I've written 2 bytes to $00-$01 of CGRAM. The first byte is fine, but no matter what I put for a 2nd byte, it's always increased by 80? Any ideas?

Sounds like a bug in your understanding of how the registers work, or a general bug in your program. I don't know how your determined "it's always increased by 80". If you're using bsnes-plus then you should know that some registers and memory is "pre-seeded" with values, so that may be what you're seeing (this still means your program is buggy :-) ).

Regarding your second question, are you saying that you're writing two 8-bit values to $2122 after setting $2121 to zero, and the top bit of the resulting 16-bit colour value is being flipped? If so, it might be a quirk of the emulator, because the top bit is a dummy bit. I don't think it's even stored; fullsnes says it's PPU2 open bus when read (via $213B). The values in CGRAM are 15-bit BGR triplets with no extra information.

OK I see now what's happening. In bsnes when I view the CGRAM, using the addresses $000 & $001, the address showing me only .421|8421 is $001. So when I write the 2nd byte to $2122, then that's the one with the leftmost bit unused.

And I was also able to direct $2121 wherever I wanted it to start within the CGRAM to write the palette color!

Very exciting so far for me!

Now I need to learn CHR-RAM, this feature I've never done on the NES, I've only worked with CHR-ROM. Any helpful tips would be grear! Can't believe I'm getting all this.

Who is online

Users browsing this forum: Google [Bot] and 4 guests

You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forumYou cannot post attachments in this forum