Author Topic: FF7 Savemap  (Read 18949 times)

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« on: 2006-02-14 23:48:53 »
After more than one year of following the forum quietly and anonymously, I wanted to be of some help on understanding the inner mechanics of FF7. I noticed the savemap had holes and decided to start with this, using Gears and the wiki as documentation.

After some bit of coding to be able to modify a psx savegame (I'm using epxse) and perform some quick binary diff between two save files, I was ready to start.

I don't know how accurate the current savemap is, as I've seen halkun say some part of it might be messed up. Anyway, a bit of brainstorming later, I went and tried to find some data I thought would be kept in there. This is what I've discovered so far :


First of all, about 'No Combat' & 'No Movie' flags : even though those options are available in Debug Mode, it appears they are not saved :-(


Offset 0x0C1E (1 byte)
Mask for the "target" text appearing over all available targets in battle
Inactive (0x00) / Active (0x40)

It looks like the other data on this byte are flags about vehicle information. For instance, when you get the Submarine, a text is displayed and lets you know how to control it : then, the mask 0x04 is applied on this byte so that the message isn't displayed again the next time you get on the world map. I haven't been able to test the others, but I suspect there are similar masks for the Buggy, the Tiny Bronco, the Highwind and quite possibly the Chocobo.


Offset 0x0E29 (1 byte)
When you visit the Chocobo Sage, he often has something new to tell you about Chocobo breeding. This byte is the Chocobo Breeding tutorial progression variable.


Offset 0x0E2A (2 bytes)
The total number of battles you must have fought in order to unlock the next part of Chocobo Breeding tutorial.
I don't know if the value added each time is fixed (e.g. a new part of the tutorial available every 5 battles) or random.


Offset 0x0EC2 (1 byte)
Mask for the fields pointers (the hand over party leader's head, red and green arrows on exits, ladders...)
Inactive (0x00) / Active (0x01)


Offset 0x10DA (1 byte)
Masks for general settings
- sound : mono (0x00) / stereo (0x01)
- controller : normal (0x00) / customize (0x04)
- cursor : initial (0x00) / memory (0x10)
- ATB : Active (0x00) / Recommended (0x40) / Wait (0x80)


Offset 0x10DB (1 byte)
Masks for general settings (continued)
- camera angle : auto (0x00) / fix (0x01)
- magic order :
   "1. restore attack indirect" = (0x00)
   "2. restore indirect attack" = (0x04)
   "3. attack indirect restore" = (0x08)
   "4. attack restore indirect" = (0x0C)
   "5. indirect restore attack" = (0x10)
   "6. indirect attack restore" = (0x14)
   (game crashes if flag set to 0x18 or 0x1C)
- extra battle window displaying information about commands & enemies : Inactive (0x00) / Active (0x40)


Offsets 10DC to 10EB (16bytes)
Controller : Button config
Offset 10DC = Left 2 (default L2)
Offset 10DD = Right 2 (default R2)
Offset 10DE = Left 1 (default L1)
Offset 10DF = Right 1 (default R1)
Offset 10E0 = Menu (default Triangle)
Offset 10E1 = Confirm (default Circle)
Offset 10E2 = Cancel (default X)
Offset 10E3 = EXT (default Square)
Offset 10E4 = Help (default Select)
Offset 10E5 = ?? Apparently unused
Offset 10E6 = ?? Apparently unused
Offset 10E7 = Pause (default Start)
Offset 10E8 = Up (default D.Pad Up)
Offset 10E9 = Right (default D.Pad Right)
Offset 10EA = Down (default D.Pad Down)
Offset 10EB = Left (default D.Pad Left)

Pad Buttons (for PSX)
0x00 : L2
0x01 : R2
0x02 : L1
0x03 : R1
0x04 : Triangle
0x05 : Circle
0x06 : X
0x07 : Square
0x08 : Select
0x09 : ?? Apparently unused
0x0A : ?? Apparently unused
0x0B : Start
0x0C : D.Pad Up
0x0D : D.Pad Right
0x0E : D.Pad Down
0x0F : D.Pad Left

Although it is possible to manually change the controls to something unusual (D.Pad Up as Confirm button, for instance), the result is messed up in the config. menu, since not all keys have bitmap associated.


From Offset 0x0FC4 to ??? (?? bytes)
All flags about chests and items to find during the game. For instance :

Offset 0x0FC4
bit 1 (LSB) : Potion #1 on KOed guards (beginning of the game)
bit 2 : Potion #2 on KOed guards
bit 3 : Potion in front of Jesse (in the Mako Reactor)
bit 4 : Phoenix Down in the chest
...


That's it for now :)
There's more data that I think should be there, such as : anything related to the Weapons (visible & defeated flags, Ultimate's HP, location, etc), the number of battles between the two visits at Lucrecia's Cave, the Wutai Quest flag, the timer during the very first mission...


EDIT : changed "Menu (default Square)" to "Menu (default Triangle)". Thanks dziugo for pointing this out.

-gone away-

  • *
  • Posts: 385
    • View Profile
FF7 Savemap
« Reply #1 on: 2006-02-15 00:42:44 »
Quote
From Offset 0x0FC4 to ??? (?? bytes)
All flags about chests and items to find during the game. For instance :

Offset 0x0FC4
bit 1 (LSB) : Potion #1 on KOed guards (beginning of the game)
bit 2 : Potion #2 on KOed guards
bit 3 : Potion in front of Jesse (in the Mako Reactor)
bit 4 : Phoenix Down in the chest


Does this mean you can edit what item's are found and where they are found??

dziugo

  • *
  • Posts: 1470
    • View Profile
    • A new copy of FF7 thanks to Salk. Pack (zip/rar/etc) your saved game before sending it to me.
FF7 Savemap
« Reply #2 on: 2006-02-15 06:52:42 »
Quote from: smithie
Does this mean you can edit what item's are found and where they are found??
I believe it is a Yes/No choice (if it's set then you can't get that item again).

As for the timer, look here. The offsets are:
Code: [Select]
Main counter:
 - 0x0B84 - counter, numer of seconds till the end of countdown
 - 0x0B88 - millis
 - 0x0B8C - millis
And variables which are used to display it in game:
 - 0x0BB8 - in-game counter - hours (based on 0x0B84)
 - 0x0BB9 - minutes
 - 0x0BBA - secs
 - 0x0BBB - millis (this one is based on 0x0B88)


And... Wow, nice job. Never though that some of these are saved in a save-game :P.

dziugo

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #3 on: 2006-02-15 10:10:48 »
Quote from: smithie
Does this mean you can edit what item's are found and where they are found??

Exactly. Setting those bits back to 0b will make the related items reappear. But you can't change their location, that kind of information isn't stored in the savemap (that would waste space).


Quote from: dziugo
As for the timer, look here.

I didn't remember this topic, thanks for the link :)


I noticed 0x0B88 and 0x0B8C were always identical, but can't seem to understand why they are related to the milliseconds stored at 0x0BBB. How did you find out ?

dziugo

  • *
  • Posts: 1470
    • View Profile
    • A new copy of FF7 thanks to Salk. Pack (zip/rar/etc) your saved game before sending it to me.
FF7 Savemap
« Reply #4 on: 2006-02-15 13:13:59 »
I didn't, that was just a guess... I've done some testings recently and this is what I've discovered:

I believe, that on PSX 0x0B84, 0x0B8C & 0x0BBB are related because FF7 can rely on the speed of it's CPU (again, just guessing). On PCs however, there is another thread running in the background which updates those vars (0x0B88 & 0x0B8C).

First var is used to update the global counter (number of secs played) and the second one is used to perform countdown (counting from 0 is also possible). Why 2 vars if they are identical? No clue.

0x0BBB holds the number of frames and countdowns from this value (field - 30). PSX has fixed FPS factor, so it could work quite well. On PC however it's overwritten if the secs in the our global counter change so... Useless var. If counter (0x0B84) reaches zero, it lets the 0x0BBB countdown to 0.

dziugo

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #5 on: 2006-02-15 14:22:28 »
Quote from: dziugo
Why 2 vars if they are identical? No clue.

Yeah, this is bothering me as well.

Anyway, that makes sense :)
My wild guess was that these variables had some connection to the random generator, but there's no way I could verify it, so I stopped wondering about it.

Now, two new elements for the savemap :

Offset 0x0E33 (1 byte)
Lucrecia's Cave progression variable
0x00 at first, it's set to 0x09 after the first visit (and during the event, it's very likely to evolve in order to reflect the progression of the flaskback).


