Secret of Evermore FAQs and Walkthroughs
SRAM Guide
-------------------------------------------------------------------------------
| Secret of Evermore SRAM Document 1.0
| by John David Ratliff
|
| The most recent version of this guide can always be found at
| http://games.technoplaza.net/soesrame/sram-doc.txt
|
| Copyright (C) 2006 emuWorks (http://games.technoplaza.net/)
| Permission is granted to copy, distribute and/or modify this document
| under the terms of the GNU Free Documentation License, Version 1.2
| or any later version published by the Free Software Foundation;
| with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
| Texts. A copy of the license can be found at
| http://www.gnu.org/licenses/fdl.html
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
| Table of Contents
-------------------------------------------------------------------------------
- 1.0 Introduction
- 2.0 Copyright Notice
- 3.0 Revision History
- 4.0 The SRAM
- 4.1 SRAM Basics
- 4.2 SRAM Offsets
- 4.3 The Sanity Algorithm
- 5.0 soesrame - Secret of Evermore SRAM Editor
- 6.0 Credits & Acknowledgements
- 7.0 Contact Information
-------------------------------------------------------------------------------
| 1.0 Introduction
-------------------------------------------------------------------------------
This document is a guide to the Secret of Evermore SRAM, the section of
memory in the Secret of Evermore cartridge used to save your progress.
SNES emulators create a special file to store this memory. These are known as
SRAM files and generally have a .srm extention (ZSNES and Snes9x both use the
.srm extention).
This guide will describe the SRAM, what it stores and where, and how to edit
it to change your save games. For a program that edits the SRAM, see section
5.0.
I consider SRAM editing superior to save state editing for two reasons.
First, generally only one emulator can read any particular save state file,
so save state hacking only works if you use that particular emulator.
Second, save state formats can change between emulator revisions, which
renders state editing documents useless. There are several old DOS save state
editors and documents for Nesticle save states. As nearly no one still uses
nesticle, all those programs and documents are useless. There are almost as
many documents and programs for ZSNES save states, but the ZSNES save state
format has changed so often, most of these programs and documents are also
useless.
Save state editors/documents are more popular than SRAM editors/documents
because they are easier to change. Because the SRAM employs a battery to
keep the data, and the battery eventually diea, SRAM files need to be sanity
checked to see if the battery is still functioning. This leads to extra
information stored in the SRAM that is used to test the validity of the data.
When you edit SRAM files, you must also correct this sanity data, or the game
will think the SRAM is not valid, and you won't be able to play your edited
games.
-------------------------------------------------------------------------------
| 2.0 Copyright Notice
-------------------------------------------------------------------------------
This document is Copyright (C) 2006 emuWorks (http://games.technoplaza.net/)
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license can be found at
http://www.gnu.org/licenses/fdl.html
Basically, it is free documentation in much the same way software under the
GNU General Public License is free software. You can modify it, redistribute
it, sell it, publish it, etc.
-------------------------------------------------------------------------------
| 3.0 Revision History
-------------------------------------------------------------------------------
Version 1.0 - Sunday, September 10, 2006
- First Public Release
-------------------------------------------------------------------------------
| 4.0 The SRAM
-------------------------------------------------------------------------------
This section details the SRAM format used by Secret of Evermore.
-------------------------------------------------------------------------------
| 4.1 SRAM Basics
-------------------------------------------------------------------------------
Secret of Evermore, like most SNES games, used an SRAM of 0x2000 (8 KB) bytes
to store its information. Up to four games could be save. Each game used
0x331 bytes of SRAM. This means 0xCC4 bytes of SRAM are reserved for the
game data, with 0x133C bytes used for other things (some unused). In this
document, we are only interested in the 0xCC4 bytes of save game data.
Not all of the information contained in the save game data is known. Most of
what is undocumented is related to quest progress and opened or already found
treasure. The only major items of interest that I've yet to find are the save
location, and the rare quest items.
Here is a short listing of what is known in no particular order. The sanity
(aka checksum) data, the known alchemys and their levels, the boy's and dog's
stats (name, experience, level, hp, and mp), the money (talons, jewels, gold
coins, and credits), and the inventory (alchemy ingredients, items, armors,
weapons, helmets, gauntlets, collars, trade goods, and charms).
The first game starts at 0x2 in the SRAM, and after its 0x331 bytes, the
second game starts and so on for the four games.
The next section will present the SRAM offsets and their meanings.
-------------------------------------------------------------------------------
| 4.2 SRAM Offsets
-------------------------------------------------------------------------------
This information is presented in no particular order. Similar information
will be grouped together.
When an offset is listed, this offset is relative to the start of the game
data. For example, if I said the boy's name is at offset 0x26, this would be
0x28 (0x2 + 0x26) from the start of SRAM for game 1, and 0x359 (0x2 + 0x331 +
0x26), and so on.
Data in the SRAM is stored in little endian format, the format used by the
SNES processor. This means words are stored with their least significant byte
first. For instance, 400 is 0x190 in hex, which is two bytes 0x01 and 0x90.
In little endian, this would be 0x9001 [90 01]. Mostly, this just means
reverse the bytes. There are plenty of endian guides on the web if you need a
more in-depth explanation.
----------------------------------------------------
Sanity Data - the sanity/checksum word
0x0 (2 bytes)
----------------------------------------------------
----------------------------------------------------
Boy's Stats
0x26 (name)
0x9D (level)
0x6E (current HP, 2 bytes)
0x8E (max HP, 2 bytes)
0x9A (experience, 3 bytes)
Dog's Stats
0x4A (name)
0xDE (level)
0xAF (current HP, 2 bytes)
0xCF (max HP, 2 bytes)
----------------------------------------------------
The boy and dog's names have storage space for 34 characters (null
terminated). However the game limits you to 15 character names. Using longer
names is untested.
The name is ASCII encoded, and names can consist of the entire alphabet
(upper and lowercase), the numbers 0-9, and the characters , (comma),
. (period), ! (exclamation point), ' (apostrophe), \ (backslash), - (hyphen),
& (ampersand), # (pound), and (space). This is the alphabet the game limits
you to using. Using characters outside this alphabet is untested.
The byte immediately after the character's name must be the null
terminator (00). If there is no terminator, the game will crash on load.
The valid range for levels are 1-99. The valid range for hp is 0-999, though
the max should probably be at least 1.
The valid range for experience is 0-7562471. The high value is the dog's
level 99 experience. Anything more than that is pointless.
The next offsets are for the money types in the game. Their valid range is
0-16,777,215. The high value is the max value for an unsigned 24-bit
number.
----------------------------------------------------
0xFC (Talons, 3 bytes)
0xFF (Jewels, 3 bytes)
0x102 (Gold Coins, 3 bytes)
0x105 (Credits, 3 bytes)
----------------------------------------------------
The next offsets are for the weapon inventory. There is a single bit for each
weapon. The first value is the offset in the SRAM, and the second is the bit
that controls it. A set bit (1) means you have the weapon, and a clear bit
means you do not have it.
Bit number start at 0 and go through 7 and run right to left. For example, in
the byte with bit pattern 10010010, bit 0 is clear and bit 7 is set.
----------------------------------------------------
0x279 bit 1 (Bone Crusher)
0x279 bit 2 (Gladiator Sword)
0x279 bit 3 (Crusader Sword)
0x279 bit 4 (Neutron Blade)
0x279 bit 5 (Spider's Claw)
0x279 bit 6 (Bronze Axe)
0x279 bit 7 (Knight Basher)
0x27A bit 0 (Atom Smasher)
0x27A bit 1 (Horn Spear)
0x27A bit 2 (Bronze Spear)
0x27A bit 3 (Lance)
0x27A bit 4 (Laser Lance)
0x27A bit 5 (Bazooka)
----------------------------------------------------
The next set of offsets are for the weapon levels. The first offset is for
the major level (1-3), and the second is for the minor (power up
progression).
The minor level ranges from 0-255. The status screen only shows values from
0-99. To convert between the actual value and the shown value, just divide
the minor level by 2.56 and ignore the decimal places.
----------------------------------------------------
0x116 0x115 (Bone Crusher)
0x118 0x117 (Gladiator Sword)
0x11A 0x119 (Crusader Sword)
0x11C 0x11B (Neutron Sword)
0x11E 0x11D (Spider's Claw)
0x120 0x11F (Bronze Axe)
0x122 0x121 (Knight Basher)
0x124 0x123 (Atom Smasher)
0x126 0x125 (Horn Spear)
0x128 0x127 (Bronze Spear)
0x12A 0x129 (Lance)
0x12B 0x12A (Laser Lance)
0x13E 0x13D (Dog's Attack Level)
----------------------------------------------------
The next set of offsets are for the alchemy ingredients. Their valid range is
from 0-99.
----------------------------------------------------
0x289 (Wax)
0x28A (Water)
0x28B (Vinegar)
0x28C (Root)
0x28D (Oil)
0x28E (Mushroom)
0x28F (Mud Pepper)
0x290 (Meteorite)
0x291 (Limestone)
0x292 (Iron)
0x293 (Gunpowder)
0x294 (Grease)
0x295 (Feather)
0x296 (Ethanol)
0x297 (Dry Ice)
0x298 (Crystal)
0x299 (Clay)
0x29A (Brimstone)
0x29B (Bone)
0x29C (Atlas Medallion)
0x29D (Ash)
0x29E (Acorn)
----------------------------------------------------
The next offsets are for the alchemy inventory. Just like the weapon
inventory, the first value is the offset and the second is the bit that
controls it. A set bit means you know the alchemy, and a clear bit means you
don't.
----------------------------------------------------
0x1F7 bit 0 (Acid Rain)
0x1F7 bit 1 (Atlas)
0x1F7 bit 2 (Barrier)
0x1F7 bit 3 (Call up)
0x1F7 bit 4 (Corrosion)
0x1F7 bit 5 (Crush)
0x1F7 bit 6 (Cure)
0x1F7 bit 7 (Defend)
0x1F8 bit 0 (Double Drain)
0x1F8 bit 1 (Drain)
0x1F8 bit 2 (Energize)
0x1F8 bit 3 (Escape)
0x1F8 bit 4 (Explosion)
0x1F8 bit 5 (Fireball)
0x1F8 bit 6 (Fire Power)
0x1F8 bit 7 (Flash)
0x1F9 bit 0 (Force Field)
0x1F9 bit 1 (Hard Ball)
0x1F9 bit 2 (Heal)
0x1F9 bit 3 (Lance)
0x1F9 bit 4 (Laser - dummied alchemy)
0x1F9 bit 5 (Levitate)
0x1F9 bit 6 (Lightning Storm)
0x1F9 bit 7 (Miracle Cure)
0x1FA bit 0 (Nitro)
0x1FA bit 1 (One Up)
0x1FA bit 2 (Reflect)
0x1FA bit 3 (Regrowth)
0x1FA bit 4 (Revealer)
0x1FA bit 5 (Revive)
0x1FA bit 6 (Slow Burn)
0x1FA bit 7 (Speed)
0x1FB bit 0 (Sting)
0x1FB bit 1 (Stop)
0x1FB bit 2 (Super Heal)
----------------------------------------------------
The next set of offsets are for the alchemy levels. The first offset is their
major level (0-9), and the second is their minor level (power-up progress).
The minor level can range from 0-99. For some reason, both of these offsets
are 2 bytes, but since the values never exceed 255, you can just ignore their
second byte and treat them like a single byte value.
----------------------------------------------------
0x19B 0x155 (Acid Rain)
0x19D 0x157 (Atlas)
0x19F 0x159 (Barrier)
0x1A1 0x15B (Call Up)
0x1A3 0x15D (Corrosion)
0x1A5 0x15F (Crush)
0x1A7 0x161 (Cure)
0x1A9 0x163 (Defend)
0x1AB 0x165 (Double Drain)
0x1AD 0x167 (Drain)
0x1AF 0x169 (Energize)
0x1B1 0x16B (Escape)
0x1B3 0x16D (Explosion)
0x1B5 0x16F (Fireball)
0x1B7 0x171 (Fire Power)
0x1B9 0x173 (Flash)
0x1BB 0x175 (Force Field)
0x1BD 0x177 (Hard Ball)
0x1BF 0x179 (Heal)
0x1C1 0x17B (Lance)
0x1C3 0x17D (Laser - dummied alchemy)
0x1C5 0x17F (Leviate)
0x1C7 0x181 (Lightning Storm)
0x1C9 0x183 (Miracle Cure)
0x1CB 0x185 (Nitro)
0x1CD 0x187 (One Up)
0x1CF 0x189 (Reflect)
0x1D1 0x18B (Regrowth)
0x1D3 0x18D (Revealer)
0x1D5 0x18F (Revive)
0x1D7 0x191 (Slow Burn)
0x1D9 0x193 (Speed)
0x1DB 0x195 (Sting)
0x1DD 0x197 (Stop)
0x1DF 0x199 (Super Heal)
----------------------------------------------------
The next offsets are for the inventory items, which include the common
items, equipment, and tradge goods. In other words, anything that can be
bought, sold, or traded.
Most items have a valid range of 0-6, but a few can be up to 99. These
include call beads, bazooka ammunition, and all the trade goods.
----------------------------------------------------
0x29F (Petal)
0x2A0 (Nectar)
0x2A1 (Honey)
0x2A2 (Dog Biscuit)
0x2A3 (Wings)
0x2A4 (Essence)
0x2A5 (Pixie Dust)
0x2A6 (Call Bead)
0x2A7 (Grass Vest)
0x2A8 (Shell Plate)
0x2A9 (Dino Skin)
0x2AA (Bronze Armor)
0x2AB (Stone Vest)
0x2AC (Centurion Cape)
0x2AD (Silver Mail)
0x2AE (Gold Plated Vest)
0x2AF (Shining Armor)
0x2B0 (Magna Mail)
0x2B1 (Titanium Vest)
0x2B2 (Virtual Vest)
0x2B3 (Grass Hat)
0x2B4 (Shell Hat)
0x2B5 (Dino Helm)
0x2B6 (Bronze Helmet)
0x2B7 (Obsidian Helm)
0x2B8 (Centurion Helm)
0x2B9 (Titan's Crown)
0x2BA (Dragon Helm)
0x2BB (Knight's Helm)
0x2BC (Lightning Helm)
0x2BD (Old Reliable)
0x2BE (Brainstorm)
0x2BF (Vine Bracelet)
0x2C0 (Mammoth Guard)
0x2C1 (Claw Guard)
0x2C2 (Serpent Bracer)
0x2C3 (Bronze Gauntlet)
0x2C4 (Gloves of Ra)
0x2C5 (Iron Bracer)
0x2C6 (Magician's Ring)
0x2C7 (Dragon's Claw)
0x2C8 (Cyberglove)
0x2C9 (Protector Ring)
0x2CA (Virtual Glove)
0x2CB (Leather Collar)
0x2CC (Spiky Collar)
0x2CD (Defender Collar)
0x2CE (Spot's Collar)
0x2CF (Thunderball)
0x2D0 (Particle Bomb)
0x2D1 (Cryo-Blast)
0x315 (Annihilation Amulet)
0x316 (Beads)
0x317 (Ceramic Pot)
0x318 (Chicken)
0x319 (Golden Jackal)
0x31A (Jeweled Scarab)
0x31B (Limestone Tablet)
0x31C (Perfume)
0x31D (Rice)
0x31E (Spice)
0x31F (Souvenir Spoon)
0x320 (Tapestry)
0x321 (Ticket for Exhibition)
----------------------------------------------------
The final offsets are for the charms. They are just like the weapon and
alchemy inventories. The first value is the offset, and the second is the
controlling bit.
----------------------------------------------------
0x200 bit 5 (Armor Polish)
0x200 bit 6 (Chocobo Egg)
0x200 bit 7 (Insect Incense)
0x201 bit 0 (Jade Disk)
0x201 bit 1 (Jaguar Ring)
0x201 bit 2 (Magic Gourd)
0x201 bit 3 (Moxa Stick)
0x201 bit 4 (Oracle Bone)
0x201 bit 5 (Ruby Heart)
0x201 bit 6 (Silver Sheath)
0x201 bit 7 (Staff of Life)
0x202 bit 0 (Sun Stone)
0x202 bit 1 (Thug's Cloak)
0x202 bit 2 (Wizard's Coin)
----------------------------------------------------
The remaining values in the SRAM are unknown. Please contact me if there you
think I have missed something important.
-------------------------------------------------------------------------------
| 4.3 The Sanity Algorithm
-------------------------------------------------------------------------------
As described earlier, Secret of Evermore uses two bytes of sanity data to
ensure the SRAM is still being saved by the battery. This section describes
that algorithm.
The following is the actual algorithm, obtained using Geiger's Snes9x
debugger. I have commented each line.
---------------------------------------------------------------------
$8D/B469 A0 2F 03 LDY #$032F ; load 0x32F into counter
$8D/B46C 22 78 B4 8D JSL $8DB478[$8D:B478] ; jump to subroutine
$8D/B478 A9 3F 04 LDA #$043F ; a = 0x43F
$8D/B47B E2 20 SEP #$20 ; use 8-bit accumulator
$8D/B47D 18 CLC ; clear carry
$8D/B47E 7D 00 00 ADC $0000,x[$30:6666] ; add data[offset]
$8D/B481 88 DEY ; y = y - 1
$8D/B482 F0 0B BEQ $0B [$B48F] ; branch if y = 0
$8D/B484 E8 INX ; x = x + 1
$8D/B485 C2 20 REP #$20 ; use 16-bit accumulator
$8D/B487 0A ASL A ; shift left
$8D/B488 E2 20 SEP #$20 ; use 8-bit accumulator
$8D/B48A 7D 00 00 ADC $0000,x[$30:6667] ; add data[offset]
$8D/B48D 80 F2 BRA $F2 [$B481] ; branch always
$8D/B48F C2 20 REP #$20 ; use 16-bit accumulator
$8D/B491 6B RTL ; return from subroutine
---------------------------------------------------------------------
The SNES used a custom WDC 65c816 processor, so if you wanted to learn more
about this code, that's the assembly language it's in.
The algorithm is fairly straightforward.
First, we take an accumulator and initialize it with 0x043F. The first byte
of game data is added to the lower byte of our accumulator. If a carry
results, we ignore it.
Next we start a loop. We shift the accumulator left by 1. The shifted bit is
placed in the carry. Then we add the next byte of data to the lower byte of
our accumulator. The carry is also added here and reset to 0. If our addition
results in a carry, it will be placed in the carry. This process is repeated
for every byte of game data. Note that the carry from our addition will be
ignored due to the shift that always occurs following the next iteration of
the loop.
Here is the C++ routine from soesrame I wrote (based on C source from
phonymike).
--------------------------------------------------------------------------
quint16 SRAMFile::checksum(int game) const {
quint32 checksum = 0x43F;
unsigned char temp = checksum +
sram[SRAM_GAME_OFFSET + 2 + game * SRAM_GAME_SIZE];
for (int i = 3; i < SRAM_GAME_SIZE; ++i) {
checksum &= 0xFF00;
checksum |= temp;
checksum <<= 1;
if (checksum > 0xFFFF) {
checksum -= 0xFFFF;
}
temp = checksum + sram[SRAM_GAME_OFFSET + i + game * SRAM_GAME_SIZE];
}
return static_cast(checksum);
}
--------------------------------------------------------------------------
To clear up any confusion, a quint16 is a 16-bit unsigned integer and a
quint32 is an unsigned 32-bit integer. These are types defined by the Qt
library which is used by soesrame.
When you edit the SRAM by hand, the checksum will be wrong. To get around
this, you can either fix the checksum, or have the game skip the sanity
check.
The latter can be accomplished by using a game gene code. DDA4-17E1 will do
this.
If you don't have a game genie (either because you're using an emulator that
doesn't support game genie codes, or because you're using a game copier on a
real SNES), then you will need to compute the checksum and fix the SRAM
sanity data for the game.
The following is a listing for a C program which will fix the sanity data for
an SRAM file.
-------------------------------- soe-sanity.c ---------------------------------
/*
* Secret of Evermore Sanity Fixer
* Copyright (C) 2006 emuWorks
* http://games.technoplaza.net/
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include
// define this at compile time on big endian systems (i.e. PPC Mac's)
#ifdef BYTE_ORDER_BIGENDIAN
#define SWAP_ON_BIGENDIAN(w) ((w << 8) | (w >> 8))
#else
#define SWAP_ON_BIGENDIAN(w) (w)
#endif
static void fix_game(unsigned char *sram, int game) {
unsigned short *offset = (unsigned short *)(sram + 2 + (game * 0x331));
unsigned long checksum = 0x43F;
unsigned char temp = checksum + sram[4 + (game * 0x331)];
int i;
for (i = 3; i < 0x331; ++i) {
checksum &= 0xFF00;
checksum |= temp;
checksum <<= 1;
if (checksum > 0xFFFF)
checksum -= 0xFFFF;
temp = checksum + sram[2 + i + (game * 0x331)];
}
*offset = SWAP_ON_BIGENDIAN(checksum);
printf("fixed checksum for game %d\n", (game + 1));
}
int main(int argc, char **argv) {
FILE *f;
int fix_mask = 0xF, i;
char sram[0x2000];
if ((argc != 2) && (argc != 3)) {
fprintf(stderr, "syntax: soe-sanity sram-file.srm [ game (1 - 4) ]\n");
return -1;
}
if (argc == 3) {
switch (*argv[2]) {
case '1': fix_mask = 0x1; break;
case '2': fix_mask = 0x2; break;
case '3': fix_mask = 0x4; break;
case '4': fix_mask = 0x8; break;
default: break; // ignore third argument if invalid
}
}
if ((f = fopen(argv[1], "rb")) == NULL) {
fprintf(stderr, "error: unable to open SRAM file '%s'\n", argv[1]);
return -1;
}
fseek(f, 0, SEEK_END);
if (ftell(f) != 0x2000) {
fprintf(stderr, "error: invalid SRAM file size.\n");
return -1;
}
fseek(f, 0, SEEK_SET);
if (fread(sram, 0x2000, 1, f) != 1) {
fprintf(stderr, "error: unable to read SRAM file.\n");
return -1;
}
fclose(f);
for (i = 0; i < 4; ++i) {
if (fix_mask & (1 << i)) {
fix_game(sram, i);
}
}
if ((f = fopen(argv[1], "wb")) == NULL) {
fprintf(stderr, "error: unable to open SRAM file '%s'\n", argv[1]);
return -1;
}
if (fwrite(sram, 0x2000, 1, f) != 1) {
fprintf(stderr, "error: unable to write SRAM data to file.\n");
return -1;
}
fclose(f);
return 0;
}
-------------------------------------------------------------------------------
There is a windows binary available at
http://games.technoplaza.net/soesrame/history/soe-sanity.zip. For other
platforms, you will need to compile it yourself. It is written in standard
ANSI C, so it should run anywhere.
If you are compiling on a big endian platform, you will need to define
BYTE_ORDER_BIGENDIAN at compile time. PowerPC and Sparc machines are probably
the most common big endian platforms. Intel machines (x86) are little endian.
gcc -o soe-sanity soe-sanity.c
Will build the program using gcc on a little endian platform.
gcc -DBYTE_ORDER_BIGENDIAN -o soe-sanity soe-sanity.c
Will buile the program using gcc on a big endian machine. I don't have much
experience with compilers other than gcc, so you'll have to figure it out
yourself if you're using something else.
Using the program should be simple. Just pass it the name of an SoE SRAM file
and it will fix the checksums for all the games automatically. If you only
want to fix one game's checksum, just pass the game number (1-4) as the
second argument. This is useful when you don't have four save games, as the
game might crash if the data in the other games isn't valid.
Examples:
soe-sanity "Secret of Evermore (U).srm"
soe-sanity soe.srm 1
The first one fixes all the checksums in Secret of Evermore (U).srm. The
second one fixes just the first game in soe.srm.
-------------------------------------------------------------------------------
| 5.0 soesrame - Secret of Evermore SRAM Editor
-------------------------------------------------------------------------------
For those that don't want to play around with the SRAM directly, I have
written a program that edits all the values documented here. It's also nice
in that it keeps the values within their valid ranges, and handles the sanity
data for you.
You can find it at http://games.technoplaza.net/soesrame/. There are binaries
for Windows, Mac OS X, and Linux. It should work on any platform that
supports Qt, so it should work on any unice with X Windows. The full source
is available as well.
-------------------------------------------------------------------------------
| 6.0 Credits & Acknowledgements
-------------------------------------------------------------------------------
I want to thank phonymike for discovering and documenting the checksum
algorithm used by Secret of Evermore. He was also very helpful in answering
questions I had about his code.
Thanks to Geiger for his debugging Snes9x version and the entire Snes9x
team for Snes9x. Without it, it would have been very difficult to find the
SRAM offsets.
-------------------------------------------------------------------------------
| 7.0 Contact Information
-------------------------------------------------------------------------------
The author (John Ratliff) can be contacted at
webmaster [AT] technoplaza [DOT] net. Replace as necessary.
I can also be reached via an online feedback form at
http://www.technoplaza.net/feedback.php