magic/rare DWORD decoding in Classic
#21
What compiler are you using? I thought even Borland's free compiler supported __int64's. I'd tested the code I'd linked to above using either Borland C++ 5.02 or MS Visual C++ 6.0. I forget which - we were switching from one compiler to the other at work around then.

-- CH
Reply
#22
CelticHound,Apr 8 2003, 06:21 AM Wrote:What compiler are you using?  I thought even Borland's free compiler supported __int64's.  I'd tested the code I'd linked to above using either Borland C++ 5.02 or MS Visual C++ 6.0.  I forget which - we were switching from one compiler to the other at work around then.

-- CH
Yes, VS definately support the __int64 data type.

Alternatively write the code in assembler :)

Here is some code snipets I once used in a program to simulate the pre expansion item creation. It generate result identical to the one in D2 (since it is identical in function although I trimed some unnessecary stuff out).

There are two functions, one is the standard rnd[x] that returns a value in the 0 to x-1 range. It also takes a paramater that is a pointer to the seed. The other simply returns the seed (after updating it once).

There is two versions of the functions I think (I just copy and paste here). The first uses a data structure with 2 32 bit values (since the game itself pretty much use such a system and you really initialize it that way and use it that way too. It is just a normal structure in at least in VS that I use that structure places those 2 32 bit values right after each other. The other set of functions is basically the same but is set to use a __int64 data type pointer instead. It really doesn't change anything. I think it is commented out in the file I copied from.

Finally there seem to be a few variants on how the function is set up for initialization code and such things (naked and non naked and such use which one you feel most comfortable with). The header file is for the non comented case only though!

Code:
// random.cpp

#include "stdafx.h"

#pragma warning( disable : 4035 )    // avoids warning for not returning any value
__declspec( naked ) unsigned int __fastcall d2rnd(struct seeddata *ptseed, unsigned int x)
{
    __asm
    {
 push edi;
 push esi;
 push ebx;
 mov edi,edx;
 mov esi,ecx;      // no check on pointer!!
 test edi,edi;      // check if x>0
 jg OK;
&nbsp;xor eax,eax; &nbsp;    // return 0 if x <= 0
&nbsp;jmp END;
OK:
&nbsp;mov eax, [esi]; &nbsp;    // get seed_lo
&nbsp;mov ecx, 0x6ac690c5;    // rndmult
&nbsp;mul ecx;
&nbsp;mov ecx,[esi+4]; &nbsp;// get seed_hi
&nbsp;xor ebx,ebx;
&nbsp;add eax,ecx;
&nbsp;adc edx,ebx;
&nbsp;mov [esi],eax; &nbsp;    // store away new seed
&nbsp;mov [esi+4],edx;
&nbsp;xor edx,edx;
&nbsp;div edi; &nbsp; &nbsp;// calculate random number based on seed_lo
&nbsp;mov eax,edx; &nbsp;    // return reminder
END:
&nbsp;pop ebx;
&nbsp;pop esi;
&nbsp;pop edi;
&nbsp;ret
    }
    // returns random value in eax
} // d2rnd
#pragma warning( default : 4035 )


#pragma warning( disable : 4035 )    // avoids warning for not returning any value
__declspec( naked ) unsigned int __fastcall d2seed(struct seeddata *ptseed)
// same as above but no division at end, returns lo_seed instead
{
    __asm
    {
&nbsp;push esi;
&nbsp;push ebx;
&nbsp;mov esi,ecx; &nbsp;    // no check on pointer!!
&nbsp;mov eax, [esi]; &nbsp;    // get seed_lo
&nbsp;mov ecx, 0x6ac690c5;    // rndmult
&nbsp;mul ecx;
&nbsp;mov ecx,[esi+4]; &nbsp;// get seed_hi
&nbsp;xor ebx,ebx;
&nbsp;add eax,ecx;
&nbsp;adc edx,ebx;
&nbsp;mov [esi],eax; &nbsp;    // store away new seed
&nbsp;mov [esi+4],edx;
&nbsp;pop ebx;
&nbsp;pop esi;
&nbsp;ret
    }
    // returns value in eax (new lo_seed)
} // d2seed
#pragma warning( default : 4035 )



/*
#pragma warning( disable : 4035 )    // avoids warning for not returning any value
int d2rnd(__int64 *ptseed, int x)
{
    __asm
    {
&nbsp;mov edi,x;
&nbsp;mov esi,ptseed; &nbsp;    // no check on pointer!!
&nbsp;test edi,edi; &nbsp;    // check if x>0
&nbsp;jg OK;
&nbsp;xor eax,eax; &nbsp;    // return 0 if x <= 0
&nbsp;jmp END;
OK:
&nbsp;mov eax, [esi]; &nbsp;    // get seed_lo
&nbsp;mov ecx, 0x6ac690c5;    // rndmult
&nbsp;mul ecx;
&nbsp;mov ecx,[esi+4]; &nbsp;// get seed_hi
&nbsp;xor ebx,ebx;
&nbsp;add eax,ecx;
&nbsp;adc edx,ebx;
&nbsp;mov [esi],eax; &nbsp;    // store away new seed
&nbsp;mov [esi+4],edx;
&nbsp;xor edx,edx;
&nbsp;div edi; &nbsp; &nbsp;// calculate random number based on seed_lo
&nbsp;mov eax,edx; &nbsp;    // return reminder
END:
    }
    // returns value in eax
} // d2rnd
#pragma warning( default : 4035 )


#pragma warning( disable : 4035 )    // avoids warning for not returning any value
int d2seed(__int64 *ptseed)
// same as above but no division at end, returns seed instead
{
    __asm
    {
&nbsp;mov esi,ptseed; &nbsp;    // no check on pointer!!
&nbsp;mov eax, [esi]; &nbsp;    // get seed_lo
&nbsp;mov ecx, 0x6ac690c5;    // rndmult
&nbsp;mul ecx;
&nbsp;mov ecx,[esi+4]; &nbsp;// get seed_hi
&nbsp;xor ebx,ebx;
&nbsp;add eax,ecx;
&nbsp;adc edx,ebx;
&nbsp;mov [esi],eax; &nbsp;    // store away new seed
&nbsp;mov [esi+4],edx;
    }
    // returns value in eax (new lo_seed)
} // d2seed
#pragma warning( default : 4035 )




#pragma warning( disable : 4035 )    // avoids warning for not returning any value
__declspec( naked ) int __fastcall d2rnd(__int64 *ptseed, int x)
{
    __asm
    {
&nbsp;push edi;
&nbsp;push esi;
&nbsp;push ebx;
&nbsp;mov edi,edx;
&nbsp;mov esi,ecx; &nbsp;    // no check on pointer!!
&nbsp;test edi,edi; &nbsp;    // check if x>0
&nbsp;jg OK;
&nbsp;xor eax,eax; &nbsp;    // return 0 if x <= 0
&nbsp;jmp END;
OK:
&nbsp;mov eax, [esi]; &nbsp;    // get seed_lo
&nbsp;mov ecx, 0x6ac690c5;    // rndmult
&nbsp;mul ecx;
&nbsp;mov ecx,[esi+4]; &nbsp;// get seed_hi
&nbsp;xor ebx,ebx;
&nbsp;add eax,ecx;
&nbsp;adc edx,ebx;
&nbsp;mov [esi],eax; &nbsp;    // store away new seed
&nbsp;mov [esi+4],edx;
&nbsp;xor edx,edx;
&nbsp;div edi; &nbsp; &nbsp;// calculate random number based on seed_lo
&nbsp;mov eax,edx; &nbsp;    // return reminder
END:
&nbsp;pop ebx;
&nbsp;pop esi;
&nbsp;pop edi;
    }
    // returns value in eax
} // d2rnd
#pragma warning( default : 4035 )



// random.h

extern unsigned int __fastcall d2rnd(struct seeddata *ptseed, unsigned int x);
extern unsigned int __fastcall d2seed(struct seeddata *ptseed);

struct seeddata {
    unsigned int    seed;
    unsigned int    mod;
};
There are three types of people in the world. Those who can count and those who can't.
Reply
#23
Wow, thanks Jarulf. You rule! Now to finish up ATMA before 1.10 is released ;)

--T
Reply
#24
Hi jarulf,

I just tried to use the PRNG and it always returned zero ... might it have something to do with

Quote:#pragma warning( disable : 4035 ) // avoids warning for not returning any value
__declspec( naked ) unsigned int __fastcall d2rnd(struct seeddata *ptseed, unsigned int x)
{
__asm
{
push edi;
push esi;
push ebx;
mov edi,edx;
mov esi,ecx;&nbsp;&nbsp; // no check on pointer!!
test edi,edi;&nbsp;&nbsp; // check if x>0
jg OK;
xor eax,eax;&nbsp;&nbsp; // return 0 if x <= 0
jmp END;
OK:

You declare x as an unsigned int but test for a negative number ?? Also, i really don't know how to read assembly but why is eax being accessed when nothing has been pushed into it?

--T

edit: Also, would you know how the 32 bit hireling ID works? Apparently, setting this to a random number and correctly setting the other parameters like experience, table index and so on will result in the first mercenary in hireling.txt being chosen with the experience you set.
Reply
#25
hakai_no_tenshi,Apr 18 2003, 05:45 AM Wrote:Hi jarulf,

&nbsp; &nbsp; I just tried to use the PRNG and it always returned zero ... might it have something to do with

Quote:#pragma warning( disable : 4035 ) // avoids warning for not returning any value
__declspec( naked ) unsigned int __fastcall d2rnd(struct seeddata *ptseed, unsigned int x)
{
__asm
{
push edi;
push esi;
push ebx;
mov edi,edx;
mov esi,ecx;&nbsp;&nbsp; // no check on pointer!!
test edi,edi;&nbsp;&nbsp; // check if x>0
jg OK;
xor eax,eax;&nbsp;&nbsp; // return 0 if x <= 0
jmp END;
OK:

You declare x as an unsigned int but test for a negative number ?? Also, i really don't know how to read assembly but why is eax being accessed when nothing has been pushed into it?

--T

edit: Also, would you know how the 32 bit hireling ID works? Apparently, setting this to a random number and correctly setting the other parameters like experience, table index and so on will result in the first mercenary in hireling.txt being chosen with the experience you set.
Ooops, my my, yeah, should probably have been a signed int. I don't think it should matter unless you send really huge values though which is not a good idea anyway.

eax is not beening accessed really, it is set to 0. xor something with itself is a common way to set it to 0 as it will always end up as 0 no matter what it held before.

Are you initializing the seed correctly by the way? If the seed is not initialized to anything (but just 0 or rather two 32 bit zero values), you always get 0 as well. You should always initialize any seed with 666 in the upper 32 bits, just as the game do! I think this might be the error you have.

I have never looked at the ID of the hirelings, sorry.
There are three types of people in the world. Those who can count and those who can't.
Reply
#26
Strange .. I'm pretty sure I did call the seed function but I'll check again. I set seeddata.seed = time(NULL); and seeddata.mod = 666; Is that right? As far as the generation of the hireling ID goes, could you look into that if you have the time? I haven't seen documentation for it anywhere. thanks.

--T
Reply
#27
hakai_no_tenshi,Apr 18 2003, 12:49 PM Wrote:Strange .. I'm pretty sure I did call the seed function but I'll check again. I set seeddata.seed = time(NULL); and seeddata.mod = 666; Is that right? As far as the generation of the hireling ID goes, could you look into that if you have the time? I haven't seen documentation for it anywhere. thanks.

--T
Sure, fine. Really, as long as it is not all 0, any seed is OK.
There are three types of people in the world. Those who can count and those who can't.
Reply
#28
Just wondering if you had any time to look at how the 32 bit merc ID at +00be is generated ?

--T
Reply
#29
hakai_no_tenshi,Apr 20 2003, 08:49 PM Wrote:Just wondering if you had any time to look at how the 32 bit merc ID at +00be is generated ?

--T
Ehh, at +00be??? Are you refering to the offset in the save file???? Or something else. On a quick look at my notes, at +00be you ar at the last byte of the merc exp, no?? Merc info in the save file header should start at +00af. First comes a flag register that only seems to use one flag anyway. Then are a bunch of stuff that appearantly someone else classify as ID, index to string table, diff level of merc and finally exp points. All these values comes fro a small merc structure on your character. That is what I have not checked out, so I really can't tell. I am currently sort of not with a computer (well, not a computer that is not very old) and thus can't either install the game or process the code files. Sorry. As soon as I get some time, I will try to take a new look.
There are three types of people in the world. Those who can count and those who can't.
Reply
#30
Oops .. sorry, i meant +00b3 .. it's the merc ID you mentioned.

--T
Reply
#31
Well, ATMA III seems to be coming along nicely. Hopefully, you'll have some time soon to check up on the merc ID data. Thanks.

--T
Reply
#32
hakai_no_tenshi,Apr 30 2003, 05:04 PM Wrote:Well, ATMA III seems to be coming along nicely. Hopefully, you'll have some time soon to check up on the merc ID data. Thanks.

--T
[right][snapback]8602[/snapback][/right]


Hi !!

I'm looking for source code for program like shadowmaster or jamella.. I'd like to do some kind of item editor, may be be character/item editor.. Well, but I don't actually now how the *.d2s files working and how they are encrypted.. Please if you can help me with this or if you show a fragment of code I'll be more than happy.

Thx a lot.. Namarïe
Reply
#33
Mortales_the_One,Mar 18 2005, 03:49 PM Wrote:Hi !!

I'm looking for source code for program like shadowmaster or jamella.. I'd like to do some kind of item editor, may be be character/item editor.. Well, but I don't actually now how the *.d2s files working and how they are encrypted.. Please if you can help me with this or if you show a fragment of code I'll be more than happy.&nbsp; &nbsp;

Thx a lot.. Namarïe
[right][snapback]71141[/snapback][/right]


Those programs you mention are very outdated and both save files and item data is stored and used extremely different in todays version of Diablo.

I sugest you go over to the Phrozen Keep. They have a thread on some of the structures in the save files. I don't think it is complete. I started out with some but never got arround to complete it, but I think some have added more info.

http://forums.d2mods.com/

http://phrozenkeep.it-point.com/forum/index.php
There are three types of people in the world. Those who can count and those who can't.
Reply
#34
The most complete listing for 1.10 can be found below. SVR (author of UdieToo) and I did some work together to compile the list.

http://home.stx.rr.com/svr/

--T
Reply
#35
hakai_no_tenshi,Mar 23 2005, 09:33 PM Wrote:The most complete listing for 1.10 can be found below. SVR (author of UdieToo) and I did some work together to compile the list.

http://home.stx.rr.com/svr/

--T
[right][snapback]71691[/snapback][/right]

Thanx a lot.. I'll check them out..
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)