hide results

    Save State Hacking Guide by taleden

    Version: 1.0 | Updated: 01/28/04 | Search Guide | Bookmark Guide

    Shining Force I Save State Hacking Addendum -- v1.0
    by Taleden <email omitted lest another address be ruined by spam>
    
    ===============================================================================
    
    INDEX
    
    I. Intro
      A. Inspiration & Introduction
      B. License
      C. Revision History
      D. Intro to Hex Editing
    II. Offsets
      A. Joined Members
        1. Gens/DGen/Genecyst save-state offsets
        2. Gens SRAM offsets
        3. DGen SRAM offsets
      B. Active Members
        1. Gens/DGen/Genecyst save-state offsets
        2. Gens SRAM offsets
        3. DGen SRAM offsets
    III. Quick Lookup
    
    
    ===============================================================================
    
    [I] Intro
    
    This section just has some introductory information; if you just need the
    offsets and values, skip to section II.
    
    
    [I.A] Inspiration & Introduction
    
    A few weeks ago, I sat down to play through Shining Force again; it had been
    some time, and I was itching for some of that awesome tactical combat from my
    youth.  Unfortunately my Genesis console stopped accepting my Shining Force
    cart long ago, so I got the latest copy of a few emulators (namely, as of this
    writing, Gens 2.11 and DGen 1.21) and sat down to play.  Around the middle of
    Chapter 4, just after Pao I had moved off and I was preparing for the battle
    with General Elliott, I realized that I had forgotten to get Kokichi in the
    last chapter!  Unwilling to play out the rest of the game without my favorite
    character, I figured I'd just go back to an old save-state and re-do a few
    battles, no big deal.. but then I realized that I didn't have any old save-
    states, and had already saved over the SRAM image, too.  I was at a loss.
    
    So, I started looking around the net for information on save state hacking,
    hoping to just add Kokichi to my Force and continue on.  I came across
    Thundergod's SF1 guide, as well as Stufff's SF2 guide, which provide the
    offsets to modify character traits, but neither of them had any mention of how
    to change which characters were members of the Force.  I also picked up a copy
    of GenEdit (a generic Genesis save-game editor) which supported SF1, and it
    even allowed you to change which members were active (that is, part of the 12-
    strong group that goes into battle) - I was able to activate Kokichi and sure
    enough he appeared on the field when I went into battle, but he was still not
    technically "part of the Force" as far as the game was concerned, so I couldn't
    transfer items to him, or replace him with other people, etc, except during
    battle, which was rather annoying.
    
    All of this led up to some toying with save states and hex editors to determine
    for myself where the joined-member data was stored, so I could add Kokichi
    properly and continue my game.  The offsets weren't too hard to find in SF1, so
    I did the same for SF2, and then figured out the active-member data storage and
    SF2's difficulty setting storage, and now offer it all as an addendum to the
    current save-state hacking guides (Thundergod's and Stufff's).
    
    Note that I have released two versions of this guide: one of them is for SF1,
    and the other is for SF2.  I originally wrote a single guide that covered both
    games, but when I decided to submit to GameFAQs I discovered that they won't
    accept guides that cover multiple games, so I split it into two versions.  If
    you read both you'll notice they are almost identical (right down to this
    paragraph), except of course for the actual addresses and places where the two
    games differ.  I apologize for being repetetive; blame GameFAQs.  :)
    
    
    [I.B] License
    
    This document is released into the public domain, and may be freely copied and
    redistributed in any form, electronic or otherwise.  However, it may not be
    used, in whole or in part, for any commercial gain; no money may be charged for
    its distribution except for the cost of the media it is distributed on, if
    applicable.  This document may be duplicated in whole or in part, or used as
    a reference for the creation of subsequent documents, provided that appropriate
    credit is given to the author (Taleden) for the use of any information provided
    by this document.  All copyrights and trademarks mentioned herein are the
    property of their respective owners, unless otherwise stated.
    
    
    [I.C] Revision History
    
    1.0 - initial release
    
    
    [I.D] Intro to Hex Editing
    
    The Thundergod and Stufff guides each provide a decent intro to hex editing
    in general, so mine will be brief.
    
    First, a comment on notation: hex editing involves the hexadecimal number
    system, which recognizes sixteen digits (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c,
    d, e, f).  The decimal system recognizes ten digits, but they are the same
    first ten digits that hexadecimal uses, so there is a possibility for
    confusion: if I say 63, do I mean the decimal number sixty-three, or the
    hexadecimal number 63 (which, in decimal, is 6*16+3=99)?  On top of that, we
    have binary, which has only the symbols 0 and 1 - symbols which now appear in
    three number systems with which we are concerned, making the number "101"
    triply ambiguous.  So, to avoid this confusion, I will always refer to
    hexadecimal values with the prefix "0x", decimal numbers with no prefix, and
    binary numbers with the prefix "x".  Although there are of course exceptions,
    generally speaking these are the conventional ways to differentiate between
    these number systems.  So, as an example, "63" means decimal sixty-three;
    "0x63" means decimal ninety-nine; "x63" means nothing, because neither 6 nor 3
    is a valid binary digit; "0x11" means decimal seventeen (1*16+1); "x11" means
    decimal three (1*2+1); and so on.
    
    Next, a comment on hexadecimal and binary: computer data is, technically
    speaking, stored in binary, but it is very cumbersome to try to look at it in
    this form, which is why we use hex editors and not binary editors.  Hexadecimal
    is a good alternative (as opposed to, say, decimal) because it lines up very
    neatly with binary: four binary digits in sequence correspond to exactly one
    hexadecimal digit.  For example, the binary value x1101 is the hexadecimal
    digit 0xD (or decimal thirteen); the binary string x001101110001 is 0x371;
    notice how neatly they line up: each group of four binary digits becomes a
    single hexadecimal digit; x0011 -> 0x3, x0111 -> 0x7, x0001 -> 0x1.
    
    Building on this, I can now discuss the concept of a 'bitvector'.  Suppose you
    were designing a game, and you had a bunch of boolean flags that you wanted to
    store; for example, has the Hero talked to this person yet?  Has the Hero
    been to this town yet?  These true/false values determine the exact state of
    the game, and must be stored when the game is saved.  However, it is generally
    not possible to save data in sizes less than one 'byte', which is eight binary
    bits or two hexadecimal digits; the simple method would be to just store each
    flag as one byte, either 0x00 for false or 0x01 for true.  But this is a huge
    waste of storage space, which (especially on a game console) might be in short
    supply.  A much better method would be to store each flag as a single binary
    bit, but since a single bit can't be stored independently of a full eight-bit
    byte, a 'bitvector' is created.  In general, a 'bitvector' is just a bunch of
    bits lumped together into a number.  In our case, we're only interested in the
    8-bit variety of bitvector, which is enough to store as a single byte.  Each
    bit of the byte represents one of the flags; this way, no space is wasted.
    
    For example: from among eight flags, suppose we wanted the second and third to
    be 'true' and the rest to be 'false'; stringing them all together, we would
    have the binary sequence x01100000, which would then be stored as the hex byte
    0x60.  Now suppose we wanted to turn the first flag on; the new sequence is
    x11100000, which is hex 0xE0.  As you can see, changing just one bit of the
    bitvector made a big difference - the hex value jumped from 0x60 to 0xE0.  This
    is because we changed the 'most-significant' bit, which for our purposes always
    means the left-most bit.
    
    
    ===============================================================================
    
    [II] Offsets
    
    [II.A] Joined Members
    
    Since there are 30 characters in the game (including the Hero), four bytes
    (32 bits) are used to store the member-has-joined flags, in the form of a
    bitvector.  However, SF1 seems to store its member data backwards; that is, the
    bit that controls whether Mae is on the Force appears after the bit for Jogurt,
    even though the game's list puts Jogurt last and Mae first.  The exact ordering
    is, in fact, identical (in reverse) to the ordering of the members list that
    you can see in the game, when you have acquired everyone: Mae, then Pelle, then
    Ken, etc.  Specifically, in order of first to last byte, and most to least
    significant bit in each byte, the flags are:
    
    1st byte: N/A,     Nova,     Jogurt,  Hanzou, Musashi, Zylo,  Adam,  Bleu
    2nd byte: Kokichi, Balbaroy, Amon,    Lyle,   Hans,    Diane, Gong,  Torasu
    3rd byte: Khris,   Lowe,     Domingo, Tao,    Alef,    Anri,  Guntz, Luke
    4th byte: Gort,    Arthur,   Earnest, Vankar, Ken,     Pelle, Mae,   Hero
    
    The first two bits (N/A and Nova) are really just glitches; there are only 30
    characters, so those two bits are not necessary and the game doesn't expect
    them to ever be true.  If you do set them, however, the first one doesn't do
    anything interesting, but the second one appears to put your adviser Nova on
    your team.
    
    
    [II.A.1] Gens/DGen/Genecyst save-state offsets
    
    Although each emulator has its own save-state file format, the data we're
    interested in appears to be in exactly the same place in save-states created
    by Gens, DGen or Genecyst, and may be the same for other emulators as well.
    The member-has-joined data begins at offset 0xC102 and occupies the four bytes
    up to and including 0xC105.
    
    For example, in your first battle you have the Hero, Ken, Luke, Tao, Lowe and
    Hans (and maybe Gong) available to you.  In this case, the bitvectors for the
    four bytes would be:
    
      x0000 0000
      x0000 1010
      x0101 0001
      x0000 1001
    
    This example includes Gong (in the second segment of the second byte); I've
    added spaces in the middle to make it easier to see the mapping to the hex
    data which would appear in the save-state file, starting at offset 0xC102:
    
      0x00 0x0A 0x51 0x09
    
    If you wanted to add Gort (who, looking back up at the table above, is the
    first bit in the fourth byte), the hex data would become:
    
      0x00 0x0A 0x51 0x89
    
    
    [II.A.2] Gens SRAM offsets
    
    SRAM refers to save-ram, which is the file an emulator creates to simulate
    the battery-backup memory on a physical genesis cartridge.  If you save your
    game with the priest and then turn off the emulator, it is this file you would
    modify before restarting the emulator and continuing your game from the
    modified SRAM.  Unfortunately, different emulators also appear to store SRAM
    differently, and in this case (unlike for save-states) the offsets for Gens-
    and DGen-created SRAM files are not the same.
    
    The member-has-joined bitvector bytes are basically the same as in the save-
    state, except that instead of being four consecutive bytes, in the Gens SRAM
    file they are stored at every other byte: the first is at 0x345, the second at
    0x347, and so on to the fourth at 0x34B.  The bytes in between appear to be
    ignored; I've never seen them with any value besides 0x00.
    
    Note however that these offsets refer to the game saved in slot 1!  I have not
    done any testing to determine the corresponding offsets for the save games in
    slots 2 or 3, but I imagine they are at the same positions relative to the
    member data (that is, the difference between the location of the Hero's name in
    game 1 and the offsets listed here is likely the same as the difference between
    the Hero's name in games 2 or 3 and the corresponding offsets in those games).
    
    
    [II.A.3] DGen SRAM offsets
    
    DGen's SRAM files appear to differ from Gens' by only one byte; whereas the
    Gens offset for member-has-joined bitvectors is 0x345, the DGen SRAM offset is
    0x344.  But in both cases, the bitvectors are stored at every other byte - from
    0x344 to 0x34A.
    
    
    [II.B] Active Members
    
    Although it would seem logical to store active-members (that is, the members
    which are part of the 12-strong active fighting force) as another bitvector
    (in which each bit reflects whether a member is active or not), game designers
    sometimes have a logic all their own, and so active-member data is stored very
    differently; instead of a bitvector, the 11 active members (the 12th is always
    the Hero) are stored in 11 bytes, as a list.  That is, if the fighting force
    was composed of only members 2, 5, 7, 8 and 10 (in a numbering system we'll get
    to in a moment), the first five bytes of this list would be 0x02, 0x05, 0x07,
    0x08 and 0x0A.  The remaining six bytes would all be 0xFF, which just means
    "nobody" - early in the game, when you do not have eleven members on the Force,
    every joined member will be in the active-members list, with the remainder
    filled with the 0xFF "empty" value.
    
    So who, exactly, is member #2?  Conveniently, the list is in exactly the same
    order as the list you see in the game (in the correct order this time, not
    backwards like the member-has-joined bitvector):
    
    #1  (0x01) Mae               #16 (0x10) Torasu
    #2  (0x02) Pelle             #17 (0x11) Gong
    #3  (0x03) Ken               #18 (0x12) Diane
    #4  (0x04) Vankar            #19 (0x13) Hans
    #5  (0x05) Earnest           #20 (0x14) Lyle
    #6  (0x06) Arthur            #21 (0x15) Amon
    #7  (0x07) Gort              #22 (0x16) Balbaroy
    #8  (0x08) Luke              #23 (0x17) Kokichi
    #9  (0x09) Guntz             #24 (0x18) Bleu
    #10 (0x0A) Anri              #25 (0x19) Adam
    #11 (0x0B) Alef              #26 (0x1A) Zylo
    #12 (0x0C) Tao               #27 (0x1B) Musashi
    #13 (0x0D) Domingo           #28 (0x1C) Hanzou
    #14 (0x0E) Lowe              #29 (0x1D) Jogurt
    #15 (0x0F) Khris                 (0xFF) (nobody)
    
    When you open save-states that were saved by the emulator, the active-members
    list will always appear in sorted order (that is, if Mae is active, she is
    always first in the list no matter who else is also active, because she is #1);
    if you modify the list, it doesn't appear to matter if you preserve the ordering
    (for example, you could replace Mae with Gort, who is #7, followed by #3 Ken),
    and the game doesn't seem to mind loading up the modified save-state (it will
    just sort the list again if you re-save).  Also, it is possible to put someone
    in the active-members list who is not part of the Force; that is, you could put
    Hanzou on the list in Chapter 1 without setting his member-has-joined bit, and
    he would appear in combat as if he were on your team.  However, in all other
    respects, the game will not recognize him as being on the team, so you cannot
    look at his stats, open his inventory, exchange him for another member at Nova,
    etc - you can only access him when in a battle.
    
    
    [II.B.1] Gens/DGen/Genecyst save-state offsets
    
    In a save-state file, the 11 byte list begins at offset 0xC603, through offset
    0xC60D.
    
    
    [II.B.2] Gens SRAM offsets
    
    The 11 bytes of the active-member list begin at offset 0xD47 in the SRAM file
    and occupy every other byte, so the end of the list is at offset 0xD5B - again,
    this is only for game 1.
    
    
    [II.B.3] DGen SRAM offsets
    
    In DGen's SRAM file, the active-member list for game 1 begins at offset 0xD46
    and fills every other byte, up to 0xD5A.
    
    
    ===============================================================================
    
    [III] Quick Lookup
    
    This guide is written (in the spirit of the other save state hacking guides)
    toward a relativly novice user, so the meat of it (the actual offsets and
    values) are jumbled up in all kinds of discussion, which is sometimes annoying.
    If you already know how this all works and just need the numbers, here they
    are, in a more concise format.
    
    -Joined Members: stored as a 4-byte bitvector
      -Bitvector byte 1: N/A, Nova, Jogurt, Hanzou, Musashi, Zylo, Adam, Bleu
      -Bitvector byte 2: Kokichi, Balbaroy, Amon, Lyle, Hans, Diane, Gong, Torasu
      -Bitvector byte 3: Khris, Lowe, Domingo, Tao, Alef, Anri, Guntz, Luke
      -Bitvector byte 4: Gort, Arthur, Earnest, Vankar, Ken, Pelle, Mae, Hero
      -Savestate offset: 0xC102 - 0xC105
      -Gens SRAM offset: 0x345 - 0x34B (every other byte)
      -DGen SRAM offset: 0x344 - 0x34A (every other byte)
    
    -Active Members: stored as an 11-byte list
      -Indecies in order from Mae (#1) to Jogurt (#29)
      -Savestate offset: 0xC603 - 0xC60D
      -Gens SRAM offset: 0xD47 - 0xD5B (every other byte)
      -DGen SRAM offset: 0xD46 - 0xD5A (every other byte)
    
    
    ===============================================================================
    
    EOF

    FAQ Display Options: Printable Version