(Link to AcmlmWiki) Offline: thank ||bass
Register | Login
Views: 13,040,846
Main | Memberlist | Active users | Calendar | Chat | Online users
Ranks | FAQ | ACS | Stats | Color Chart | Search | Photo album
04-29-24 10:43 AM
0 users currently in ROM Hacking.
Acmlm's Board - I3 Archive - ROM Hacking - ROM Structure New poll | |
Add to favorites | Next newer thread | Next older thread
User Post
Rom Manic









Since: 12-18-05
From: Detroit, WHAT?!

Last post: 6279 days
Last view: 6279 days
Posted on 12-07-06 05:18 PM Link | Quote
I was trying to do some research on Assembly when I had some random questions come into mind:

- What is the basic structure of an SNES ROM, or for that matter, any type of ROM?
- Is there anything to compare/contrast between SNES/NES/Etc. ROM's besides the obvious?

I understand that they generally have a header, a footer, and...Well, the filler in between. But since I'm going to be coding homebrew games fairly soon (Maybe January I'll start, but it depends when the script gets finished), I need to program a tool to insert all the game data into a ROM image.

So as to not confuse my SNES console on what the bloody hell is really on the cart, I was curious if anyone knew a good source to look at, or knows anything about the subject.
Kejardon

Shyguy








Since: 05-21-06

Last post: 6280 days
Last view: 6279 days
Posted on 12-07-06 06:53 PM Link | Quote
I can't compare it to other rom types, but I can give you a good bit of info about the SNES specifically.

Many SNES roms have a header. However, for most purposes, headers are useless. If you're planning to copy a rom onto a cartridge, you *might* require one... I don't know, I don't have a copier. For all the following notes, I'm assuming there is no header... if there is one, you just have to add $200 to all offsets.
There's no footer for SNES roms.
The only required structure in an SNES rom is that there is special data at the end of the first bank. Depending on the rom type, this may be at 7FC0 ('LoRom', read in the game as 80:FFC0) or FFC0 ('HiRom', read in the game as C0:FFC0).
You will definitely want to look into this part a bit. It determines a *lot* of stuff about the ROM, including: Size of the ROM, size of SRAM, name of the ROM, where to start the main program code, code to run at interrupts, code to run at software breaks, and more.

ROMs are also split up into banks. Depending on the data at 7FC0/FFC0, you can have 32 kB banks (generally called 'LoRom') or 64 kB banks ('HiRom'). Most data can not cross banks, but if you call it correctly, some data can (such as music).
::edit:: Fixed the size of banks. Was stupidly thinking $8000 = 8 kB for a minute. ::/edit::

Other than that, the only way to figure out what's what is basically to emulate it (or to find patterns in the data). In other words, you can put code wherever you want, you can put graphics wherever you want, and you can put text wherever you want. You just need to call it correctly.
Well, the only exception to that would be that your code has to start in the first bank. But it can go anywhere you want it to go from there.

And I'm out of time for now. Off to class.


(edited by Kejardon on 12-07-06 07:01 PM)
Gideon Zhi

Keese








Since: 12-05-05
From: ...behind you! Boo!

Last post: 6282 days
Last view: 6279 days
Posted on 12-07-06 08:19 PM Link | Quote
What Kej has said is mostly correct.

SNES ROMs can have two different kinds of headers - a copier header and a cartridge header. The data in the last 64 bytes of the first bank (C0:FFC0 hirom, 80:FFC0 or 00:FFC0 lorom) is the cartridge header. This contains things such as interrupt and reset vectors, the name of the cartridge, things like that. This header *must* be present.

A copier header, on the other hand, is 512 bytes of (for our purposes) vestigal data. This provides some small information to a backup unit when the game is run from the backup unit's internal memory. (This has nothing to do with programming your own carts, Kej.) For the purposes of romhacking, the copier header serves only to confound calculations and make things more complicated than they should be. Delete it.