Offset 0x0E35 (2 bytes)
Still related to the Lucrecia's Cave : you go there the first time and are granted with Vincent's memories. Then you can come back later to get Death Penalty and Chaos. You have to fight several battles before the second event triggers. This variable keeps the total number of battles you must GET PAST (not reach) in order to unlock this second event.

However, contrary to what I've seen everywhere, you don't have to fight 10 battles before returning to the cave. It was 6 in my game... this could be a random value, though.

I've also discovered which byte is used to check if Chaos & Death Penalty have been picked up, but I'm doing some research on it, as it could hold more than this. Stay tuned :wink:

ChaosControl

  • *
  • Posts: 741
  • ¤
    • View Profile
FF7 Savemap
« Reply #6 on: 2006-02-15 14:38:40 »
then you could make it seem as if you picked em up already? (100th post, yay..)

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #7 on: 2006-02-15 15:23:39 »
I suppose you're talking about Death Penalty & Chaos. Yes, if you apply the right mask on the proper byte, the game will believe they have already been picked up.

ChaosControl

  • *
  • Posts: 741
  • ¤
    • View Profile
FF7 Savemap
« Reply #8 on: 2006-02-15 20:49:52 »
Quote from: FeuFeu
I suppose you're talking about Death Penalty & Chaos. Yes, if you apply the right mask on the proper byte, the game will believe they have already been picked up.

