Back to ericjwin



Warning!!
These files are for Diablo II LOD Version 1.09 only

Back to Diablo 2 Hex Editing Tutorial


IcpdoggQ Hex Editing Tips



1. Introduction
One day, I was playing D2X 1.07, and I got 2 rings, both were rings of greed, but with different values which I can't remember clearly. So my curiosity drove my to compare the two rings.
First, I had to pull the rings out of the d2s file. Because it was too easy, by guessing and trying, I did it.
Second, I did as many of you are now doing. I viewed the hex codes, figured out the difference, made some change, and pushed the rings back to the d2s file (lukily, 1.07 had no checksum). I just let the game show me the change. But soon, I realized that the value of attributes are not byte aligned, so I decided to involve in bin.
At first, I made 2 programmes, one was for viewing and saving ASCII bin codes of item files, the other was for storing the attributes I found. Later on, I made several samll tools, such as "Name" for the conversion between 8-bit ASCII and 7-bit ASCII (inscribed name uses 7-bit ASCII characters).
Guessing-Modifying-Crashing-Guessing-......, that best describes the work I've done. After I figured out several tens of attributes, the progress was slowed down. At time, I heard Jamella. I downloaded it, added all the attributes I had not known.
When 1.09 came out, I fixed some attributes which were changed by 1.09.
Months ago, I found useful info about Item Structure on Nightshiver --- Diablo II Item Format on Erijwin's Page.
Weeks ago, I downloaded MpqView from ProzenKeep, then most of the attributes are found in a file --- ItemStatCost.txt.
All clues and experience together have made things clear, which is what I'm going to tell you...


2. D2X Item Structure


[111111111 xxx] [01234] [0123] [0123454678] [01234567 01234567] [0123456789] 0 [xxx] [xxx] [xxx] 0 0010 1011101 01001000 11010110 01111110 11010100 000 00100000 01100100 01110011 01100111 001 0000 0000 0000 000 00011001000000000 0 1 0 0000 0 00000 0 000000 1 0000 01001101 01001010

-----*-----|- | | | | | |->Def | | | | | | ----------------*------------------ | ----------------*------------------ | | | | | | | | | | 'M' 'J'

| | | | | | |->MaxDura | | | | | |->unknown(143-149) |->Random Unique ID |->gems inside | | | | | |->Location(58-60) | | | | |->Identified(20)

| | | | | |->CurDura | | | | |->quality(150-153) (111-142) (108-110) |->Item Type ID | | | |->equipwhere(61-64) | | | |->Socketed(27)

| | | | |->Quivers Quantity | | | |->(Ring/Amulet/Charm/Jewel) Graph(154) (76-107) | | |->column(65-68) | | |

| | | |->Number of Sockets | | |->(Ring/Aumlet/Charm/Jewel) Graph Type | |->row(69-71) | | |->Starting Item(33)

| | |->Set Item Addition | |->Low/High/Magical/Rare/Set/Unique/Crafted Affixes |->placewhere(73-75) | |->Ethereal(38)

| |->Attributes |->Inscribed Name |->Name Inscribed(40)

|->1st Attribute Field

__________________________________________________________________________________________________________



I. quality(150-153):
low quality = 1
normal = 2
high quality = 3
magical = 4
set = 5
rare = 6
unique = 7
crafted = 8

i. low quality: [3bits]
crude = 0
cracked = 1
damaged = 2
low quality = 3

ii. normal: [0] (nothing)

iii. high quality: [3] (random)

iv. magical: [11]suffix [11]prefix

v. set: [12]

Set Item Addition:
00000 = has 1 attribute field
00001 = 2 attribete fields
00011 = 3 attribete fields
00111 = 4 attribete fields
01111 = 5 attribete fields

vi. rare: [8]Pre ->

[8]Suf ->
[1] 0: no 1st MPre, 1: has 1st MPre [11]MPre ->
[1] 0: no 2nd MPre, 1: has 2nd MPre [11]MPre ->
[1] 0: no 3rd MPre, 1: has 3rd MPre [11]MPre

vii. unique: [12]

viii. crafted: [?]

II. graph(154):
0: normal
1: other
i. normal: [1] 0
ii. other: [4] ring:0-4, amulet:0-2, charm:0-2, jewel:0-5



III.

About Quivers/Keys:
normal quality, quantity, no dura, no def.

About Gems/Runes:
normal quality, no quantity, no dura, no def.



IV. location, etc.
location(58-60): 0: stored (in inventory/stash/cube)
1: equiped
2: in belt(sash)
4: being picked up
6: inserted(in a socket)

