diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f6e3c2d --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# gitignore for C++ +# Compiled Object files +*.slo +*.lo +*.o + +# Compiled Dynamic libraries +*.so +*.dylib + +# Compiled Static libraries +*.lai +*.la +*.a + +# Visual Studio Files +Debug +Release +*.suo +*.csproj.user +*.vbproj.user +ipch +*sdf +.vs +*.aps diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..f5e778e --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 nyfrk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Lib/LICENSE.md b/Lib/LICENSE.md new file mode 100644 index 0000000..f5e778e --- /dev/null +++ b/Lib/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 nyfrk + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Lib/README.md b/Lib/README.md new file mode 100644 index 0000000..b2064b7 --- /dev/null +++ b/Lib/README.md @@ -0,0 +1,11 @@ +# hLib: A Library for external Cheats + +Revision: c50b3bb11e014c84813e2409dab999f4eda8e097 +Date: 04.07.2020 15:50:40 +Toolset: v141_xp + +Flavors: +* static, x86, release: hlib.lib +* static, x86, debug: hlib-d.lib + +License: [MIT](LICENSE.md) diff --git a/Lib/hLib-d.lib b/Lib/hLib-d.lib new file mode 100644 index 0000000..d69986e Binary files /dev/null and b/Lib/hLib-d.lib differ diff --git a/Lib/hLib.lib b/Lib/hLib.lib new file mode 100644 index 0000000..065a17d Binary files /dev/null and b/Lib/hLib.lib differ diff --git a/Lib/hlib.h b/Lib/hlib.h new file mode 100644 index 0000000..05c6ae1 --- /dev/null +++ b/Lib/hlib.h @@ -0,0 +1,310 @@ +/////////////////////////////////////////////////////////////////////////////// +// MIT License +// +// Copyright (c) 2020 nyfrk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +/////////////////////////////////////////////////////////////////////////////// +// +/////////////////////////////////////////////////////////////////////////////// +// Quick and dirty library for external hacks. No additional dependencies needed. +/////////////////////////////////////////////////////////////////////////////// +// +// +#ifndef HLIB_H +#define HLIB_H + +#include "windows.h" +#include +#include + +namespace hlib { + + typedef void* HMEMORYMODULE; + + /** + * Adjust token priviliges such that this process is allowed to debug. + */ + void SetDebugPrivileges(void); + + /** + * Get a process handle. This will request the following rights: + * PROCESS_SUSPEND_RESUME, PROCESS_VM_OPERATION, PROCESS_VM_READ, + * PROCESS_VM_WRITE, PROCESS_QUERY_INFORMATION, PROCESS_CREATE_THREAD, + * PROCESS_TERMINATE, SYNCHRONIZE + * + * @param dwId The ID of the process. + * @return HANDLE of the process. Call CloseHandle() for it when done. + */ + HANDLE GetProcessHandleById(DWORD dwId); + + /** + * Get a process handle. This will request the following rights: + * PROCESS_SUSPEND_RESUME, PROCESS_VM_OPERATION, PROCESS_VM_READ, + * PROCESS_VM_WRITE, PROCESS_QUERY_INFORMATION, PROCESS_CREATE_THREAD, + * PROCESS_TERMINATE, SYNCHRONIZE + * + * @param comp The name of the process. Eg "GTA5.exe". + * @param hMod An optional pointer that is to receive the base address of the game. + * @return HANDLE of the process. Call CloseHandle() for it when done. + */ + HANDLE GetProcessHandleByName(const char* comp, HMODULE* hMod = NULL); + + /** + * Get a process handle. This will request the following rights: + * PROCESS_SUSPEND_RESUME, PROCESS_VM_OPERATION, PROCESS_VM_READ, + * PROCESS_VM_WRITE, PROCESS_QUERY_INFORMATION, PROCESS_CREATE_THREAD, + * PROCESS_TERMINATE, SYNCHRONIZE + * + * @param comp The name of the processes window. Eg "Grand Theft Auto V". + * @param hMod An optional pointer that is to receive the base address of the game. + * @return HANDLE of the process. Call CloseHandle() for it when done. + */ + HANDLE GetProcessHandleByWindowName(const char* comp, HMODULE* hMod = NULL); + + /** + * Find the HMODULE of a DLL in a remote process. + * + * @param hProcess The handle of the process. + * @param dllname The name of the DLL. Eg. "kernel32". This is passed to LoadLibraryA. + * @return The HMODULE (base address) of the DLL in the remote process. Or NULL if the + * DLL cannot be found. + */ + HMODULE SearchDllInProcess(HANDLE, const char*); + + /** + * Inject a DLL into a remote process. + * + * @param hProcess The handle of the process. + * @param dllname The name of the DLL. Eg. "kernel32". This is passed to LoadLibraryA. + * @param hModule A pointer to a HMODULE to receive the HMODULE of the injected DLL. + * @return if successfull true, otherwise false. + */ + bool InjectDLL(HANDLE hProcess, const char* dllname, HMODULE* hModule); + + /** + * Inject a DLL into a remote process using manual memory mapping. (Load a DLL from + * memory) + * + * @param hProcess The handle of the process. + * @param data A pointer to the DLL in memory. + * @param size The size of the DLL in bytes. + * @param hMod A pointer to a HMEMORYMODULE to receive the HMEMORYMODULE of the injected DLL. + * Note that since windows is not aware of this DLL many functions that expect a + * HMODULE do not work. + * @return if successfull true, otherwise false. + */ + bool InjectDLL(HANDLE hProcess, const void* data, UINT64 size, HMEMORYMODULE* hMod); + + /** + * Call a function of a DLL in a remote process. + * + * @param hProcess The handle of the process. + * @param dllname The name of the DLL. Eg. "kernel32". + * @param func The name of the function to call. Eg. "GetModuleHandleA" + * @param params A structure that is copied to the target processes virtual memory. + * The pointer of this memory is passed as argument to the target function. + * @param szParams How many bytes of params to copy to the target process. If it is 0 the params argument + * will be pushed directly onto the stack. + * @return The return value of the executed function is returned or 0 is an error occured. + * + * Note: To speed up performance make sure the DLL is loaded by this process. Otherwise the + * DLL will be loaded and unloaded after the function has been called. + */ + UINT64 CallProcessDLL(HANDLE hProcess, const char* dllname, const char* func, const void* params, int szParams); + + /** + * Call a function of a DLL in a remote process. + * + * @param hProcess The handle of the process. + * @param hMod The HMODULE of the DLL in the target process (ie the base address). + * @param dllname The name of the DLL. Eg. "kernel32". + * @param func The name of the function to call. Eg. "GetModuleHandleA" + * @param params A structure that is copied to the target processes virtual memory. + * The pointer of this memory is passed as argument to the target function. + * @param szParams How many bytes of params to copy to the target process. If it is 0 the params argument + * will be pushed directly onto the stack. + * @return The return value of the executed function is returned or 0 is an error occured. + * + * Note: To speed up performance make sure the DLL is loaded by this process. Otherwise the + * DLL will be loaded and unloaded after the function has been called. + */ + UINT64 CallProcessDLL(HANDLE hProcess, HMODULE hMod, const char* dllname, const char* func, const void* params, int szParams); + + /** + * Call a function of a DLL in a remote process. + * + * @param hProcess The handle of the process. + * @param hMod The HMODULE of the DLL in the target process (ie the base address). + * @param myMod The HMODULE of the DLL in the current process (ie the base address). Eg GetModuleHandle("kernel32"). + * @param func The name of the function to call. Eg. "GetModuleHandleA" + * @param params A structure that is copied to the target processes virtual memory. + * The pointer of this memory is passed as argument to the target function. + * @param szParams How many bytes of params to copy to the target process. If it is 0 the params argument + * will be pushed directly onto the stack. + * @return The return value of the executed function is returned or 0 is an error occured. + * + * Note: To speed up performance make sure the DLL is loaded by this process. Otherwise the + * DLL will be loaded and unloaded after the function has been called. + */ + UINT64 CallProcessDLL(HANDLE hProcess, HMODULE hMod, HMODULE myMod, const char* func, const void* params, int szParams); + + class StringPattern { + public: + StringPattern(const std::string pattern); + StringPattern(const StringPattern& obj); + const char* getMask() const; + const unsigned char* getPattern() const; + unsigned int len() const; + private: + std::string m_mask; // x for match, ? for ignore + std::vector m_pattern; + }; + + /** + * Find a pattern in process memory. The address of the first match will be returned. + * + * @param hProcess The handle of the process. + * @param startAddr The first address to start searching + * @param pattern The pattern. Eg. StringPattern("12 34 ? 1F C3"). Note that the pattern must not start with a wildcard. + * @param endAddr Do not search at addresses greater or equal to the endAddr. (endAddr is excluded) + */ + UINT64 FindPattern(HANDLE hProcess, UINT64 startAddr, const StringPattern& pattern, UINT64 endAddr = -1); + + /** + * Find a pattern in process memory. The address of the first match will be returned. + * + * @param hProcess The handle of the process. + * @param startAddr The first address to start searching + * @param pattern The pattern. Eg. "\x12\x34\x00\x1F\xC3") + * @param mask The mask. Eg. "xx?xx". Note that the mask must not start with a wildcard. + * @param len The length of the pattern in bytes. + * @param endAddr Do not search at addresses greater or equal to the endAddr. (endAddr is excluded) + */ + UINT64 FindPattern(HANDLE hProcess, UINT64 startAddr, const unsigned char* pattern, const char* mask, unsigned int len, UINT64 endAddr = -1); + + /** + * Undocumented Windows functions that allow to suspend and resume processes + * and all their threads. Make sure the debug priviliges are set by calling + * SetDebugPrivileges(). Make sure the HANDLE has the PROCESS_SUSPEND_RESUME + * Right. + * Also make sure ntdll.dll is loaded. + * + * @param ProcessHandle The handle of the process. + */ + typedef LONG(NTAPI* NtSuspendProcessFunc)(IN HANDLE ProcessHandle); + typedef LONG(NTAPI* NtResumeProcessFunc)(IN HANDLE ProcessHandle); + extern NtSuspendProcessFunc NtSuspendProcess; + extern NtResumeProcessFunc NtResumeProcess; + + + + + /////////////////////////////////////////////////////////////////////////////// + // Quick and dirty byte patching class that keeps track of the patched address. + // You can implement a custom patch by inheriting from AbstractPatch. + // Or include the template to create easy static patches + /////////////////////////////////////////////////////////////////////////////// + class AbstractPatch { + public: + AbstractPatch(); + AbstractPatch(UINT64 addr, size_t len); + AbstractPatch(UINT64 addr, size_t len, const void* orig); + AbstractPatch(const AbstractPatch&) = delete; + AbstractPatch& operator=(const AbstractPatch&) = delete; + AbstractPatch(AbstractPatch&&); + AbstractPatch& operator=(AbstractPatch&&); + ~AbstractPatch(); + + bool patch(HANDLE hProcess); + bool unpatch(HANDLE hProcess); + + // Call this to read the memory and check if the patch is applied. Returns + // false if the state is broken (neither applied nor the expected state) + bool update(HANDLE hProcess); + + bool isPatched() const; + + UINT64 getAddress() const; + virtual bool setAddress(UINT64 addr); // change address if patch is not applied yet + + protected: + virtual bool applyPatch(HANDLE hProcess) = 0; + virtual bool cmpPatch(const void* mem) = 0; + + UINT64 m_addr; + bool m_isStrict; + bool m_isPatched; + void* m_orig; + size_t m_len; + }; + + class Patch : public AbstractPatch { + public: + struct BYTE5 { const BYTE buf[5]; }; + Patch(); + Patch(UINT64 address, const void* patch, size_t len); + Patch(UINT64 address, const void* patch, const void* expectedOrig, size_t len); + Patch(UINT64 address, DWORD patch); // patch 4 bytes + Patch(UINT64 address, DWORD patch, DWORD expectedOrig); + Patch(UINT64 address, BYTE patch); // patch 1 bytes + Patch(UINT64 address, BYTE patch, BYTE expected); // patch 1 bytes + Patch(UINT64 address, BYTE bPatch, DWORD dwPatch, size_t nops = 0); // patch 5 bytes and some nops (0x90) after these 5 bytes + Patch(UINT64 address, BYTE bPatch, DWORD dwPatch, const BYTE5* expected, size_t nops = 0); + + ~Patch(); + + Patch(Patch&&); + Patch& operator=(Patch&&); + + protected: + virtual bool applyPatch(HANDLE hProcess); + virtual bool cmpPatch(const void* mem); + void* m_patch; + }; + class JmpPatch : public Patch { + public: + JmpPatch(); + JmpPatch(UINT64 address, DWORD jumpTargetAddr, size_t nops = 0); + JmpPatch(UINT64 address, DWORD jumpTargetAddr, const BYTE5* expectedOrig, size_t nops = 0); + virtual bool setAddress(UINT64 addr); // change address if patch is not applied yet + bool setDestination(UINT64 dest); // change destination if patch is not applied yet + protected: + JmpPatch(BYTE opcode, UINT64 address, DWORD jumpTargetAddr, size_t nops); + JmpPatch(BYTE opcode, UINT64 address, DWORD jumpTargetAddr, const BYTE5* expectedOrig, size_t nops); + }; + class CallPatch : public JmpPatch { + public: + CallPatch(); + CallPatch(UINT64 address, DWORD jumpTargetAddr, size_t nops = 0); + CallPatch(UINT64 address, DWORD jumpTargetAddr, const BYTE5* expectedOrig, size_t nops = 0); + }; + class NopPatch : public AbstractPatch { + public: + NopPatch(); + NopPatch(UINT64 address, size_t len = 1); + NopPatch(UINT64 address, const void* expected, size_t len); + protected: + virtual bool applyPatch(HANDLE hProcess); + virtual bool cmpPatch(const void* mem); + }; + +} + +#endif diff --git a/README.md b/README.md new file mode 100644 index 0000000..c312b9c --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# The Settlers 4: Terrain Texture Changer + +This ASI mod will make every map appear in the new world textures - even the old maps. + +![demo](demo.gif) + +There is a [German translation for this README](README_DE.md). Please note that it may be outdated. + +This mod is an ASI repack of the well known Cybertom's Texture Swapper. Though the ASI mod works slightly different and does not require you to alter any game files. + +## Features + +* Force the new world terrain textures on every map you play! +* No game files are altered on your hard drive. +* Compatibility: Works with the Gold Edition and the History Edition of The Settlers 4 and even with the map editors of both versions. +* Multiplayer interoperability: You can play multiplayer with participants that do not use this mod. +* Open Source: Most parts of the project including patterns, offsets, enums and structs are open source! + + + +## How to use + +You need an ASI Loader to use this mod. I recommend [The Settlers 4: ASI Loader](https://github.com/nyfrk/Settlers4-ASI-Loader) as it works nicely with the Gold and History Edition of The Settlers 4 and does not require any configuration. If you already have an ASI loader installed skip the first steps and jump directly to step 5. + +1. Navigate to your installation directory of your game. +2. Find a file named `binkw32.dll` and rename it to `binkw32Hooked.dll`. (For the Gold Edition it is in a subdirectory named `Exe`) +3. [Download a release of the Settlers 4 ASI Loader](https://github.com/nyfrk/Settlers4-ASI-Loader/releases) and unpack the `binkw32.dll` to the very same directory. +4. Create a `plugins` directory next to your `S4_Main.exe` +5. [Download a release of the Settlers 4 Terrain Texture Changer Mod](https://github.com/nyfrk/Settlers4-TextureChanger/releases). Unpack the `S4_TerrainTexturesChanger.asi` to the `plugins` directory. +6. Start the game. The mod will load automatically. + +To uninstall the mod remove `S4_TerrainTexturesChanger.asi` from the `plugins` directory. If you do not want to use the ASI loader anymore just reverse the described steps. + + + +## Known Problems + +* You must have a game version that has the new world textures included. You to have at least the add-on *The Settlers IV: The New World* or the History Edition of the game. + + + +## Issues and Questions + +The project uses the Github Issue tracker. Please open a ticket [here](https://github.com/nyfrk/Settlers4-TextureChanger/issues). + + + +## Contribute + +The official repository of this project is available at https://github.com/nyfrk/Settlers4-TextureChanger. You can contribute in the following ways: + +* Answer questions +* Submit bugs or help to verify them +* Review code and test the proposed fixes +* Submit pull requests + +#### Compile it yourself + +Download Visual Studio 2017 or 2019 with the C++ toolchain. The project is configured to build it with the Windows XP compatible **v141_xp** toolchain. However, you should be able to change the toolchain to whatever you like. No additional libraries are required so it should compile out of the box. + +#### Developers + +The *New World* textures are packed in the GFX/41.\* files. The classic textures are stored in the GFX/2.\* files. This mod will simply redirect all file access from the later to the former thus tricking the game into always loading the new world textures even if it wanted to load the classic texture pack. If you do not have *The Settlers IV: The New World* add on installed, the game will not work as it will not be able to find the GFX/41.\* files. In that case ask a friend that has the expansion pack to send you a copy of the GFX/41.\* files. The mod should also work with the map editors since it hooks the Windows natives for opening files. + +#### Future Work + +* Allow players to force New World Maps to use the old textures +* Allow for more customization of the terrain textures (ie user defined texture packs) + + + +## License + +The project is licensed under the [MIT](LICENSE.md) License. + + + +## Acknowledgments + +Special thanks to Cybertom for the original tool from 2003 (though I could not find any source code) and to [Settlermania](https://settlermania.wordpress.com/2013/07/11/texture-swapper-for-tropical-textures/) for conserving this tool to the public even after the initial website went offline. \ No newline at end of file diff --git a/README_DE.md b/README_DE.md new file mode 100644 index 0000000..f2a9c05 --- /dev/null +++ b/README_DE.md @@ -0,0 +1,83 @@ +# Siedler 4: Texturenwechsler ASI Mod + +Mit dem Add-On *The Settlers IV: The New World* wurde ein neues Terraintexturenpack dem Spiel hinzugefügt. Mit diesem Mod wird es in jeder Karte verwendet - auch in den klassischen Karten, die eigentlich gar nicht dafür vorgesehen sind. + +![demo](demo.gif) + +Für dieses README gibt es eine [englische Version](README.md). Bitte beachte, dass die deutsche Übersetzung ggf. veraltet sein kann. + +Diese Mod ist ein ASI-Repack des bekannten Texturenwechslers von Cybertom. Allerdings funktioniert die ASI-Mod etwas anders und erfordert daher keine Änderungen an den Spieldateien. + + + +## Features + +* Erzwinge die *Neue Welt* Texturen auf jeder Karte, die Du spielst! +* Es werden keine Spieldateien verändert. + +* Kompatibilität: Die Mod läuft sowohl mit der Gold Edition als auch der History Edition von Die Siedler 4 und sogar mit den Karteneditoren beider Editionen. +* Mehrspieler-Interoperabilität: Du kannst im Mehrspieler-Modus mit Teilnehmern spielen, die diesen Mod nicht verwenden. +* Open Source: Die meisten Teile des Projekts, einschließlich Muster, Offsets, Enums und Structs sind quelloffen! + + + +## Installation + +Du benötigst einen ASI Loader um die Mod zu nutzen. Ich empfehle den [The Settlers 4: ASI Loader](https://github.com/nyfrk/Settlers4-ASI-Loader), da er gut mit der Gold und History Edition von Die Siedler 4 funktioniert und keinerlei Konfiguration erfordert. Wenn Du bereits einen ASI-Loader installiert hast, überspringe die ersten Schritte und fahre direkt mit Schritt 5 fort. + +1. Navigiere zum Installationsverzeichnis des Spiels. +2. Suche eine Datei namens `binkw32.dll` und benennen sie in `binkw32Hooked.dll` um. (Bei der Gold Edition befindet sie sich in einem Unterverzeichnis namens `Exe`) +3. Lade ein [Release des ASI Loaders](https://github.com/nyfrk/Settlers4-ASI-Loader/releases) herunter und entpacke die `binkw32.dll` in dasselbe Verzeichnis. +4. Erstellen ein Verzeichnis namens `plugins` neben der `S4_Main.exe`. +5. Lade eine Version des [Texturenwechsler Mods](https://github.com/nyfrk/Settlers4-TextureChanger/releases) herunter. Entpacke die Datei `S4_TerrainTexturesChanger.asi` in das Verzeichnis `plugins`. +6. Starte das Spiel. Die Mod sollte nun automatisch geladen werden. + +Um die Mod zu deinstallieren, entferne die `S4_TerrainTexturesChanger.asi` aus dem `plugins`-Verzeichnis. Wenn Du den ASI-Loader nicht mehr verwenden möchtest, kannst Du einfach alle Schritte wieder rückgängig machen. + + + +## Bekannte Probleme + +* Du musst eine Spielversion haben, die die Neuen-Welt Texturen enthält. Dazu muss mindestens das Add-on *Die Siedler IV: Die neue Welt* oder die History Edition des Spiels vorhanden sein. + + + +## Probleme und Fragen + +Das Projekt verwendet den Github Issue Tracker. Bitte öffne [hier](https://github.com/nyfrk/Settlers4-TextureChanger/issues) ein Ticket für dein Anliegen. + + + +## Mitmachen + +Das offizielle Repository dieses Projekts ist unter https://github.com/nyfrk/Settlers4-TextureChanger verfügbar. Du kannst auf die folgenden Arten einen Beitrag leisten: + +* Beantworte Fragen +* Fehler melden oder bei der Verifizierung dieser helfen +* Code sichten und die vorgeschlagenen Korrekturen testen +* Pull Requests einreichen + +#### Kompilieren + +Lade Visual Studio 2017 oder 2019 mit der C++-Toolchain herunter. Das Projekt ist so konfiguriert, dass es mit der Windows XP-kompatiblen **v141_xp**-Toolchain gebaut wird. Du solltest jedoch die Toolchain nach Belieben ändern können. Es sind keine zusätzlichen Bibliotheken erforderlich, sodass das Projekt ohne weiteres gebaut werden kann. + +#### Entwickler + +Die *New World*-Texturen sind in den GFX/41.\*-Dateien gespeichert. Die klassischen Texturen sind in den GFX/2.\*-Dateien gespeichert. Diese Mod leitet einfach alle Dateizugriffe von den letzteren auf die ersteren um und trickst das Spiel so aus, dass es immer die Texturen der neuen Welt lädt, auch wenn es das klassische Texturpaket angefordert hat. Wenn Du das Addon *Die Siedler IV: Die Neue Welt* nicht installiert hast, wird das Spiel nicht funktionieren, da es die GFX/41.\*-Dateien nicht finden kann. Bitte in diesem Fall einen Freund, der das Add On hat, Dir eine Kopie der GFX/41.\*-Dateien zu schicken. Der Mod sollte auch mit den Karteneditoren funktionieren, da er die Windows-Natives zum Öffnen von Dateien hooked. + +#### Zukünftige Arbeit + +* Erlaube Spielern, die neuen klassischen Texturen auch in Neue-Welt Karten zu erzwingen. +* Erlaube benutzerdefinierte Terraintexturenpacks + + + +## Lizenz + +Das Projekt ist unter der [MIT](LICENSE.md)-Lizenz lizenziert. + + + +## Danksagungen + +Special thanks to Cybertom for the original tool from 2003 (though I could not find any source code) and to [Settlermania](https://settlermania.wordpress.com/2013/07/11/texture-swapper-for-tropical-textures/) for conserving this tool to the public even after the initial website went offline. \ No newline at end of file diff --git a/S4_TerrainTexturesChanger.sln b/S4_TerrainTexturesChanger.sln new file mode 100644 index 0000000..3de437c --- /dev/null +++ b/S4_TerrainTexturesChanger.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29503.13 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "S4_TerrainTexturesChanger", "S4_TerrainTexturesChanger\S4_TerrainTexturesChanger.vcxproj", "{C0BFDA19-085A-4E31-A2FC-81ED47F90939}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C0BFDA19-085A-4E31-A2FC-81ED47F90939}.Debug|x86.ActiveCfg = Debug|Win32 + {C0BFDA19-085A-4E31-A2FC-81ED47F90939}.Debug|x86.Build.0 = Debug|Win32 + {C0BFDA19-085A-4E31-A2FC-81ED47F90939}.Release|x86.ActiveCfg = Release|Win32 + {C0BFDA19-085A-4E31-A2FC-81ED47F90939}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B16F78F3-D1DE-4450-9E4C-288895083CC8} + EndGlobalSection +EndGlobal diff --git a/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.rc b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.rc new file mode 100644 index 0000000..c9495fe Binary files /dev/null and b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.rc differ diff --git a/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj new file mode 100644 index 0000000..014bda6 --- /dev/null +++ b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj @@ -0,0 +1,174 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + {C0BFDA19-085A-4E31-A2FC-81ED47F90939} + Win32Proj + S4TerrainTexturesChanger + + + + DynamicLibrary + true + v141_xp + Unicode + + + DynamicLibrary + false + v141_xp + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + .asi + $(SolutionDir)Lib;$(IncludePath) + $(SolutionDir)Lib;$(LibraryPath) + + + true + + + false + .asi + $(SolutionDir)Lib;$(IncludePath) + $(SolutionDir)Lib;$(LibraryPath) + + + false + + + + Level3 + Disabled + true + WIN32;_DEBUG;S4TERRAINTEXTURESCHANGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + MultiThreadedDebug + + + Windows + true + false + hLib-d.lib;%(AdditionalDependencies) + + + + + Use + Level3 + Disabled + true + _DEBUG;S4TERRAINTEXTURESCHANGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + false + + + + + Level3 + MaxSpeed + true + true + true + WIN32;NDEBUG;S4TERRAINTEXTURESCHANGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + MultiThreaded + + + Windows + true + true + true + false + hLib.lib;%(AdditionalDependencies) + + + + + Use + Level3 + MaxSpeed + true + true + true + NDEBUG;S4TERRAINTEXTURESCHANGER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + pch.h + + + Windows + true + true + true + false + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj.filters b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj.filters new file mode 100644 index 0000000..269f295 --- /dev/null +++ b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj.filters @@ -0,0 +1,32 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Quelldateien + + + + + Headerdateien + + + + + Ressourcendateien + + + \ No newline at end of file diff --git a/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj.user b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/S4_TerrainTexturesChanger/S4_TerrainTexturesChanger.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/S4_TerrainTexturesChanger/dllmain.cpp b/S4_TerrainTexturesChanger/dllmain.cpp new file mode 100644 index 0000000..4070230 --- /dev/null +++ b/S4_TerrainTexturesChanger/dllmain.cpp @@ -0,0 +1,100 @@ +/////////////////////////////////////////////////////////////////////////////// +// MIT License +// +// Copyright (c) 2020 nyfrk +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +/////////////////////////////////////////////////////////////////////////////// + +#define WIN32_LEAN_AND_MEAN +#include +#include +using namespace hlib; + +HANDLE WINAPI CreateFileW_Hook(LPCWSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE); + +static JmpPatch CreateFileWPatch((UINT64)GetProcAddress(GetModuleHandleW(L"KERNELBASE.DLL"), "CreateFileW"), (DWORD)CreateFileW_Hook,(Patch::BYTE5 *)"\x8B\xFF\x55\x8B\xEC"); +static const DWORD OrigRetAddr = (DWORD)CreateFileWPatch.getAddress() + 5; + +HANDLE __declspec(naked) WINAPI CreateFileW_Orig( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) { + _asm { + // prepare for future replacement with the orig 5 bytes + mov edi, edi + push ebp + mov ebp, esp + + // back to orig + jmp OrigRetAddr + } +} + +HANDLE WINAPI CreateFileW_Hook( + LPCWSTR lpFileName, + DWORD dwDesiredAccess, + DWORD dwShareMode, + LPSECURITY_ATTRIBUTES lpSecurityAttributes, + DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, + HANDLE hTemplateFile) { + + // Be careful to not call any functions that may recursively call CreateFileW in this hook! + + static const struct { LPCWSTR from, to; } redirects[] = { + {L"Gfx\\2.gh5", L"Gfx\\41.gh5"}, + {L"Gfx\\2.gh6", L"Gfx\\41.gh6"}, + {L"Gfx\\2.gl5", L"Gfx\\41.gl5"}, + {L"Gfx\\2.gl6", L"Gfx\\41.gl6"}, + }; + + for (auto& r : redirects) { + if (!wcscmp(lpFileName,r.from)) { + lpFileName = r.to; + break; + } + } + + return CreateFileW_Orig(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: { + if (!CreateFileWPatch.patch(GetCurrentProcess())) { + MessageBoxA(NULL, "Cannot change textures because the target is already hooked. Please open an issue here to solve this incompatibility:\nhttps://github.com/nyfrk/Settlers4-TextureChanger/issues", "Texture Changer ASI Plugin", MB_ICONEXCLAMATION | MB_OK); + } + break; + } + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: { + CreateFileWPatch.unpatch(GetCurrentProcess()); + break; + } + } + return TRUE; +} + diff --git a/S4_TerrainTexturesChanger/resource.h b/S4_TerrainTexturesChanger/resource.h new file mode 100644 index 0000000..b3ba533 --- /dev/null +++ b/S4_TerrainTexturesChanger/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by S4_TerrainTexturesChanger.rc + +// N�chste Standardwerte f�r neue Objekte +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/demo.gif b/demo.gif new file mode 100644 index 0000000..27431ac Binary files /dev/null and b/demo.gif differ diff --git a/demo.jpg b/demo.jpg new file mode 100644 index 0000000..c176044 Binary files /dev/null and b/demo.jpg differ