Will they only be gone from the lucrecia place or will they also be in your inventory then?

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #9 on: 2006-02-15 21:25:18 »
Just gone. The inventory is handled in another part of the savemap (Party Item Stock is stored between offsets 0x04FC and 0x077B), you would need to add them manually... or pick them up in the game, of course.


Another "discovery" :
Offset 0x0BD7 (1 byte)
Mask 0x10 indicates Chaos and Death Penalty have been picked up in Lucrecia's Cave.

The other bits are probably masks for other (events involving) items but I haven't been able to discover which ones.

dziugo

  • *
  • Posts: 1470
    • View Profile
    • A new copy of FF7 thanks to Salk. Pack (zip/rar/etc) your saved game before sending it to me.
FF7 Savemap
« Reply #10 on: 2006-02-16 09:44:22 »
You might want to double-check the Menu default in Button Config.

dziugo

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #11 on: 2006-02-16 10:29:30 »
Quote from: dziugo
You might want to double-check the Menu default in Button Config.

Oh, my bad :oops: (damn you, "copy/paste")

Offset 10E0 = Menu (default Triangle, not Square)


And another set of new variables :

Offset 0x0D2D (1 byte)
Kalm Traveler quest progression :
Mask 0x40 applied the first time he says he's looking for the Guide Book, the Earth Harp and the Desert Rose.
Mask 0x08 applied when you give him the Guide Book, 0x10 for the Desert Rose and 0x20 for the Earth Harp.
Mask 0x80 applied once the Kalm Traveler has collected the 3 items he was looking for. He goes on a journey and you never see him again in the game.


