Introduction
The other day someone on my twitter stream mentioned that he wanted to try some SNES programming. Since the SNES is still my all time favorite video game system I’m always happy to see people working on it. Ideally with the result of them releasing something for it. Be it some demo scene production or a little game. I quickly compiled a little email with some information on how to get started. When some others mentioned interest as well I decided to put together a little blog entry for it.
History
The Super Famicom was first released in Japan in 1990. Releases in North America and Europe followed in 1991 and 1992 as Super NES and Super Nintendo respectively. Now if that makes you feel old that’s completely normal. The System was launched with “Super Mario World” as pack-in game and unless you’ve been hiding under a rock for a rather long time you probably know many of the gems released for it in the course of the years:
- Street Fighter 2
- F-Zero
- Zelda: A Link To The Past
- Super Metroid
- Final Fantasy Series
- Starfox
- etc etc etc …
According to Wikipedia the last official game released for the Super Famicom in Japan was ‘Metal Slader Glory: Director’s Cut’. Sure enough there were many unofficial releases after that. Don’t hold your breath though because those are mostly really crappy NES game conversions or just slight modifications of existing games.
I am sure you are very capable of looking things up on wikipedia yourself but let me just mention a few random tidbits that come to my mind on the SNES in no special order:
-
The SNES was rival to SEGA’s Genesis which was released just two years prior in 1988. While Genesis games never looked quite as colorful and mostly didn’t sound as good as many SNES games did I am certain about one thing: Genesis developers must have led a much happier life than their SNES targeting counterparts. Why? Because while SEGA decided to go for the Motorola 68k Nintendo chose the Ricoh 5A22 …
-
Like Microsoft in 2013 Nintendo wasn’t to keen on the idea of people being able to freely play games from region A in region B. Apart from shaping the cartridges differently they also added regional lockout chips to the game system unit and the cartridges which would only allow for matching region pairs of system and game to work. It took until 2010 for this custom chip to be fully reversed (http://sd2snes.de/blog/cool-stuff/supercic).
-
The SNES was designed in a way that would allow for interfacing with special chips embedded on cartridges. The most popular is the SuperFX chip used in games like the Starfox and Stunt FX Racing. The Super FX is a custom RISC processor with simple polygon drawing features. Other enhancement chips were developed as well. Apart from custom decompression of graphics data the features provided were mostly various 2D graphical transformations. Results would be rendered directly to the SNES VRAM via DMA.
-
Homebrew development was sparked by the release of backup stations in Hong Kong and mainland china. These units would plug in your SNES like a normal cartridge. On top there is another cartridge slot and a 3.5″ floppy drive. Of course those units were exclusively purchased with the intention of creating original software for it… The console warez scene that emerged in the 90s relied heavily on it and the units got more sophisticated adding features like parallel port interfacing, real time saving, support for cheat codes and so forth. Manufacturers worth mentioning in this context are Bung (which went on to produce similar devices for other systems including the Gameboy Color, Nintendo 64 and others but was later forced to cease production of copying devices after a jointly filed suit by Nintendo, Sony and Microsoft in 2002 against the then famous Lik-Sang reseller.) and Front Far East (FFE). Among the most popular devices were the Super Wildcard produced by FFE and the Gamedoctor by Bung.
Hardware
I will provide you with plenty of links to documentation that contain tons of detailed information on all that matters and more but let me nonetheless provide some basic information right now to give you an idea what you are dealing with:
CPU
How should I put this nicely … well I think I cannot. The SNES CPU is a bloody punch in the face. Ever wondered why the SNES never had a game that was even remotely similar to the super fast Sonic titles on the Genesis ? Meet Ricoh 5A22, 3.55 Mhz of 65c816 awesomeness. It is so awesome you cannot even reliably disassemble any SNES code because the bit width of arguments may depend on the setting of a cpu status register. Thus you cannot be sure if you are looking at ‘LDA #12’ or ‘LDA #1234’. The opcode for LDA remains the same. (To add insult to injury it should be noted that the initial plan was to use a 10Mhz 68k CPU. This was discarded because of (a) economical reasons, the system just got too expensive and (b) because Nintendo wanted to provide backwards compatibility with the NES. We all know how splendidly that worked out).
Very roughly put you get a spiced up 6502 CPU with …
- a 24bit address bus and 8bit data bus
- 16bit accumulator and index registers (X and Y) all of which can be toggled between 8 and 16 bit modes
- A zero page which is now called direct page that can be placed within the first 64K of RAM
- 128KB of DRAM which is mapped all over the place in address space
- 64KB of VRAM (512 + 32bytes sprite RAM + 256 x 15bits palette RAM)
- 64KB audio RAM
- Various DMA and HDMA modes with 8 distinct channels. HDMA can be used to achieve interesting effects
- by changing display data during the horizontal blanking period
- Hardware Division and Multiplication
You also get a whole lot of addressing modes. Those range from the obvious candidates like immediate (lda #ff) or absolute (lda $00ff) to the new absolute long indexed (lda $80ff00, x) or the stack relative indirect indexed (lda (1,s),y). Unless you plan to use the stack for passing arguments to subroutines you probably won’t be needing the latter though.
Graphics
- Like most other systems of its era the SNES uses tile based graphics which was most useful for the majority of games developed in the 16bit era.
- Up to 4 background layers depending on the chosen video mode (mode0 to mode7)
- Special mode with rotation and scaling using matrix transformations in Mode 7
- Hardware Mosaic Effect (omg please don’t use it)
- Color Addition/Subtraction
- Window Clipping
- Hardware Scrolling
- Progressive Scan Resolutions: 256×224, 512×224, 256×239, 512×239
- Interlaced Resolutions: 512×448, 512×478
- Hardware sprite support for 8×8, 16×16, 32×32 or 64×64 sprites
- 128 sprites in total, 32 sprites per line max
Typically you will prepare video data in memory to be transfered to VRAM via DMA. All VRAM is accessed via CPU Registers. You can set the destination address and how the designated address should be increased at each step. This is useful if you don’t want to change continuous regions in video memory but only stripes. DMA allows for transfers from either RAM or ROM to VRAM. As usual data needs to be transfered during vblank or forced blank. You can use the horizontal blanking period to achieve nice effects by changing scroll values, colors, fiddle with OAM (object attribute memory) to get implement multiplexing etc. I’ve also seen mid-frame video mode changes in order to achieve mode7 3d transformations on top and multi-layer graphics in a different mode on the bottom of the screen. For a lot of this you can use HDMA which reads data from a predefined table and transfers it to consecutive horizontal blanking periods of specified lines (You can also specify gaps).
You can use the nmi (non-maskable interrupt) to trigger a routine at the start of the vblank and you can also trigger interrupts at the start of a given scanline.
Audio
- Sony SPC700
- 16bit ADPCM with 8 channels
- 32khz 16bit stereo
- ADSR evenlope control
- frequency scaling and modulation using Gaussian interpolation Echo noise generation
Quite honestly I don’t have anything to add to this because I’ve never concerned myself with audio programming at all. Luckily there some useful converters and player libraries to convert/play .xm/.mod files that work just fine.
Development Tools
Moving on we get to the practical part of this: The tools that you will be using.
Compiler/Assembler
I take it as given that you want to program in assembler. First and foremost because it’s fun but also because the 658c16 sucks for C and the only working compiler solution that I know of (https://code.google.com/p/snes-sdk/) is not maintained anyomre either. If you still want to have a look at the C approach here is another link for you though: http://www.portabledev.com/wiki/doku.php?id=start – A C library and some examples to get you started.
But as I said I suggest you take the red pill and climb down the rabbit hole which in this case leads to : ca65. If you’ve done 65xx programming on other platforms you might have used it before. It’s a bit verbose and not as straight forward as other assemblers that are targeted at snes but it’s the assembler I like best.
If you want to get started you can check out my sfckit repository on github: https://github.com/gilligan/snesdev It contains various examples and some routines to get you started. Be careful though: I haven’t touched it in quite a while and i’m sure there are bugs and/or messy pieces of code all over. It should certainly be helpful as a starting point though. Setting up ca65 configuration/link scripts is not exactly the most entertaining thing I can think of. Thus feel free to rip anything you find useful from my repository.
Get the assembler(/compiler) here: http://www.cc65.org/
Emulators
In order to quickly test code while you are developing you’ll want to use an emulator. There are different valid options for this but also at least one emulator you should stay the hell away from: SNES9X: Your code may run just fine on snes9x and everything looks dandy until you try it on the real hardware and everything just explodes right into your face: glitch-o-rama. It just isn’t accurate enough at all. So stay away. Valid options for testing your code are:
- bsnes (now called higan) : This is the most accurate snes emulator there is. It might in fact be one of the most accurate emulators for any platform. Recently it mutated into a multi-arch emulator. Personally I am not to terribly keen on that so I stick to some older version which is snes only. Traditionally it has also always been a bit of a pain in the arse to get bsnes to compile because the author is rather keen on using recent C++11 features and the code sometimes just wouldn’t compile on OSX. I am also disappointed by the fact that the debugger was dropped at some point in the past.
- ssnes (now called retroArch): This project started out as a frontend to the bsnes emulation core but has also evolved into a more elaborate multi-platform solution. Again i’m not too terribly fond of that but I keep an older version around which I adjusted to my needs (I’m listening to SIGUSR in the main loop to allow for quick ROM reloads without restarting the emulator. If anyone is interested in this let me know).
- no$sns: Finally there is the most recent snes emulator from the author of the awesome no$gmb Gameboy emulator. Like his other emulators it features a great debugging environment. It also has built-in features like a stdout which you can use by writing to a custom register in your snes code to get debugging output. The downside is that the author is really keen on writing all his emulators in win32asm. Luckily for me it works just fine under wine on my macbook so that’s how I use it.
(You can find links to the emulators at the end.)
Hardware
Emulators are a must-have for fast testing-cycles and debugging but you should also always check your code on the real hardware to make sure its actually working. There are a couple of options to choose from:
- You could look for an old backup device like the Super Wildcard DX2 or the GDSF7. These work just fine and when sending code via the parallel port you can even get fast test-cycles. The only problem is finding a computer with a parallel port. Do you have one ? Let me check the back of my Macbook Pro .. hm, nope. I also doubt that there are any USB-Parallel-Port dongles that would work. If there are I would love to know that though :) You might find one here: http://www.tototek.com/store/index.php?main_page=index&cPath=1_8_11
- My personal favorite is the quickdev16: https://www.assembla.com/spaces/quickdev16/wiki – The only problem is that I doubt you can still purchase one. If I remember correctly all info for building one yourself is available though.
- There are several other flash cart solutions that you can get. These work fine but unlike the quickdev16 they are made for gamers not developers. Copying a ROM file to an SD-card and then putting that back into your flashcart isn’t exactly ideal. You can find some shop links at the end of this article.
Documentation
If you have made it to here chances are you are still interested in SNES development. Luckily there is lot of reading material so let’s get started!
LINKS
I hope this little article was helpful to someone or at least managed to wet your appetite a bit for looking further into this nice retro system. Feel free to give feedback/corrections!
In case you were hoping to see actual code or a rundown of some hello world program – Sorry. Took me long enough to just write this silly intro. Feel free to have a look at http://bit.ly/18erbNt and see if you get it to compile. I hope it isn’t all completely broken :-)