Alpaca - A Modern PlugY Fork

Discuss applications of D2Mod (v1.10), NefEx (v1.11+), and PlugY, and post suggestions for future plugins.

Moderators: Nefarius, Yohann, SVR

Post Reply
FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Alpaca - A Modern PlugY Fork

Post by FearedBliss » Thu Sep 14, 2017 3:59 pm

(Previously known as Gardenia, Now Alpaca)

Hello all,

I was gonna wait a bit longer before posting here about this but might as well do it now since I've cleaned up a bunch of stuff already. So basically I ended up forking the PlugY source code in order to do the following things:

1. Remove all features not really to infinite stash. The purpose is to have a small core that can be more easily maintained and ported to newer D2 versions.
2. Rewrite a lot of the core module loading code and offset/function pointer retrieval in order to facilitate the updating of the mod.
3. Use modern C++ practices.

I was able to remove a lot of preprocessor usages that were being used before (I still need to remove a lot more of them and move more of those preprocessor substitutions into the new object model) and implemented a proper object model for each of the libraries. Due to the new object model, it is much more easy to read the code and see what functions you would need to look for in the new version. I don't think that updating to 1.14 would be as difficult as before, and even if Blizzard merged all of the .dlls into the .exe, it might be easier providing that once you load up Game.exe and retrieve its base offset, every other offset that you would get would be based off of that one. With the new object model in place, the internal infrastructure can remain the same.

Example, if we wanted to get the D2GetDropRoom function pointer that is in the D2Common dll, we can easily do:

D2Common->D2GetDropRoom

If we wanted to get the D2LoadInventory function that is in D2Game, we could do:

D2Game->D2LoadInventory

All function pointers for the corresponding version are dynamically retrieved when the LibraryLoader first starts up (Before anything else).

You can find the source code here: https://github.com/fearedbliss/Alpaca

It is released under the GPLv3 since that's the license Yohann used. I'm not a pro at ASM so I'm still trying to learn ways to improve my reverse engineering skills and be able to better find offsets. At the moment the only idea I have is to use the latest 1.13d offsets and try to do a pattern match for each function that the app requires, that would probably only get us so far until something more than just updating the function pointer kicks in. If anyone wants to assist in updating it to 1.14, now would be the time to do so.

EDIT: I wasn't able to figure out how to get my Visual Studio's debugger to hit a breakpoint for the project, so I did all of this by just using the log file output. It was a pain but it's not the first time I've had to work on something without a debugger.