equipwhere(61-64): if item is equiped(see location)
1: head (helm)
2: neck (amulet)
3: tors (body armor)
4: rarm (weapon)
5: larm (shield)
6: rrin (ring)
7: lrin (ring)
8: belt (belt)
9: feet (boots)
10: glov (gloves)
11: rarm2 (alternative right arm)
12: larm2 (alternative left arm)

column(65-68): if item is in inventory/stash/cube/belt (see location)

inventory: 0-9
stash: 0-5
cube: 0-3
belt: 0-3: 1st row, 4-7: 2nd row, 8-11: 3rd row, 12-15: 4th row

row(69-71): if item is in inventory/stash/cube (see location)
inventory: 0-3
stash: 0-7
cube: 0-3

placewhere(73-75): if item is in inventory/stash/cube (see location)
0: item is not stored (in inventory/stash/cube)
1: inentory
4: cube
5: stash


V. Inscribed Name:

e.g. inscribe "Fuzzier" (set Name Inscribed(40) first):
code: 00000001110010110010111010011111010111101011101011000110
decode: 0000000 1110010 1100101 1101001 1111010 1111010 1110101 1000110
'\0' 'r' 'e' 'i' 'z' 'z' 'u' 'F'
(null-terminated 7-bit ASCII string)



3. Magical Attributes

Each magical attribute has an 9-bit ID, as well as 1 to 4 value fields. For example, "% Enchanced Damage" ID: 000010001, value 1: length=9 bits, base=0, +%Min Dmg, value 2: length=9 bits, base=0, +Max Dmg, so "000000010 000000001 000010001" means "+1% Enchanced Min Damage and +2% Enchanced Max Damage".
There are at least 248 implemented magical attributes, a few are useless, several may even crash your game. Because the list is so long, I will only give you several examples.

i. Damage Reduced By %
A lot of people talk about this attribute these days.
ID: 000100100
value: length=8 bits, base=0
e.g. 00001010 000100100 --- Damage Reduced By 10%

ii. Attack Freezes Target
ID: 010000110
value: length=5 bits, base=0
e.g. 00010 010000110 --- Attack Freezes Target +2

