Before writing your actual program’s code, you need a header to describe WLA the SNES’ memorymap. This is basically just a file you will include into your source. It contains all of the basic information about your ROM. The following is a basic header file for a 2 Mbit ROM. Look at the comments beside each line for a brief explanation of that line. I will provide a better explanation after revealing the code.
If you do not know how the memory in the SNES is organized, just sit tight. Right now you just need to know that there are a couple different ways game cartridges organize the memory. We’ll be making a LoRom program, where our game ROM will be from
$8000-$FFFF in banks
$00-$07 (2 Mbit size). You can form up to 24-bit addresses in the SNES, and the bank number is the first 8 bits. Hope you got that. Email me if you need help. The first steps into the SNES are bumpy.
;------------------------------ Header File --------------------------------- ; This is basically a combo of MarctheMER's and Neviksti's header files ; Perhaps reading their's will also help your understanding of the header, ; but I believe this will be the simplest method of defining your header, ; as Marc's doesn't provide a full explanation, and Neviksti's can be ; a bit more difficult for beginners (using the WLA directives is easier). ;---------------------------------------------------------------------------- ;==LoRom== ; We'll get to HiRom some other time. .MEMORYMAP ; Begin describing the system architecture. SLOTSIZE $8000 ; The slot is $8000 bytes in size. DEFAULTSLOT 0 ; There's only 1 slot in SNES SLOT 0 $8000 ; Define's Slot 0's starting address. .ENDME ; End MemoryMap definition .ROMBANKSIZE $8000 ; Every ROM bank is 32 KBytes in size .ROMBANKS 8 ; 2 Mbits - Tell WLA we want to use 8 ROM Banks .SNESHEADER ID "SNES" ; 1-4 letter string, just leave it as "SNES" NAME "SNES Program Name " ; Program Title - can't be over 21 bytes, ; "123456789012345678901" ; use spaces for unused bytes of the name. SLOWROM LOROM CARTRIDGETYPE $00 ; $00 = ROM only, see WLA documentation for others ROMSIZE $08 ; $08 = 2 Mbits, see WLA doc for more.. SRAMSIZE $00 ; No SRAM see WLA doc for more.. COUNTRY $01 ; $01 = U.S. $00 = Japan, that's all I know LICENSEECODE $00 ; Just use $00 VERSION $00 ; $00 = 1.00, $01 = 1.01, etc. .ENDSNES .SNESNATIVEVECTOR ; Define Native Mode interrupt vector table COP EmptyHandler BRK EmptyHandler ABORT EmptyHandler NMI VBlank IRQ EmptyHandler .ENDNATIVEVECTOR .SNESEMUVECTOR ; Define Emulation Mode interrupt vector table COP Emptyhandler ABORT EmptyHandler NMI VBlank RESET Start IRQBRK EmptyHandler .ENDEMUVECTOR .BANK 0 SLOT 0 ; Defines the ROM bank and the slot it is inserted in memory. .ORG 0 ; .ORG 0 is really $8000, because the slot starts at $8000 .SECTION "EmptyVectors" SEMIFREE EmptyHandler: rti .ENDS .EMPTYFILL $00 ;---------------------------------- END -------------------------------------
What we basically just did was write a file which told the assembler about the SNES’ memory organization. We also provided some information about our program, such as the ROM size. Now I will walk through the code. Skip over anything you already understand.
This just begins the memory map definition. We describe the SNES’ memory architecture to WLA in the block of code that follows. What we want to say is that the SNES has ROM at locations
$8000-$FFFF in every bank, and that this area is
$8000 bytes in size.
This is where we tell WLA that the slot is
$8000 bytes in size. Check it out: We’re going to say SNES has ROM at
$8000-$FFFF, well that area is $8000 bytes in size. Pretty simple. I’m not 100% aware of what slots are, but in the SNES you don’t need to interact with it at all in your code since there’s only 1 slot in the SNES, and it’s defaulted to that 1 slot. Just don’t worry about it :).
As said in the comment, SNES has only 1 slot, so we make that slot the default slot.
SLOT defines a slot and its starting address. So we’re saying that slot 0 starts at
$8000, and WLA judges from our earlier commands that this slot is
$8000 bytes in size and is the default slot.
Ends the .MEMORYMAP directive.
comment says it all.
comment says it all.
Begins the SNES header definition. See the WLA document for COMPLETE INFO. Everything contained inside that block of code is described in the WLA doc. Also make sure you read the comments beside the code.
End the .SNESHEADER header definition.
This is where we define where the code will jump to when a certain interrupt occurs in NATIVE MODE (not 6502 emulation mode). We simply provide the address or labels of where the interrupt handler resides. The EmptyHandler just does nothing for interrupts we don’t care about.
cmon take a guess, by now you should know the .ENDxxxx means the end of a directive.. I won’t describe those anymore.
We will be focusing on the NMI a lot, so I trust you know what an interrupt is. We’ll use the NMI interrupt for doing routines when the T.V.’s tracer is in VBLANK (vertical blank), when it’s not tracing to the screen. That allows us to write certain data correctly.
Defines the same as .SNESNATIVEVECTOR, but for 6502 emulation mode.
This basically says the ROM bank we’re in. You don’t really need to specify SLOT 0 because, as I said earlier, SNES only has 1 slot, SLOT 0. You could just say .BANK 0.
Defines the starting address relative to the ROM bank given with
.BANK. .ORG 0 is really
$8000 since the slot starts at
$8000. I hope this isn’t too confusing. What you can do in WLA is
.ORGA $8000 (see the WLA doc), which helps prevent any confusion. You cannot .ORGA
$1000 or something below
$8000 because our ROM starts at
$8000. You can however use the RAM at locations below
$8000. More on that later.
This defines a section of code named EmptyVectors positioned in bank 0 and somewhere after
$0000 ($8000). Please read ALL of what the WLA document has to say about the .SECTION directive, especially if you want to clearly understand what FREE, SEMIFREE, SUPERFREE, FORCE, etc mean. I will say what SEMIFREE means. SEMIFREE sections are positioned somewhere in the bank starting from .ORG. This is useful for making sure the section is not placed anywhere before the address specified in the .ORG. Our file .ORG’s to 0, so SEMIFREE is not that useful, we could just use FREE, which puts the section anywhere in the defined bank (I use SEMIFREE for when we expand our header into a LoRom Hirom combo. You can use FREE for now if you want). See the WLA doc to find out what other names mean. This description is bloated enough.
This directive is used to fill the unused areas of the ROM file with the byte it is given, in this case $00.
Well that is your basic LoRom header file!!! I really described the whole file to make sure you are understanding it. Try writing it out yourself, and then save it as header.inc or something.inc. This will gave you some basic practice and memorization. The next tutorial will focus on an ACTUAL SNES PROGRAM!
On to Initializing the SNES!
Tutorial by bazz