forked from ternence-li/diablo2-1
-
Notifications
You must be signed in to change notification settings - Fork 0
/
README
executable file
·129 lines (93 loc) · 5.27 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
dupescan109 - Diablo II 1.09d Dupe Scanner
==========================================
How do I compile it?
Just type "make".
How do I set the default directory?
There is a macro defined which is called "DEFAULT_DIRECTORY" in the
dupescan109.c file.
How to use it?
The usage is quite easy. You have two main modes, first, the scan mode (-s)
which scans all files in a given (or the default) directory for duplicate
items. The second mode is the character mode (-c) which prints the itemlist,
including base address in file, length, fingerprint and itemtype of a given
character.
For the first mode, there are three additional options. Verbose (-v),
debug (-d) and quiet (-q). Verbose adds the info stuff from character
mode for every character in the directory, debug mode prints additional
debugging information and quiet (-q) suppresses all information except
the final ones. The second mode only has the debug flag.
Ok, examples:
Scan a directory for dupes:
./dupescan109 -s/home/diablo/var/charsave
Print characters items:
./dupescal109 -c/home/diablo/var/charsave/mychar
NOTE: There is no space between the option and the parameter!
How does it work?
Well, first of all, I have to give you a quick introduction to the d2s file
format of 1.09. The files are binary coded and not human readable. Stuff that
is important for a dupescanner is:
File version (offset 4, size long)
Character name (offset 20, size 16 chars)
Character status (offset 36, size 1 byte)
Ok, so far with the character info. Now lets get into the item info. The data
before the item list has variable length, so there is no fixed offset for the
beginning of the item list. But it has the magic prefix "JM" at the beginning
and "JM", followed by two nullbytes, at the end. So everything between our
first "JM" and our first "JM\0\0" is our (first) item list. Note: a character
can have multiple item lists, for example for the merc (only in LoD) or the
corpse (only in SC mode) or one item for the golem if you are a Nec.
However, the game server I wrote this dupescanner for only allows hardcore
mode players for D2 Classic, so the only items it will check are the main
ones (no corpse, no merc, dont care about golem).
From now on, I will refer to the offset of "J" (of "JM") as zero, so offset
1 is "M", etc.. After the JM, there is a 16 bit number (short) which holds
the number of items that follow. Each following item also starts with "JM"
(but it does not end with anything, you know that you are at its end when
you read the "JM" of the next item).
Now, there are two main types of items. Standard items and extended items.
All standard items have a fixed length of 14 bytes, everything that is longer
than 14 bytes is extended. Extended items have a variable length, but thats
not an issue because we only care about the item fingerprint. Only extended
items have fingerprints.
The fingerprint is a 32 bit unique identifier which is random-generated by
the server on item drop. The chance of generating two 32 bit random numbers
which are the same is 1 to 2^32, so dont bother about collisions. However,
this is the main point of dupe detecting. If there are two items with the
same fingerprints, this means that the items are the same and therefore are
duped. So all we have to do is read all fingerprints and compare them.
The fingerprints starts at bit 111 and is, as I said, 32 bit long. Those of
you who did pass math will notice that 111 is not dividable by 8, which means
that the fingerprint data is not byte aligned. It looks like this:
byte 13 byte 14 byte 15 byte 16 byte 17
xxxxxxxA|AAAAAAAA|AAAAAAAA|AAAAAAAA|AAAAAAAy
We dont care about the x and y, we just want A. I solved this with a packed
bitfield structure.
There is one other value that I use, the item type. A 32 bit value (4 chars) at
bit offset 76. Same shit, different data. Not byte aligned :-) It starts in the
middle of byte 9 and ends at the middle of byte 13.
How did you know how the file format looks like?
http://www.ladderhall.com/ericjwin/109/trevin/trevinitemformat.html
http://www.ladderhall.com/ericjwin/109/trevin/trevinfileformat.html
http://home.stx.rr.com/svr/formats/d2s.htm
Why only 1.09d??
Well, actually, it should work with every 1.09 version, but I only tested it
with 1.09d. But it will definitely not work with a non-1.09 version. The
reason for this is simple. Blizzard changes the d2s file format with every
version and this software was written with 1.09 in mind.
I am using 1.09d, but the scanner gives me errors!
You may notice an error like:
Error: myTestChar is not a valid v1.09 character file or he has never been in a game
(File version is 89, should be 92)
I am not completely sure, but it happened to me some times when I created a
char and never played it. Looks like an "empty" char which never has been in
a real game does not necessarily have the "92" file version set (which stands
for 1.09).
Your code sucks!
Hehe, well, maybe it does, I dont really know, because I am not a very experienced C coder, but
it works for me. If you dont like it, dont use it. But I would appreciate it if you send me bug
reports.
Who did this?
Florian 'fw' Weingarten
http://hackvalue.de/
Thanks to
Trevin Beattie for his great file format description and his email support