Otherwise, you might want to look into lorom/hirom, fastrom/slowrom, and cartridge pinouts. I can tell you about lorom and hirom addressing, but I'm hungry and I haven't eaten since breakfast. Food is more important right now
Rom Manic









Since: 12-18-05
From: Detroit, WHAT?!

Last post: 6279 days
Last view: 6279 days
Posted on 12-08-06 01:42 AM Link | Quote
Hey, thanks for the replies! This stuff can help me in the future, so I hope you guys don't mind if I store this topic in my webspace

However, what I need now is what is the basic things a SNES rom should have. We've established a header is needed, but as Kejardon said, I need to know how to initialize the actual code of the game. Putting pointers and graphics and anything else in there is really low priority.

So any idea's on how the SNES knows where to look for the first line of code to start the game? Apologies if this ends up being a different topic in a few posts
MathOnNapkins

1100

In SPC700 HELL


 





Since: 11-18-05

Last post: 6279 days
Last view: 6279 days
Posted on 12-08-06 02:42 AM Link | Quote
So any idea's on how the SNES knows where to look for the first line of code to start the game? Apologies if this ends up being a different topic in a few posts

In the "cartridge header" as Ghideon describes it, there is a 16 bit value called the "reset vector". This is a pointer to the very first instruction the game executes. It's a 16 bit value because this location is always in the first bank ($00/$80 in LoRom case, $C0 in hirom case). Now here's something to pay attention to, there are actually two reset vectors. If you know much about the 65816 internals, you know there is 6502 emulation mode where the processor behaves pretty much like its ancestor, and there is native 65816 mode. The processor always starts up in emulation mode, and is later switched to native mode manually.

You'll want to check out this page and the pages like it: Linky

In the attached picture, you can see that in a LoRom game (in this example, Zelda 3), the vector table starts at $7FE4. In the picture, there are two 16 bit value enclosed b/c the top on is the native mode vector, and the bottom one is the emulation mode vector. One thing that stands out is that they have no BRK vector set at all for this game. This is pretty lazy error checking. If the SNES encounters a BRK instruction in Native mode, it will look at $00:FFFF for an instruction and get absolute garbage, causing a hard crash. The native mode BRK vector is sensibly set to $00:822C which is the address of an RTI instruction (ReTurn from Interrupt), though the 6502 uses BRK differently anyway so it will never use that vector. Notice the Abort vectors are also set to $00:822C, even though the SNES will not experience an Abort interrupt in a million years. The reset Vector has listed $00:8000. This corresponds to the very first (non header) byte in the rom. Many early games do this.

http://en.wikibooks.org/wiki/Super_NES_Programming/Initialization_Tutorial

This is also a good tutorial I looked over a while ago, but it kind of depends on you using WLA-DX as your assembler. I could cook up a xkas alternative if I felt like it though. Not sure what you're using.

Attachments




(edited by MathOnNapkins on 12-08-06 01:50 AM)
Kejardon

Shyguy








Since: 05-21-06

Last post: 6280 days
Last view: 6279 days
Posted on 12-08-06 02:47 AM Link | Quote
::edit:: Wee, Simu-post. And Math's post is far more informative than mine, of course. ::/edit::

huh. I never realized those 64 bytes were also called a header, though it makes perfect sense to do so.

Originally posted by Kejardon
...there is special data at the end of the first bank. Depending on the rom type, this may be at 7FC0... or FFC0.
You will definitely want to look into this part a bit. It determines a *lot* of stuff about the ROM, including: ... where to start the main program code...

...your code has to start in the first bank


More specifically, at $FFFC in the first bank is a pointer to the first instruction of code (which will also be in the first bank).
If you're going to make a game from scratch, you really need to look at the data at $FFC0, learn how it works, and decide what to put there to start with. You'll want to take a look at what HiRom and LoRom are as well. And AFAIK, just enable FastRom right off - there's no reason not to enable it (and now that I've said that someone will likely point out such a reason)

Unfortunately, I don't know of a single good document/website to refer you to... I just go to google whenever there's some specific tidbit I need that I don't remember.


