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
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<number>, and some in there, readQuestsX<number>_<number>, 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
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. :)
Hi Steffen,
ReplyDeleteSorry, I'm no programmer, nothing harder than creating innosetup installs. :)
If there's anything else I can help you with, I'd be more than happy too.
Hey, don't you worry. Your wish to help is enough for me! Thank you! :D
ReplyDeleteHOLY CRAP SIR!!!!!I have never seen anything more confusing in my life!!I am super sorry buy this is definitely a foreign language to me,and this is why I also said you had mad skills!!!! but like I have said before if i can help out with anything else I will? I really wish I could help out with this. I know it could free you up with sometime, and than you can go do something for yourself :D
ReplyDeletei wonder if thisIsTheLastQuest is actually selected quest.
ReplyDeletee5 9a 39 db 3d
seems to occur in all games. likely a marker, doesn't always occur at the same offset.
count is maybe quest display count, i believe. maybe not directly, say quest+3. i had 100 some quests, and my file said a9. i finished one main quest, and it changed to aa. i then finished 3 more quests (a main, a side and a cont), bringing it to ad. i did not scan the whole file - this number is purely with respect to the marker (4th byte before marker).
given
03 XX 00 00 YY
e5 9a 39 db 3d 00 00 00 00 01 00 00 00 26 00 00 00 01 21 00 00 00 01 24
i don't have quest id 03 or 04, if this is the FIRST quest, i think i'd have it somewhere after the marker (since you can't avoid it); it's not in the save file at all. my solution would be to start a few characters and all complete the quest and see what the marker looks like.
in quest2, do you have examples of count? what is the scope of count, is it defined every function call? is it 1, 3, 4 or is it 1002, 5890 or is it 1e8, 1e9, etc.
furthermore, if it really is
XX YY 00 00 00 ZZ
by setting ZZ from 01 to 00, a chapter 8 quest showed up in ch 13. this is wrong, however. finding the universal key from the mayor seems to be a universal 'fall back' quest for the game. randomly corrupted games tend to show 'big daddy' as a quest, regardless of chapter or known quests.
lastly, my marker starts at offset 1230 most of the time. when does the game stop reading quest data, exactly? i don't want to start parsing bullets fired as quest data, for example.
Hello!
DeleteThank you so much for giving this some thought.
The counts are scoped within the function (readQuests, readQuestX3_2, etc).
After I wrote this article, I learned that the quest data changes after each quest *phase* (task/step as I previously called it). Explained here:
https://bitbucket.org/SteffenAL/di-quests
To make it easier to compare, it would be nice with a tool that makes a copy of the save, on-demand (a push of a button). I know there's a AutoHotkey script for that already, though.
I also think that there are some things not stored in the save. This makes it hard or impossible to read the date correctly without knowing it. For example one or two of the counts in there.
All of the quest data is stored in section 0x67 in the save, as explained here:
http://deadislandsaveeditor.blogspot.no/2011/10/tutorial-fixing-corrupted-game-save.html
You can also export game progres from DISE. All of the quest data is at the bottom, base64-encoded.
Hai steffen, its me haziq, look man i know nothing about all this stuff but after some research i think i already know what makes save data (for 360) crash, i dunno how and why but apparently the diamond is the reason, having too much will completely ruin your save, sometimes even the stuff in inventory itself will make the game crash... hmmm... i wonder why... this alway happen to me long ago before i know about your DISE even now it still happen...
ReplyDeletewhen your'e on dise and say you wanted 999999 diamonds there will be a pop-up asking if you want them in stacks press yes, this may be the solution? im on ps3 so i dont have a clue but try that anyway. or use a hex editor and find the binary code for diamonds x(however many you have) then edit the amount then save then put it back in xbox maybe?
DeleteI downloaded the editor and weapons AI has a very low damage, how fix this?
ReplyDeleteHello! Without modding the game's internals, I'm afraid there isn't anything you can do about it. They were never meant for the player so I think one should expect them to not work just as regular weapons.
DeleteI will look into this more hex is my second language
ReplyDeleteHey! Sorry, I forgot to reply. Did you figure out anything?
Deletehey, ive been messing with the hex since the game came out, having anything in your inventory with the max value of 999,999,999 will crash your game if you pick up another item with the max or even close to the max within a value of 10. just reduce it to say 7F FF FF FF and should fix major crashes among that issue, its still quite a few of one object. but as for the ammo in guns the 999,999,999 seems to be ok as you shoot often reducing the number.
ReplyDeleteThomas nailed it. I had 500 grenades and on a quest I received 1 and it crashed. I don't need to travel with that many anyway. Besides, you can put half in storage or duplicate when you need more if you don't care to re-edit often. ;)
ReplyDeletewhat console are you doing it for? and i have an idea!! get a save example: chapter 3. make sure its right at the end of whatever chapter like, just about to go to chapter> then take chapter 3 save, and then take the chapter 4 save and then see what changes have happened between the two save's but dont pick anything up or anything like that or it will have to many change's to tell with one was the chapter change. I hope this helps.
ReplyDeleteI'm on ps3 and when I have connected my USB and then open USB Device (PS3) for it in the file tab on dise but it says and it says "Device Not Connected"
ReplyDeleteIf you e-mail me, I'll hook you up with a development build of DISE that fixes your problem. :)
DeleteThank you Everybody gotta love smart people like you!!!
DeleteI wouldn't go as far as to say that, but thanks for the feedback! :D
DeleteHi I'm using your dead island save editor and I need help with editing the quest I need to know the names of the active quest and also what chaper there are in I mess up my save by deleting the active quest and now I can't do anything I can't start a new quest at all
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete