Dragon Age: Inquisition Modding Tools

All about modding tools for Dragon Age: Inquisition
It is currently Mon Jun 26, 2017 8:56 pm

All times are UTC



Welcome
Welcome to the Dragon Age Modding tools forum

You are currently viewing our boards as a guest, which gives you limited access to view most discussions and access our other features. By joining our free community, you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content, and access many other special features. In addition, registered members also see less advertisements. Registration is fast, simple, and absolutely free, so please, join our community today!


Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 94 posts ]  Go to page 1, 2, 3, 4, 5 ... 10  Next
Author Message
 Post subject: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Tue Dec 09, 2014 6:18 pm 
Offline
User avatar

Joined: Tue Dec 09, 2014 5:21 pm
Posts: 33
Has thanked: 35 time
Have thanks: 32 time
Save games and profile options (in %UserProfile%/Documents/Bioware/Dragon Age Inquisition/save/) seem to use a common container format that starts with the header "FBCHUNKS". The "FB" suggests a connection to FrostBite but googling turned up almost nothing.

Save names consist of "DAISAVE" + tag + id32 + ".DAS", where id32 is the left eight digits of the 128-bit character id that is found in the save game header. <tag> is one of "QUIK", "AUTO", "CHAP" or "TIME" for quick saves and various auto save types, or "U" + 3-digit hex counter for user saves.

The layout of an FBCHUNKS file seems to be this:

Code:
offs sz example 
---------------------
0000 8  "FBCHUNKS"
0008 2  01 00        apparently constant, meaning not deducible
000A 4  00000204     header_size (here: size of the FBHEADER block, including the preceding checksum)
000E 4  00066D1F     data_size