(edited by Kejardon on 12-08-06 01:52 AM)
Rom Manic









Since: 12-18-05
From: Detroit, WHAT?!

Last post: 6279 days
Last view: 6279 days
Posted on 12-08-06 06:46 PM Link | Quote
Originally posted by MathOnNapkins
http://en.wikibooks.org/wiki/Super_NES_Programming/Initialization_Tutorial


This is a good reference, thanks for pointing that out. However, I won't be using an assembler to write my games, or at least, not a 65816 assembler. I think I'll be using my own utility, which should work out since I'll be able to modify it as I program the game. Some of you know what I'm talking about here, but thats another thread

The topic from Zsnes forum should come in handy, too. Ill look it over when I have more time, but thanks again.

Originally posted by Gideon Zhi
This has nothing to do with programming your own carts, Kej


Well, thats the thing. I will be coding for cartridges specifically. So whatever information I can get for doing so is what I'm looking for here

Originally posted by Kejardon
If you're planning to copy a rom onto a cartridge, you *might* require one... I don't know, I don't have a copier


Well, according to the dev manual it says every game MUST have game information stored at a certain location, somewhat farther down near $FFB0-FFBF. It pretty much just includes the name of the game ($21 bytes max length), map mode, cartridge type, ROM and RAM size, and others. I'm not sure if this is what's in the header, but somewhere in the ROM it's there. It's a submission requirement.

But anyway, based on what everyone has said, in a nutshell, here's what I got:

Originally posted by The jist of it
Depending on the ROM being HiRom or LoRom, the bank with the "Reset Vector" is either at $00 or $80 in the case of a LoRom, or $C0 in the case of a HiRom. This information located at those locations is a pointer to the first line of Assembly code. However, there is also more bytes of data in $FFFC that do the same thing.

I should look at the data in the bank which starts at $FFC0, which, assumably, modifies whether native or emulation mode is enabled, amongst other things (Assumably).

INSERT SECOND RESET VECTOR HERE.

If the game encounters a BRK instruction without a BRK vector table anywhere in sight, it will stick it's head in the sand (Much like an ostrich, but less funny). However, if there IS a vector table, which is commonly located at $822C, there is an RTI assembly instruction there which adds a value to the stack pointer to tell the game where to go next.

Jason cut off every ROM's feet.


Tried to lighten it up a bit, but it probably sounds corny, so meh. But yes, I would like to learn about LoRom and HiRom addressing, Gideon

PS: Eggsaredone XD


(edited by Rom Manic on 12-08-06 05:47 PM)
Kejardon

Shyguy








Since: 05-21-06

Last post: 6280 days
Last view: 6279 days
Posted on 12-08-06 09:20 PM Link | Quote
Originally posted by Rom Manic
Originally posted by Gideon Zhi
This has nothing to do with programming your own carts, Kej

Well, thats the thing. I will be coding for cartridges specifically. So whatever information I can get for doing so is what I'm looking for here