Offset 0x0FFB (1 byte)
Kalm Traveler prices
Mask 0x01 applied when you give him the Guide Book and he put the Underwater Materia on the ground. The Mask is set back to 0x00 when you pick up the Materia.
Mask 0x02 (Master Command), 0x04 (Master Magic) and 0x08 (Master Summon) applied when you give him the Earth Harp and he put the 3 Master Materia on the ground. Each mask is set back to 0x00 when you pick up the corresponding Master Materia.
Mask 0x10 applied when you give him the Desert Rose and he calls the Gold Chocobo. The flag is set back to 0x00 when you "pick up" the Gold Chocobo (you need a free stable, of course).


While you can't give him more than one Guide Book, you can cheat and trade several Desert Rose or Earth Harp, and collect the prize as many times as you want. Of course, this has no impact on a normal game since you can only have one of each, but it's still interesting to know :)

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
FF7 Savemap
« Reply #12 on: 2006-02-16 17:35:04 »
One of these days we have to make a real script dumper to see how these vars are manipulated...

That's if we ever get around to figuring out all the opcodes.

Oh well, I have a GF now so any free time I had while going to school has now offically been flushed down the toilet.

Qhimm

  • Founder
  • *
  • Posts: 1996
    • View Profile
    • Qhimm.com
FF7 Savemap
« Reply #13 on: 2006-02-16 18:48:05 »
This is normally where I'd step up and be immensely helpful, but right now I don't have time to dig up my old code... IIRC I did write a tiny feature to scan all script files to find all accesses of a specific variable. It was an ugly hack though, had to hard-code the input to it, so it was only used a couple of times to help Terence out when he was mapping stuff. :P

I swear, some time when I have some time off work I'll get back on some of my older projects. Really! :)

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #14 on: 2006-02-16 20:22:17 »
halkun : Would it be easier to work on the savemap using a script dumper ? In that case, where can I find one ?

Qhimm : Is this old code of yours available somewhere ? :P


Anyway, here's another one.


Offset 0x0BD5 (1 byte)
Materia Cave flags : the following masks are applied when you pick up the corresponding Materia.
0x08 : Knights of the Round
0x04 : Quadra Magic
0x02 : HP <-> MP
0x01 : Mime

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
FF7 Savemap
« Reply #15 on: 2006-02-17 03:39:45 »
I have a somewhat broken way to extract the opcodes in gears, but I'm missing how many arguments are appended to each opcode. Some commads like AOKI, (Sound manipulation), have something like 9 arguments to the command. I have seven's original script dumper for the PSX FF7 in a now disfucntional computer (The hard drive is fine)

If you want, there is instructions on how to hack a psxe savestate so you can play with the opcodes in the dubug rooms while the game is running. (It was how I decrypted the MENU command.) It's somewhere in the history here.

It was pretty fun.

Anyways, I must now wait for a phone call so I'm off to home. (No internet there)

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #16 on: 2006-02-17 16:27:01 »
I guess you're talking about this topic : http://forums.qhimm.com/viewtopic.php?t=3961
I'll try this way, then :)

No new progress here, but I should have something new soon. Looks like I have narrowed some xyz coordinates... for the submarine and/or Chocobo, I guess. Or maybe Cloud on the world map as it seems to me the offsets in Gears are a bit off.

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #17 on: 2006-02-18 00:26:22 »
Offset 0x0F5C (3 bytes) : Party's X coordinates on the world map.
Offset 0x0F5F (1 byte) : Party's heading on the world map.
Offset 0x0F60 (3 bytes) : Party's Y coordinates on the world map.
Offset 0x0F63 (1 byte) : Party's Z coordinates on the world map.

NOTE : If X is set too high, this causes the whole coordinates to be set back to 0. The party leader will then appear at the top left of the world map, stuck in water :D I haven't tested with Y, but the behavior should be the same.


Offset 0x0F6C (3 bytes) : Chocobo's X coordinates on the world map.
Offset 0x0F6F (1 byte) : Chocobo's heading on the world map.
Offset 0x0F70 (3 bytes) : Chocobo's Y coordinates on the world map.
Offset 0x0F73 (1 byte) : Chocobo's Z coordinates on the world map.


