Reverse engineering Diablo v1.09b (last patch)
#8
Hello.

Is anyone aware of how Diablo deals with a player's health?

I've clearly found the 20 bytes (yes: 20!) that pertain directly the the character's health / effective health & maximum health / effective maximum health.

The last 4 bytes I am not sure how is used (that may be apart of what's causing my issues).

Here's what I've gathered (first: A good laugh): Math is killing me!!!
[Image: xFEW4fA.png]

I had Diablo in the background while I was trying to input what I believe will produce 110HP! Only to find my Sorcerer dead on the floor in town.

Desired HP: 100
100(HP) / 4 = 25
25 = 0x00 0x19

Desired HP: 108 (+4 HP more)
108(HP) / 4 = "27"
"27" = 0x00 0x1B

Desired HP: 112 (+4 HP more)
108(HP) / 4 = "27"
"27" = 0x00 0x1B

I can clearly predict how to apply new health using the 2nd byte (divisible by 4).

How would one apply the health of 111? Or 110 (even number)? I thought perhaps this would work:

Desired HP: 110
110(HP) / 2 = 55
55 = 0x37 0x00

Unfortunately, this produces some odd side effects.

The health orb displays: 1 / 0 HP (alive in town).
The lying character screen displays: 0 / 1 HP (alive in town).

The 20th byte went from a usual 0x50 (80); Which usually represents 100% health to: 0x5D (93).

Any ideas? Thanks! Confused

EDIT: I just thought of something real fast... If I can maintain "0x50" on the 20th byte: It should work!
I was close... I modified my health values (all 4) to this:

Code:
006865D8 - 37 0D 00 00 37 0D 00 00 37 0D 00 00 37 0D 00 00  7...7...7...7...

Unfortunately: It produced half of my desired target of 110HP (52HP generated). Angry

EDIT #2: Now I am REALLY confused! I doubled the first byte and it added +1HP (52 -> 53)????

(Me)
Quote:When the 1st byte is: 0
The 2nd byte is treated as divisible by 4.

When the first byte is NOT 0: It is divisible by 2
The second byte increments by +1

EDIT #3: OK! I think I've figured this out almost all the way (taking quite a bit)...

Code:
006865D8 - A1 1B 00 00 A1 1B 00 00 A1 1B 00 00 A1 1B 00 00  ¡...¡...¡...¡...

0xA1 = 26
0x1B = 27

A1 / 2 = 80
A1 + 1B = 107 (rounded: 110?)

OR

0x1B 0xA1 = 7073
(7073 / 8) / 8 = 110

The latter seems to yield more predictable results.

0x1C 0xA1 = 7329
(7329 / 8) / 8 = 114

EDIT #4: Yes... It seems that is the formula. I am just doing something wrong. I almost have this down! Smile

I predicted that the target "113" HP would be:
0x37 0x1C

It yielded 112HP (off by 1).

The correct answer:
0x40 0x1C!

EDIT #5: Yup! Close, but just off by 1! Frustrating.
Target HP: 133 (odd number)
Idea: Multiply target HP by 4
Split value into two bytes represented in hex

EG: 0x214 = 0x04 0x21
Turns out (maybe I read it wrong?) the answer is: 0x40 0x21!

EDIT #6: Yes! I absolutely have the answer now. The only problem is: I do not know how to mathematically (programatically) explain what I am doing.

Code:
Is the desired HP divisible by 4 evenly?
Step 1: Divide target HP by 4 (100 -> 25)
Step 2: Write 00 to the first byte; Write quotient (25 or 0x19) to the second byte

Is the desired HP an odd number (not divisible ending in a whole number for a quotient)?
Step 1: Multiply target HP by 4 (123 (7B) -> 492 (1EC))
Step 2: Divide by 16 (quotient: 30 (0x1E))
Step 3: Write quotient to the 2nd byte (30 (0x1E))
Step 4: Write the ???? to the 1st byte (12 (0x1C))

The 20th byte remains at 0x50 (80); I am not sure how "80" represents 100% health, but I may be incorrect on what it's purpose is.

... In fact: You can use the latter formula to calculate evenly divisible numbers (it comes out all the same).
100 -> 400 -> 25 (0x19 to the 2nd byte)

... This is actually incorrect. Although it is the closest thing to an accurate solution I've come up with yet.
I feel stuck on figuring out what the formula is or how to extract it. Any pointers (no jokes please!) or help would be appreciated.

EDIT #???: Oh... You can just simply multiply the desired HP by 4 and use only base-16 (no division necessary). Angry

EDIT: I would love to know how to solve this mathematically and pragmatically. I am assuming in C: You would solve this with either bit shifting or the modulus operator.
However: Using only pencil and paper: I am failing to come up with a solution here.

123 * 4 = 492
492 / 16 = 30

This is the first value we need to extract (to write to the 2nd byte). 0x1E
How do you extract the other digit? 0x0C! This has me stumped. I can almost describe what it is I am trying to do, but I cannot quite put my tongue on it.

Another (with a calculator, of course) method that I've been successfully using is to do this:
Target HP = 983
983 * 4 = 3932 (0xF5C)
3932 * 16 = 0xF5 0xC0

0xC0 0xF5 0x00 0x00 yields our results in-game! 983.
Reply


Messages In This Thread
RE: Reverse engineering Diablo v1.09b (last patch) - by TheKillerVortex - 01-31-2018, 09:48 AM

Forum Jump:


Users browsing this thread: 1 Guest(s)