What Gideon was saying (to me, because I said I didn't know) is that the cartridge header (the optional $200 bytes that may be at the start of the rom) is NOT used to copy a rom onto a cartridge.
So yeah. Your rom file should be an *exact* multiple of $10000 bytes when you copy it to cartridge.

Originally posted by Rom Manic
Well, according to the dev manual it says every game MUST have game information stored at a certain location, somewhat farther down near $FFB0-FFBF. It pretty much just includes the name of the game ($21 bytes max length), map mode, cartridge type, ROM and RAM size, and others. I'm not sure if this is what's in the header, but somewhere in the ROM it's there. It's a submission requirement.

There is nothing important at $FFB0 - $FFBF. The important part starts at $FFC0. Also, the name of the game is 21 ($15) bytes max, IIRC.

Now, as for your 'jist of it'... let's try explaining banks again from scratch, to start with.

The game is split up into banks. These may be 32 kB ($8000) or 64 kB ($10000) depending if it's LoRom or HiRom. These banks are *entirely* what the ROM is composed of - aside from the optional $200 header at the start, there is *nothing* else in a rom file. When you open it up in a hex-editor, all the data from 0 - $7FFF (or 0 - $FFFF) is the first bank, all the data from $8000 - $FFFF (or $10000 - $1FFFF) is the second bank, and so on.
The last 64 bytes of the first bank hold the special data we've been talking about.

The number of the banks DOES NOT start at 1, however (and for most purposes, not at 0, either). Instead, LoRom starts at $80 and HiRom starts at $C0. So, for LoRom, offsets $0 - $7FFF in a hex editor are actually $808000 - $80FFFF to the SNES, then $8000 - $FFFF are $818000 - $81FFFF. For HiRom, offsets $0 - $FFFF are $C00000 - $C0FFFF, and $110000 - $11FFFF are $D10000 - $D1FFFF.
LoRom's ROM is only readable as $8000 - $FFFF in all the banks. $0 - $7FFF will call ram or cpu registers instead.

I'm not an expert on memory mapping modes for the SNES though, so this is neither comprehensive (there are more options than just lorom and hirom, but those are by far the most common), and may not be completely correct.

When the game needs an address, the most common address used is 2 bytes ($0000 - $FFFF). The game is told beforehand what bank to read in, either by the 'program bank' register or the 'data bank' register, depending if it's looking for code or for data. Occassionally, you'll want to use a 3 byte address instead ($000000 - $FFFFFF). This makes the game ignore the current program bank and data bank register.

Now then, those addresses given in the data at $FFC0 will refer to the FIRST bank. Although, IIRC, it uses bank $00 (which will also read from the first bank for addresses $8000 - $FFFF). This is usually changed immediately to $80 or $C0, because the SNES can work with those bank numbers quicker than it can $00.

Anomie's document can show all the mapping, though it's for all SNES mappings. http://www.romhacking.net/docs/memmap.txt
A mapping of LoRom and HiRom might be more useful to you: http://www.romhacking.net/docs/snesmem.txt
Gideon Zhi

Keese








Since: 12-05-05
From: ...behind you! Boo!

Last post: 6282 days
Last view: 6279 days
Posted on 12-08-06 11:42 PM Link | Quote
This is, again, mostly correct The only thing I have to add/change is that LoROM $80-$FF can be mirrored at $00, although I'm not sure what exactly happens past bank 3F. It could be that you can address up to 28 megabits in lorom mirrored $00 range (up to bank $6F) but I'm not positive of that. I've also seen situations were LoROM games use HiROM addressing for certain data (see Super Robot Wars Gaiden...) but I don't really know much about how exactly that works, I just know it does.

Also, Static RAM begins at bank $70. Work RAM is contained in $7E:0000-$7F:FFFF irregardless of LoROM or HiROM mapping.
Rom Manic









Since: 12-18-05
From: Detroit, WHAT?!

Last post: 6279 days
Last view: 6279 days
Posted on 12-09-06 02:19 AM Link | Quote
Kejardon: Ah, so if I have the address $xxyyyy, xx is the bank and yyyy is any 16 bits in the bank, correct?

Anyways, here is what I was talking about:

http://img90.imageshack.us/img90/3408/gameinfoah1.gif

But yeah, different mappers place the game data differently once it's copied, I suppose. Anyway, I'll leave it for you to decipher as it's fairly simple to understand.

Gideon: I think I get LoRom and HiRom, if only on a small scale. If you go on IRC at all, I'm usually in #rohmacking on irc.esper.net if you want to get ahold of me. #rom-hacking kicked me out, I think
Add to favorites | Next newer thread | Next older thread
Acmlm's Board - I3 Archive - ROM Hacking - ROM Structure |


ABII

Acmlmboard 1.92.999, 9/17/2006
©2000-2006 Acmlm, Emuz, Blades, Xkeeper

Page rendered in 0.018 seconds; used 414.56 kB (max 507.60 kB)