// start of <header_size> bytes of header info
0012 4  47A8FC57     checksum (standard zip CRC32 of header data sans the the checksum field itself, with initial value 0x12345678 instead of 0)
0016 8  "FBHEADER"
001E 5  00 01        big endian 1?
0023 1  00 00 00 10  big endian 10h? (== # of key/value pairs that follow == item_count)
repeat item_count times
   0000 4 id32       32-bit number that identifies the value (some hash of the identifier name?)
   0004 2 00 <value_length>                 // i.e. constant 00 followed by byte length, maybe 16-bit big endian, who knows
   0006 <value_length characters>  value text

// start of <data_size> bytes of data at <0x12 + header_size>
???? 4 7DD2A03B     checksum
???? 7 "FB" 00 "SAVE"
...

There are usual several FB SAVE blocks - between one and a dozen or so - but they do not seem to contain a header with size info, meaning they cannot be skipped properly without parsing their contents. Here's a decoded FBHEADER block for an actual save game:

Code:
00000012 26F02ED7                           // standard CRC32 with initial value 0x12345678 instead of 0
00000016 FBHEADER 00 01 00 00 00 10

0000000E 72677992 0006 Alayna               // character name
0000001A A06F6E92 0001 0                    // race (human = 0, elf, dwarf, qunari)
00000021 8A71AE06 0001 1                    // gender (male = 0, female)
00000028 3DAD9C97 000D 385628.593750        // == 107:07:08 h (time played in seconds)
0000003B D8BD15B6 0024 19E2E45B-5636-272C-F5A6-EAA911C246EB  // 128-bit character id
00000065 FB9770E1 0001 1                    // class (warrior = 1, rogue, mage)
0000006C 032FCAE1 0002 17                   // level
00000074 F0BD21A5 0013 POS-1.7;91.6;-41.1;  // position
0000008D 340F505F 0006 187535               // this may be some location code (area id)
00000099 B82F852F 0011 Cradle of Sulevin
000000B0 9F1F99B3 002A UI/Static/SaveScreens/level_RevenentChurch
000000E0 892D839A 0053 DA3/Layouts/ThematicLevels/the_RevenentChurch/the_RevenentChurch/the_RevenentChurch
00000139 B08AAA39 000C 212284536181         // 2014-12-04 22:43:01 (seconds since 0001-01-01 00:00)
0000014B B0F50985 0006 856038               // game exe build number (-> version.json)
00000157 F1EA4603 0001 1                    // patch level?
0000015E 47FB864D 00CE                      // loaded add-ons, with ~ as separator/terminator
   SP_SLKEY_802@Dragon Age™: Inquisition Deluxe Edition Items~
   SP_SLKEY_805@Flames of the Inquisition Armor~
   SP_SLKEY_804@Flames of the Inquisition Armored Mount~
   SP_SLKEY_803@Flames of the Inquisition Weapons~

EDIT 2014-12-12: added race, gender and class; changed comment for F1EA4603, 47FB864D
EDIT 2014-12-14: the checksum after the header belongs to the data portion, not the header
EDIT 2014-12-16: added explanations for B0F50985 and F1EA4603 (build and patch level)

ProfileOptions does not have an FBHEADER block; its header seems to consist of a 32-bit group count preceded by its checksum. The checksum following this header is part of the data portion.

Code:
0000 8 "FBCHUNKS"
0008 2 01 00
000A 4 00000008      desc_size
000E 4 000FA000      data_size

// header
0012 4 0FF70E97      checksum  // CRC32 with init = 0x12345678
0016 4 0000000F      group_count

// data
001A 4 A8CEA7C7      checksum  // CRC32 with init = 0x12345678
repeat group_count times
   0000 4 item_count
   repeat item_count times
      0000 4 type_code (1, 2 and 4 seem to be text, 5 is binary)
      0004 1 name_length
      0005 <name_length characters> value_name
      ???? 4 data_length
      ???? <value_length bytes> value_data

(the rest of the file contains nulls up to the fixed size)


file_size - FBCHUNKS.desc_size - FBCHUNKS.data_size = 12h, which is the size of the FBCHUNKS record. FBCHUNKS.desc_size is exactly equal to the header size, whether it be FBHEADER or the slimmer version used in ProfileOptions. This means that FBCHUNKS.data_size gives the size of all the rest, which comprises not only the actual data block but also the four-byte checksum between the FBCHUNKS record and the header. That's why I put the (+4) after data_size.

The difficult part will be making sense of the FB SAVE blocks, which may contain inclusions of random junk or may be partly scrambled. Or both. In any case the spectra seem a bit off in places. I guess the easiest way to get to the bottom of this would be to compare the hex dumps of actual save games. Like a save made right at the start of the game after accepting defaults for everything (quickly) to minimise the content differences. For reference I'm attaching the save game I used in the example above.

It would also be useful to figure out which checksum was used, so that we can indulge in a bit of creative save game editing (Fereldan Locks anyone?). I tried several variations of standard 32-bit CRCs - including Ethernet, Castagnoli and so on, conditioned and unconditioned - but to no avail...

P.S.: I tried to attach the save game and it did some uploady thingy but now it seems to be gone... :?

P.P.S.: logic and Bioware tradition would suggest that the 32-bit tags in FBHEADER are FNV32 or CRC32 of some property names, but so far I had no luck guessing. Anyway, all it takes to throw a monkey wrench into guessing is some constant prefix like HeaderInfo.CharacterName instead of CharacterName... To get there quickly we'd need a clean dump of the EXE and a 64-bit copy of IDA, but I have neither. My support plan timed out a few months ago, so I can't upgrade to 64-bit... :(

EDIT 2014-12-14: identified 3 checksums as standard (zip) CRC32 with the oddball init value 0x12345678 instead of 0


Last edited by DarthGizka on Mon Dec 15, 2014 9:28 am, edited 5 times in total.

Top
 Profile  
 
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Tue Dec 09, 2014 7:49 pm 
Offline
Site Admin

Joined: Fri Dec 05, 2014 3:26 pm
Posts: 635
Has thanked: 921 time
Have thanks: 314 time
My hero!!! I'm trying to mod my save files :)

_________________
ar-lath-ma-vhenan


Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Wed Dec 10, 2014 3:18 am 
Offline

Joined: Fri Dec 05, 2014 4:28 am
Posts: 64
Has thanked: 17 time
Have thanks: 41 time
I'm attempting to find out how to catch something - anything - with saving games in the debugger. It's not great, but simply tagging a conditional breakpoint on memcpy with a source pointer of either the in-executable FBCHUNKS string or the FB(null)SAVE string gets me in the neighborhood of the code. Tracing forward from here will show various chunks getting moved in memory, likely in preparation for writing to disk, but the memcpy is a bit late... I have no idea what to do at this point. Today, I mostly just skimmed line after line looking for a clear XOR and came up empty.

I don't know how to find the right call to write out to disk - CheatEngine was able to find a call to WriteFileEx, but that wasn't the right call for saving games. Frankly, tracing backwards from there seems like the wrong way to move in, since I would bet the game would be writing out chunks of previously-constructed saves at that point.

I previously did hexbyte comparisons of similar save games - simply saving an early game multiple times - but found that there are hundreds of small (less than 16 byte) blocks that change, as well as the entire 2nd half of the save game.

Edit : I should clarify - watching memcpy on the conditional breakpoint will show you the save chunk being moved exactly as it exists on disk, so that's something. Again, that's a bit too late in the process, I think.
wogoodes has been thanked by:


Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Wed Dec 10, 2014 4:10 am 
Offline
User avatar

Joined: Tue Dec 09, 2014 5:21 pm
Posts: 33
Has thanked: 35 time
Have thanks: 32 time
Cool! One of the last steps before the file is written should be the calculation of the checksum. It would be extremely valuable to get our fingers on that, because it seems to be required to make edited savegames palatable for the game... And the nature of any XORish activities would be very interesting indeed. And you are doing all this with CheatEngine? Or are you using something like IDA?

One new tactic might be a mem write breakpoint on the location of the checksum in the memcpy() source location (assuming that the data gets assembled there). That would bring the checksum within arm's reach. Tomorrow I'll look at alternatives to IDA, like CheatEngine, so that I can play a more active role... Assembly and checksums are right down my alley. :mrgreen:
DarthGizka has been thanked by:


Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Wed Dec 10, 2014 5:07 am 
Offline

Joined: Fri Dec 05, 2014 4:28 am
Posts: 64
Has thanked: 17 time
Have thanks: 41 time
DarthGizka wrote:
And you are doing all this with CheatEngine?

CheatEngine's VEH debugger is the only one I've found that works. I don't own IDA, and both x86dgb and Visual DuxDebugger cause immediate crashes. No idea why.

DarthGizka wrote:
One new tactic might be a mem write breakpoint on the location of the checksum in the memcpy() source location (assuming that the data gets assembled there).

Nope, source location appears to be allocated and not in a static location.

You might want to glance at DAI.exe+42C7519 - that's the only thing that appeared to be doing something checksummish, but it placed IDs with what I believe were inventory records. It could be checksummish, since it looks like it keeps an accumulator variable that is multiplied by 21 and XORed against 32 bits pulled from memory, plus 20. 32 more bits are pulled each loop for the XOR until an ending character or the end of the loop is found. The result is truncated to the lower 32 bits. Without any knowledge whatsoever of checksums, to me, this sounds like it's a bit more of a hash/unique ID/random-ish number. Don't know why a checksum would truncate.
wogoodes has been thanked by:


Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Wed Dec 10, 2014 8:41 am 
Offline
User avatar

Joined: Tue Dec 09, 2014 5:21 pm
Posts: 33
Has thanked: 35 time
Have thanks: 32 time
I downloaded CheatEngine and hiked to the address you pointed out:

Code:
DragonAgeInquisition.exe+42C74F4 - 4D 89 C1              - mov r9,r8
DragonAgeInquisition.exe+42C74F7 - 49 89 CA              - mov r10,rcx
DragonAgeInquisition.exe+42C74FA - 48 85 D2              - test rdx,rdx
DragonAgeInquisition.exe+42C74FD - 74 25                 - je DragonAgeInquisition.exe+42C7524

DragonAgeInquisition.exe+42C74FF - 41 0FB6 44 12 FF      - movzx eax,byte ptr [r10+rdx-01]
DragonAgeInquisition.exe+42C7505 - 48 FF CA              - dec rdx
DragonAgeInquisition.exe+42C7508 - 44 8D 40 BF           - lea r8d,[rax-41]
DragonAgeInquisition.exe+42C750C - 41 83 F8 19           - cmp r8d,19
DragonAgeInquisition.exe+42C7510 - 77 03                 - ja DragonAgeInquisition.exe+42C7515

DragonAgeInquisition.exe+42C7512 - 83 C0 20              - add eax,20
DragonAgeInquisition.exe+42C7515 - 4D 6B C9 21           - imul r9,r9,21
DragonAgeInquisition.exe+42C7519 - 48 63 C8              - movsxd  rcx,eax
DragonAgeInquisition.exe+42C751C - 49 31 C9              - xor r9,rcx
DragonAgeInquisition.exe+42C751F - 48 85 D2              - test rdx,rdx
DragonAgeInquisition.exe+42C7522 - 75 DB                 - jne DragonAgeInquisition.exe+42C74FF

DragonAgeInquisition.exe+42C7524 - 4C 89 C8              - mov rax,r9
DragonAgeInquisition.exe+42C7527 - C3                    - ret


That's a simple FNV hash, with lower-casing of upper-case ASCII.

EDIT 2014-12-12: it is actually the so-called djb2 or 'Dan Bernstein k = 33' hash. FNV has the same structure and the hackish version of 'toupper()' is connected to a well-known Bioware legacy; however, FNV uses different initial values and different multipliers.

In C the hash would look something like this:

Code:
uint64_t oddish_fnv (char const *text, uint64_t length, uint64_t hash /* = 5381 */)
{
   while (length)
   {
      unsigned c = (uint8_t)text[--length];
     
      if (c - 'A' <= (unsigned)'Z' - 'A')      // converts upper-case ASCII to lower-case
         c += 'a' - 'A';
     
      hash = hash * 33 ^ c;
   }
   
   return hash;
}


Bioware uses this FNV to generate 32-bit ids from identifier names, in the same way CRC32 was used in DA:O. The disassembly shows some oddities, like RAX being used even though its upper 32 bits are never given a specific value. But that might be due to global optimisations, i.e. the compiler knowing things that we cannot see in this small fragment. Or the disassembly thing might have ignored an instruction modifier/prefix.

This is probably not the checksum used for sealing savegames but I haven't tried different initial values yet, only the standard 5381 that I found on the 'net. So I'll try that next. In any case this proves that you've got a sharp eye and an unerring instinct... Keep up the good work! And I've got a new toy (CheatEngine 6.4) that finally allows me to explore DAI.exe. My first expedition will be on the trail of 32-bit CRC polynomials...
DarthGizka has been thanked by:


Last edited by DarthGizka on Fri Dec 12, 2014 2:01 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Thu Dec 11, 2014 1:02 am 
Offline

Joined: Fri Dec 05, 2014 4:28 am
Posts: 64
Has thanked: 17 time
Have thanks: 41 time
DarthGizka wrote:
Bioware uses this FNV to generate 32-bit ids from identifier names...


Aaaand there we go! One thing I learned here : CheatEngine sometimes does not draw the jump arrows correctly. Read the code and find the address yourself.

By the way, you really wanna check out the 'DAS file PC character swapper' thread.


Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Fri Dec 12, 2014 9:22 am 
Offline
User avatar

Joined: Tue Dec 09, 2014 5:21 pm
Posts: 33
Has thanked: 35 time
Have thanks: 32 time
I've identified race, gender and class enums in the FBHEADER block; the description in the top post has been amended accordingly.

The FB SAVE blocks stubbornly continue to defy decipherment, and I need to make some helper scripts to aid bulk analysis. Next weekend I'll try differencing again. I've got a small script that polls for quick saves; if it sees one then it moves it elsewhere and gives it a numbered name. This makes it possible to create pairs of quick saves that differ only in one major aspect apart from noise like time stamps. Example: walk up to elf root, hit F5, harvest elf root, hit F5 again.

The number of occurrences of "FB\0SAVE" varies a lot, between exactly one and several dozen. The occurrence of that string does not necessarily signify the presence of an FB SAVE block; it might as well be junk that was included when saving a larger structure. However, until we know more we can only work on the hypothesis that each of those strings starts its own FB SAVE block.

Here's a dump of the beginnings and endings of FB SAVE blocks in one particularly fat savegame (first and last 32 bytes of each block, without the magic string "FB\0SAVE"):

Code:
00000239 0000427D 0A 12 6E 94 36 98 80 00 00 00 0B A2 20 A4 A9 A0 AB 22 A8 AA A4 A5 98 9C A2 99 22 9A 1A A1 17 22 .. 00 11 20 00 00 00 00 00 04 48 00 00 00 00 00 01 12 00 00 00 00 00 0A C2 00 00 00 08 00 00 00 A4
000044B6 000000D5 0A 00 04 80 11 80 00 4F E0 00 00 33 20 00 26 90 00 00 00 30 00 00 02 2A 32 10 02 9A 0A B2 28 50 .. 14 88 C8 40 0A 68 2A C8 A1 40 00 90 02 30 00 09 FC 00 00 06 64 00 04 D2 00 00 00 04 00 00 00 45
0000458B 00000174 0A 00 04 80 11 80 00 20 90 00 00 0B 50 00 09 D8 01 48 00 00 88 00 0C 04 04 6E 4F 1C 00 00 C5 00 .. 14 88 C8 40 0A 68 2A C8 A1 40 00 90 02 30 00 09 FC 00 00 06 64 00 04 D2 00 00 00 04 00 00 00 45
000046FF 00000737 0A 00 04 80 11 80 00 20 90 00 00 0B 50 00 09 D8 01 48 00 00 88 00 0C 04 04 6E 4F 1C 00 00 C5 80 .. 00 00 27 00 00 00 00 00 00 00 00 00 80 00 00 01 12 00 00 00 00 00 0A C2 00 00 00 08 00 00 00 A4
00004E36 000002C9 0A 00 04 80 11 80 00 4F E0 00 00 33 20 00 26 90 00 00 00 20 00 00 02 2A 32 10 02 9A 0A B2 28 50 .. 03 E0 00 0F 27 34 9A 32 00 00 54 00 00 00 00 00 00 00 00 02 00 00 00 08 00 00 02 59 00 00 00 47
000050FF 000009ED 0A 00 00 00 48 01 18 00 02 1A 00 00 00 BA 00 00 A2 40 00 00 00 00 01 C0 00 00 00 00 00 00 00 00 .. 00 00 00 00 02 07 FB FF FF F8 00 00 00 00 00 01 12 00 00 00 00 00 02 F2 00 00 00 02 00 00 00 27
00005AEC 00000925 0A 00 04 80 11 80 00 11 80 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 04 00 .. EF 05 F8 00 00 84 00 00 00 00 00 00 10 00 00 00 42 00 00 00 00 00 00 08 00 00 34 A1 00 00 06 90
00006411 00000289 0A 00 10 00 17 48 02 42 22 09 99 7B 23 2B 9B 4B 3B 73 1B 7B 73 A3 2B 73 A1 7A 13 AB 73 23 63 2B .. 00 00 00 00 00 00 10 00 00 02 90 00 04 00 00 00 02 00 00 00 00 00 04 D2 00 00 00 0A 00 00 00 45
0000669A 00001A7F 0A 00 04 80 11 80 00 20 90 00 00 0B 50 00 09 D8 01 48 00 00 88 00 0C 04 04 6E 4F 1C 00 00 C5 80 .. 01 03 14 27 E2 20 00 00 00 04 00 01 04 00 06 00 00 00 00 00 00 00 04 D2 00 00 00 02 00 00 00 45
00008119 000323D7 0A 00 04 80 11 80 00 20 90 00 00 0B 50 00 09 D8 01 48 00 00 88 00 0C 04 04 6E 4F 1C 00 00 C5 00 .. A9 F1 21 61 D2 02 73 3E 4C CC CC 00 4B 52 00 03 00 19 78 00 1A 00 00 98 03 06 DD 8F 00 00 00 0B
0003A4F0 00000016 0A 00 00 00 00 00 98 03 20 03 FC 00 00 00 0B
0003A506 00000016 0A 00 00 00 00 05 A0 05 27 F3 CD 00 00 00 AC
0003A51C 000000B7 0A 00 01 00 01 37 89 0B 28 6D 13 42 8A 35 E4 39 11 E7 C0 00 00 00 19 56 4E B7 E0 00 00 00 1F FF .. 00 40 00 21 40 02 C4 85 94 36 8F 49 2B 45 94 00 06 00 48 02 02 00 00 98 06 F8 BB 84 00 00 00 0B
0003A5D3 00000016 0A 00 00 00 00 00 98 07 26 33 6D 00 00 00 0B
0003A5E9 00000016 0A 00 00 00 00 00 98 10 A4 FA B4 00 00 00 0B
0003A5FF 00000016 0A 00 00 00 00 00 98 16 F9 11 B5 00 00 00 0B
0003A615 00000016 0A 00 00 00 00 00 98 1F 72 36 B9 00 00 00 0B
0003A62B 00000016 0A 00 00 00 00 00 98 2D 6D 14 B4 00 00 00 0B
0003A641 00000016 0A 00 00 00 00 00 98 35 B2 76 AC 00 00 00 0B
0003A657 00000016 0A 00 00 00 00 00 98 3F 20 99 E3 00 00 00 0B
0003A66D 00000016 0A 00 00 00 00 00 98 44 68 2F 2C 00 00 00 0B
0003A683 00000016 0A 00 00 00 00 00 98 51 64 0D 3C 00 00 00 0B
0003A699 00000016 0A 00 00 00 00 00 98 60 2D 6E 34 00 00 00 0B
0003A6AF 00000016 0A 00 00 00 00 00 98 60 C7 31 54 00 00 00 0B
0003A6C5 00000016 0A 00 00 00 00 03 18 62 F8 22 7C 00 00 00 5B
0003A6DB 00000066 0A 00 00 80 01 37 89 0B 28 6D 35 29 7E 65 63 DC CC 27 E0 00 00 00 01 FC 3E 07 C0 00 00 00 00 00 .. 00 20 00 10 A0 01 62 42 CA 1B 40 2F 8D 02 1A 00 04 16 9D 01 01 00 00 98 80 9D C1 4D 00 00 00 0B
0003A741 00000016 0A 00 00 00 00 00 98 89 1D E3 2D 00 00 00 0B
0003A757 00000016 0A 00 00 00 00 00 98 8F 38 5C 39 00 00 00 0B
0003A76D 00000016 0A 00 00 00 00 00 98 A5 3D 09 AD 00 00 00 0B
0003A783 00000016 0A 00 00 00 00 00 98 B8 16 91 F9 00 00 00 0B
0003A799 00000016 0A 00 00 00 00 00 98 BF 57 1B 3C 00 00 00 0B
0003A7AF 00000016 0A 00 00 00 00 00 98 CD 52 A6 AD 00 00 00 0B
0003A7C5 00000016 0A 00 00 00 00 00 98 E0 BC B6 79 00 00 00 0B
0003A7DB 00000016 0A 00 00 00 00 00 98 E5 2A 07 02 00 00 00 0B
0003A7F1 00000016 0A 00 00 00 00 00 98 FA 03 F2 6C 00 00 00 0B
0003A807 0000BFF7 0A 00 00 00 00 31 9A 00 00 00 21 00 19 00 01 E2 12 16 50 DA 26 85 14 6B C0 00 00 02 78 3E 89 6F .. BA D1 1D 84 00 00 04 00 01 28 48 59 43 69 CB A0 18 73 09 03 10 90 00 0A 00 00 00 00 00 00 0C 2E
000467FE 00000C36 0A 00 01 00 11 53 80 11 47 80 01 00 04 00 01 5B 81 80 01 4B 80 05 89 0B 28 6D 3A F9 E2 48 60 00 .. 96 00 00 00 00 21 35 01 F5 2C E7 F0 00 00 02 13 11 FC 52 AF 00 00 00 00 00 00 00 01 00 00 0B 7B
00047434 00000B83 0A 00 01 00 0E 70 80 0E 64 80 01 00 04 00 00 E1 82 80 00 D1 80 05 89 0B 28 6D 0B 0C 05 EC A0 00 .. 2C 00 00 00 00 42 6A 03 EA 59 CF E0 00 00 04 26 23 F8 A5 5E 00 00 00 00 00 00 00 02 00 00 0A 50
00047FB7 00000A58 0A 00 01 00 0A 1D 00 0A 11 00 01 00 03 80 00 E1 82 00 00 D1 80 05 89 0B 28 6D 0C 19 C5 2E A0 00 .. 2C 00 00 00 00 42 6A 03 EA 59 CF E0 00 00 04 26 23 F8 A5 5E 00 00 00 00 00 00 00 03 00 00 09 AA
00048A0F 000009B2 0A 00 01 00 0B 2E 00 0B 22 00 01 00 03 80 03 9A 80 00 03 8A 80 05 89 0B 28 6D 1F 9C 40 47 60 00 .. 2C 00 00 00 00 42 6A 03 EA 59 CF E0 00 00 04 26 23 F8 A5 5E 00 00 00 00 00 00 00 04 00 00 0A C7
000493C1 00000ACF 0A 00 01 00 0E 8C 80 0E 80 80 01 00 04 00 00 E1 82 00 00 D1 80 05 89 0B 28 6D 25 81 15 5C 60 00 .. B0 00 00 00 01 09 A8 0F A9 67 3F 80 00 00 10 98 8F E2 95 70 00 00 00 00 00 00 00 05 00 00 07 CF
00049E90 000007D7 0A 00 01 00 06 B5 80 06 A9 80 01 00 02 80 01 1E 80 80 01 0E 80 05 89 0B 28 6D 07 9C 36 0B A0 00 .. 2C 00 00 00 00 42 6A 03 EA 59 CF E0 00 00 04 26 23 F8 A5 5C 00 00 00 00 00 00 00 06 00 00 08 A4
0004A667 000008AC 0A 00 01 00 06 D0 80 06 C4 80 01 00 03 00 00 E1 82 00 00 D1 80 05 89 0B 28 6D 0D 50 61 DB 20 00 .. 96 00 00 00 00 21 35 01 F5 2C E7 F0 00 00 02 13 11 FC 52 AE 00 00 00 00 00 00 00 07 00 00 09 1D
0004AF13 00000925 0A 00 01 00 06 D0 80 06 C4 80 01 00 03 00 00 E1 82 80 00 D1 80 05 89 0B 28 6D 38 E8 34 B5 20 00 .. C0 00 00 00 04 26 A0 3E A5 9C FE 00 00 00 42 62 3F 8A 55 EF 05 8A F0 00 00 00 00 08 00 00 09 65
0004B838 0000096D 0A 00 01 00 0A 97 00 0A 8B 00 01 00 03 80 00 E1 82 00 00 D1 80 05 89 0B 28 6D 0D 50 61 DB 20 00 .. 2C 00 00 00 00 42 6A 03 EA 59 CF E0 00 00 04 26 23 F8 A5 5E F0 58 AF 00 00 00 00 09 00 00 08 61
0004C1A5 0002BAA1 0A 00 01 00 06 20 00 06 14 00 01 00 02 80 01 5B 80 00 01 4B 80 05 89 0B 28 6D 1E 61 D5 44 E0 00 .. D8 D8 5D 19 59 DB DC 9E 4F 8F 0B D8 D8 5D 19 59 DB DC 9E 4F 8F 0B D9 98 58 D9 58 DB D9 19 4F 80


The lines above will probably wrap unless you maximise your browse window, but having a bit of data to look at can be helpful.

Here's another one, with shorter dumps to make it easier to take in at a glance:
Code:
00000000 FBCHUNKS 0001 00000203 0007F903
00000012 02B72BC4
...
00000219 00007041 0A 0D 21 17 36 98 80 00 00 00 0B A2 .. 00 00 00 08 00 00 0E 51 00 00 01 C6
0000725A 000005A0 0A 00 00 00 48 01 18 00 0D DA 00 00 .. 00 00 00 08 00 00 05 69 00 00 00 A9
000077FA 000001D8 0A 00 00 00 48 01 18 00 05 2C 00 00 .. 00 00 00 08 00 00 30 A1 00 00 06 10
000079D2 0000199C 0A 00 00 00 48 01 18 00 30 5E 00 00 .. 74 D2 7B C1 7E 00 54 69 00 00 0A 89
0000936E 00002435 0A 00 08 00 13 88 01 CA 22 09 99 7A .. 00 00 04 D2 00 00 00 0C 00 00 00 45
0000B7A3 0003523A 0A 00 04 80 11 80 00 20 90 00 00 0B .. 1C 00 00 98 03 06 DD 8F 00 00 00 0B
000409DD 00000016 0A 00 00 00 00 00 98 03 20 03 FC 00 00 00 0B
000409F3 00000016 0A 00 00 00 00 05 A0 05 27 F3 CD 00 00 00 AC
00040A09 000000B7 0A 00 01 00 01 37 89 0B 28 6D 13 42 .. 02 00 00 98 07 26 33 6D 00 00 00 0B
00040AC0 00000016 0A 00 00 00 00 00 98 10 A4 FA B4 00 00 00 0B
00040AD6 00000016 0A 00 00 00 00 00 98 16 F9 11 B5 00 00 00 0B
00040AEC 00000016 0A 00 00 00 00 00 98 1F 72 36 B9 00 00 00 0B
00040B02 00000016 0A 00 00 00 00 00 98 27 D3 12 34 00 00 00 0B
00040B18 00000016 0A 00 00 00 00 00 98 28 09 81 19 00 00 00 0B
00040B2E 00000016 0A 00 00 00 00 00 98 29 D8 68 74 00 00 00 0B
00040B44 00000016 0A 00 00 00 00 00 98 2D 6D 14 B4 00 00 00 0B
00040B5A 00000016 0A 00 00 00 00 00 98 35 B2 76 AC 00 00 00 0B
00040B70 00000016 0A 00 00 00 00 00 98 3F 20 99 E3 00 00 00 0B
00040B86 00000016 0A 00 00 00 00 00 98 44 68 2F 2C 00 00 00 0B
00040B9C 00000016 0A 00 00 00 00 00 98 51 64 0D 3C 00 00 00 0B
00040BB2 00000016 0A 00 00 00 00 00 98 60 2D 6E 34 00 00 00 0B
00040BC8 00000016 0A 00 00 00 00 00 98 60 C7 31 54 00 00 00 0B
00040BDE 00000016 0A 00 00 00 00 03 18 62 F8 22 7C 00 00 00 5B
00040BF4 00000066 0A 00 00 80 01 37 89 0B 28 6D 35 29 .. 01 00 00 98 80 9D C1 4D 00 00 00 0B
00040C5A 00000016 0A 00 00 00 00 00 98 89 1D E3 2D 00 00 00 0B
00040C70 00000016 0A 00 00 00 00 00 98 8F 38 5C 39 00 00 00 0B
00040C86 00000016 0A 00 00 00 00 00 98 A5 3D 09 AD 00 00 00 0B
00040C9C 00000016 0A 00 00 00 00 00 98 B8 16 91 F9 00 00 00 0B
00040CB2 00000016 0A 00 00 00 00 00 98 BF 57 1B 3C 00 00 00 0B
00040CC8 00000016 0A 00 00 00 00 00 98 CD 52 A6 AD 00 00 00 0B
00040CDE 00000016 0A 00 00 00 00 00 98 E0 BC B6 79 00 00 00 0B
00040CF4 00000016 0A 00 00 00 00 00 98 E5 2A 07 02 00 00 00 0B
00040D0A 00000016 0A 00 00 00 00 00 98 FA 03 F2 6C 00 00 00 0B
00040D20 0003EDF8 0A 00 00 00 00 00 30 00 00 00 00 00 .. 7C 78 5E CC C2 C6 CA C6 DE C8 CA 7C

The last byte of a block seems suspiciously correlated to the size of the next block for a large number of these, or rather to block_size - 0Bh. However, this scheme falls a bit on its face because the first block is not prefixed by any size and the last block does not have a successor for which it could give a size but its last byte is not zero. Also, for some blocks this does not work at all (the second and third blocks in the first dump end with 45h but have successors of different sizes). This may well be another junk inclusion, i.e. some bits that just happened to be lurking at that place in memory when the block was written. Or there may be certain criteria that dictate whether or not a block has the size of its successor at the end. Or the size may be somewhere inside the 'non-conforming' blocks instead of at the end, because of the way the blocks are parsed/written. There are numerous possibilities.

Here are a few more short blocks that do not have size 16h bytes (from different savegames):
Code:
(#25) 0000F4B9 0000001C 0A 00 00 00 48 01 18 00 36 DC 00 00 34 B6 00 0C 99 00 00 01 8F
(#51) 00004711 0000001C 0A 00 00 00 48 01 18 00 84 C2 00 00 7E A0 00 15 A1 00 00 02 B0
(#52) 00004B64 0000001C 0A 00 00 00 48 01 18 00 77 15 00 00 70 F3 00 15 A1 00 00 02 B0
(#54) 000089E9 0000001C 0A 00 00 00 48 01 18 00 30 84 00 00 2E 5E 00 11 E1 00 00 02 38

Short blocks like these may be useful in coming up with some testable hypotheses.


Last edited by DarthGizka on Fri Dec 12, 2014 9:34 am, edited 2 times in total.

Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Fri Dec 12, 2014 9:31 am 
Offline
Site Admin
User avatar

Joined: Fri Dec 05, 2014 3:43 am
Posts: 629
Has thanked: 14 time
Have thanks: 751 time
One thing that might be worth trying to identify is, EBX files have lots of mentions of StableSaveID integer. I suspect these may be located in the save files (Not certain, just a hunch). So you might want to extract some EBX files, collect some StableSaveID's maybe from closer to the start of the game, and see if they can be identified.
Ehamloptiran has been thanked by:


Top
 Profile  
 
 Post subject: Re: FBCHUNKS files (ProfileOptions and save games)
PostPosted: Fri Dec 12, 2014 9:49 am 
Offline
User avatar

Joined: Tue Dec 09, 2014 5:21 pm
Posts: 33
Has thanked: 35 time
Have thanks: 32 time
Have a look at the 32-bit values at offset 7 in the short 16h-byte blocks (offset -8 relative to the block end):
Code:
000409DD 00000016 0A 00 00 00 00 00 98 03 20 03 FC 00 00 00 0B
000409F3 00000016 0A 00 00 00 00 05 A0 05 27 F3 CD 00 00 00 AC
00040A09 000000B7 0A 00 01 00 01 37 89 0B 28 6D 13 42 .. 02 00 00 98 07 26 33 6D 00 00 00 0B
00040AC0 00000016 0A 00 00 00 00 00 98 10 A4 FA B4 00 00 00 0B
00040AD6 00000016 0A 00 00 00 00 00 98 16 F9 11 B5 00 00 00 0B
00040AEC 00000016 0A 00 00 00 00 00 98 1F 72 36 B9 00 00 00 0B
00040B02 00000016 0A 00 00 00 00 00 98 27 D3 12 34 00 00 00 0B
00040B18 00000016 0A 00 00 00 00 00 98 28 09 81 19 00 00 00 0B
00040B2E 00000016 0A 00 00 00 00 00 98 29 D8 68 74 00 00 00 0B
00040B44 00000016 0A 00 00 00 00 00 98 2D 6D 14 B4 00 00 00 0B
00040B5A 00000016 0A 00 00 00 00 00 98 35 B2 76 AC 00 00 00 0B
00040B70 00000016 0A 00 00 00 00 00 98 3F 20 99 E3 00 00 00 0B
00040B86 00000016 0A 00 00 00 00 00 98 44 68 2F 2C 00 00 00 0B
00040B9C 00000016 0A 00 00 00 00 00 98 51 64 0D 3C 00 00 00 0B
00040BB2 00000016 0A 00 00 00 00 00 98 60 2D 6E 34 00 00 00 0B
00040BC8 00000016 0A 00 00 00 00 00 98 60 C7 31 54 00 00 00 0B
00040BDE 00000016 0A 00 00 00 00 03 18 62 F8 22 7C 00 00 00 5B
00040BF4 00000066 0A 00 00 80 01 37 89 0B 28 6D 35 29 .. 01 00 00 98 80 9D C1 4D 00 00 00 0B
00040C5A 00000016 0A 00 00 00 00 00 98 89 1D E3 2D 00 00 00 0B
00040C70 00000016 0A 00 00 00 00 00 98 8F 38 5C 39 00 00 00 0B
00040C86 00000016 0A 00 00 00 00 00 98 A5 3D 09 AD 00 00 00 0B
00040C9C 00000016 0A 00 00 00 00 00 98 B8 16 91 F9 00 00 00 0B
00040CB2 00000016 0A 00 00 00 00 00 98 BF 57 1B 3C 00 00 00 0B
00040CC8 00000016 0A 00 00 00 00 00 98 CD 52 A6 AD 00 00 00 0B
00040CDE 00000016 0A 00 00 00 00 00 98 E0 BC B6 79 00 00 00 0B
00040CF4 00000016 0A 00 00 00 00 00 98 E5 2A 07 02 00 00 00 0B
00040D0A 00000016 0A 00 00 00 00 00 98 FA 03 F2 6C 00 00 00 0B


They are sorted in strict lexicographic order, are all prefixed with 98h, and there's matching data at offset -8 from the end of the larger block... These values must be some sort of id/tag, since they reoccur in saves of wildly different ages. I'll scan the EXE and the game data, to see if I can find some correlation.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 94 posts ]  Go to page 1, 2, 3, 4, 5 ... 10  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
suspicion-preferred