Important Message

You are browsing the archived Lancers Reactor forums. You cannot register or login.
The content may be outdated and links may not be functional.


To get the latest in Freelancer news, mods, modding and downloads, go to
The-Starport

Decompiler for Savegame .FL files?

Here you can find the postings on the different editing utilities found for Freelancer

Post Tue Jun 10, 2003 4:13 pm

Jor + IGx89 (FX voice='Juni') Nice job! (/FX)

If there is interest then I can hack up some C/C++ reference code for the hash algorithm sometime this week. I have already created a cleaned-up reference version in Fox (good boy!) but I have not got around to do the C code yet.

The reason is that it is very difficult to devise an automatic verification procedure; the only strategy that I could find is to process savegames and/or InitialWorld.ini and verify that each hash value there has a nickname somewhere in the game's ini files that hashes to that value and that makes sense in this context (e.g. "ge_fighter" doesn't match an entry like "npc_locked_gate" ).

Edited by - Sherlog on 10-06-2003 17:15:28

Post Tue Jun 10, 2003 4:40 pm

You mean the C code to convert the numbers in names, like li01_base01? if you're talking about the code to actually decrypt saved game files, we already have that (and I will be including it with my utility).

Post Tue Jun 10, 2003 6:21 pm

I mean code for turning nicknames into numbers. Of course, having such a function and a set of possible names one can then write code for turning the numbers into names by looking for matches.

You can actually write nicknames instead of hash numbers into the savegame but you'd have to know which numbers to replace. Works for adding things, though (e.g. cargo).

P.S.: thank you both for providing magic decoder rings for FL savegame files. This means other folks can now poke around in savegames and discover things. I completely forgot about that necessity. (FX voice=Tobias) I'm proud of you! (/FX)

Edited by - Sherlog on 10-06-2003 19:26:24

Post Wed Jun 11, 2003 1:57 pm

I'm having trouble compiling the .c file uploaded by Jor.

When I tried to compile it using LCC Win32, it gave an error:
Warning: <directory>\flcodec.c 198 missing return value

