d2s-format
d2s-format copied to clipboard
[Suggestion]: My C++ version of the checksum algorithm should it help anyone
This is ready to be built in VS2022.
#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <stdio.h>
#include<string>
using namespace std;
char** argv = NULL;
void main(int argc, char** argv)
{
if (argv[1] == NULL) {
cout << "\n\n\tNo .d2s file specified. \n\n\tUsage: d2scs.exe char.d2s\n\n" << endl;
return;
}
FILE* charFile;
charFile = fopen(argv[1], "r+b");
// zero out the previous checksum
char zero[4] = { 0 };
fseek(charFile, 12, SEEK_SET);
fwrite(zero, sizeof(char),sizeof(zero), charFile);
fflush(charFile);
fseek(charFile, 0, SEEK_SET);
unsigned char saveFileData[16];
unsigned long counter = 0;
unsigned int uSum = 0;
int n;
int uVar = 0;
int byte;
while ((n = fread(saveFileData, sizeof(char), 16, charFile)) > 0) {
int i;
for (i = 0; i < n; i++) {
// Current byte in charFile
byte = (unsigned)saveFileData[i];
//SAME as uSum line, just to double check if both produce the same checksum
if (uVar < 0)
byte++;
uVar = byte + uVar * 2;
//SAME as above block, just to double check if both produce the same checksum
uSum = ((uSum << 1) | (uSum >> 31)) + (unsigned)saveFileData[i];
}
counter += 16;
}
unsigned long r_uVar = _byteswap_ulong(uVar);
unsigned long r_uSum = _byteswap_ulong(uSum);
// write new checksum
fseek(charFile, 12, SEEK_SET);
fwrite(&uVar, sizeof(uVar), 1, charFile);
fflush(charFile);
fseek(charFile, 0, SEEK_SET);
printf("\n\n\t%08x checksum written to %s\n\n", r_uVar, argv[1]);
fclose(charFile);
}
Here's the original function located at 6FD269D3
inside D2Game.dll
1.10F
**************************************************************
* *
* FUNCTION *
**************************************************************
uint __fastcall FUN_6fd269d3(byte * param_1, int param_2)
uint EAX:4 <RETURN>
byte * ECX:4 param_1
int EDX:4 param_2
FUN_6fd269d3 XREF[1]: FUN_6fc8a140:6fc8a187(c)
6fd269d3 85 d2 TEST param_2,param_2
6fd269d5 75 1b JNZ LAB_6fd269f2
6fd269e3 e8 06 5d CALL FOG.DLL::Ordinal_10023 undefined Ordinal_10023()
ff ff
6fd269ed e8 fb 5d CALL FUN_6fd1c7ed undefined FUN_6fd1c7ed(UINT para
ff ff
-- Flow Override: CALL_RETURN (CALL_TERMINATOR)
6fd269f3 83 c8 ff OR EAX,0xffffffff
LAB_6fd269f7 XREF[1]: 6fd26a0d(j)
6fd269f7 0f b6 31 MOVZX ESI,byte ptr [param_1]
6fd269fa 0f b6 f8 MOVZX EDI,AL
6fd269fd 33 f7 XOR ESI,EDI
6fd269ff c1 e8 08 SHR EAX,0x8
6fd26a02 8b 34 b5 MOV ESI,dword ptr [ESI*0x4 + DAT_6fd2a248]
48 a2 d2 6f
6fd26a09 33 c6 XOR EAX,ESI
6fd26a0b 41 INC param_1
6fd26a0c 4a DEC param_2
6fd26a0d 75 e8 JNZ LAB_6fd269f7
6fd26a11 f7 d0 NOT EAX
6fd26a13 c3 RET
Here is the original function in C++
uint __fastcall FUN_6fd269d3(byte *param_1,int param_2)
{
uint uVar1;
if (param_2 == 0) {
Ordinal_10023(s__dwSize_6fd43f6b + 1,s_C:\projects\D2\head\Diablo2\Sour_6fd43f74,0x40);
/* WARNING: Subroutine does not return */
FUN_6fd1c7ed(0xffffffff);
}
uVar1 = 0xffffffff;
do {
uVar1 = uVar1 >> 8 ^ *(uint *)(&DAT_6fd2a248 + ((uint)*param_1 ^ uVar1 & 0xff) * 4);
param_1 = param_1 + 1;
param_2 = param_2 + -1;
} while (param_2 != 0);
return ~uVar1;
}
If you notice there is a certain table whose values are being XOR'd with the checksum. Find the table at 6FD2A248
. It's DWORD[256]
DAT_6fd2a248 XREF[1]: FUN_6fd269d3:6fd26a02(R)
The values in the table are as follows:
00 => 0X0
01 => 0X77073096
02 => 0XEE0E612C
03 => 0X990951BA
04 => 0X076DC419
05 => 0X706AF48F
06 => 0XE963A535
07 => 0X9E6495A3
08 => 0X0EDB8832
09 => 0X79DCB8A4
0A => 0XE0D5E91E
0B => 0X97D2D988
0C => 0X09B64C2B
0D => 0X7EB17CBD
0E => 0XE7B82D07
0F => 0X90BF1D91
10 => 0X1DB71064
11 => 0X6AB020F2
12 => 0XF3B97148
13 => 0X84BE41DE
14 => 0X1ADAD47D
15 => 0X6DDDE4EB
16 => 0XF4D4B551
17 => 0X83D385C7
18 => 0X136C9856
19 => 0X646BA8C0
1A => 0XFD62F97A
1B => 0X8A65C9EC
1C => 0X14015C4F
1D => 0X63066CD9
1E => 0XFA0F3D63
1F => 0X8D080DF5
20 => 0X3B6E20C8
21 => 0X4C69105E
22 => 0XD56041E4
23 => 0XA2677172
24 => 0X3C03E4D1
25 => 0X4B04D447
26 => 0XD20D85FD
27 => 0XA50AB56B
28 => 0X35B5A8FA
29 => 0X42B2986C
2A => 0XDBBBC9D6
2B => 0XACBCF940
2C => 0X32D86CE3
2D => 0X45DF5C75
2E => 0XDCD60DCF
2F => 0XABD13D59
30 => 0X26D930AC
31 => 0X51DE003A
32 => 0XC8D75180
33 => 0XBFD06116
34 => 0X21B4F4B5
35 => 0X56B3C423
36 => 0XCFBA9599
37 => 0XB8BDA50F
38 => 0X2802B89E
39 => 0X5F058808
3A => 0XC60CD9B2
3B => 0XB10BE924
3C => 0X2F6F7C87
3D => 0X58684C11
3E => 0XC1611DAB
3F => 0XB6662D3D
40 => 0X76DC4190
41 => 0X01DB7106
42 => 0X98D220BC
43 => 0XEFD5102A
44 => 0X71B18589
45 => 0X06B6B51F
46 => 0X9FBFE4A5
47 => 0XE8B8D433
48 => 0X7807C9A2
49 => 0X0F00F934
4A => 0X9609A88E
4B => 0XE10E9818
4C => 0X7F6A0DBB
4D => 0X086D3D2D
4E => 0X91646C97
4F => 0XE6635C01
50 => 0X6B6B51F4
51 => 0X1C6C6162
52 => 0X856530D8
53 => 0XF262004E
54 => 0X6C0695ED
55 => 0X1B01A57B
56 => 0X8208F4C1
57 => 0XF50FC457
58 => 0X65B0D9C6
59 => 0X12B7E950
5A => 0X8BBEB8EA
5B => 0XFCB9887C
5C => 0X62DD1DDF
5D => 0X15DA2D49
5E => 0X8CD37CF3
5F => 0XFBD44C65
60 => 0X4DB26158
61 => 0X3AB551CE
62 => 0XA3BC0074
63 => 0XD4BB30E2
64 => 0X4ADFA541
65 => 0X3DD895D7
66 => 0XA4D1C46D
67 => 0XD3D6F4FB
68 => 0X4369E96A
69 => 0X346ED9FC
6A => 0XAD678846
6B => 0XDA60B8D0
6C => 0X44042D73
6D => 0X33031DE5
6E => 0XAA0A4C5F
6F => 0XDD0D7CC9
70 => 0X5005713C
71 => 0X270241AA
72 => 0XBE0B1010
73 => 0XC90C2086
74 => 0X5768B525
75 => 0X206F85B3
76 => 0XB966D409
77 => 0XCE61E49F
78 => 0X5EDEF90E
79 => 0X29D9C998
7A => 0XB0D09822
7B => 0XC7D7A8B4
7C => 0X59B33D17
7D => 0X2EB40D81
7E => 0XB7BD5C3B
7F => 0XC0BA6CAD
80 => 0XEDB88320
81 => 0X9ABFB3B6
82 => 0X03B6E20C
83 => 0X74B1D29A
84 => 0XEAD54739
85 => 0X9DD277AF
86 => 0X04DB2615
87 => 0X73DC1683
88 => 0XE3630B12
89 => 0X94643B84
8A => 0X0D6D6A3E
8B => 0X7A6A5AA8
8C => 0XE40ECF0B
8D => 0X9309FF9D
8E => 0X0A00AE27
8F => 0X7D079EB1
90 => 0XF00F9344
91 => 0X8708A3D2
92 => 0X1E01F268
93 => 0X6906C2FE
94 => 0XF762575D
95 => 0X806567CB
96 => 0X196C3671
97 => 0X6E6B06E7
98 => 0XFED41B76
99 => 0X89D32BE0
9A => 0X10DA7A5A
9B => 0X67DD4ACC
9C => 0XF9B9DF6F
9D => 0X8EBEEFF9
9E => 0X17B7BE43
9F => 0X60B08ED5
A0 => 0XD6D6A3E8
A1 => 0XA1D1937E
A2 => 0X38D8C2C4
A3 => 0X4FDFF252
A4 => 0XD1BB67F1
A5 => 0XA6BC5767
A6 => 0X3FB506DD
A7 => 0X48B2364B
A8 => 0XD80D2BDA
A9 => 0XAF0A1B4C
AA => 0X36034AF6
AB => 0X41047A60
AC => 0XDF60EFC3
AD => 0XA867DF55
AE => 0X316E8EEF
AF => 0X4669BE79
B0 => 0XCB61B38C
B1 => 0XBC66831A
B2 => 0X256FD2A0
B3 => 0X5268E236
B4 => 0XCC0C7795
B5 => 0XBB0B4703
B6 => 0X220216B9
B7 => 0X5505262F
B8 => 0XC5BA3BBE
B9 => 0XB2BD0B28
BA => 0X2BB45A92
BB => 0X5CB36A04
BC => 0XC2D7FFA7
BD => 0XB5D0CF31
BE => 0X2CD99E8B
BF => 0X5BDEAE1D
C0 => 0X9B64C2B0
C1 => 0XEC63F226
C2 => 0X756AA39C
C3 => 0X026D930A
C4 => 0X9C0906A9
C5 => 0XEB0E363F
C6 => 0X72076785
C7 => 0X05005713
C8 => 0X95BF4A82
C9 => 0XE2B87A14
CA => 0X7BB12BAE
CB => 0X0CB61B38
CC => 0X92D28E9B
CD => 0XE5D5BE0D
CE => 0X7CDCEFB7
CF => 0X0BDBDF21
D0 => 0X86D3D2D4
D1 => 0XF1D4E242
D2 => 0X68DDB3F8
D3 => 0X1FDA836E
D4 => 0X81BE16CD
D5 => 0XF6B9265B
D6 => 0X6FB077E1
D7 => 0X18B74777
D8 => 0X88085AE6
D9 => 0XFF0F6A70
DA => 0X66063BCA
DB => 0X11010B5C
DC => 0X8F659EFF
DD => 0XF862AE69
DE => 0X616BFFD3
DF => 0X166CCF45
E0 => 0XA00AE278
E1 => 0XD70DD2EE
E2 => 0X4E048354
E3 => 0X3903B3C2
E4 => 0XA7672661
E5 => 0XD06016F7
E6 => 0X4969474D
E7 => 0X3E6E77DB
E8 => 0XAED16A4A
E9 => 0XD9D65ADC
EA => 0X40DF0B66
EB => 0X37D83BF0
EC => 0XA9BCAE53
ED => 0XDEBB9EC5
EE => 0X47B2CF7F
EF => 0X30B5FFE9
F0 => 0XBDBDF21C
F1 => 0XCABAC28A
F2 => 0X53B39330
F3 => 0X24B4A3A6
F4 => 0XBAD03605
F5 => 0XCDD70693
F6 => 0X54DE5729
F7 => 0X23D967BF
F8 => 0XB3667A2E
F9 => 0XC4614AB8
FA => 0X5D681B02
FB => 0X2A6F2B94
FC => 0XB40BBE37
FD => 0XC30C8EA1
FE => 0X5A05DF1B
FF => 0X2D02EF8D
You can either use the XOR Table and XOR the value of every byte or you can use the algorithm in the previous post.
uVar1 = uVar1 >> 8 ^ DWORD_ARRAY_6fd2a248[(uint)*param_1 ^ uVar1 & 0xff];