A small article regarding ZSNES
Moderator: ZSNES Mods
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
I'm not sure if just that section would be enough, but your program is cool
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
I fixed it to work on a real SNES. I had the vblank backwards v_v;
May wish to download it again, although it's a tad slower now.
I've tested it out and here are my results:
Upon powerup, registers are set as follows:
A - 0000
X - 0000
Y - 0000
SP - 01FF (0100 on my Super UFO. It's better to use 01FF.)
D - 0000
DB - 00
Memory: ALL memory from 7E0000-7FFFFF = 00, This may be done via the UFO. It is possible that ZSNES has this correct with 55. I don't see a reason to change this from 55, other than to fix BS Zelda. You may want to look into that.
Upon resetting the system, registers are set as this:
A remains the same as it was exactly when the system was reset.
X and Y also remain the same as they were exactly when the system was reset, however, because emulation mode is enabled, the top 8 bits need to be cleared (X:1234 becomes X:0034.)
S/SP remains the same as it was when the system was reset, only subtract 3 from it. So if S = 01FF when the system was reset, it should start at 01FC after reset. The high byte of S should always be 01.
D and DB are reset to 0000 and 00.
ALL MEMORY FROM 7E0000-7FFFFF REMAINS THE SAME. No changes to memory should occur upon reset.
I have noticed absolutely no change in any of the memory after resetting the SNES. I also tried holding in the reset button for two minutes to make sure that won't affect the memory. I scrolled through every single byte in memory (using up and down only in my program) and am certain this is correct.
Anyway, the source is there for anyone to verify. I'm absolutely certain there aren't any glitches that would invalidate my findings. The only thing I am not 100% certain of is the default S state upon poweron (is it 0100, or 01FF?). I have proven that it should be decremented by 3, and the high byte then set to 01, however.
-- By the way, I know reset.zip is written very suboptimally. I intentionally didn't buffer the tilemap because I didn't want to write to any RAM that I didn't absolutely have to. :)
May wish to download it again, although it's a tad slower now.
I've tested it out and here are my results:
Upon powerup, registers are set as follows:
A - 0000
X - 0000
Y - 0000
SP - 01FF (0100 on my Super UFO. It's better to use 01FF.)
D - 0000
DB - 00
Memory: ALL memory from 7E0000-7FFFFF = 00, This may be done via the UFO. It is possible that ZSNES has this correct with 55. I don't see a reason to change this from 55, other than to fix BS Zelda. You may want to look into that.
Upon resetting the system, registers are set as this:
A remains the same as it was exactly when the system was reset.
X and Y also remain the same as they were exactly when the system was reset, however, because emulation mode is enabled, the top 8 bits need to be cleared (X:1234 becomes X:0034.)
S/SP remains the same as it was when the system was reset, only subtract 3 from it. So if S = 01FF when the system was reset, it should start at 01FC after reset. The high byte of S should always be 01.
D and DB are reset to 0000 and 00.
ALL MEMORY FROM 7E0000-7FFFFF REMAINS THE SAME. No changes to memory should occur upon reset.
I have noticed absolutely no change in any of the memory after resetting the SNES. I also tried holding in the reset button for two minutes to make sure that won't affect the memory. I scrolled through every single byte in memory (using up and down only in my program) and am certain this is correct.
Anyway, the source is there for anyone to verify. I'm absolutely certain there aren't any glitches that would invalidate my findings. The only thing I am not 100% certain of is the default S state upon poweron (is it 0100, or 01FF?). I have proven that it should be decremented by 3, and the high byte then set to 01, however.
-- By the way, I know reset.zip is written very suboptimally. I intentionally didn't buffer the tilemap because I didn't want to write to any RAM that I didn't absolutely have to. :)
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
Thanks, I'll try to implement what I can.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
-
- Romhacking God
- Posts: 922
- Joined: Wed Jul 28, 2004 11:27 pm
- Contact:
While we're getting to the bottom of alot of these quirks, it might be a good idea to present these findings on the SNES9x board as well.
The core problems may have a better chance of getting fixed there than ZSNES. Pagefault has obviously not been around to comment and has shown little interest in fixing these sorts of bugs as of late.
There are some smart cookies over there at the 9x board that may be able to add even more information.
I also have a UFO, so I couldn't help regarding the SP pointer. Although maybe it would be useful to see if they are the same?
The core problems may have a better chance of getting fixed there than ZSNES. Pagefault has obviously not been around to comment and has shown little interest in fixing these sorts of bugs as of late.
There are some smart cookies over there at the 9x board that may be able to add even more information.
I also have a UFO, so I couldn't help regarding the SP pointer. Although maybe it would be useful to see if they are the same?
[url=http://transcorp.romhacking.net]TransCorp[/url] - Home of the Dual Orb 2, Cho Mahou Tairyku Wozz, and Emerald Dragon SFC/SNES translations.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
[url=http://www.romhacking.net]ROMhacking.net[/url] - The central hub of the ROM hacking community.
The explanation is quite simple about the update of registers during blank, it was decided for 2 factors. Speed and lack of precise timing information.
At some point we had code to disable writes outside of vblank (last time I remember was when testing some Tintin game that had color problems) but it was failing in many cases because the timing was not accurate enough. (For examples, dma time is not counted). To obtain perfect timing, we couldn't use the simple but fast time tables anymore so this would also have affected performance which was a major factor in all decisions when we were initially working on the emulator. (though I guess it isn't one as much now with current processors being quite faster as the initial 486-33 I was working on)
_Demo_
At some point we had code to disable writes outside of vblank (last time I remember was when testing some Tintin game that had color problems) but it was failing in many cases because the timing was not accurate enough. (For examples, dma time is not counted). To obtain perfect timing, we couldn't use the simple but fast time tables anymore so this would also have affected performance which was a major factor in all decisions when we were initially working on the emulator. (though I guess it isn't one as much now with current processors being quite faster as the initial 486-33 I was working on)
_Demo_
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
pagefault told me I can't use tests on a copier to verify initial values.
But I now have ZSNES not reseting 7E0000-7FFFFF when clicking reset in the GUI.
I need to track down the reset key so I can fix that too, then I'll clean up my code and commit it.
Anyone know of a simple way aside from byuusan's program I can check if I did this right or not? Is there a game where it remembers something that I can test real quick?
But I now have ZSNES not reseting 7E0000-7FFFFF when clicking reset in the GUI.
I need to track down the reset key so I can fix that too, then I'll clean up my code and commit it.
Anyone know of a simple way aside from byuusan's program I can check if I did this right or not? Is there a game where it remembers something that I can test real quick?
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
Okay, fixed up key reset, cleaned up code, commited.
SSF2 now remembers my high score on reset
SSF2 now remembers my high score on reset
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
What, pagefault, ipher, and myself made ~20 commits in the past week and you want a WIP?
Besides, certain code for a certain upcoming translation release is in middle of being worked on, and certain code isn't stable at the moment.
Besides, certain code for a certain upcoming translation release is in middle of being worked on, and certain code isn't stable at the moment.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
_Demo_, that makes perfect sense. I see how it's especially a problem now. If timing is modified much, it would probably break many games. If vblank rules are enforced, it'll also break many games. The only way ZSNES can ever do this, is if we get totally perfect timing, which no one knows how to do yet... assuming it's something that you all want to fix (given there isn't much payoff -- 99.9% of games already play fine), the only two solutions would be a separate branch of ZSNES, or a ground-up emulator focused on timing. Then once we have all the gaps filled in, add the timing to ZSNES / SNES9x.
What I would like is someone to load up my two demos on a flash cart instead of a copier, maybe modify the first program to give you D and DB too. I really have a feeling that SNES memory should not start with 55's. I see the binary pattern (0101010101010101...), but it doesn't seem right to me. Perhaps just the BSX flushes memory to 00's before executing the games?
Yeah, I definately wouldn't trust the default register states I provided. The UFO BIOS sets those by hand before jumping to my code. This includes A, X, Y, S, D, DB, and the memory being all 00's. However, once the UFO has a game in DRAM, the BIOS is no longer executing any code. The effect on A, X, Y, S, D, DB and memory upon reset I mentioned is definately correct. Anyway, it isn't important to implement. Absolutely no game in the world would rely on knowing the register states -right- when the game was reset. The important one was memory state, and that seemed to work well. I hope effects show up in other games to make it worth your while, thanks for implementing that for me :Dpagefault told me I can't use tests on a copier to verify initial values.
What I would like is someone to load up my two demos on a flash cart instead of a copier, maybe modify the first program to give you D and DB too. I really have a feeling that SNES memory should not start with 55's. I see the binary pattern (0101010101010101...), but it doesn't seem right to me. Perhaps just the BSX flushes memory to 00's before executing the games?
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
Yeah right. The # is much closer to 90%.byuusan wrote:99.9% of games already play fine
It probably shows up in a bunch of games, I know the credits in SSF2 is one of them. But it should really be done, because it was easy, doesn't really effect speed or anything adversly, and the correct effect.byuusan wrote:The important one was memory state, and that seemed to work well. I hope effects show up in other games to make it worth your while, thanks for implementing that for mepagefault told me I can't use tests on a copier to verify initial values.
And you're welcome
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
I remember seeing it look fairly random before. From a hardware standpoint, I wouldn't expect the WRAM or VRAM to have a definite startup state anyway.byuusan wrote:What I would like is someone to load up my two demos on a flash cart instead of a copier, maybe modify the first program to give you D and DB too. I really have a feeling that SNES memory should not start with 55's.
I can run some flash cart tests for you.
I believe Snes9x already has this "soft reset" option. It came up (I think) when TheDumper noticed Dezaemon had a neat "restart" screen on the real system. The power up states of WRAM, VRAM, and even APU RAM have been checked before. So it might be worth searching the old snes9x boards for the info.
Most of the register stuff you mentioned is in the 65816 datasheet. It's nice to see verification. The SL value on powerup doesn't look like it is specified in the datasheet.
As for the stack decreasing by 3 during soft reset, this is probably just an artifact of the CPU treating the /RESET as a normal interrupt in emulation mode (ie. push the 2 byte address and the processor status on the stack). I may check this later just for kicks.
Hmm... just noticed this in the 65816 document:
So I guess we wouldn't see the previous address on the stack after a reset.
Also...
I'm sure others have noticed this a long time ago, but I don't ever use emulation mode, so I never noticed this till now:
I can't believe they'd make a CPU that did that. What's the point of even having emulation mode if you can't really emulate the old code since any interrupt would cause a crash?
Does it really work like this?
[ EDIT: Well, there are two other places in the doc that describe the details of RTI. Those places describe it as acting as one would expect in emulation mode. So the above must just be a mistake in the 65816 document I have.
... ah, okay I read the document wrong.
I guess by... not pushed, pulled
it meant not pushed, and not pulled.]
The specifics of the failure I'm not sure about. Stack 'wrapping' doesn't always happen perfect.
So the bytes may actually be pushed to: 0100,0ff,0fe
after the operation the stack probably becomes 01fe
then changing to native and RTL, the address is pulled from: 01fe,01ff,0200
As noted, I don't have much experience with emulation mode, so the above is just my best guess of the failure specifics.
Code: Select all
When Reset is brought high, an interrupt sequence is initiated:
* R/W remains in the high state during the stack address cycles.
Also...
I'm sure others have noticed this a long time ago, but I don't ever use emulation mode, so I never noticed this till now:
Code: Select all
rearranged a bit for clarity, from (Table 2. G65SC802 and G65SC816 Mode Comparison)
Program Bank (PB)
During Interrupt RTI
when E=1 Not pushed pulled
when E=0 Pushed pulled
Does it really work like this?
[ EDIT: Well, there are two other places in the doc that describe the details of RTI. Those places describe it as acting as one would expect in emulation mode. So the above must just be a mistake in the 65816 document I have.
... ah, okay I read the document wrong.
I guess by... not pushed, pulled
it meant not pushed, and not pulled.]
Well, that's the idea.byuusan wrote:I've figured out the problem now with the JSL thing. Neviksti is correct, since the stack starts at 0100 in emulation mode, my first JSL pushes the address to: 0100, 01ff, 01fe. I then switch to native mode in my routine, so when I go to issue rtl, it pulls the address from 0100, 00ff, 00fe.
The specifics of the failure I'm not sure about. Stack 'wrapping' doesn't always happen perfect.
Code: Select all
In the Emulation mode, the Stack address range is 000100 to 0001FF.
The following opcodes and addressing modes can increment or decrement beyond
this range when accessing two or three bytes:
JSL; JSR (a,x); PEA; PEI; PER; PHD; PLD; RTL; d,s; (d,s),y.
after the operation the stack probably becomes 01fe
then changing to native and RTL, the address is pulled from: 01fe,01ff,0200
As noted, I don't have much experience with emulation mode, so the above is just my best guess of the failure specifics.
WRAM is randomly generated, possibly by the CIC? Anyway none of the WRAM is set to zero. I located some WRAM that was not affected by the Backup Unit and it generated differently each time the system was powered on.neviksti wrote:I remember seeing it look fairly random before. From a hardware standpoint, I wouldn't expect the WRAM or VRAM to have a definite startup state anyway.byuusan wrote:What I would like is someone to load up my two demos on a flash cart instead of a copier, maybe modify the first program to give you D and DB too. I really have a feeling that SNES memory should not start with 55's.
My emulator sets the WRAM differently, if the ROM Checksum is OK then WRAM is set to $55, else it is set to zero. Basically if the ROM Checksum is bad the game is deemed to have been hacked and thus can only be run on a copier and copiers reset WRAM to zero.
On a side note, I have found that both of my machines set the SPC RAM differently. My PAL Machine resets the SPC RAM to a set pattern and my Super Famicom doesn't reset the SPC RAM at all.
> WRAM is randomly generated, possibly by the CIC?
?? The CIC isn't related to the memory.
The /RESET line does connect to the WRAM chip, but I believe this is just because the $218x regs are built into the chip and these are reset (maybe?).
As I mentioned earlier, from a hardware point of view, there is no reason to expect the WRAM, which is DRAM, to have a definite power on state.
> I located some WRAM that was not affected by the Backup Unit and it
> generated differently each time the system was powered on.
Yeah, that sounds reasonable.
> My emulator sets the WRAM differently, if the ROM Checksum is OK
> then WRAM is set to $55, else it is set to zero. Basically if the ROM
> Checksum is bad the game is deemed to have been hacked and thus
> can only be run on a copier and copiers reset WRAM to zero.
Hmm... that's a neat way to handle it. However, I often don't think to setup the checksum because the real system could care less, and emulators didn't either (well, till now). I'd kind of preferr it just always acted like the normal system without copier.
I guess there's no perfect way to handle that if some programs are meant to run on the copier. Oh well.
> On a side note, I have found that both of my machines set the SPC
> RAM differently. My PAL Machine resets the SPC RAM to a set pattern
> and my Super Famicom doesn't reset the SPC RAM at all.
I wouldn't expect SRAM to have a definite startup state either. Often it has a kind of "pattern" that shows up though. Not sure what causes it.
What pattern are you seeing? I wonder what my NTSC machine shows up as, I'll have to check again later.
Oh, and sorry for not running those tests yet. Homework got the best of me. Goodnight.
?? The CIC isn't related to the memory.
The /RESET line does connect to the WRAM chip, but I believe this is just because the $218x regs are built into the chip and these are reset (maybe?).
As I mentioned earlier, from a hardware point of view, there is no reason to expect the WRAM, which is DRAM, to have a definite power on state.
> I located some WRAM that was not affected by the Backup Unit and it
> generated differently each time the system was powered on.
Yeah, that sounds reasonable.
> My emulator sets the WRAM differently, if the ROM Checksum is OK
> then WRAM is set to $55, else it is set to zero. Basically if the ROM
> Checksum is bad the game is deemed to have been hacked and thus
> can only be run on a copier and copiers reset WRAM to zero.
Hmm... that's a neat way to handle it. However, I often don't think to setup the checksum because the real system could care less, and emulators didn't either (well, till now). I'd kind of preferr it just always acted like the normal system without copier.
I guess there's no perfect way to handle that if some programs are meant to run on the copier. Oh well.
> On a side note, I have found that both of my machines set the SPC
> RAM differently. My PAL Machine resets the SPC RAM to a set pattern
> and my Super Famicom doesn't reset the SPC RAM at all.
I wouldn't expect SRAM to have a definite startup state either. Often it has a kind of "pattern" that shows up though. Not sure what causes it.
What pattern are you seeing? I wonder what my NTSC machine shows up as, I'll have to check again later.
Oh, and sorry for not running those tests yet. Homework got the best of me. Goodnight.
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
MK had some tests done a while back. Various hardware included in the cartridge had various memories initilized differently. There were a few games that expect a certian initial value, and they aren't all the same.
For that reason, he wanted that each ROM dump should have with it some sort of list of the hardware it used.
For that reason, he wanted that each ROM dump should have with it some sort of list of the hardware it used.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
Hmm, I realize it's DRAM and thus upon power on its state is undefined, but I was thinking maybe the SNES manually went in and cleared the RAM to a certain value, sort of like how S gets its initial value. Guess not though.
Nach: I read the posts about the new SNES header you guys were throwing around. It sounds like a great idea, actually. The only problem is finding out all this info for every game out there is a serious amount of work. Perhaps have the new header have a byte that specifies if the information was manually validated or guessed.
Mr. D has done an extreme amount of work on identifying SNES cartridges and their hardware, and the both of us own probably hundreds of SNES carts. If you guys want, I'll create a base specification and create tools to turn an SMC directory to the new format and vice versa, along with a package with headers for every GoodSNES game. Since a header has 512 bytes, it would be easy to extend upon anything I miss at a later date.
Nach: I read the posts about the new SNES header you guys were throwing around. It sounds like a great idea, actually. The only problem is finding out all this info for every game out there is a serious amount of work. Perhaps have the new header have a byte that specifies if the information was manually validated or guessed.
Mr. D has done an extreme amount of work on identifying SNES cartridges and their hardware, and the both of us own probably hundreds of SNES carts. If you guys want, I'll create a base specification and create tools to turn an SMC directory to the new format and vice versa, along with a package with headers for every GoodSNES game. Since a header has 512 bytes, it would be easy to extend upon anything I miss at a later date.
Yeah forget that, just something i remembered seeing on a patent a long, long time ago.neviksti wrote:> WRAM is randomly generated, possibly by the CIC?
?? The CIC isn't related to the memory.
The /RESET line does connect to the WRAM chip, but I believe this is just because the $218x regs are built into the chip and these are reset (maybe?).
As I mentioned earlier, from a hardware point of view, there is no reason to expect the WRAM, which is DRAM, to have a definite power on state.
There's a few public Domain games that don't run unless WRAM is set to zero. Calculating the checksum is easy though, i think the lastest version of wla does it for you.neviksti wrote: > My emulator sets the WRAM differently, if the ROM Checksum is OK
> then WRAM is set to $55, else it is set to zero. Basically if the ROM
> Checksum is bad the game is deemed to have been hacked and thus
> can only be run on a copier and copiers reset WRAM to zero.
Hmm... that's a neat way to handle it. However, I often don't think to setup the checksum because the real system could care less, and emulators didn't either (well, till now). I'd kind of preferr it just always acted like the normal system without copier.
I guess there's no perfect way to handle that if some programs are meant to run on the copier. Oh well.
Basically, each byte is filled with bit 5 of it's address. Here's the program i used. It copys the upper 32K of the SPC700 RAM to SRAM.neviksti wrote: > On a side note, I have found that both of my machines set the SPC
> RAM differently. My PAL Machine resets the SPC RAM to a set pattern
> and my Super Famicom doesn't reset the SPC RAM at all.
I wouldn't expect SRAM to have a definite startup state either. Often it has a kind of "pattern" that shows up though. Not sure what causes it.
What pattern are you seeing? I wonder what my NTSC machine shows up as, I'll have to check again later.
spchack.zip
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
I have a copy of MK's proposed format, as well as my own tools that can work as needed with headers.byuusan wrote: Mr. D has done an extreme amount of work on identifying SNES cartridges and their hardware, and the both of us own probably hundreds of SNES carts. If you guys want, I'll create a base specification and create tools to turn an SMC directory to the new format and vice versa, along with a package with headers for every GoodSNES game. Since a header has 512 bytes, it would be easy to extend upon anything I miss at a later date.
The main reason why this hasn't really went anywhere is because of lack of interest by everyone else.
If people are suddenly interested, I could break out the old work already done.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
I would probably implement it into NSRT and ZSNES if I see it worthwhile.byuusan wrote:Well, I wouldn't mind seeing it posted here, if you don't mind... it's up to you guys if you want to implement it into zsnes/snes9x, however.
Let me paste the specs here, hope the board can handle it.
Code: Select all
Purpose: The format specification made here is designed to reintroduce information lost in the dumping process of a SNES cart, particularly data about memory mapping. However, the format exceeds this purpose, simply because the opportunity exists to handle other problematic cases that plague emulators.
Format:
The format shall consist of two parts:
1. The header
2. The ROM
Let us begin with the ROM. This is the part that is problematic for emulators, as they depend on internal data to determine the entire configuration of the cart. In several commercial releases, this internal data is present multiple times, or is malformed, or just incorrect. In addition, this information is frquently tampered with by translation groups, copier cracks, pirated carts, or is absent or misplaced in betas, pirates, and homebrew games.
The proposed format is designed to provide a consistant location for the data needed by emulators, as well as allowing the information to be updated independant of the emulator. The working assumption is that in at least some cases, updating this information can improve game performance without emulator modifications. It need not occur in many or all situations to provide a worthwhile benefit to this aim.
In order to facilitate the consistant handling of the ROM, the following guidelines are held to be requirements for the proposed format:
SPC7110 ROMs shall be Program ROM first, data ROM second. All known dumps obey this rule already.
ROMs larger than 32 Mbit that lack special addressing hardware shall be ordered as a 32 Mbit chunk followed by the remaining chunk. This is consistant with the common dumps of Tales of Phantasia and Dai Kaiju Monogatari 2, the only commercial games that fall into this category.
All other ROMs shall be in linear order, and shall not be interleaved, nor contain a copier header.
All values are in SNES order (little-endian).
Offset:
0x000 header version (uint16)
This is the revision of the header spec used. Emulators should display a text message warning of outdated headers and should not try to gather meaningful information from fields added after the listed version. Emulators may optionally reject outdated headers.
Emulators may optionally display a warning that the emulator may be out of date if the version is newer than supported. In this case, the emulator should use the available data as best it can. Rejection is strongly disapproved for this case.
0x002 file size (uint32)
This is the uncompressed size of the ROM
0x006 compression type (uint16)
This is the method of compression used.
Current values are:
00 None
08 zlib deflate
0x008 Tool Name (32 bytes)
The name of the tool generating the header. This is mainly used to catch tools that are outdated or broken.
0x028 Tool version string (16 bytes)
This is a string because some tools use letters, such as b or RC, and it's important to note which is which.
0x038 Canonical name (32 bytes)
This is a less than complete name. The purpose is simply to make the specific game easy to identify.
For example, Dezaemon's proper name is much longer than "Dezaemon". But Dezaemon is sufficient to identify the game. This field is meant to be independant of renaming conventions. These are for identifcation purposes only. Don't whine about them not being complete or exact. We honestly don't care, unless there are duplicates.
This is meant to be a simple title, and the pok�OM.exe tools can bicker about official names.
0x058 ROM CRC32 (uint32)
This is the expected CRC32 of the ROM portion of the file. Emulators should reject any ROM that fails to match this, unless the "hacked" flag is set. Emulators may alert users to the hacked flag being set, but this is not required.
0x05C special chip (uint16)
This is an integer value specifying the special chip used in the game.
Currently known values are:
0000: none
0001: DSP-1
0002: DSP-2
0003: DSP-3
0004: DSP-4
0005: SuperFx (mario Chip)
0006: SuperFx (GSU-1)
0007: SuperFx (GSU-2)
0008: SuperFx (GSU defaulting to 21 Mhz)
0009: SA-1
000A: C4
000B: OBC1
000C: S-DD1
000D: SPC7110
000E: SPC7110 + RTC
000F: SRTC
0010: Seta ST010
0011: Seta ST011
0012: Seta ST018
0013: BSX registers
0014: Super Gameboy
0015 and higher are undefined currently. Subsequent versions of the spec may make use of them.
0x05E addressing map (uint16)
This field provides information on the memory mapping of the cart.
Currently, the only supported map is 0xFFFF, which is reserved for "emulator determined". This is due to lack of current information. Future drafts will detail more of the memory maps supported. Documentation of a given map must be provided in order for it to be considered valid. This spec should not be redistributed with such documentation, as it may become rapidly outdated. All proposed and supported maps must be included with the spec.
0x060 fallback base map (uint16)
This is a subset of known maps, derived from the closest supported map by ALL participating emulators. 0xFFFF is the only supported map for this value currently.
0x062 Cart RAM size (uint16)
This is the number of kilobytes of onboard RAM supplied by the cart. Remember that chips are generally sold by the bit. Hence, 4 Mbits of RAM should be listed as "512" in this field.
0x064 Cart SRAM size (uint16)
This is similar to the preceding field, except that this field is for battery-backed RAM.
0x066 port 1 controllers (uint16)
This is an enumerated value of controllers supported by the game.
0000 - None (port is empty)
0001 - Gamepad
0002 - Superscope
0003 - Mouse
0004 - Multitap 5
0005 - Justifier
0006 - Barcode Battler
0007 - Laser Birdie system
0008 - Turbo File Twin
0009 - SFC Modem
000A - X-Band keyboard
000B - Miracle Piano System
0x068 port 2 controllers (uint16)
this uses the same system as port 1. Note that some controllers may not be supported on some ports, regardless of the ability to have the flags set that way.
0x06A Slot Contents (uint8)
This field is used on a base cart to determine the accepted types of add-on carts.
This field also doubles as the type field for the add-in cart. (ROM/FLASH is forbidded on add-in carts)
The Sufami Turbo BIOS should use STMINI.
FLASH should be used as the type for data downloaded on the BS, but that cannot be executed on the BS.
BSFLASH should be used as the type for data that is meant be executed on the BS system.
In the event that data can be used on both the BS and off it, FLASH is the more correct type.
Possible values are: NONE, ROM, SRAM, ROM/FLASH, FLASH, BSFLASH, STMINI, STSRAM, and UNKNOWN. (start at 0 and count)
0x06B init sram style (uint8)
This tells the emulator what type of fill to use.
Recognized values are:
00 flood fill with constant value
01 fill with random function
80 fill with a predefined pattern
For pattern fill, see the initial sram value entry
0x06C initial sram value (uint8)
This value is either the pattern number for a pattern fill, or the value used for a flood fill.
This should be 0 for a random fill.
There are no currently defined patterns.
0x06D copier mask (uint8)
Some homebrew ROMs require special initialization to work. They expect the environment to match the copier that they were programmed against. This field specifies which fields require initialization.
01 wram
02 vram
all other bits are reserved for future stuff we might need to initialize.
0x06E copier init wram (uint8)
The value to use for wram initialization to mimic a copier.
0x06F copier init vram (uint8)
The value to use for vram initialization to mimic a copier.
0x070 Ignore CRC32 check (bool)
This field, if it is exactly 0x80, should tell the emulator not to reject the game if the CRC32 is a mismatch.
This is primarily meant for the sanity of the translators, and should NOT be set for ANY distributed ROM.
0x071 BAD VRAM flag (bool)
This flag should default to 0xFF, as a convention. If it is set at 0, emulators should ignore the restriction for VRAM writes during display. This is meant as support for legacy translations, and should never be willingly used.
0x072 Translator (optional 32 characters)
This field exists to encourage translators to use the format.
0x092 reserved (0x00) (0x16A bytes)
0x1FC header checksum (uint16)
this is a checksum of the header. All 512 bytes. ROMs should be rejected if this does not match.
0x1FE checksum compliment (uint16)
this is 0xFFFF - the header checksum. If this does not add up, the ROM should be rejected.
Field Size notes:
byte is considered to be 8 bits
a character is considered to be an 8-bit ASCII character.
uint8, 16, and 32 indicates the bit size of the field.
Text fields should be 8-bit ASCII only (meaning kludge any entries
into the English alphabet before filling the fields)
Why this cannot be piggybacked:
1. lack of decent documentation of existing formats.
We are unable to find accurate and detailed documentation of the formats used by various copiers.
2. Incompatibilities.
Some copiers require interleave formats, which are contrary to this goals of this format.
3. Enforcement of spec.
Allowing the additional header to cohabitate with this header erodes the ability to rigidly enforce the header spec.
Code: Select all
Proposed map list:
MAD-1 LoROM
MAD-1 HiROM
Pure LoROM (ROM mirrored across A15, responds to any read request passed out of the SNES)
Pure HiROM (ROM mirrored across A22, responds to any read request passed out of the SNES) -Killer instinct
Basic Sram LoROM - adds Sram in the low half of banks 70-7D, F0-FF
Basic Sram HiROM - adds Sram to 6/7xxx from banks 30 to 3F and B0 to Bf
Full Bank LoROM SRAM - uses all of banks 70-7D and F0-FF -Ys3
Cross Sram LoROM - LoROM with Sram in the Basic HiROM area
Slotted SA-1
Same Game
X-Band
SuperFx
SA-1
S-DD1
SPC7110
BS-X
Sufami Turbo
Extended ROM
More details on each of these as header research progresses
Emulators should default to using the MAD-1 maps. In addition, Tales of Phantasia and DKJM2 are MAD-1 maps, but these are over 48 Mbit, and may be handled separately by the emulator.
There are currently one or two more maps that are not listed, due to ambiguity.
Pure and Basic Sram may be merged.
0000 - MAD-1 LoROM
0001 - MAD-1 HiROM
0002 - Pure LoROM
0003 - Pure HiROM
0004 - Basic Sram LoROM
0005 - Basic Sram HiROM
0006 - Full bank sram LoROM
0007 - Cross SRAM LoROM
0008 - SuperFx
0009 - X-Band
000A - SA-1
000B - SA-1 Slotted
000C - S-DD1
000D - SPC7110
000E - BS-X
000F - Sufami Turbo
0010 - Same Game
0011 - Hypothetical 95 Mbit mixed ROM
FFFE - Absolute ROM
FFFF - Emulator Default
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
I also would add that due to more recent research, a field or two needs to be modified.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
This should be revised. What about games that support more than one input, such as joypad + superscope, or joypad + mouse?This is an enumerated value of controllers supported by the game.
0000 - None (port is empty)
0001 - Gamepad
0002 - Superscope
0003 - Mouse
0004 - Multitap 5
0005 - Justifier
0006 - Barcode Battler
0007 - Laser Birdie system
0008 - Turbo File Twin
0009 - SFC Modem
000A - X-Band keyboard
000B - Miracle Piano System
I suggest using bit masks for this field.
Code: Select all
(In hex:)
0000 - None (port is empty)
0001 - Gamepad
0002 - Superscope
0004 - Mouse
0008 - Multitap 5
0010 - Justifier
0020 - Barcode Battler
0040 - Laser Birdie system
0080 - Turbo File Twin
0100 - SFC Modem
0200 - X-Band keyboard
0400 - Miracle Piano System
A checksum of all 512 bytes is impossible. I'm sure he meant the first 508 bytes.0x1FC header checksum (uint16)
this is a checksum of the header. All 512 bytes. ROMs should be rejected if this does not match.
Overall, I like it. I'd use it in translations I've created. One side suggestion would be to accept the header as being separate from the rom, or appended to the top. E.G. Mygame.smc + Mygame.shf (or whatever), or Mygame.snf (or whatever). It really makes working with a game easier when you don't have to always add 512 to all the addresses to find data in the ROM. Thanks for posting that, by the way.
Oh yes, one thing: please don't use the compression area if you do implement this. It would be far better to just support zipped roms. Otherwise, you're forcing all emulator authors, as well as all ROM Tool authors (who need to access the ROM data, e.g. for crc verification), who use this spec to add zlib. Not to mention, ROMs are only 4mb, with four exceptions. Hard Drives come at a minimum of 40GB these days. Do we really need to compress them? :)
-
- ZSNES Developer
- Posts: 3904
- Joined: Tue Jul 27, 2004 10:54 pm
- Location: Solar powered park bench
- Contact:
Of course it's possible. I do it all the time. the last 4 bytes are opposites, go do the math.byuusan wrote:A checksum of all 512 bytes is impossible. I'm sure he meant the first 508 bytes.0x1FC header checksum (uint16)
this is a checksum of the header. All 512 bytes. ROMs should be rejected if this does not match.
May 9 2007 - NSRT 3.4, now with lots of hashing and even more accurate information! Go download it.
_____________
Insane Coding
_____________
Insane Coding
I think this is a miscommunication.
Ok, say you have a 4-byte header:
data[] = { 82 14 00 00 };
The last two bytes are 00's because we don't know the CRC of the 4 bytes yet. So then:
82 + 14 + 00 + 00 = 96
96 ^ FF = 69
So now it becomes:
data[] = { 82 14 96 69 };
But now the checksum is invalid again!
82 + 14 + 96 + 69 = 0195 (95)
The checksum + complement = FFFF. The only way a checksum would be doable would be if you force incremented the checksum by 1, or you made the complement 10000-checksum, which really isn't a complement anymore. Is this what you mean?
Ok, say you have a 4-byte header:
data[] = { 82 14 00 00 };
The last two bytes are 00's because we don't know the CRC of the 4 bytes yet. So then:
82 + 14 + 00 + 00 = 96
96 ^ FF = 69
So now it becomes:
data[] = { 82 14 96 69 };
But now the checksum is invalid again!
82 + 14 + 96 + 69 = 0195 (95)
The checksum + complement = FFFF. The only way a checksum would be doable would be if you force incremented the checksum by 1, or you made the complement 10000-checksum, which really isn't a complement anymore. Is this what you mean?