This post is a bit technical, so here's the GEEK ALERT.

Update Jun 2 2012: Source code: Reading quest data from saves (you can help!)

For the last few days, I've been trying hard to figure out exactly how the quests are read by the game, for several reasons:

  • Improved fixing of corrupted saves
  • Converting/Exporting game-saves
  • A step towards a quest progress editor

It has proven to be a bit difficult for me, but I haven't given up. I could however use all the help I can get if you're familiar with x86 assembly code and using a debugger/disassembler.

I don't expect to receive any help from anyone, but I would appreciate it if you can and if you're willing. :)

"Intro" I'm going to show you some of my work, in case you get interested and you're up for helping. Maybe it'll even help me understand it better just by posting this and looking at it again.

The data I'll show you was taken after starting a new game (prologue), going down into the elevator and stepping right outside to reach the checkpoint.

All quest progress data:

04000000 E59A39DB 02000000 01 03000000 01 04000000 00 26000000 2F000000 91010000 00 01000000

The parts being read will be highlighted. The current values being read will have this color while subsequent reads will have different colors.

I'm going to name the main function readQuests, and the functions inside readQuestX, and some in there, readQuestsX_, etc.. Just to call them at least something that is somewhat meaningful, but without nesting them deeply.

Question marks in the code just means that I don't know what they are and/or where the values come from.

My "code" here isn't in any specific language, and doesn't include all the logic. It's just an attempt to explain kind of how this works.

Please note that I also don't guarantee that the info here is correct.

readQuests
04000000 E59A39DB 02000000 01 03000000 01 04000000 00 26000000 2F000000 91010000 00 01000000

uint32 count = 4 // not equal to the number of quests seen in-game, nor the amount of "tasks" or "steps"
uint32 unk1 = 0xDB399AE5
while i < count:
  readQuestX1()
  readQuestX2()


readQuestX1
   This is read later
   This is read even later
04000000 E59A39DB 02000000 01 03000000 01 04000000 00 26000000 2F000000 91010000 00 01000000

int32 questId = 2 // maybe
bool thisIsTheLastQuest = true // maybe something like that (last quest in this loop), but I don't know. Probably not hasFinishedQuestStep (or task or whatever). **Update:** this name must be wrong, but not totally off.


readQuestX2
if (questId < 0) or (questId >= 403): return false
if not thisIsTheLastQuest: return true
ptr = ? // pointer to some interface or something?
if ptr: // maybe safe to assume that this always happens
  readQuestX3()
count = ?
while j < count:
  x = address to the memory reallocated earlier
  // I think it reads int32 here sometimes, but not with the quest data I'm using this time


readQuestX3
// This is where it gets a bit tricky
readQuestX3\_1()
readQuestX3\_2() or someOtherFunction() // calls readQuestX3\_2() the first time, but calls someOtherFunction() the the recursive call (at least the first call)


readQuestX3\_1
   This is read later
   This is read even later
04000000 E59A39DB 02000000 01 03000000 01 04000000 00 26000000 2F000000 91010000 00 01000000
int32 unk1 = 0x26 // or 38 (dec)
if unk1 == 0: return true
bounds check on unk1, return false if outside of bounds
return true


readQuestX3\_2
// Loop + read recursively
count = ? // 1 in this case
while i < count:
  readQuestX3()


someOtherFunction()
// doesn't read from the file, but reallocates some memory

In the end... I managed to highlight all of the reads here, but I'm having a hard time figuring how the game chooses to read sometimes and not read other times, and figuring out the count value in some loops.

I wonder if the game just knows the values already, so that we can't simply read the quest data without knowing what the game already knows prior to reading.

Like I said earlier, I don't expect to receive any help from anyone, but you know how to contact me. :)