When I ran the debugger on it, it highlights the line:
int main (int argc, char *argv[)

and in the box on the bottom of the screen:
argc = 0
stderr = (&_job [2)

also, when I pass the mouse over *argv[, it pops up with a message saying:
*char * argv[ = NULL

This results in a Error: read() failed: No error message when I try to encode the edited text file.

Please help!!!!!

Post Wed Jun 11, 2003 2:59 pm

I got the same error on Win98 with LCC32, though I could still create an executable using
lcclnk -o flcodec.exe flcodec.obj

With that flcodec.exe I was able to successfully decrypt a savegame file, but trying to encrypt it again returned:
Error: read() failed: No error

Since the decrypted savegame file I got was about 5 kB larger than the original savegame (it should be 4 Bytes smaller instead), I guess Jor forgot the Win32 newline issue.

Being more familiar with Perl rather than C, I just took Sherlogs algorithm and Jors Source, added some evilness (Perl is evil) and here is what I got, just in case somebody cares:

<pre><font size=1 face=Courier>
#!/usr/bin/perl -w
&help unless @ARGV == 3;

open OUT,'>', pop or die $!;
binmode OUT;
open IN, ,'<', pop or die $!;
binmode IN;

$ARGV[0 eq '-d'
? ($/ = \4, scalar <IN> ne 'FLS1' ? die "no FL Savegame" : undef)
: ($ARGV[0 eq '-e' ? print OUT 'FLS1' : &help);
$/ = \1;

my $i = 0;
print OUT chr( ord <IN> ^ (0x80 / (ord(qw(G e n e)[$i % 4) + $i++) % 256 ) ) until eof IN;

sub help {
print STDERR "usage: $0 -d infile.fl outfile.txt\n";
print STDERR " to decode a .fl savegame file into the named text file\n";
print STDERR "or: $0 -e infile.txt outfile.fl\n";
print STDERR " to encode a text file back into a .fl savegame file.\n";
exit(1);
}
</font></pre>
If you don't have Perl installed, you may either get it from CPAN or more likely wait until someone releases a fully working Win32 binary of the converter.

Jor

Post Wed Jun 11, 2003 5:52 pm

Sherlog: [Code that translates hashes to names That would be great!

From the news comments for my little encoder/decoder tool:

Ok, here it is: On Windows you need to append
/ O_BINARY
to every open() call option arg (the second argument, behind the other O_XXX).
Fixed source code available at http://jors.net/jor/src/flcodec.c

And now it works (tested on win89 compiled with lcc).

Binary is now available at: http://jors.net/jor/flcodec.exe

*****************************************************************
Note: Do not edit the .fl file while the game is running!
*****************************************************************

Post Wed Jun 11, 2003 10:49 pm

repiV, Perl is one of the things I've always wanted to do and never gotten around to. Perl may be evil, but it's a very seductive kind of evil. Thanks for posting the snippet, I think it shows the power of Perl very well.

Jor , I have not yet written anything that translates hash values into nicknames. This is basically a database problem: scan all .ini files in the data tree for nicknames, hash them, and build a table indexed by hash. But I do have written something that is necessary for this: some compilable reference code for the hash function that FL uses.

The algorithm resembles a bit-reversed and byte-swapped (Big Endian) version of the standard CRC16, tweaked to yield more than 16 bits. The hash has effectively 28 bits instead of 30 because 2 bits are lost because of a programming error. This gives a theoretical collision threshold of 16384; IOW, it is unlikely that you can hash more than 16000 things without getting a collision. The actual threshold is probably lower because of the poly and the nature of the things to be hashed (lower-case letters instead of random byte values).

Here's the guts of the algorithm:
<pre><font size=1 face=Courier>
/* standard CRC16 polynomial */
#define FLHASH_POLYNOMIAL 0xA001ul
.
#define LOGICAL_BITS 30
#define PHYSICAL_BITS 32
#define SHIFTED_POLY (FLHASH_POLYNOMIAL << (LOGICAL_BITS - 16))
.
void InitFLHashContext (FLHashContext *ctx) {
DWORD i, bit;
for (i = 0; i < 256; i++) {
DWORD x = i;
for (bit = 0; bit < 8; bit++)
x = x & 1 ? (x >> 1) ^ SHIFTED_POLY : x >> 1;
ctx->lookup??(i??) = x; }
}
.
DWORD FLHash (FLHashContext const *ctx, char const *text, size_t length) {
DWORD hash = 0;
size_t i;
for (i = 0; i < length; i++)
hash = (hash >> 8) ^ ctx->lookup[(BYTE)hash ^ (BYTE)tolower(text??(i??));
return (BSwap32(hash) >> (PHYSICAL_BITS - LOGICAL_BITS)) / 0x80000000ul;
}
</font></pre>
Note: I had to use the trigraphs ??( and ??) instead of square brackets, because the forum script tries to interpret things in square brackets.

The archive FLHashReferenceCode.rar contains source code (FLHash.c, FLHash.h) that can be incorporated into C/C++ projects as is. You can also compile this into a stand-alone console program by defining the symbol STANDALONE_TEST. A Win32 console exe is included, with PGP signature.

The program is simple because its main purpose is to serve as a reference implementation. You can supply one or more nicknames on the command line and the program will print the hashes for them. Example:

<pre><font size=1 face=Courier>D:\dev\out\FL\FLHash> FLHash shield01_mark01_lf ge_fighter_power01
"shield01_mark01_lf", 3088051465, -1206915831, 0xb80fed09
"ge_fighter_power01", 2779996489, -1514970807, 0xa5b36149 </font></pre>

The program also contains a selftest, where the hash function is run against known hash/text pairs from InitialWorld.ini.

Have fun!

Edited by - Sherlog on 11-06-2003 23:58:33

Post Sat Aug 16, 2003 8:23 pm

Sherlog,

You're a much smarter man than I - this is much appreciated! It's exactly what I've been looking for.

--JoeBoomz
IONCROSS

Post Tue Sep 02, 2003 1:36 am

Sherlog,

Check yer e-mail!

I've downloaded the above file and all I find in it is a header file! You're the only one I've seen that has come this far with the hash codes and I need to be able to interpret them to add any more functionality to my save game editor! PLEASE respond to either my e-mail address or in this forum! Myself and about 1500 users depend on YOUR knowledge

MUCHO appreciated!
-- JoeBoomz
IONCROSS

Post Tue Sep 02, 2003 1:45 am

I think he's disappeared; I sent him an e-mail about a month ago, and he still hasn't responded .

Post Tue Sep 02, 2003 6:40 am

No! it can't be! He's our missing link!

Do you have anything on these hashcodes? I've got a few other sources to try, but Sherlog seems to have the best bead on them so far!

-- JoeBoomz
IONCROSS

Post Wed Sep 03, 2003 12:17 am

I assume that you're wanting to know about hash codes to convert the hashes in the saved game files into their respective nicknames, right? Well, to do that you'll have to create a database of hash numbers/nicknames by creating hashes of every nickname in the ini files, and then have your program reference that database.

Post Wed Sep 03, 2003 12:24 am

that I'm willing to do... however, I haven't been able to get Sherlog's code to get it working yet! The above link to download only contains a single header file and none of the extra code! If you managed to get the whole thing, would you please e-mail it to me? It's all I really need to get started on a database of all the hashcodes for all the ships and equipment in the game.

-- JoeBoomz
IONCROSS

Post Fri Sep 05, 2003 3:44 am

I just re-downloaded it, and it includes both the .c and the .h files, and a .sig and .exe file. Are you using WinRAR to open it?

Post Fri Sep 05, 2003 7:57 pm

IG,

WinACE actually. Can it be that it doesn't probably extract RAR files? This would be odd, they're generally the same format.

I'll get WinRAR and try it again. Thanks a bundle!

-- JoeBoomz
IONCROSS

Return to Freelancer Editing Utilities Forum