iii. Poison Damage
ID: 000111001
value 1: length=9 bits, base=0, Min Poison Dmg (#*value3/255)
value 2: length=9 bits, base=0, Max Poison Dmg (#*value3/255)
value 3: length=8 bits, base=0, Poison Length (#/25 = length (sec))
e.g. 00110010 001100110 000110011 000111001 --- 10-20 poison dmg over 2 sec.
A little confused? Let me explain to you.
value3 = 00110010 = 50 in Dec, so poison length = 50/25 = 2 (sec). value2 = 001100110 = 102 in Dec, so Max Poison Dmg = 102 * 50 / 255 = 20.
value1 = 000110011 = 51 in Dec, so Min Poison Dmg = 51 * 50 / 255 = 10.
Hence we get "10 - 20 Poison Damage Over 2 Seconds".


4. Practice

Create a magical small charm by Jamella or my creator. Save it to test.d2i. Dump the file, you'll see 111111111 (9 '1's) at the end (left-most side) of the code, that is "End of Item" (EoI for short), add your attributes before (at the right side of) it. For example, after you add "Damage Reduced By 10%", the code looks like something as "00111111111 00001010 000100100 ...". Undump it.
=====================================================

Binary Lesson #1

This lesson is not to explain how to hack diablo. It is to teach you the basics of binary, how it works and understanding it. If you need further lessons on hacking diablo 2 lod with binary, go to the binary forum. This lesson was also
intended for beginners with few/no hex or binary experience.

First of all what does binary look like? Well when your editing binary you will see something like this: 00011101 00101111 00000100 10101011 01011011
When a computer processes information it sends electrical signals down multiple wires. If you were to convert those electrical signals into 0's and 1's This is how it would work. One electrical signal would represent a 1. And if the electrical signal is missing, it would be presented as a 0. In the earlier days the telegraph worked similar. You had a long pulse or a short pulse and all you do is send signals down a wire to the receiver. The you would use morse code to decode the message.

In the computer world, Morse code is known as ASCII, and Short and long pulses is known as binary and works a bit different. If we compare Morse code to binary for the alphabet this is how it would work.

Lets say in morse code 3 long pulses equaled an O, in binary we still use electrical signals to represent one letter but in a bit differently.
In binary 01001111 equals O. or otherwise known as: No Pulse, Pulse, No pulse, No pulse, Pulse, Pulse, Pulse, Pulse. (of electricity)

So in simpler terms. All that binary is, is Raw Computer Language.

If you knew hex then FF in hex would equal 11111111 in binary. Hex just shortened it up
====================================================
1. What is byte?
Usually, 1 byte = 8 bits. Byte is used as a unit to measure the size of information.

1 byte can be represented by the following diagram:
MSB LSB

0 1 0 0 1 1 1 0


What value would the COMPUTER "think" this byte has? 01001110 B. Note that MSB is the highest bit in the Bin number, and LSB is the lowest bit, because the computer "thinks" like this.

1 byte consists of 8 bits, and its value ranges from 00000000 B (0 in Dec) to 11111111 B (255 in Dec). If we use 00000001 B to represent the character 'A', and 00000010 B 'B', ..., 00100101B 'Z', we can combine several bytes to construct a meaningful sentence --- information, and its size = the number of bytes.

1K bytes = 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 bytes = 2^10 bytes = 1024 bytes
1M bytes = 1KK bytes = 2^20 bytes = 1,048,576 bytes
1G bytes = 1KM bytes = 2^30 bytes = 1,073,741,824 bytes
1T bytes = 1MM bytes = 2^40 bytes = 1,099,511,627,776 bytes

Question: why my 40 GB diskette has only 37.25GB after formatted?
Answer: this "40 GB" means "40,000,000,000 Bytes", divided by 230, then you get 37.25GB.

2. How Bytes Are Stored
You may think this an easy question even you can answer without hesitation. But do listen to me, carefully.

Bytes are stored one by one in memory or disk, every byte has its own Address --- the first one at address 0, the second one at 1, ...

And the LSB, MSB position is represented below (this is Vital Important!!!):
MSB LSB MSB LSB

0 1 0 0 1 1 1 0 0 1 0 0 1 1 1 0

1 Word = 2 Continuous Bytes. The above 2 bytes together can be regarded as 1 word, and its value = 01001111 10011010 B = 8F9A H.

3. How Bits Are Stored
We usually write Hex code byte after byte, e.g. 4A 4D 10 00 80 01 64 4A H is at address 0, 4D H is at 1, 10 H is at 2, ... If we want to Bin edit the code, we must how BITS are stored. How to do it? Someone may say the code is 01001010 01001101... B. But remember our writing habit --- the right-most digit is the lightest, and the left-most digit is the heaviest (543: '5' means 500, '4' means 40, '3' means 3), so when we write down 4A 4D 10 ..., we put low address byte at left side, high right. The correct code is .... 01001101 01001010 B.

4. How to Dump a File
i. dump
In order to Bin Editing code, we have to see every bit of the file --- value and position.
I introduce a method:
Read the 1st byte of the file, convert it to ASCII bits, write them down; read the 2nd byte, convert it to ASCII bits, write them down after (at the left side of) the previous byte; and so on. c code:
====================================================

1. Conversion from Bin to Dec
In Bin, we just use 0 and 1 to count. Just like the above, 10 in Bin = 1 x 2 + 0 x 1 in Dec = 2 in Dec. 101 B = 1 x 2 x 2 + 0 x 2 + 1 x 1 in Dec = 5 D. 10110 B = 1 x 2 x 2 x 2 x 2 + 0 x 2 x 2 x 2 + 1 x 2 x 2 + 1 x 2 + 0 x 1 in Dec = 22 D. This kind of work is easy.

110010 in Bin = ___ in Dec

2. Conversion from Bin to Hex
This part is very import. We know now numbers from 0000 to 1111 in Bin (0 to 15 in Dec) exactly represent the Hex numbers from 0 to F. If we group them --- 4 bits (bit: 0 or 1 in a Bin number) per group, we can easily convert Bin numbers to Hex. e.g. 100101001 B = 0001 0010 1001 B = 1 2 9 H.

Remember how to convert Hex number to Dec number? OK, let's do it in Bin. Now we use a simpler number 10010 B, or 0001 0010 B. Divide 0001 0010 B by 10000 B (16 in Dec), the remainder is 0001 B, the quotient is 0010 B, and we get 0001 0010 B = 0001 B x 10000 B + 0010 B, which is 0001 0010 B = 1 x 16 + 2 in Dec = 12 in Hex. What about 0001 0010 1001 B? You can do it yourself.

1100 1010 B = ___ in Hex
1101110101100 B = ___ in Hex

____________________________________________________________________
answers:
110010 in Bin = 1 x 2 x 2 x 2 x 2 x 2 + 1 x 2 x 2 x 2 x 2 + 0 x 2 x 2 x 2 + 0 x 2 x 2 + 1 x 2 + 0 x 1 in Dec = 50 in Dec

1100 1010 B = CA in Hex
1101110101100 B = 0001 1011 1010 1100 B = 1BAC in Hex