| #pragma once
|
|
|
| #ifndef _D2PATCH_H
|
| #define _D2PATCH_H
|
|
|
| #include "D2PatchConst.h"
|
| #include <iostream>
|
| #include <iomanip>
|
| #include <sstream>
|
| #include <windows.h>
|
| #include <string>
|
| #include <vector>
|
| #include <map>
|
| #include <fstream>
|
| #include <algorithm>
|
| #include <unordered_map>
|
| #include <Windows.h>
|
| #include <memoryapi.h>
|
|
|
| // Function to read setting from the INI file and provide detailed information
|
| int ReadSettingFromIni(const char* section, const char* key, int defaultValue) {
|
| // Get the file path
|
| const char* filePath = "./D2Mod.ini";
|
|
|
| // Check if the file exists and can be found
|
| DWORD fileAttributes = GetFileAttributesA(filePath);
|
| if (fileAttributes == INVALID_FILE_ATTRIBUTES) {
|
| MessageBoxA(NULL, "INI file not found or inaccessible.", "INI File Error", MB_OK | MB_ICONERROR);
|
| return defaultValue;
|
| }
|
|
|
| // Try to read the setting from the INI file
|
| int value = GetPrivateProfileIntA(section, key, defaultValue, filePath);
|
| {
|
| //DWORD lastError = GetLastError();
|
| //if (value == 0 && lastError != 0) {
|
| // // Error occurred while reading from INI file
|
| // char errorMessage[512];
|
| // sprintf(errorMessage, "Error reading setting from INI file:\n\n"
|
| // "INI File Path: %s\n"
|
| // "Section: %s\n"
|
| // "Key: %s\n"
|
| // "Default Value: %d\n"
|
| // "Error Code: %d\n\n"
|
| // "Ensure that the section and key exist in the INI file and the file is accessible.",
|
| // filePath, section, key, defaultValue, lastError);
|
| // MessageBoxA(NULL, errorMessage, "INI File Error", MB_OK | MB_ICONERROR);
|
| //}
|
| //else {
|
| // // Successfully read the setting
|
| // char successMessage[256];
|
| // sprintf(successMessage, "Setting read from INI file:\n\n"
|
| // "INI File Path: %s\n"
|
| // "Section: %s\n"
|
| // "Key: %s\n"
|
| // "Value: %d", filePath, section, key, value);
|
| // MessageBoxA(NULL, successMessage, "INI File Success", MB_OK | MB_ICONINFORMATION);
|
| //}
|
| }
|
| return value;
|
| }
|
|
|
|
|
|
|
| // Function to calculate relative offset (D2COMMON base address is 0x6F600000)
|
| DWORD calculateRelativeOffsetD2Common(DWORD offset) {
|
| return offset - 0x6F600000;
|
| }
|
|
|
| // Function to calculate relative offset (D2COMMON base address is 0x6F600000)
|
| DWORD calculateRelativeOffsetD2Client(DWORD offset) {
|
| return offset - 0x6FAA0000;
|
| }
|
|
|
| // Define settings from D2Mod.ini
|
| BYTE leftBorder = ReadSettingFromIni("CharmZone", "leftBorder", 0x04);
|
| BYTE rightBorder = ReadSettingFromIni("CharmZone", "rightBorder", 0x08);
|
| BYTE topBorder = ReadSettingFromIni("CharmZone", "topBorder", 0x00);
|
| BYTE bottomBorder = ReadSettingFromIni("CharmZone", "bottomBorder", 0x04);
|
|
|
| // Function to reverse the bytes of a hexadecimal number
|
| uint32_t reverseHexBytes(uint32_t hexNumber) {
|
| uint32_t reversedHex = 0;
|
|
|
| // Reverse the bytes
|
| reversedHex |= (hexNumber & 0x000000FF) << 24; // Move the last byte to the first byte
|
| reversedHex |= (hexNumber & 0x0000FF00) << 8; // Move the second last byte to the second byte
|
| reversedHex |= (hexNumber & 0x00FF0000) >> 8; // Move the second byte to the second last byte
|
| reversedHex |= (hexNumber & 0xFF000000) >> 24; // Move the first byte to the last byte
|
|
|
| return reversedHex;
|
| }
|
|
|
| /*
|
| CPU Disasm
|
| Address Hex dump Command Comments
|
| 6F68D570 > \85C0 TEST EAX,EAX
|
| 6F68D572 . 75 03 JNE SHORT 6F68D577
|
| 6F68D574 . C2 0800 RETN 8 ; return FALSE if reqs are not met
|
| 6F68D577 > 8B44E4 04 MOV EAX,DWORD PTR SS:[ESP+4] ; pItem
|
| 6F68D57B . 8B40 2C MOV EAX,DWORD PTR DS:[EAX+2C] ; pitem->pPath
|
| 6F68D57E . 8378 0C 05 CMP DWORD PTR DS:[EAX+0C],5 ; pPath->posX, 5 == leftBorder
|
| 6F68D582 . 72 1A JB SHORT 6F68D59E
|
| 6F68D584 . 8378 0C 07 CMP DWORD PTR DS:[EAX+0C],7 ; pPath->posX, 7 == rightBorder
|
| 6F68D588 . 77 14 JA SHORT 6F68D59E
|
| 6F68D58A . 8378 10 03 CMP DWORD PTR DS:[EAX+10],3 ; pPath->posY, 3 == topBorder
|
| 6F68D58E . 72 0E JB SHORT 6F68D59E
|
| 6F68D590 . 8378 10 04 CMP DWORD PTR DS:[EAX+10],4 ; pPath->posY, 4 == botomBorder
|
| 6F68D594 . 77 08 JA SHORT 6F68D59E
|
| 6F68D596 . B8 01000000 MOV EAX,1 ; return TRUE
|
| 6F68D59B . C2 0800 RETN 8
|
| 6F68D59E > 31C0 XOR EAX,EAX ; return FALSE
|
| 6F68D5A0 . C2 0800 RETN 8
|
| */
|
|
|
| __declspec(naked) void customD2CommonASM() {
|
| __asm {
|
| // Load parameters
|
| TEST EAX, EAX
|
| JNE lbl_not_in_charm_zone
|
| MOV EAX, DWORD PTR SS : [ESP + 0x04]
|
| MOV EAX, DWORD PTR DS : [EAX + 0x2C]
|
|
|
| // Load border values into 8-bit registers
|
| MOV CL, leftBorder
|
| MOV DL, rightBorder
|
| MOV BL, topBorder
|
| MOV AH, bottomBorder // Using AH register for bottomBorder assuming it's not used elsewhere
|
|
|
| // Check if within charm zone boundaries
|
| CMP BYTE PTR DS : [EAX + 0x0C] , CL
|
| JB lbl_not_in_charm_zone
|
| CMP BYTE PTR DS : [EAX + 0x0C] , DL
|
| JA lbl_not_in_charm_zone
|
| CMP BYTE PTR DS : [EAX + 0x10] , BL
|
| JB lbl_not_in_charm_zone
|
| CMP BYTE PTR DS : [EAX + 0x10] , AH
|
| JA lbl_not_in_charm_zone
|
|
|
| // Return 1 if within charm zone, otherwise return 0
|
| MOV EAX, 1
|
| RETN 8
|
|
|
| lbl_not_in_charm_zone :
|
| XOR EAX, EAX
|
| RETN 8
|
| }
|
| }
|
|
|
|
|
|
|
| //__declspec (naked) void customD2ClientASM() {
|
| // __asm {
|
| // TEST EAX, EAX
|
| // JE lbl_not_found
|
| // PUSH 0xD
|
| // PUSH ESI
|
| // CALL D2Common_10731
|
| // TEST EAX, EAX
|
| // JE lbl_not_found
|
| // MOV EAX, DWORD PTR SS : [ESP + 0x20]
|
| // PUSH EAX
|
| // PUSH ESI
|
| // CALL D2Common_10840
|
| // TEST EAX, EAX
|
| // JE lbl_not_found
|
| // JMP lbl_found
|
| // lbl_not_found :
|
| // JMP lbl_not_found_address
|
| // lbl_found :
|
| // RET
|
| //
|
| // lbl_not_found_address :
|
| // mov eax, 0x6FAE1197
|
| // JMP eax
|
| // }
|
| //}
|
|
|
|
|
| static const DLLPatchStrc gptTemplatePatches[] =
|
| {
|
| //////////////////////////////
|
| // //
|
| // D2COMMON PATCHES //
|
| // //
|
| //////////////////////////////
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F65FEF4), (DWORD)PATCH_JMP, FALSE, 0x01},
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F65FEF5), (DWORD)customD2CommonASM, TRUE, 0x00},
|
|
|
| /*
|
| // Patching TEST EAX, EAX at address 0x6F68D570
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D570), (DWORD)(0xC085), FALSE, 0x00},
|
| // Patching JNE SHORT 6F68D577 at address 0x6F68D572
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D572), (DWORD)(0x0375), FALSE, 0x00},
|
| // Patching RETN 8 at address 0x6F68D574
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D574), (DWORD)(0x0008C2), FALSE, 0x00},
|
| // Patching MOV EAX,DWORD PTR SS:[ESP+4] at address 0x6F68D577
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D577), (DWORD)(0x04E4448B), FALSE, 0x00},
|
| // Patching MOV EAX,DWORD PTR DS:[EAX+2C] at address 0x6F68D57B
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D57B), (DWORD)(0x2C408B), FALSE, 0x00},
|
|
|
| // Patching CMP DWORD PTR DS:[EAX+0C],leftBorder at address 0x6F68D57E
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D57E), (DWORD)(0x0C7883), FALSE, 0x0},
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D581), (DWORD)leftBorder, FALSE, 0x01},
|
| // Patching JB SHORT 6F68D59E at address 0x6F68D582
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D582), (DWORD)(0x1A72), FALSE, 0x0},
|
|
|
| // Patching CMP DWORD PTR DS:[EAX+0C],rightBorder at address 0x6F68D584
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D584), (DWORD)(0x0C7883), FALSE, 0x0},
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D587), (DWORD)rightBorder, FALSE, 0x01},
|
| // Patching JA SHORT 6F68D59E at address 0x6F68D588
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D588), (DWORD)(0x1477), FALSE, 0x0},
|
|
|
| // Patching CMP DWORD PTR DS:[EAX+10],topBorder at address 0x6F68D58A
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D58A), (DWORD)(0x107883), FALSE, 0x0},
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D58D), (DWORD)topBorder, FALSE, 0x01},
|
| // Patching JB SHORT 6F68D59E at address 0x6F68D58E
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D58E), (DWORD)(0x0E72), FALSE, 0x0},
|
|
|
| // Patching CMP DWORD PTR DS:[EAX+10],bottomBorder at address 0x6F68D590
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D590), (DWORD)(0x107883), FALSE, 0x0},
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D593), (DWORD)bottomBorder, FALSE, 0x01},
|
| // Patching JA SHORT 6F68D59E at address 0x6F68D594
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D594), (DWORD)(0x0877), FALSE, 0x0},
|
|
|
| // Patching MOV EAX,1 at address 0x6F68D596
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D596), (DWORD)reverseHexBytes(0xB8010000), FALSE, 0x0},
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D59A), (DWORD)(0x00), FALSE, 0x1},
|
|
|
| // Patching RETN 8 at address 0x6F68D59B
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D59B), (DWORD)(0x0008C2), FALSE, 0x0},
|
| // Patching XOR EAX,EAX at address 0x6F68D59E
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D59E), (DWORD)(0xC031), FALSE, 0x0},
|
| // Patching RETN 8 at address 0x6F68D5A0
|
| {D2DLL_D2COMMON, calculateRelativeOffsetD2Common(0x6F68D5A0), (DWORD)(0x0008C2), FALSE, 0x0},
|
| */
|
|
|
| //////////////////////////////
|
| // //
|
| // D2CLIENT PATCHES //
|
| // //
|
| //////////////////////////////
|
|
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FAE118F), (DWORD)PATCH_JMP, FALSE, 0x00},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FAE1190), (DWORD)reverseHexBytes(0x6CB30800), FALSE, 0x00},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FAE1194), (DWORD)0x90, FALSE, 0x03},
|
|
|
| // Patching TEST EAX,EAX at address 0x6FB6C500
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C500), (DWORD)(0xC085), FALSE, 0x00},
|
|
|
| // Patching JE 6FAE1283 at address 0x6FB6C502
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C502), (DWORD)(0x840F), FALSE, 0x00},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C504), (DWORD)reverseHexBytes(0x7B4DF7FF), FALSE, 0x00},
|
|
|
| // Patching PUSH 0D at address 0x6FB6C508
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C508), (DWORD)(0x0D6A), FALSE, 0x00},
|
|
|
| // Patching PUSH ESI at address 0x6FB6C50A
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C50A), (DWORD)(0x56), FALSE, 0x00},
|
|
|
| // Patching CALL <JMP.&D2Common.#10731> at address 0x6FB6C50B
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C50B), (DWORD)(0xE8), FALSE, 0x01},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C50C), (DWORD)reverseHexBytes(0x10E7FFFF), FALSE, 0x00},
|
|
|
| // Patching TEST EAX,EAX at address 0x6FB6C510
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C510), (DWORD)(0xC085), FALSE, 0x00},
|
| // Patching JE 6FAE1197 at address 0x6FB6C512
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C512), (DWORD)(0x840F), FALSE, 0x00},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C514), (DWORD)reverseHexBytes(0x7F4CF7FF), FALSE, 0x00},
|
|
|
| // Patching MOV EAX,DWORD PTR SS:[ESP+20] at address 0x6FB6C518
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C518), (DWORD)reverseHexBytes(0x8B44E420), FALSE, 0x00},
|
| // Patching PUSH EAX at address 0x6FB6C51C
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C51C), (DWORD)(0x50), FALSE, 0x01},
|
| // Patching PUSH ESI at address 0x6FB6C51D
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C51D), (DWORD)(0x56), FALSE, 0x01},
|
| // Patching CALL <JMP.&D2Common.#10840> at address 0x6FB6C51E
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C51E), (DWORD)(0xE8), FALSE, 0x01},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C51F), (DWORD)reverseHexBytes(0x19EFFFFF), FALSE, 0x00},
|
|
|
|
|
| // Patching TEST EAX,EAX at address 0x6FB6C523
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C523), (DWORD)(0xC085), FALSE, 0x00},
|
|
|
| // Patching JE 6FAE1283 at address 0x6FB6C525
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C525), (DWORD)(0x840F), FALSE, 0x00},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C527), (DWORD)reverseHexBytes(0x584DF7FF), FALSE, 0x00},
|
|
|
| // Patching JMP 6FAE1197 at address 0x6FB6C52B
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C52B), (DWORD)(0xE9), FALSE, 0x01},
|
| {D2DLL_D2CLIENT, calculateRelativeOffsetD2Client(0x6FB6C52C), (DWORD)reverseHexBytes(0x674CF7FF), FALSE, 0x00},
|
|
|
|
|
|
|
|
|
| {D2DLL_INVALID} // this must be the last entry in the array!
|
| };
|
|
|
| #endif // _D2PATCH_H
|