EDIT 2 (13/9/17): I figured out how to attach the debugger to the code. At the moment I'm able to debug anything after the DLL is loaded and called by D2 (attach to Game.exe). However, I'm still trying to get the debugger to work during the init stages of the DLL (Before D2 fully starts but the dll's init is called).. It might be as simple as attaching to the Gardenia.exe with specific settings (and of course having debug symbols).
Last edited by FearedBliss on Thu Oct 04, 2018 9:51 pm, edited 4 times in total.

User avatar
Medoway
Posts: 12
Joined: Sat Jun 14, 2008 11:00 am
Location: England

Re: Gardenia - PlugY fork

Post by Medoway » Thu Sep 14, 2017 6:15 pm

Sounds great! Thanks for all the hard work so far :D

User avatar
Necrolis
Site Admin
Throne
Posts: 8912
Joined: Sat Mar 25, 2006 1:22 pm
Location: The Land of the Dead
Contact:
South Africa

Hand-picked

Re: Gardenia - PlugY fork

Post by Necrolis » Thu Sep 14, 2017 7:46 pm

FearedBliss" wrote:EDIT 2 (13/9/17): I figured out how to attach the debugger to the code. At the moment I'm able to debug anything after the DLL is loaded and called by D2 (attach to Game.exe). However, I'm still trying to get the debugger to work during the init stages of the DLL (Before D2 fully starts but the dll's init is called).. It might be as simple as attaching to the Gardenia.exe with specific settings (and of course having debug symbols).
You are going to struggle a bit with this; I'd recommend using OllyDbg or x64DBG and using the break on new module loaded. Else an old trick that works, use MessageBoxA with MB_APPLMODAL from the DllMain function.
Image
Netiquette, Do you USE it?!?! | Nefarius' Fixed TXT Files | Terms Of Service
Blackened | Day of Death
"What was yours is mine. Your land, your people, and now your life." - Lim-Dul, the Necromancer
Judgement is Final, Death is Eternal

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Gardenia - PlugY fork

Post by FearedBliss » Tue Sep 19, 2017 1:15 pm

Thanks Necrolis for the tips. Slowing down the init so that I have enough time to attach to Game.exe before the DLL does its operations seems like the easiest way to go given the situation. Probably using a 10 second timer in DllMain would work as well, but I like your idea of using the modal dialog better. Also I do have olly and x32dbg on my machine so I will try the break on new module as well, I usually avoid having multiple debuggers or dissemblers attached but maybe it won't cause too much instability.

EDIT (19/9/17) - Necrolis, the messagebox tricked worked wonderfully. Now I can debug all of the dll code, thanks!

https://i.imgur.com/wiTMKV3.png

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Gardenia - PlugY fork

Post by FearedBliss » Thu Sep 21, 2017 5:30 pm

Alright guys, after a few weeks of hard work and more than 40 hours, I'm happy to announce version 1.00 of Gardenia. Hopefully my efforts to rewrite/restructure/and encapsulate all of the D2 functions in the mod will allow people to more easily maintain and upgrade the mod. There are too many changes to list, but you can read the github commit descriptions if interested, many of them have detailed explanations of what happened in that commit. Personally I only cared for supporting versions 1.09b and 1.13d so those are the only ones that I'm supporting in my branch. More information can be found in the read me.

Ultimately, moving to a 1 version system is probably best, I probably will end up doing that. People could always just stick to an older version to play on the older versions of D2. Supporting only one version will allow a lot of flexibility, increase maintainability, and reduce workload.

User avatar
thaison
Dark Alliance Beta Test
Crusader
Posts: 65
Joined: Fri Apr 03, 2015 11:59 am
Location: Viet Nam
Vietnam

Re: Gardenia - PlugY fork

Post by thaison » Wed Sep 12, 2018 3:48 pm

Project dead???

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Gardenia - PlugY fork

Post by FearedBliss » Tue Oct 02, 2018 6:00 pm

Hey Thaison,

I've re-uploaded the sources in case you wanna work on it.

- Jonathan

User avatar
thaison
Dark Alliance Beta Test
Crusader
Posts: 65
Joined: Fri Apr 03, 2015 11:59 am
Location: Viet Nam
Vietnam

Re: Gardenia - PlugY fork

Post by thaison » Thu Oct 04, 2018 1:44 am

Thanks :D

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Alpaca - A Modern PlugY Fork

Post by FearedBliss » Thu Oct 04, 2018 9:46 pm

The project is now called "Alpaca" and development will continue here:

https://github.com/fearedbliss/Alpaca

The following changes have been released with version 1.3.0
- Project Rebranded to Alpaca
- Deleted Extended Stats Page
- Removed Item Level and More
- Removed useless "Active Display Battle Net" message from log
- Cleaned up more files
- TCP/IP (LAN) is now fixed.
- Removed 51+ Useless Functions which should allow the mod to
more easily be ported to newer versions.
- More Offset Cleanups
Last edited by FearedBliss on Sat Oct 06, 2018 11:08 pm, edited 2 times in total.

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Alpaca - A Modern PlugY Fork

Post by FearedBliss » Sat Oct 06, 2018 11:08 pm

Alpaca 1.3.1 is now available.
- The binaries are now compiled in "Release" mode since most people
do not have the debugging DLLs necessary to run it in the "Debug" build.

- For your convenience, the Visual C++ 2017 Redistributable Setups are
included in the "Other" folder. If you see an error message on launch
about missing DLLs, try installing both of them, restarting your machine,
and trying again.

- The ability to disable the increased stash size and multi page functionality
has been removed. The entire point and sole purpose of the mod is to be an
infinite stash with increased space. It is pointless to turn these off, thus
removing these options to remove configuration clutter.

- There was a bug where the color of the version text would apply to both
the d2 version and the alpaca version. These colors can now be independently set.

- Some configuration options have been slightly renamed to improve readability,
and to know more easily what exactly is being affected:

ActiveVersionTextChange -> ActiveDiabloVersionTextChange
VersionText -> ActiveDiabloVersionText
ActivePrintVersion -> ActiveAlpacaPrintVersion
NEW: ColorOfDiabloVersionText
ColorOfVersionText -> ColorOfAlpacaVersionText

- The ability to disable command inputs in game has been removed.

- The documentation has been updated and clarified.

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Alpaca - A Modern PlugY Fork

Post by FearedBliss » Wed Oct 10, 2018 6:20 am

1.3.2 and 1.4.0 have been released. Patch notes accordingly:

1.4.0
- The parameter loading for Alpaca has been overhauled. There will now only
be one configuration file (Alpaca.ini) which will provide all exposed options.
AlpacaFixed.ini and AlpacaDefault.ini are no longer used and may be
deleted.

- The Alpaca.log has been significantly cleaned up.

- "MaxPersonnalPages" has been changed to "MaxPersonalPages"

- Logging will happen during Alpaca/Diablo II termination regardless of
whether active logging is enabled. This allows us to log any errors that
may happen when Diablo II is shutting down without affecting the performance
of the game during normal play.

- Adding gitattributes to fix CRLF endings during checkout. Alpaca will
fail to load if it uses Unix line endings and not CRLF.
1.3.2
- The "Personal Page" and "Shared Page" will now display the page number
surrounded by "[]" instead of the current degrees string.

- When a page has a custom name, the page number will now also be displayed
alongside. This allows one to easily be able to toggle and swap pages and
know exactly which page they are looking at.

- The following commands have been simplified:

/renamepage -> /rename
/setindex -> /set
/unsetindex -> /unset
/setmainindex -> /setmain
/insertpage -> /insert
/deletepage -> /delete

FearedBliss
Posts: 65
Joined: Sat Oct 16, 2010 4:29 pm

Re: Alpaca - A Modern PlugY Fork

Post by FearedBliss » Tue Oct 16, 2018 4:35 am

Below are all the updates published between 1.4.1 and 1.5.0:

1.5.0
Massive Stability Improvements and Cleanups

Alpaca.dll
=============

- Localization has been removed, and English will be the only language displayed.
However this isn't really a big deal with Alpaca since Alpaca only kept the core
part of PlugY and thus there really aren't many strings to localize either way (about 12).

- More function and code removal

- Custom Library Support has been removed.

- Fixed a bug where Diablo II would load fine but would crash when entering a game while
running in Windows 7 Compatibility Mode (on Windows 10). It would run fine if you weren't
in compatibility mode on Windows 10. It seems after Windows 8, Microsoft changed some
internal behavior related to memory/strings.

As a result of the above bug, I tested that the following combinations
load the game fine, and that your character also loaded and that you were
able to use the buttons and commands properly (Aggresive Smoke Test):

Alpaca.[exe/dll]
=============

Admin Mode
-----------
Windows 95
Windows 98 / Windows Me
Windows XP (SP2)
Windows XP (SP3)
Windows Vista
Windows Vista (SP1)
Windows Vista (SP2)
Windows 7
Windows 8
Windows 10

Non-Admin Mode
--------------
Windows 95
Windows 98 / Windows Me
Windows Vista
Windows Vista (SP1)
Windows Vista (SP2)
Windows 7
Windows 8
Windows 10

Alpaca.exe
=============

- More debugging statements have been added to Alpaca.exe's "Read process memory failed."
[2] and [4] messages. When this happens again, we will be able to see exactly what bytes
and addresses are mismatching.

- Added numbers to some additional assertions messages.

- An experimental fix for the read process memory failed [2] / [4] is now active.
If the fix doesn't work, it will gracefully fall back to the old behavior the error
output.

Alpaca.ini
=============

- The following parameters have been removed:

Library
DllToLoad
DllToLoad2
ActiveCheckMemory

"Library" option has been removed since loading Alpaca.dll is given and the only dll supported.

ActiveCheckMemory has been removed. If you get a problem related to this, then it already means
something is wrong and your environment/configuration should be inspected (or a bug report opened
if it is an Alpaca bug).

- The following parameters have been renamed:

NbPagesPerIndex -> NumberOfPagesPerIndex
NbPagesPerIndex2 -> NumberOfPagesPerIndexWhenShiftPressed
1.4.3
Stability Updates and Feature Additions

- Fixed a bug where toggling a stash to a stash that is surrounded by empty
stashes would cause an access violation and crash the program.

- The game will now remember the last page you selected across stash
types for the duration of the game session.

- New command implemented: /page <page #>

This command will take you to the corresponding page.
1.4.2
Access violations related to loading custom files at launch should now be fixed

The custom file loading function (Which is responsible for loading
LocalizedStrings.ini) has been completely rewritten. It no longer uses the
"InstallPath" directory which was causing an access violation for some users
during startup. This was because Diablo II automatically sets the InstallPath
during Diablo II Launch, and also every time you join/exit a game. The install
path location in some situations doesn't seem to be correct and thus
causes Alpaca to fail to find its own Localization file. With this change,
from my experience with working with this code base, there are no more registry
keys that are being used, with the exception of the "Save Path" key. This is needed
since we need to know where the save directory is so that we can place the shared
stash there and any other character data manipulation stuff. If there
are any errors related to registry keys or if anyone scans the code and
finds any usages of registry keys other than the "Save Path" key, please
let me know.
1.4.1
Lots of improvements, cleanups, stability throughout the codebase.

Alpaca.ini

- The "ActiveSharedStash" and "ActiveSharedGold" options have been consolidated into "SoloSelfFound".

Alpaca.exe

- No longer uses the "InstallPath" registry key at all. The directory where
Alpaca.exe is located should be the same directory that Game.exe is in
(Your Diablo II Root Directory). This should alleviate some specific problems
that some people were having when their "InstallPath" wasn't set.

- Cleaned/Partially re-wrote the main initialization function.

- The program was still looking for "ActiveWindowed" in Alpaca.ini,
this option no longer exists in the ini, thus it now doesn't check
for this.

- Alpaca no longer launches the game "normally" if Alpaca failed.
Thus if an error with Alpaca exists, it will definitely terminate
and let you know immediately, instead of launching without Alpaca
and wasting your time. Launching normally means that the game would
be launched as if you had ran Game.exe directly with no mods.

- Will now check for version incompatibility at an earlier stage.
No point to keep processing stuff it it isn't compatible.

- When a "Read process memory failed" error occurs, there will now
be a number next to it that will help with figuring out at which
stage the memory exception occurred. Hopefully this can help me
narrow down the root cause of this issue.

Alpaca.dll

- Removed remnant D2Mod support code since this is a 1.09 mod and D2Mod is a 1.10 plugin system.
- When in Solo Self Found mode, placing your cursor above the empty Shared Stash Button will
display the following tooltip for the appropriate language: "Solo Self Found is enabled. Good Luck!".

Post Reply

Return to “PlugY|NefEx|D2Mod”