I had a freaking hard time confirming the Z coordinate because the game usually corrects the value and puts the character correctly on the ground. In order to go past it, I had to manipulate Cloud's coordinates for him to appear in a place he shouldn't be able to access (such as high mountains). This way, the Z coordinate isn't adjusted and the character is really displayed at the desired "altitude" :P
http://img492.imageshack.us/img492/175/floatingcloud1fo.png

Another thing I noticed : if the Z coordinate is set too high (0x80 is enough), it causes some overflow and everything around the character becomes black.
http://img390.imageshack.us/img390/1483/blackworldmap3fv.png


Knowing this, I'll quickly locate the coordinates for the Highwind and the Submarine.

halkun

  • Global moderator
  • *
  • Posts: 2097
  • NicoNico :)
    • View Profile
    • Q-Gears Homepage
FF7 Savemap
« Reply #18 on: 2006-02-18 16:57:34 »
You should be saving your discoveries in the wiki.

There's a link to the savemap

http://wiki.qhimm.com/FF7/Savemap

Now, remeber, this savemap does not include the headers that are found at the beginning of the PSX or PC savegames. This is a map of the varibles found *in memory* initialized from the initial kernal.bin load.

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #19 on: 2006-02-18 18:34:01 »
I've been using it for a while along with Gears, but I wasn't sure I could edit it. By the way, I can't create an account on the wiki, the signup/login page doesn't display the registration form.


I have found where are stored the other world map coordinates.

Offset 0x0F74 (3 bytes) : Buggy/Highwind's X coordinates.
Offset 0x0F77 (1 byte) : Buggy/Highwind's heading.
Offset 0x0F78 (3 bytes) : Buggy/Highwind's Y coordinates.
Offset 0x0F7B (1 byte) : Buggy/Highwind's Z coordinates.

Offset 0x0F7C (3 bytes) : Submarine's X coordinates.
Offset 0x0F7F (1 byte) : Submarine's heading.
Offset 0x0F80 (3 bytes) : Submarine's Y coordinates.
Offset 0x0F83 (1 byte) : Submarine's Z coordinates.


Offset 0x0F6C (3 bytes) : Tiny Bronco's X coordinates.
Offset 0x0F6F (1 byte) : Tiny Bronco's heading.
Offset 0x0F70 (3 bytes) : Tiny Bronco's Y coordinates.
Offset 0x0F73 (1 byte) : Tiny Bronco's Z coordinates.
(the same offsets used for the Chocobo's ones)

Also, the Offsets 0x0F64 to 0x0F6B are/were probably coordinates of something else. I don't know they are used or not in the game.

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #20 on: 2006-02-20 14:00:30 »
Some new data :)

Offset 0x0BFF (3 bytes) : Ultimate Weapon's remaining HP

Offset 0x0F84 (3 bytes) : Ultimate Weapon's X coordinates.
Offset 0x0F87 (1 byte) : Ultimate Weapon's heading.
Offset 0x0F88 (3 bytes) : Ultimate Weapon's Y coordinates.
Offset 0x0F8B (1 byte) : Ultimate Weapon's Z coordinates.

I'm sure there are others variables related to this Weapon, but there's so many offsets modified (0x0C23, 0x0CAE, 0x0CBA, 0x0F32, 0x0F36, 0x0FA1, etc) I have no idea what purpose they have (modifying them "wildly" have no apparent effect). I think the following is likely to be kept :
- is Ultimate Weapon visible/moving/dead or not
- what's its next destination
- the dead status and the appearance of a crater near the Ancient Forest might not stored at the same offset.
- the appearance of Ruby Weapon should also be flagged somewhere

Apart from that, I'm short of new ideas.
Should I look for chest flags (since we know it begins at offset 0x0FC4) ? It'll be tedious, but still useful to know. Or is there anything else I should focus on ?
Comment welcome :wink:

Cyberman

  • *
  • Posts: 1572
    • View Profile
