Latest Diablo 3 News
DiabloWiki Updates
Support the site! Become a Diablo: IncGamers PAL - Remove ads and more!

Cactus - A Modern Diablo II Version Switcher [C#/.NET]

Discussion in 'Diablo 2 Community Forum' started by fearedbliss, May 13, 2018.

  1. fearedbliss

    fearedbliss IncGamers Member

    Joined:
    Jun 29, 2011
    Messages:
    398
    Likes Received:
    111
    Trophy Points:
    157
    Hello all,

    A few days ago I posted a long post on reddit describing the reasons why I want to rewrite my "Bliss Version Switcher" Diablo II application (Which you can read here). With this said, I'll be spending the next few weeks completely rewritting BVS from scratch in C#/.NET. This new design will have a clean and proper internal architecture which will use the following:

    - Dependency Injection
    - Inversion of Control
    - MVVM Architecture Design
    - Unit Tests for most/all non-view related components.

    (Castle Windsor, MVVM Light, Moq, and MSTest are being used to accomplish the above).

    So far I have most of the initial core infrastructure pieces in place, and the design/code will continue to evolve as the weeks ago by. I'm pretty excited about this since it's already better architecturally than the previous BVS/Java based application. Being able to run this application as an administrator directly from windows, and also being able to directly communicate with the registry, are already both a huge win.

    The application currently looks like this (I am using the Windows XP Luna theme that Microsoft provides for modern desktop applications - but it can easily be changed in a second since it is just a skin):

    [​IMG]

    and the desktop icon looks like this:

    [​IMG]

    I'll update this page once the application is close to being released/or when released.

    Cactus will be released under the Apache License 2.0 and development can be followed here:

    https://github.com/fearedbliss/Cactus

    - Jonathan
     
  2. Noodle

    Noodle Moderator

    Joined:
    Jul 18, 2003
    Messages:
    9,150
    Likes Received:
    510
    Trophy Points:
    222
  3. GalaXyHaXz

    GalaXyHaXz IncGamers Member

    Joined:
    Mar 16, 2011
    Messages:
    720
    Likes Received:
    565
    Trophy Points:
    160
    Too lazy to do a pull request, so I'll put it here before you get to far along with Cactus.

    Perhaps a good way to keep things more maintainable would be to make the version system dynamic. You can get the version of the game from game.exe as follows:
    Code:
    /* 1024 entries, 2 bytes each. first is game version, second is trailing letter stored as number */
    char VersionList[1024][2];
    /* the first free entry in the above table */
    static int gnVersionEntry = 0;
    
    void GetVersion(int nEntry, char *dest) // prints entry in version table, i.e. '1.09d' or '1.12'
    {
       sprintf(dest, "1.%02d%c", VersionList[nEntry][0], VersionList[nEntry][1]+'a');
    }
    
    void AddVersion(char *GameExePath)
    {
        int nLen;
        void *ptr;
        unsigned int uBytes;
        DWORD dwHandle;
        VS_FIXEDFILEINFO *vinfo;
    
       nLen = GetFileVersionInfoSizeA(GameExePath, &dwHandle);
       if ( nLen )
       {
           ptr = malloc(nLen);
           if ( GetFileVersionInfoA(GameExePath, 0, nLen, ptr)
             && VerQueryValueA(ptr, "\\", &vinfo, &uBytes) )
           {
               VersionList[gnVersionEntry][0] = (vinfo->dwProductVersionLS >> 16) & 0xFFFF; // low version, e.g. '9', '14'
               VersionList[gnVersionEntry][1] = (vinfo->dwProductVersionLS >> 0 ) & 0xFFFF; // trail byte, e.g. '0', '1' (a/b/c/d)
               gnVersionEntry++;
           }
           free(ptr);
       }
    }
    
    void BuildVersionList()
    {
       int i;
       char szPath[MAX_PATH];
    
       for(i = 0; i < 1024; i++)
       {
           // code to parse and read all directories in version folder here
           // returns current dir as a string (BVS/Version/1.xx)
           // ReadNextDir(szPath);
           AddVersion(szPath);
       }
    }
    
    Basically instead of having to add every version manually and then add code to handle each version, you can query all versions installed to the subfolder. This would be versatile and support all mods as well. You can also get rid of the version-specific Patch_D2.mpq checking code, and copy all files from the corresponding directory instead.

    Users would be able to, for example, drag and drop the folders "1.06" and "MedianXL v2.3" into their version folder, they will be scanned and added to the versions list with the path as prefix to the version. (folder name/game.exe version)
    "My_classic_folder/1.06"
    "1.07/1.07"
    "MedianXL v2.3/1.10f"
    "fix_this_$#@#/1.13d"


    Code for handling specific versions can be handled by querying the low byte from the version table.
     
  4. fearedbliss

    fearedbliss IncGamers Member

    Joined:
    Jun 29, 2011
    Messages:
    398
    Likes Received:
    111
    Trophy Points:
    157
    Auto scanning directories and supporting mods to files that aren't provided by Blizzard is not something I want to pursue. For Cactus, only core DLL files in the original version are supported.

    Also, this code is C code and I would need to not only port it over to C#, but it's making system calls that will need to be mocked or wrapped around in order to unit test the consuming code. The assumptions of the designs we are pursuing are significantly different as well. I want a reproducible, consistent, and specific list of files to be generated and switched. Letting the user provide their own directories and files adds a level of complexity and unpredictability I don't want to handle. Plus I would still need to keep a list of versions internally because once I queried the version from the exe, I would need to see what files are supported for that version.
     
    Last edited: May 14, 2018 at 11:30 PM
  5. GalaXyHaXz

    GalaXyHaXz IncGamers Member

    Joined:
    Mar 16, 2011
    Messages:
    720
    Likes Received:
    565
    Trophy Points:
    160
    It's written in C because I'm not too familiar with .Net, but it's a rough sample of the concept. If you wanted to keep a list of files for specific versions, that could still be achieved. All you'd have to do after querying the version list is check the number to see what category it falls under for switching. The advantage is that it auto-checks each folder in the version folder and adds them for you, and can then categorically organize them with the folder prefix. You can also check whether the game.exe is classic or expansion to further organize it. This makes it easier for both you and the end users.
     
  6. fearedbliss

    fearedbliss IncGamers Member

    Joined:
    Jun 29, 2011
    Messages:
    398
    Likes Received:
    111
    Trophy Points:
    157
    Hello all,

    Almost a week ago I announced that I would be rewritting my Bliss Version Switcher application. I'm proud to announce the first alpha version of it which I will label it 0.0.1. All of the core features are working (Exception for the Up and Down buttons in the main UI (These are just for positioning the entries).

    There is still a lot more work to do to bring it to a more polished state, but the application is more than working atm. Make sure to backup your characters before trying this since it's experimental and there probably are weird edge cases/bugs.

    You can view all of the code here:

    https://github.com/fearedbliss/Cactus

    and directly download it here:

    https://github.com/fearedbliss/Cactus/archive/next.zip

    The .exe is located in the "Release" folder. Please follow the instructions in the README for the initial setup since that's usually the most tricky part.

    You can download my "Bliss Complete Collection" package that contains all of the version files. Due note, that to play versions before 1.12, you will need a legal ISO or a legal disc. There are also graphical setting changes that you may need to change depending on the version of Windows you are running. These are _not_ issues with Cactus, but rather the game is just that old.

    Current UI:

    [​IMG]
    [​IMG]
    [​IMG]

    - Jonathan
     
    Fruit and LozHinge the Unhinged like this.
  7. fearedbliss

    fearedbliss IncGamers Member

    Joined:
    Jun 29, 2011
    Messages:
    398
    Likes Received:
    111
    Trophy Points:
    157
    Version 0.0.4 is now available. Yes I skipped 3 minor versions since it's that many changes.

    Download
     
  8. fearedbliss

    fearedbliss IncGamers Member

    Joined:
    Jun 29, 2011
    Messages:
    398
    Likes Received:
    111
    Trophy Points:
    157
    Hello folks,

    I've finally been able to do a lot of testing, review the code, and implement more changes to finally consider Cactus as feature complete. Instead of making a 0.0.5 release, I'll release this as 1.0.0 and any future versions will just be maintenance, bug fixes, and maybe some slight UI improvements. But as I said, the application is feature complete and it is capable of completely replacing Bliss Version Switcher out of the box. Cactus and BVS both use the exact same Entries.json file with the same format, thus Cactus is a drop in replacement to BVS. I hope you guys enjoy this release as much as I will enjoy using it and enjoyed developing it.

    1.0.0 Changes

    Project Page

    Download Here

     
    Last edited: May 20, 2018 at 5:17 AM

Share This Page