• 0

    posted a message on Greetings
    Hello all,


    Firstly I'd like to commend you Kevin on creating this fantastic website; I know you'll be reading this.

    As for me, I've been a sporadic Battle.net user since 1998 and a Diablo II player since about 2001. I've had a persistant affinity with Diablo -- it's great game -- and one of few that has kept my interest over the years and will do so into the near forseeable future.

    In my parallel life I work as a system's programmer of which often manifests itself in the game's I play; if you've ever used the BnetDiagTool, D2Guard, or WC3Admin then you know who to thank.

    Some day I'll have a grand surprise for all you Diablo II faithfuls ... one day.
    Posted in: Introduction
  • 1

    posted a message on A bit of help from code experts
    You can contact me if you're in need of help with parsing .D2S files (or any other technical information regarding Diablo II for that matter)

    In regards to your specific issue, the bulk of the file is static except for the stats section and the items. The stats section is very straight-forward to parse; each entry begins with a 9-bit identifier followed by the value (of which's length can be gleamed from d2_patch.mpq/global/excel/ItemStatCost.txt)

    Below is taken from a project of mine that you may find helpful.

    /*
     * D2SDecode.cpp
     * =============
     * Version: 1.0
     * Author:  Matt.J
     *
     *
     * Description:
     *   Provides an interface for dealing with Diablo II save-files (.D2S)
     *
     *
     *********************************************************************************************************************/
    #include "D2SDecode.h"
    using namespace D2S;
    
    
    
    
    
    
    /////////////////////////////////////////////////////////////////////
    // Internal Functions
    /////////////////////////////////////////////////////////////////////
    Dword STDCALL ReadBits(Void* pStream, Dword dwOffset, Dword dwSize);
    
    
    
    
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // General Routines
    //
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    
    Void FASTCALL D2S::Decode(Game::Player* pPlayer, Byte* pD2S)
    {
        Dword dwOffset = 0;
        Dword dwStatId;
        Dword dwStatVal;
    
    
        // Save class.
        pPlayer->Character.wClass = ((D2SBase*) pD2S)->Class;
        pPlayer->Character.wLevel = ((D2SBase*) pD2S)->Level;
    
        // Traverse to the start of player stats.
        pD2S += sizeof(D2SBase);
        pD2S += ((D2SQuest*) pD2S)->wSize;
        pD2S += sizeof(D2SWaypoints);
        pD2S += ((D2SNPC*) pD2S)->wSize;
        pD2S += 2; // Skip 'gf'
    
        // Reset total stat count.
        pPlayer->Character.wStatsUsed = 0;
    
        // Decode stats and store in the given Player.
        while((dwStatId = ReadBits(pD2S, dwOffset, 9)) != 511)
        {
            // Read the stat value.
            dwStatVal = ReadBits(pD2S, (dwOffset += 9), SIT[dwStatId].Size);
            dwOffset += SIT[dwStatId].Size;
    
            // Adjust for Diablo II's bullshit.
            dwStatVal = (SIT[dwStatId].Div ? (dwStatVal / SIT[dwStatId].Div) : dwStatVal);
    
            // Save.
            switch(dwStatId)
            {
                case 0: pPlayer->Character.wStr = (Word) dwStatVal; break;
                case 1: pPlayer->Character.wNrg = (Word) dwStatVal; break;
                case 2: pPlayer->Character.wDex = (Word) dwStatVal; break;
                case 3: pPlayer->Character.wVit = (Word) dwStatVal; break;
                case 4: pPlayer->Character.wStats = (Word) dwStatVal; break;
                case 5: pPlayer->Character.wSkills = (Word) dwStatVal; break;
                case 6: pPlayer->Character.dwCurLife = dwStatVal; break;
                case 7: pPlayer->Character.dwMaxLife = dwStatVal; break;
                case 8: pPlayer->Character.dwCurMana = dwStatVal; break;
                case 9: pPlayer->Character.dwMaxMana = dwStatVal; break;
            }
    
            // Total stat counter.
            if(dwStatId < 4) pPlayer->Character.wStatsUsed += ((Word) dwStatVal);
        } dwOffset += 9;
    
        // Traverse to skills, stats assumed to be padded to the next byte.
        pD2S += (dwOffset / 8) + ((dwOffset % 8) ? 1 : 0);
    
        // Verify header integrity.
        if(((D2SSkills*) pD2S)->strTag[0] != 'i' || ((D2SSkills*) pD2S)->strTag[1] != 'f')
        {
            // ERROR:
            Out("[ERROR] Failed to find 'if' header.");
            return;
        }
    
        // Count total skill points used.
        pPlayer->Character.wSkillsUsed   = 0;
        pPlayer->Character.wHighestSkill = 0;
    
        for(Int i = 0; i < 30; i++) 
        {
            pPlayer->Character.wSkillsUsed += ((D2SSkills*) pD2S)->Level[i];
            pPlayer->Character.wHighestSkill = (((D2SSkills*) pD2S)->Level[i] > pPlayer->Character.wHighestSkill ? ((D2SSkills*) pD2S)->Level[i] : pPlayer->Character.wHighestSkill);
        }
    
        // Offset based on class.
        dwOffset = (BST[pPlayer->Character.wClass].Str + BST[pPlayer->Character.wClass].Dex + BST[pPlayer->Character.wClass].Vit + BST[pPlayer->Character.wClass].Nrg);
        pPlayer->Character.wStatsUsed = (Word) (pPlayer->Character.wStatsUsed > dwOffset ? (pPlayer->Character.wStatsUsed - dwOffset) : 0);
    }
    
    
    
    
    
    
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Helper Functions
    //
    ///////////////////////////////////////////////////////////////////////////////////////////////////
    
    NAKED Dword STDCALL ReadBits(Void* pStream, Dword dwOffset, Dword dwSize)
    {
        __asm
        {
            // PROLOGUE:
            push ebx
    
            // Calculate the bytewise offset, and remainder.
            mov eax, [esp+8]
            mov edx, [esp+12]
            mov ecx, 7
            and ecx, edx
            shr edx, 3
    
            // Read in the containing dword.
            mov ebx, [eax + edx]
    
            // Compensate for the offset.
            shr ebx, cl
    
            // Generate a mask for the significant bits of the desired sequence.
            mov ecx, [esp+16]
            mov eax, 1
            shl eax, cl
            sub eax, 1
    
            // Extract the result.
            and eax, ebx
    
            // EPILOGUE:
            pop ebx
            ret 12
        }
    
    }



    /*
     * D2SDecode.h
     * ===========
     * Version: 1.0
     * Author:  Matt.J
     *
     *
     * Description:
     *   D2SDecode module interface.
     *
     *
     *********************************************************************************************************************/
    #ifndef D2SDECODE_H
    #define D2SDECODE_H
    #include "Master.h"
    
    
    
    
    
    
    /////////////////////////////////////////////////////////////////////
    // D2SDecode Module
    /////////////////////////////////////////////////////////////////////
    
    namespace D2S
    {
        /////////////////////////////////////////////////////////////////////
        // D2S Structures
        /////////////////////////////////////////////////////////////////////
    
        struct D2SBase
        {
            Dword dwTag; /* 0x55AA55AA */
            Dword dwVersion;
            Dword dwSize;
            Dword dwCRC;
            Dword dwWeaponSet;
            Char  strName[16];
            Byte  Type;
            Byte  Title;
            Word  wUnknown1;
            Byte  Class;
            Word  wUnknown2;
            Byte  Level;
            Dword dwUnknown3;
            Dword dwTimeStamp;
            Dword dwUnknown4;
            Dword dwHotkey[16];
            Dword dwLeftSkill1;
            Dword dwRightSkill1;
            Dword dwLeftSkill2;
            Dword dwRightSkill2;
            Byte  Outfit[16];
            Byte  Colors[16];
            Byte  NTown;
            Byte  MTown;
            Byte  HTown;
            Dword dwMapSeed;
            Word  wUnknown5;
            Byte  bDeadMerc;
            Byte  Unknown6;
            Dword dwMercSeed;
            Word  wMercName;
            Word  wMercClass;
            Dword dwMercExp;
            Byte  Unknown[0x90];
        };
    
        struct D2SQuest
        {
            Char  strTag[4]; /* Woo! */
            Dword dwActs;
            Word  wSize;
        };
    
        struct D2SWaypoints
        {
            Char strTag[2]; /* WS */
            Byte Unknown[6];
            Dword dwData[3*6];
        };
    
        struct D2SNPC
        {
            Char strTag[2]; /* w4 */
            Word wSize;
        };
    
        struct D2SSkills
        {
            Char strTag[2]; /* if */
            Byte Level[30];
        };
    
        struct D2SItems
        {
            Char strTag[2]; /* JM */
            Word wItems;
        };
    
    
        /////////////////////////////////////////////////////////////////////
        // Stat Information Table
        /////////////////////////////////////////////////////////////////////
    
        CONST struct
        {
            Byte Size;
            Word Div;
            Char* pstrName;
        } SIT[] = 
        {
            10, 0, "Str",
            10, 0, "Nrg",
            10, 0, "Dex",
            10, 0, "Vit",
            10, 0, "Stat Points",
            8,  0, "Skill Points",
            21, 256, "CurLife",
            21, 256, "MaxLife",
            21, 256, "CurMana",
            21, 256, "MaxMana",
            21, 256, "CurStamina",
            21, 256, "MaxStamina",
            7,  0, "Level",
            32, 0, "Experience",
            25, 0, "Invo Gold",
            25, 0, "Stash Gold",
        };
    
    
        /////////////////////////////////////////////////////////////////////
        // Base Stat Table
        /////////////////////////////////////////////////////////////////////
    
        CONST struct _BST
        {
            Char* pstrClass;
            Byte Str;
            Byte Dex;
            Byte Vit;
            Byte Nrg;
            Byte Life;
            Byte Mana;
            Byte LifePerLvl;
            Byte ManaPerLvl;
            Byte LifePerVit;
            Byte ManaPerNrg;
        } BST[] =
        {
            /* Ama */ "Amazon",      20, 25, 20, 15, 50, 15, 8, 6, 12, 6,
            /* Sor */ "Sorceress",   10, 25, 10, 35, 40, 35, 4, 8, 8, 8,
            /* Nec */ "Necromancer", 15, 25, 15, 25, 45, 25, 6, 8, 8, 8,
            /* Pal */ "Paladin",     25, 20, 25, 15, 55, 15, 8, 6, 12, 6,
            /* Bar */ "Barbarian",   30, 20, 25, 10, 55, 10, 8, 2, 16, 4,
            /* Dru */ "Druid",       15, 20, 25, 20, 55, 20, 6, 8, 8, 8,
            /* Ass */ "Assassin",    20, 20, 20, 25, 50, 25, 8, 6, 12, 7,
        };
    
    
        /////////////////////////////////////////////////////////////////////
        // Exposed Routines
        /////////////////////////////////////////////////////////////////////
        EXTERN Void FASTCALL Decode(Game::Player* pPlayer, Byte* pD2S);
    }
    
    
    #endif
    Posted in: Diablo Tools
  • 0

    posted a message on Interest in native Linux client?
    Without fail the same tired old ignorant arguments from Linux users. Many, many years ago Linux users were rational, intelligent people comprised primarily of atleast mediocre programmers ... now that reputation has been irreversibly tainted by the clueless horde of morons that now constitute the significant portion of it's userbase.

    I think the saddest part of all is the motivation these people have for using Linux; frankly, in most cases it just seems like a vain attempt to be perceived as technically adapt by their peers which is derived from their ignorance about computers in general, lending to their perception that undertaking a convoluted (relative to an average user) task to render the same results somehow promotes them in the IT foodchain.

    Exhibit A:
    As for why windows sux

    1) Gotta pay a rediculous amount of money for it
    2) DRM
    3) Its windows
    4) Repeast step 3 an infinite amount of times.

    Exhibit B:
    I don't like windows for so many reason. My linux machine can't have virus so I don't need anti virus.
    [...]
    I don't like windows becaouse after I installed it I need to install anti virus, word processosor, pdf reader and so while linux come with it built in. I don't like windows because It take som much space and resources then linux.

    Exhibit C:
    The only people i've met that hates linux is people who can't operate it, they can't click and install every toolbar they see, can't get any virus etc.
    Posted in: General Discussion (non-Diablo)
  • 0

    posted a message on Interest in native Linux client?
    Without fail the same tired old ignorant arguments from Linux users. Many, many years ago Linux users were rational, intelligent people comprised primarily of atleast mediocre programmers ... now that reputation has been irreversibly tainted by the clueless horde of morons that now constitute the significant portion of it's userbase.

    I think the saddest part of all is the motivation these people have for using Linux; frankly, in most cases it just seems like a vain attempt to be perceived as technically adapt by their peers which is derived from their ignorance about computers in general, lending to their perception that undertaking a convoluted (relative to an average user) task to render the same results somehow promotes them in the IT foodchain.

    Exhibit A:
    As for why windows sux

    1) Gotta pay a rediculous amount of money for it
    2) DRM
    3) Its windows
    4) Repeast step 3 an infinite amount of times.


    Exhibit B:
    I don't like windows for so many reason. My linux machine can't have virus so I don't need anti virus.
    [...]
    I don't like windows becaouse after I installed it I need to install anti virus, word processosor, pdf reader and so while linux come with it built in. I don't like windows because It take som much space and resources then linux.


    Exhibit C:
    The only people i've met that hates linux is people who can't operate it, they can't click and install every toolbar they see, can't get any virus etc.
    Posted in: General Discussion (non-Diablo)
  • 0

    posted a message on D3 Programming Language?
    God Kev ... you need screening method for people who join this site; the stupidity is amazing.
    Posted in: Diablo III General Discussion
  • To post a comment, please or register a new account.