Attention! This is not for all Lego games.
Naturally, this is done by editing a saved game.
However, the data is checked against the checksum.
That's what we're going to explore.
But if you're lazy, you can use this tool:
If you're interested, there are two ways: find and use a checksum generation algorithm.
Or patch the game itself at the point where the checksum is checked.
Let's explore LEGO Indiana Jones 2 as an example.
First, we take a saved game file from:
The file itself is a Rich Saved Games format with the following structure:
typedef struct _RICH_GAME_MEDIA_HEADER\n{\n DWORD dwMagicNumber;\n DWORD dwHeaderVersion;\n DWORD dwHeaderSize;\n LARGE_INTEGER liThumbnailOffset;\n DWORD dwThumbnailSize;\n GUID guidGameId;\n WCHAR szGameName[RM_MAXLENGTH];\n WCHAR szSaveName[RM_MAXLENGTH];\n WCHAR szLevelName[RM_MAXLENGTH];\n WCHAR szComments[RM_MAXLENGTH];\n} RICH_GAME_MEDIA_HEADER;We are interested in two values:
We look at the current balance, convert it to HEX, and search for it in the file. Don't forget about the byte order, as we have little endian. In other words, if HEX = 00005F32, we should search for 32 5F 00 00.
In LEGO Indiana Jones 2, this is the offset 0x22FF0 from the beginning of the file. Alternatively, the offset within the data for the checksum is (0x22FF0-dwHeaderSize)=0x20FC8
The checksum is calculated by simply adding (add) four bytes (dword) to the constant 0x5c09999:
09AB1D2 mov esi, 05C0999\n09AB1D7 jle 09AB1EA\n09AB1D9 mov edx, [esp+4+arg_0]\n09AB1DD lea ecx, [ecx+0]\n09AB1E0 add esi, [edx+ecx*4]\n09AB1E3 add ecx, 1\n09AB1E6 cmp ecx, eax\n09AB1E8 jl 09AB1E0And it starts exactly after RICH_GAME_MEDIA_HEADER header, that is, with an offset of dweadersize bytes, and continues to the end of the file minus 8 bytes, which are:
That is, we get this code:
start = dwHeaderSize;\nlength = filesize - dwHeaderSize - 8;\nchecksum = 0x5C0999;\n\nfor (i = start; i < length; i = i + 4) {\n\tchecksum += data[i]; // DWORD, 4 bytes\n}You can take a different approach. Instead of recalculating the checksum every time, you can simply change the number of coins by patching the LEGOIndy2.exe file.
09AB4FF cmp eax, [edi+ebx] ; 3B 04 1F\n09AB502 jnz 09AB529 ; 75 25If the checksums are not equal, it jumps away. You just need to not jump. Change one byte 25 -> 00:
09AB502 jnz 09AB504 ; 75 00For LEGOStarWarsSaga.exe and LEGOBatman.exe, you need to jump. We also look for 3B 04 1F:
0XXXXXX cmp eax, [edi+ebx] ; 3B 04 1F\n0XXXXXX jz 0XXXXXX ; 74 12The same checksum check, and if equal, then jumps to the right place. You need to force 74 -> EB:
0XXXXXX jmp 0XXXXXX ; EB 12