Still to-do
8. Look into a way of dealing with the save location and sharing of save files between 1998 version/The Reunion and Steam.
I have some thoughts on this. Though first a couple disclaimers:
[list type=decimal]
[*]I'm not sure I fully understand the problem. From your post
here, I gather that Steam is wantonly deleting files if it doesn't like their checksum. I'm
assuming that you don't mean the checksum internal to the save file itself but rather the checksum for the save file noted in Steam's metadata.xml file. If I'm incorrect about that, then everything I'm about to say should probably be ignored.
[*]I'm not in a position to test any of this because I don't have the Steam version (still have my discs from 1998) or Windows 10 (I use Linux).
[/list]
Anywho, I think the following would work:
- Add two fields to Reunion's config file:
[list type=decimal]
- LinkSavesWithSteam (bool, default: false)
- SteamUserID (string, default: this_is_not_a_valid_steam_id)
[*]Add the following behavior to the installer:
[list type=decimal]
[*]Check if %userprofile%\My Documents\Square Enix\FINAL FANTASY VII Steam\ exists. If not, stop.
[*]Ask the user if they want to link their Reunion saves with their Steam saves. If so, set the LinkSavesWithSteam option in Reunion's config file. If not, stop.
[*]Enumerate the immediate child subdirectories of %userprofile%\My Documents\Square Enix\FINAL FANTASY VII Steam\. If none, stop. If one, select that. If more than one, ask the user to select one.
[*]Save the name of selected subdirectory to the SteamUserID field of Reunion's config file.
[*]Check if the selected Steam save directory contains any save files. Also check if the '98-edition save directory contains any conflicting save files. As appropriate, ask if the user wants to keep all, none, or only the non-conflicting Steam save files.
[*]Move the indicated Steam save files to the '98-edition save directory.
[*]Perform the same steps as the modified launcher behavior, described below.
[/list]
[*]Add the following behavior to the launcher, to be performed
AFTER ff7.exe returns:
[list type=decimal]
[*]Check LinkSavesWithSteam in the Reunion config file. If false, stop.
[*]Check if %userprofile%\My Documents\Square Enix\FINAL FANTASY VII Steam\ exists and contains an immediate child directory matching the SteamUserID stored in the Reunion config file. If not, stop.
[*]Iterate over the save files in the '98-edition save directory. For each file, create a symlink in the Steam save directory to that file, overwriting if necessary.
- NOTE: It's important to symlink each individual file rather than to symlink the containing directory in order to make sure Steam can't muck with the real save files. A process with access to a directory symlink can delete files within the target directory, but a process with access to a file symlink can't delete the target file. (At least that's the way things work in operating systems that properly implement symlinks. I've heard rumors that in certain circumstances Win10 will allow you to delete a target from the link, but I haven't cared enough to look into them.)
[*]Rewrite Steam's metadata.xml file. How? It looks like
this source file from Black Chocobo contains most of the answers we need:
- Crib the overall xml structure from an existing file. Looks simple.
- Timestamps are actually quite a pain. We're going to have to keep a persistent memo file on the side to figure out which slots have changed.
- Ignoring the first 9 bytes, chop the save file up into 15 chunks of 4,340 bytes representing the individual slots. (Those numbers came from here.) For each chunk:
[list type=decimal]
- Check if the first two bytes equal 0x4D1D. If so, the slot is empty, so the timestamp should be blank.
- Otherwise, hash the chunk (using whatever hash algorithm you like) and compare against the prior hash from the memo file.
- If the hash is unchanged, use the prior timestamp from the memo file.
- Otherwise, the new timestamp is the file's last modified date (accessible via system call) expressed as milliseconds since the Unix epoch.
- Now go rewrite the memo file with the updated hashes and timestamps for next time.
- (I'm not really sure how to deal with the initial case when we don't have a memo file yet. I guess for files moved from the Steam save directory, we'll need to preserve whatever the original metadata.xml said; and for files originating in the '98-edition save directory, just timestamp all the nonblank slots with the file's last modified date and live with whatever errors that creates. (I guess you could get fancy and parse the game time out of each slot to invent believable in-order timestamps...))
- (Since this is such a pain, I'd be tempted to experiment with what Steam does when the timestamps are wrong. If the consequences aren't that bad, I'd put less effort into getting them right.)
[*]To calculate the "signature," start with the file content, append the Steam user ID encoded as ASCII (or ISO 8859-1, same difference for numerals), take the md5 hash of that, and express the hash output as lowercase hex.
[/list]
[/list]
[/list]