FF7 Savemap
« Reply #21 on: 2006-02-21 18:56:35 »
FeuFeu are the 3byte X/Y values just 24bit integers or 8:16 binary fractions?
I've decided to update my Jenova editor for the playstation version of the game (LOL) and was wondering how the encoding worked.  My guess is it's either an integer or a fraction of sorts but I'm not too sure.

The heading is it in in fractions of a full revolution?
I suppose this means I should have a map of FF7 world and put little marks on it representing these things (sigh) LOL.

Cyb

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #22 on: 2006-02-23 11:57:57 »
Sorry, took me a while to answer.

I'm fairly sure the X and Y coordinates are just an integer, provided how Cloud moves when I modify the values. Let's take the X coordinate :
- 00 00 00 is the origin, at the left of the world map
- FF 00 00 will barely move Cloud to the right (I don't know the exact scale, though).
- 00 10 00 will move Cloud a few screens away from its original location
- 00 00 01, finally, will almost move Cloud a third of the map away from the origin

I've noticed some strange behavior, by the way. A value like 00 00 04 seemed to create an overflow (Cloud is replaced at the origin), but I've also seen some higher values and Cloud was still placed "correctly" on the map, as if there's some sort of 'mod' formula applied on the value.


As for the heading, here's what the wiki says :
e.g: 00: South, 40: East, 80: North, C0: West
So... yeah, this is a fraction of a full revolution.

A map would certainly help, indeed  :)

Cyberman

  • *
  • Posts: 1572
    • View Profile
FF7 Savemap
« Reply #23 on: 2006-02-24 19:28:59 »
Quote from: FeuFeu
Sorry, took me a while to answer.

I'm fairly sure the X and Y coordinates are just an integer, provided how Cloud moves when I modify the values. Let's take the X coordinate :
- 00 00 00 is the origin, at the left of the world map
- FF 00 00 will barely move Cloud to the right (I don't know the exact scale, though).
- 00 10 00 will move Cloud a few screens away from its original location
- 00 00 01, finally, will almost move Cloud a third of the map away from the origin

All right this means it's stored as a little endian value.
A proper 'conversion' to an unsigned int might be
(LOC[2] & 0xFF) << 16 | (LOC[1] & 0xFF) << 8 | (LOC[0] & 0xFF)
It may be a two's compliment number, so I recomend for fun try this number
00 EF FF
(FFEF00) it should move Cloud a few screens to the left if it's little endian based (IE signed)
Quote from: FeuFeu
I've noticed some strange behavior, by the way. A value like 00 00 04 seemed to create an overflow (Cloud is replaced at the origin), but I've also seen some higher values and Cloud was still placed "correctly" on the map, as if there's some sort of 'mod' formula applied on the value.


As for the heading, here's what the wiki says :
e.g: 00: South, 40: East, 80: North, C0: West
So... yeah, this is a fraction of a full revolution.

A map would certainly help, indeed  :)

Ahhh doh :D oh well in any case I'll see if I can twiddle the numbers and stuff to make sense of them.

Cyb

FeuFeu

  • *
  • Posts: 54
    • View Profile
FF7 Savemap
« Reply #24 on: 2006-02-24 21:17:08 »
Here are some tests I've just done.

http://img137.imageshack.us/img137/9980/ff7map12fu.png
Cloud's coordinates (red point)
X : 00 EF FF (equivalent to 00 00 00)
Y : 00 00 00

Highwind's coordinates (white point, near Cosmo Canyon)
X : 39 4A 19
Y : C1 78 02

Submarine's coordinates (pink point, near Junon)
X : 12 99 6A
Y : FC 48 42


http://img527.imageshack.us/img527/3114/ff7map20au.png

Cloud's coordinates
X : 2A 80 02
Y : 53 AC E1

Highwind's coordinates
X : 03 87 7D
Y : 80 44 AF

Yes, Cloud and Highwind are at the same place this time, but the coordinates are completely different :x