diff --git a/Makefile b/Makefile
index a91c825..d6a27ee 100644
--- a/Makefile
+++ b/Makefile
@@ -30,6 +30,7 @@ OBJS := \
obj/dll/rugburn/main.o \
obj/hooks/kernel32/inject.o \
obj/hooks/msvcr100/msvcr100.o \
+ obj/hooks/projectg/us852/ranking.o \
obj/hooks/user32/window.o \
obj/hooks/ws2_32/redir.o \
obj/hooks/wininet/netredir.o \
@@ -38,6 +39,7 @@ OBJS := \
obj/bootstrap.o \
obj/common.o \
obj/config.o \
+ obj/hex.o \
obj/ijlfwd.o \
obj/json.o \
obj/patch.o \
diff --git a/rugburn.vcxproj b/rugburn.vcxproj
index e571d45..bbd19bd 100644
--- a/rugburn.vcxproj
+++ b/rugburn.vcxproj
@@ -141,7 +141,6 @@
false
MultiThreaded
$(IntDir)%(RelativeDir)
- stdcpp17
Console
@@ -150,7 +149,7 @@
true
exportvs.def
DllMain
- kernel32.lib;user32.lib;shlwapi.lib;libvcruntime.lib;libcmt.lib;libucrt.lib;%(AdditionalDependencies)
+ kernel32.lib;user32.lib;shlwapi.lib;%(AdditionalDependencies)
@@ -193,7 +192,7 @@
-
+
@@ -204,4 +203,4 @@
-
\ No newline at end of file
+
diff --git a/scripts/setup-clangd.sh b/scripts/setup-clangd.sh
index a5a7110..364580f 100755
--- a/scripts/setup-clangd.sh
+++ b/scripts/setup-clangd.sh
@@ -22,5 +22,5 @@ cp ".tmp/h/sdkddkve.h" ".tmp/h/sdkddkver.h"
echo "-I$PWD/.tmp/h" > compile_flags.txt
echo "-D__va_list=__builtin_va_list" >> compile_flags.txt
echo "-D_exception_code=__exception_code" >> compile_flags.txt
+echo "-D__stdcall=" >> compile_flags.txt
echo "-fms-extensions" >> compile_flags.txt
-
diff --git a/src/bootstrap.c b/src/bootstrap.c
index a9e4920..767c7ff 100644
--- a/src/bootstrap.c
+++ b/src/bootstrap.c
@@ -85,7 +85,7 @@ typedef struct _TEB {
#else // x86
PTEB tebPtr = (PTEB)__readfsdword(OFFSETOF(NT_TIB, Self));
#endif
- return tebPtr;
+ return tebPtr;
}
#endif
diff --git a/src/config.c b/src/config.c
index 5e0aef4..365a218 100644
--- a/src/config.c
+++ b/src/config.c
@@ -58,8 +58,8 @@ void ReadJsonPatchAddressMap(LPSTR *json, LPCSTR key) {
FatalError("Reached maximum number of Patch address!");
}
- Config.PatchAddress[Config.NumPatchAddress].addr = ReadDword(key);
- TranslateHexInText(value, Config.PatchAddress[Config.NumPatchAddress].patch, sizeof(Config.PatchAddress[Config.NumPatchAddress].patch), &Config.PatchAddress[Config.NumPatchAddress].patch_len);
+ Config.PatchAddress[Config.NumPatchAddress].addr = ParseAddress(key);
+ ParsePatch(value, &Config.PatchAddress[Config.NumPatchAddress].patch, &Config.PatchAddress[Config.NumPatchAddress].patchLen);
Config.NumPatchAddress++;
}
@@ -141,15 +141,17 @@ BOOL RewriteAddr(LPSOCKADDR_IN addr) {
}
void PatchAddress() {
- int i;
-
- for (i = 0; i < Config.NumPatchAddress; i++) {
-
- if (Config.PatchAddress[i].addr != 0 && Config.PatchAddress[i].patch_len > 0 && Config.PatchAddress[i].patch[0] != '\0') {
-
- Patch((LPVOID)Config.PatchAddress[i].addr, Config.PatchAddress[i].patch, Config.PatchAddress[i].patch_len);
-
- Log("PatchAddress: 0x%08lX, Len: %d, Value: %s\r\n", Config.PatchAddress[i].addr, Config.PatchAddress[i].patch_len, Config.PatchAddress[i].patch);
- }
- }
+ int i;
+ for (i = 0; i < Config.NumPatchAddress; i++) {
+ if (Config.PatchAddress[i].addr == 0) {
+ Warning("Patch %d at address 0 will be ignored.", i);
+ continue;
+ }
+ if (Config.PatchAddress[i].patchLen == 0) {
+ Warning("Patch %d is empty.", i);
+ continue;
+ }
+ Patch((LPVOID)Config.PatchAddress[i].addr, Config.PatchAddress[i].patch, Config.PatchAddress[i].patchLen);
+ Log("PatchAddress: 0x%08lX, Len: %d, Value: %s\r\n", Config.PatchAddress[i].addr, Config.PatchAddress[i].patchLen, Config.PatchAddress[i].patch);
+ }
}
diff --git a/src/config.h b/src/config.h
index 2938f77..61ac0ee 100644
--- a/src/config.h
+++ b/src/config.h
@@ -21,8 +21,8 @@ typedef struct _PORTREWRITERULE {
typedef struct _PATCHADDRESS {
DWORD addr;
- CHAR patch[1024];
- int patch_len;
+ LPSTR patch;
+ DWORD patchLen;
} PATCHADDRESS, *LPPATCHADDRESS;
typedef struct _RUGBURNCONFIG {
diff --git a/src/dll/rugburn/main.c b/src/dll/rugburn/main.c
index 966af52..8aea7d5 100644
--- a/src/dll/rugburn/main.c
+++ b/src/dll/rugburn/main.c
@@ -14,10 +14,10 @@
#include "../../bootstrap.h"
#include "../../common.h"
#include "../../config.h"
+#include "../../hooks/hooks.h"
#include "../../ijlfwd.h"
#include "../../patch.h"
-#include "../../hooks/hooks.h"
-#include "../../patch_usa_852.h"
+#include "../../hooks/projectg/us852/ranking.h"
/**
* InitEnvironment configures the PANGYA_ARG environment to avoid needing to
@@ -44,9 +44,9 @@ static VOID InitEnvironment() {
* Implements the GameGuard patches for Pangya US 852.00.
*/
static DWORD STDCALL PatchGG_US852(PVOID unused) {
- while(1) {
+ while (1) {
// TODO(john): Remove hardcoded addresses.
- if (*(DWORD*)0x00A495E0 == 0x8F143D83) {
+ if (*(DWORD *)0x00A495E0 == 0x8F143D83) {
Patch((LPVOID)0x00A495E0, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A49670, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A49690, "\xC3\x90\x90\x90\x90\x90\x90", 7);
@@ -56,35 +56,36 @@ static DWORD STDCALL PatchGG_US852(PVOID unused) {
Log("Patched GG check routines (US 852)\r\n");
Patch((LPVOID)0x00A6ECC9, "\x30\xC0", 2);
- Log("Patched Cookie Point Item (US 852)\r\n");
-
- Patch((LPVOID)0x005FB990, "\x80\xB9\x40\x02\x00\x00\x00\x0F\x85\x0D\x00\x00\x00\x8B\x89\x8C\x01\x00\x00\x8B\x01\x8B\x50\x4C\xFF\xD2\xC2\x04\x00", 29);
- Log("Patched Cookie Btn in onCallback that's disabled (US 852)\r\n");
-
- Patch((LPVOID)0x005FB9AD, "\xB3\x01\x31\xFF\x90\x53\xBA\xB4\x6A\xCE\x00\xE9\xC9\x31\x00\x00", 16);
- Patch((LPVOID)0x005FEB7E, "\xE9\x2A\xCE\xFF\xFF", 5);
- Patch((LPVOID)0x005FEB8D, "\x53", 1);
- Patch((LPVOID)0x005FEB9A, "\x53", 1);
- Patch((LPVOID)0x005FB9BD, "\x6A\x01\xBA\xB4\x6A\xCE\x00\x8B\xCE\xE8\xF5\x2C\x00\x00\x6A\x01\xBA\xB0\x69\xCE\x00\xE9\x29\x32\x00\x00", 26);
- Patch((LPVOID)0x005FEBF9, "\xE9\xBF\xCD\xFF\xFF", 5);
- Log("Patched Btn Cookie, Gacha and Scratch disabled (US 852)\r\n");
-
- Patch((LPVOID)0x008BC729, "\x01", 1);
- Patch((LPVOID)0x008C1495, "\xEB\x0C", 2);
- Patch((LPVOID)0x008C14A3, "\xE8\xF8\xB2\xFF\xFF\x88\x86\xE4\x00\x00\x00\x5E\xC3", 13);
- Log("Patched Btn Change Nickname disabled (US 852)\r\n");
-
- unsigned char jmp_to_patch_ranking[5] = { 0xE9u, 0u, 0u, 0u, 0u };
-
- DWORD relAddr = (DWORD)OnUnderBar_RankingUp - 0x00655630u - 5u;
-
- memcpy(&jmp_to_patch_ranking[1], &relAddr, 4u);
-
- Patch((LPVOID)0x00655630, jmp_to_patch_ranking, sizeof(jmp_to_patch_ranking));
- Log("Patched Ranking System disabled (US 852)\r\n");
+ Log("Patched Cookie Point Item (US 852)\r\n");
+
+ Patch((LPVOID)0x005FB990,
+ "\x80\xB9\x40\x02\x00\x00\x00\x0F\x85\x0D\x00\x00\x00\x8B\x89\x8C\x01\x00\x00\x8B"
+ "\x01\x8B\x50\x4C\xFF\xD2\xC2\x04\x00",
+ 29);
+ Log("Patched Cookie Btn in onCallback that's disabled (US 852)\r\n");
+
+ Patch((LPVOID)0x005FB9AD,
+ "\xB3\x01\x31\xFF\x90\x53\xBA\xB4\x6A\xCE\x00\xE9\xC9\x31\x00\x00", 16);
+ Patch((LPVOID)0x005FEB7E, "\xE9\x2A\xCE\xFF\xFF", 5);
+ Patch((LPVOID)0x005FEB8D, "\x53", 1);
+ Patch((LPVOID)0x005FEB9A, "\x53", 1);
+ Patch((LPVOID)0x005FB9BD,
+ "\x6A\x01\xBA\xB4\x6A\xCE\x00\x8B\xCE\xE8\xF5\x2C\x00\x00\x6A\x01\xBA\xB0\x69\xCE"
+ "\x00\xE9\x29\x32\x00\x00",
+ 26);
+ Patch((LPVOID)0x005FEBF9, "\xE9\xBF\xCD\xFF\xFF", 5);
+ Log("Patched Btn Cookie, Gacha and Scratch disabled (US 852)\r\n");
+
+ Patch((LPVOID)0x008BC729, "\x01", 1);
+ Patch((LPVOID)0x008C1495, "\xEB\x0C", 2);
+ Patch((LPVOID)0x008C14A3, "\xE8\xF8\xB2\xFF\xFF\x88\x86\xE4\x00\x00\x00\x5E\xC3", 13);
+ Log("Patched Btn Change Nickname disabled (US 852)\r\n");
+
+ InitUS852RankingHook();
+ Log("Patched Ranking System disabled (US 852)\r\n");
return TRUE;
}
- if (*(DWORD*)0x00A49580 == 0x8F143D83) {
+ if (*(DWORD *)0x00A49580 == 0x8F143D83) {
Patch((LPVOID)0x00A49580, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A49670, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A49690, "\xC3\x90\x90\x90\x90\x90\x90", 7);
@@ -94,18 +95,18 @@ static DWORD STDCALL PatchGG_US852(PVOID unused) {
Log("Patched GG check routines (US 824)\r\n");
return TRUE;
}
- Delay(5);
+ Delay(5);
}
- return FALSE;
+ return FALSE;
}
/**
* Implements the GameGuard patches for Pangya JP 972.00.
*/
static DWORD STDCALL PatchGG_JP972(PVOID unused) {
- while(1) {
+ while (1) {
// TODO(john): Remove hardcoded addresses.
- if (*(DWORD*)0x00A5CD10 == 0x1BA43D83) {
+ if (*(DWORD *)0x00A5CD10 == 0x1BA43D83) {
Patch((LPVOID)0x00A5CD10, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A5CDA0, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A5CDC0, "\xC3\x90\x90\x90\x90\x90\x90", 7);
@@ -115,7 +116,7 @@ static DWORD STDCALL PatchGG_JP972(PVOID unused) {
Log("Patched GG check routines (JP 972)\r\n");
return TRUE;
}
- if (*(DWORD*)0x00A5CF80 == 0x1BA43D83) {
+ if (*(DWORD *)0x00A5CF80 == 0x1BA43D83) {
Patch((LPVOID)0x00A5CF80, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A5C010, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A5C030, "\xC3\x90\x90\x90\x90\x90\x90", 7);
@@ -125,7 +126,7 @@ static DWORD STDCALL PatchGG_JP972(PVOID unused) {
Log("Patched GG check routines (JP 974)\r\n");
return TRUE;
}
- if (*(DWORD*)0x00A5CF80 == 0x1C143D83) {
+ if (*(DWORD *)0x00A5CF80 == 0x1C143D83) {
Patch((LPVOID)0x00A5CF80, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A5C010, "\xC3\x90\x90\x90\x90\x90\x90", 7);
Patch((LPVOID)0x00A5C030, "\xC3\x90\x90\x90\x90\x90\x90", 7);
@@ -135,20 +136,22 @@ static DWORD STDCALL PatchGG_JP972(PVOID unused) {
Log("Patched GG check routines (JP 983)\r\n");
return TRUE;
}
- Delay(5);
+ Delay(5);
}
- return FALSE;
+ return FALSE;
}
static VOID STDCALL PatchDynamicAndGG(LPTHREAD_START_ROUTINE patchThread) {
- if (!patchThread) {
- Warning("It looks like no patch exists for this version of PangYa™.\nThe game will likely exit a couple minutes after detecting GameGuard is not present.");
- PatchAddress();
- }else {
- if (patchThread(NULL) == TRUE)
- PatchAddress();
- }
+ if (!patchThread) {
+ Warning("It looks like no patch exists for this version of PangYa™.\nThe game will likely "
+ "exit a couple minutes after detecting GameGuard is not present.");
+ PatchAddress();
+ } else {
+ if (patchThread(NULL) == TRUE) {
+ PatchAddress();
+ }
+ }
}
/**
@@ -202,7 +205,7 @@ extern BOOL STDCALL SlipstrmDllMain(HANDLE hInstance, DWORD dwReason, LPVOID res
PFNDLLMAINPROC pSlipstreamOep;
BOOL bOepResult;
- pSlipstreamOep = (PFNDLLMAINPROC)((*(DWORD*)((DWORD)hInstance + 0x40))+(DWORD)hInstance);
+ pSlipstreamOep = (PFNDLLMAINPROC)((*(DWORD *)((DWORD)hInstance + 0x40)) + (DWORD)hInstance);
// Call OEP; return failure if it fails.
bOepResult = pSlipstreamOep(hInstance, dwReason, reserved);
diff --git a/src/hex.c b/src/hex.c
index c8e1468..e306ca7 100644
--- a/src/hex.c
+++ b/src/hex.c
@@ -1,130 +1,122 @@
-#include "hex.h"
-
-DWORD ReadDword(LPCSTR _text) {
-
- if (_text == NULL) {
- FatalError("Hex - Read Dword hex in text, parameters invalid!");
- }
-
- if (_text[0] == '\0')
- return 0;
-
- LPSTR pos = (LPSTR)_text;
- DWORD dw = 0;
- int len = 0;
-
- if ((pos = strstr(pos, "0x")) == NULL) {
- FatalError("Hex - Read Dword hex in text, invalid dword hex!");
- }
-
- while (isxdigit(pos[len + 2]))
- len++;
-
- if (len > 0) {
-
- CHAR ctmp = pos[len + 2];
- pos[len + 2] = '\0';
-
- dw = strtol(pos + 2, NULL, 16);
- }
-
- return dw;
-}
-
-void TranslateHexInText(LPCSTR _text, LPSTR _result, int _size_result, int* _size_out) {
-
- if (_text == NULL || _result == NULL || _size_result == 0 || _size_out == NULL) {
- FatalError("Hex - Translate hex in text, parameters invalid!");
- }
-
- *_size_out = 0;
-
- if (_text[0] == '\0') {
-
- _result[*_size_out++] = '\0';
-
- return;
- }
-
- LPSTR pos = (LPSTR)_text;
- LPSTR rest = NULL;
- int len = 0, num = 0;
-
- do {
-
- rest = strstr(pos, "\\x");
-
- if (rest != NULL) {
-
- len = rest - pos;
-
- if (len > 0) {
-
- if ((*_size_out + len) > _size_result) {
- FatalError("Hex - Translate hex in text, overflow result buffer!");
- }
-
- memcpy(_result + *_size_out, pos, len);
- *_size_out += len;
-
- pos = rest;
- }
-
- len = 0;
-
- while (len < 2 && isxdigit(pos[len + 2]))
- len++;
-
- if (len > 0) {
-
- CHAR ctmp = pos[len + 2];
- pos[len + 2] = '\0';
-
- num = strtol(pos + 2, NULL, 16);
-
- if ((*_size_out + 1) > _size_result) {
- FatalError("Hex - Translate hex in text, overflow result buffer!");
- }
-
- pos += len + 2;
- *pos = ctmp;
-
- _result[*_size_out] = (CHAR)num;
-
- *_size_out += 1;
-
- }else {
-
- if ((*_size_out + 1) > _size_result) {
- FatalError("Hex - Translate hex in text, overflow result buffer!");
- }
-
- _result[*_size_out] = *pos++;
-
- *_size_out += 1;
- }
-
- }else {
-
- len = strlen(pos);
-
- if ((*_size_out + len) > _size_result) {
- FatalError("Hex - Translate hex in text, overflow result buffer!");
- }
-
- memcpy(_result + *_size_out, pos, len);
- *_size_out += len;
-
- pos += len;
- }
-
- } while(*pos != '\0');
-
- if ((*_size_out + 1) > _size_result) {
- FatalError("Hex - Translate hex in text, overflow result buffer!");
- }
-
- _result[*_size_out] = '\0';
-
- *_size_out += 1;
-}
+#include "hex.h"
+
+static BOOL ParseHex(CHAR ch, LPDWORD pOutValue) {
+ if (ch >= '0' && ch <= '9') {
+ *pOutValue = ch - '0';
+ } else if (ch >= 'a' && ch <= 'f') {
+ *pOutValue = ch - 'a' + 10;
+ } else if (ch >= 'A' && ch <= 'F') {
+ *pOutValue = ch - 'A' + 10;
+ } else {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+DWORD ParseAddress(LPCSTR lpszText) {
+ LPCSTR pos = lpszText;
+ DWORD hexDigitVal;
+ DWORD result = 0;
+
+ if (lpszText == NULL) {
+ FatalError("ParseAddress: Received unexpected NULL string");
+ }
+
+ if (lpszText[0] == '\0') {
+ return 0;
+ }
+
+ if (pos[0] != '0' || pos[1] != 'x' || pos[2] == 0) {
+ FatalError("ParseAddress: Invalid input, expected 0x-prefixed hex number");
+ }
+
+ pos += 2;
+
+ while (ParseHex(*pos, &hexDigitVal) == TRUE) {
+ result <<= 4;
+ result |= hexDigitVal;
+ pos++;
+ }
+
+ if (*pos) {
+ FatalError("ParseAddress: Unexpected text remaining after address: %s", pos);
+ }
+
+ return result;
+}
+
+void ParsePatch(LPCSTR lpszText, LPSTR *pDataOut, DWORD *pSizeOut) {
+ DWORD hexDigitVal;
+ DWORD hexOctetVal;
+ LPCSTR inPos;
+ LPSTR outPos;
+ *pSizeOut = 0;
+
+ // Calculate length
+ inPos = lpszText;
+ while (*inPos) {
+ switch (*inPos++) {
+ case '\\':
+ switch (*inPos++) {
+ case 'x':
+ if (ParseHex(*inPos++, &hexDigitVal) == FALSE) {
+ FatalError("ParsePatch: Bad hex escape near %s", inPos);
+ }
+ if (ParseHex(*inPos++, &hexDigitVal) == FALSE) {
+ FatalError("ParsePatch: Bad hex escape near %s", inPos);
+ }
+ (*pSizeOut)++;
+ break;
+ case '\\':
+ (*pSizeOut)++;
+ break;
+ case '\0':
+ FatalError("ParsePatch: Unexpected end of string in escape code");
+ break;
+ default:
+ FatalError("ParsePatch: Unknown escape code: %s", inPos);
+ }
+ default:
+ (*pSizeOut)++;
+ }
+ inPos++;
+ }
+
+ // Allocate memory
+ *pDataOut = AllocMem(*pSizeOut);
+
+ // Parse
+ inPos = lpszText;
+ outPos = *pDataOut;
+ while (*inPos) {
+ switch (*inPos) {
+ case '\\':
+ inPos++;
+ switch (*inPos++) {
+ case 'x':
+ if (!ParseHex(*inPos++, &hexDigitVal)) {
+ FatalError("ParsePatch: Bad hex escape near %s", inPos);
+ }
+ hexOctetVal = hexDigitVal << 4;
+ if (!ParseHex(*inPos++, &hexDigitVal)) {
+ FatalError("ParsePatch: Bad hex escape near %s", inPos);
+ }
+ hexOctetVal |= hexDigitVal;
+ *outPos++ = (CHAR)(BYTE)hexOctetVal;
+ break;
+ case '\\':
+ (*pSizeOut)++;
+ *outPos++ = '\\';
+ break;
+ case '\0':
+ FatalError("ParsePatch: Unexpected end of string in escape code");
+ break;
+ default:
+ FatalError("ParsePatch: Unknown escape code: %s", inPos);
+ }
+ default:
+ *(outPos++) = *(inPos++);
+ }
+ inPos++;
+ }
+}
diff --git a/src/hex.h b/src/hex.h
index 57ab4ac..e6189c8 100644
--- a/src/hex.h
+++ b/src/hex.h
@@ -1,9 +1,9 @@
-#ifndef HEX_H
-#define HEX_H
-
-#include "common.h"
-
-DWORD ReadDword(LPCSTR _text);
-void TranslateHexInText(LPCSTR _text, LPSTR _result, int _size_result, int* _size_out);
-
-#endif
\ No newline at end of file
+#ifndef HEX_H
+#define HEX_H
+
+#include "common.h"
+
+DWORD ParseAddress(LPCSTR lpszText);
+void ParsePatch(LPCSTR lpszText, LPSTR *pDataOut, DWORD *pSizeOut);
+
+#endif
diff --git a/src/hooks/projectg/us852/ranking.c b/src/hooks/projectg/us852/ranking.c
new file mode 100644
index 0000000..e4027d9
--- /dev/null
+++ b/src/hooks/projectg/us852/ranking.c
@@ -0,0 +1,206 @@
+#include "ranking.h"
+#include "../../../patch.h"
+
+typedef struct _stMsgObject {
+ LPVOID m_pIActor;
+ DWORD m_id;
+ DWORD m_com[5];
+ DWORD m_time;
+} stMsgObject;
+
+inline stMsgObject MakeMsgObject(LPVOID _pIActor, DWORD _id, DWORD _c0, DWORD _c1, DWORD _c2, DWORD _c3, DWORD _c4) {
+ stMsgObject obj;
+ obj.m_pIActor = _pIActor;
+ obj.m_id = _id;
+ obj.m_com[0] = _c0;
+ obj.m_com[1] = _c1;
+ obj.m_com[2] = _c2;
+ obj.m_com[3] = _c3;
+ obj.m_com[4] = _c4;
+ obj.m_time = 0u;
+ return obj;
+}
+
+#define GETTHISPOINTERMEMBER(_type_, _addr_, _this_) (_type_ *)(((BYTE *)(_this_)) + (_addr_))
+#define GETVTABLEFN(_this_, _addr_) ((LPVOID)(*((LPCSTR *)(_this_)) + (_addr_)))
+
+typedef LPVOID (__cdecl *PFNMAKEINSTANCEFRLOGINRSDLG)(void);
+typedef LPCSTR (STDCALL *PFNBRASILTRANSLATESTRINGPROC)(LPCSTR _str);
+typedef VOID (STDCALL *PFNFRLOGINRSDLGSETSTATEPROC)(DWORD _state);
+
+typedef LPVOID (STDCALL *PFNFRFORM_INITPROC)(LPVOID, LPVOID, LPVOID, LPCSTR, LPVOID);
+typedef LPVOID (STDCALL *PFNIOBJECTDYNAMICCASTPROC)(LPVOID, LPCVOID);
+typedef LPVOID (STDCALL *PFNFRFORMLOGINRSDLGSCALARDELETINGDESTRUCTORPROC)(LPVOID, DWORD);
+
+typedef DWORD64 (STDCALL *PFNCSHAREDDOCISCONTROLSERVERSERVICEPROC)(LPVOID, DWORD64);
+typedef VOID (STDCALL *PFNVIRTUALIACTORHANDLEMSGPROC)(LPVOID, stMsgObject *);
+typedef VOID (STDCALL *PFNVIRTUALIACTORCLOSEALLDIALOGSPROC)(LPVOID);
+typedef BOOL (STDCALL *PFNWNETWORKSYSTEMISCONNECTEDPROC)(LPVOID, DWORD);
+typedef BOOL (STDCALL *PFNWNETWORKSYSTEMINITPROC)(LPVOID, DWORD);
+typedef BOOL (STDCALL *PFNWNETWORKSYSTEMSENDMESSAGEAPROC)(LPVOID, DWORD, DWORD);
+typedef VOID (STDCALL *PFNCONSTRUCTORWSENDPACKETPROC)(LPVOID, DWORD);
+typedef VOID (STDCALL *PFNDESTRUCTORWSENDPACKETPROC)(LPVOID);
+typedef VOID (STDCALL *PFNWSENDPACKETSENDPROC)(LPVOID, DWORD);
+typedef VOID (STDCALL *PFNCLOBBYMAINCLEARTOOLTIPPROC)(LPVOID, LPVOID);
+typedef BOOL (STDCALL *PFNFRLOGINRSDLGONLOGINRSDLGRESULTPROC)(LPVOID, DWORD, LPVOID);
+typedef BOOL (STDCALL *PFNFRFORMOPENPROC)(LPVOID, LPVOID, DWORD, DWORD, DWORD, DWORD);
+
+static PFNMAKEINSTANCEFRLOGINRSDLG pMakeInstanceFrLoginRsDlg = NULL;
+static PFNFRFORM_INITPROC p_Init = NULL;
+static PFNIOBJECTDYNAMICCASTPROC pDynamicCast = NULL;
+
+static PFNCSHAREDDOCISCONTROLSERVERSERVICEPROC pIsControlServerService = NULL;
+static PFNBRASILTRANSLATESTRINGPROC pBrasilTranslateString = NULL;
+static PFNWNETWORKSYSTEMISCONNECTEDPROC pIsConnected = NULL;
+static PFNWNETWORKSYSTEMINITPROC pInit = NULL;
+static PFNWNETWORKSYSTEMSENDMESSAGEAPROC pSendMessageA = NULL;
+static PFNCONSTRUCTORWSENDPACKETPROC pConstructorWSendPacket = NULL;
+static PFNDESTRUCTORWSENDPACKETPROC pDestructorWSendPacket = NULL;
+static PFNWSENDPACKETSENDPROC pSend = NULL;
+static PFNCLOBBYMAINCLEARTOOLTIPPROC pClearToolTip = NULL;
+static PFNFRLOGINRSDLGSETSTATEPROC pSetState = NULL;
+static LPVOID pOnUnderBar_RankingUpThunk = NULL;
+static LPVOID pOnLoginRsDlgResultThunk = NULL;
+
+static void STDCALL OnUnderBar_RankingUp(LPVOID _this);
+static BOOL STDCALL OnLoginRsDlgResult(LPVOID _this, DWORD exit_code, LPVOID _pFrForm);
+
+VOID InitUS852RankingHook() {
+ pMakeInstanceFrLoginRsDlg = (PFNMAKEINSTANCEFRLOGINRSDLG)0x00AC4680u;
+ p_Init = (PFNFRFORM_INITPROC)BuildStdcallToThiscallThunk((LPVOID)0x00BCDD40u);
+ pDynamicCast = (PFNIOBJECTDYNAMICCASTPROC)BuildStdcallToThiscallThunk((LPVOID)0x0047EFF0u);
+
+ pIsControlServerService =
+ (PFNCSHAREDDOCISCONTROLSERVERSERVICEPROC)BuildStdcallToThiscallThunk((LPVOID)0x0062E4A0);
+ pBrasilTranslateString =
+ (PFNBRASILTRANSLATESTRINGPROC)BuildStdcallToThiscallThunk((LPVOID)0x00B3A7E0u);
+ pIsConnected =
+ (PFNWNETWORKSYSTEMISCONNECTEDPROC)BuildStdcallToThiscallThunk((LPVOID)0x00A3AEB0u);
+ pInit = (PFNWNETWORKSYSTEMINITPROC)BuildStdcallToThiscallThunk((LPVOID)0x00A3AD40u);
+ pSendMessageA =
+ (PFNWNETWORKSYSTEMSENDMESSAGEAPROC)BuildStdcallToThiscallThunk((LPVOID)0x00A3ADB0u);
+ pConstructorWSendPacket =
+ (PFNCONSTRUCTORWSENDPACKETPROC)BuildStdcallToThiscallThunk((LPVOID)0x00A3BEE0u);
+ pDestructorWSendPacket =
+ (PFNDESTRUCTORWSENDPACKETPROC)BuildStdcallToThiscallThunk((LPVOID)0x00A3BCD0u);
+ pSend = (PFNWSENDPACKETSENDPROC)BuildStdcallToThiscallThunk((LPVOID)0x00A3B340u);
+ pClearToolTip = (PFNCLOBBYMAINCLEARTOOLTIPPROC)BuildStdcallToThiscallThunk((LPVOID)0x00656770u);
+ pSetState = (PFNFRLOGINRSDLGSETSTATEPROC)BuildStdcallToThiscallThunk((LPVOID)0x00AC4380u);
+ pOnUnderBar_RankingUpThunk = BuildThiscallToStdcallThunk((LPVOID)OnUnderBar_RankingUp);
+ pOnLoginRsDlgResultThunk = BuildThiscallToStdcallThunk((LPVOID)OnLoginRsDlgResult);
+ InstallHook((LPVOID)0x00655630, (LPVOID)pOnUnderBar_RankingUpThunk);
+}
+
+static LPVOID CreateFormFrLoginRsDlg(LPVOID _pFrWndManager, LPVOID _pFrCmdTarget, LPCSTR _name,
+ LPVOID _pFrWnd) {
+ static LPVOID g_pFrLoginRsDlgObject = NULL;
+
+ LPCVOID pFrLoginRsDlg_m_RTTI = (LPCVOID)0x00ECA148u;
+
+ LPVOID pFrLoginRsDlgObject = pMakeInstanceFrLoginRsDlg();
+
+ LPVOID pFrLoginRsDlgObjectAfter;
+
+ if (pFrLoginRsDlgObject == NULL) {
+ return NULL;
+ }
+
+ pFrLoginRsDlgObjectAfter =
+ p_Init(pFrLoginRsDlgObject, _pFrWndManager, _pFrCmdTarget, _name, _pFrWnd);
+
+ if (pFrLoginRsDlgObjectAfter != NULL) {
+ // Test to see if it saves the value in tls as it is in pangya
+ g_pFrLoginRsDlgObject = pFrLoginRsDlgObjectAfter;
+
+ return pDynamicCast(pFrLoginRsDlgObjectAfter, pFrLoginRsDlg_m_RTTI);
+ }
+
+ if (pFrLoginRsDlgObject != NULL) {
+ // TODO: need virtual thunk
+ PFNFRFORMLOGINRSDLGSCALARDELETINGDESTRUCTORPROC pPerformLoginRsDlgScalarDeletingDestructor =
+ (PFNFRFORMLOGINRSDLGSCALARDELETINGDESTRUCTORPROC)BuildStdcallToThiscallThunk(
+ GETVTABLEFN(pFrLoginRsDlgObject, 0x04u));
+ pPerformLoginRsDlgScalarDeletingDestructor(pFrLoginRsDlgObject, 1u);
+ FreeMem(pPerformLoginRsDlgScalarDeletingDestructor);
+ }
+
+ return NULL;
+}
+
+static BOOL STDCALL OnLoginRsDlgResult(LPVOID _this, DWORD exit_code /*I think*/, LPVOID _pFrForm) {
+ if (_this != NULL) {
+ *GETTHISPOINTERMEMBER(LPVOID, 0x160u, _this) = NULL;
+ }
+
+ return TRUE;
+}
+
+static void STDCALL OnUnderBar_RankingUp(LPVOID _this) {
+ LPCSTR gRankingDisabledServiceMsg = (LPCSTR)0x00D244E8u;
+ LPVOID gCSharedDocInstance = (*(LPVOID *)0x00E10FACu);
+ LPVOID gWNetworkSystemInstance = (*(LPVOID *)0x00E3CFD0);
+ LPVOID gFresh = (*(LPVOID *)0x00EC9640);
+ LPVOID *FormWndObject = NULL;
+
+ if (pIsControlServerService(gCSharedDocInstance, 0x10000u) != 0u) {
+ LPCSTR translatedMsgStr;
+ stMsgObject msg;
+
+ if (_this == NULL) {
+ return;
+ }
+
+ translatedMsgStr = pBrasilTranslateString(gRankingDisabledServiceMsg);
+ msg = MakeMsgObject(_this, 0x23u, (DWORD)translatedMsgStr, 0u, 0u, 0u, 0u);
+
+ // TODO: need virtual thunk
+ {
+ PFNVIRTUALIACTORHANDLEMSGPROC pIActorHandleMsg =
+ (PFNVIRTUALIACTORHANDLEMSGPROC)BuildStdcallToThiscallThunk(GETVTABLEFN(_this, 0x2Cu));
+ pIActorHandleMsg(_this, &msg);
+ FreeMem(pIActorHandleMsg);
+ return;
+ }
+ }
+
+ // TODO: need virtual thunk
+ {
+ PFNVIRTUALIACTORCLOSEALLDIALOGSPROC pIActorCloseAllDialogs =
+ (PFNVIRTUALIACTORCLOSEALLDIALOGSPROC)BuildStdcallToThiscallThunk(
+ GETVTABLEFN(_this, 0x3Cu));
+ pIActorCloseAllDialogs(_this);
+ FreeMem(pIActorCloseAllDialogs);
+ }
+
+ if (pIsConnected(gWNetworkSystemInstance, 0) == FALSE) {
+ pInit(gWNetworkSystemInstance, 3);
+ pSendMessageA(gWNetworkSystemInstance, 3, 0);
+ } else {
+ BYTE WSendPacketObject[40u];
+ pConstructorWSendPacket((LPVOID)WSendPacketObject, 0x47u);
+ pSend((LPVOID)WSendPacketObject, 0);
+ pDestructorWSendPacket((LPVOID)WSendPacketObject);
+ }
+
+ FormWndObject = GETTHISPOINTERMEMBER(void *, 0x160u, _this);
+
+ if (*FormWndObject == NULL) {
+ *FormWndObject = CreateFormFrLoginRsDlg(*GETTHISPOINTERMEMBER(void *, 0x40u, gFresh),
+ (void *)GETTHISPOINTERMEMBER(void *, 0x18, _this),
+ "login_gs", NULL);
+
+ pSetState(1u);
+
+ // TODO: need virtual thunk
+ {
+ PFNFRFORMOPENPROC pFrFormOpen =
+ (PFNFRFORMOPENPROC)BuildStdcallToThiscallThunk(GETVTABLEFN(*FormWndObject, 0x64u));
+ pFrFormOpen(*FormWndObject, pOnLoginRsDlgResultThunk, 0xFFFFFFE8u, 0, 0, 0x41);
+ FreeMem(pFrFormOpen);
+ }
+ }
+
+ pClearToolTip(_this, NULL);
+
+ return;
+}
diff --git a/src/hooks/projectg/us852/ranking.h b/src/hooks/projectg/us852/ranking.h
new file mode 100644
index 0000000..0e75745
--- /dev/null
+++ b/src/hooks/projectg/us852/ranking.h
@@ -0,0 +1,8 @@
+#ifndef HOOKS_PROJECTG_US852_RANKING_H
+#define HOOKS_PROJECTG_US852_RANKING_H
+
+#include "../../../common.h"
+
+VOID InitUS852RankingHook();
+
+#endif
diff --git a/src/patch.c b/src/patch.c
index a90e59c..cb32870 100644
--- a/src/patch.c
+++ b/src/patch.c
@@ -143,3 +143,77 @@ PVOID HookProc(HMODULE hModule, LPCSTR szName, PVOID pfnTargetProc) {
return pfnTrampolineProc;
}
+
+/**
+ * Creates a thunk that translates from MSVC thiscall to stdcall calling
+ * convention. The returned function pointer can be used in MSVC ABI vtables.
+ */
+PVOID BuildThiscallToStdcallThunk(PVOID pfnProc) {
+ DWORD thunkLen = 9;
+ DWORD oldProtect;
+ DWORD relAddr;
+ PCHAR codeblock;
+
+ // Calculate the jump address.
+ relAddr = (DWORD)pfnProc - (DWORD)codeblock;
+
+ // Allocate data for thunk.
+ codeblock = AllocMem(thunkLen);
+
+ // Create calling convention thunk.
+ // We want to put the this pointer, from ecx, onto the stack at the
+ // left-most argument. Since we were called via stdcall, return address is
+ // the current value on the stack, followed by left-most argument. So, pop
+ // the return address, push the this pointer, and then push the return
+ // address back onto the stack.
+ codeblock[0] = 0x58; // pop eax
+ codeblock[1] = 0x51; // push ecx
+ codeblock[2] = 0x50; // push eax
+ codeblock[3] = 0xE9; // jmp
+ memcpy(&codeblock[4], &relAddr, 4);
+
+ // ...and a return at the end, for good measure.
+ codeblock[8] = 0xC3;
+
+ // Mark the codeblock as executable.
+ pVirtualProtect(codeblock, thunkLen, PAGE_EXECUTE_READWRITE, &oldProtect);
+
+ return codeblock;
+}
+
+/**
+ * Creates a thunk that translates from stdcall to MSVC thiscall calling
+ * convention. The returned function pointer can be called using stdcall.
+ */
+PVOID BuildStdcallToThiscallThunk(PVOID pfnProc) {
+ DWORD thunkLen = 9;
+ DWORD oldProtect;
+ DWORD relAddr;
+ PCHAR codeblock;
+
+ // Calculate the jump address.
+ relAddr = (DWORD)pfnProc - (DWORD)codeblock;
+
+ // Allocate data for thunk.
+ codeblock = AllocMem(thunkLen);
+
+ // Create calling convention thunk.
+ // We want to put the this pointer, from the stack at the left-most
+ // argument, into ecx. Since we were called via thiscall, return address is
+ // the current value on the stack, followed by the this pointer argument.
+ // So, pop the return address, pop the this pointer to ecx, and then push
+ // the return address back onto the stack.
+ codeblock[0] = 0x58; // pop eax
+ codeblock[1] = 0x59; // pop ecx
+ codeblock[2] = 0x50; // push eax
+ codeblock[3] = 0xE9; // jmp
+ memcpy(&codeblock[4], &relAddr, 4);
+
+ // ...and a return at the end, for good measure.
+ codeblock[8] = 0xC3;
+
+ // Mark the codeblock as executable.
+ pVirtualProtect(codeblock, thunkLen, PAGE_EXECUTE_READWRITE, &oldProtect);
+
+ return codeblock;
+}
diff --git a/src/patch.h b/src/patch.h
index c4a55e0..630ed1f 100644
--- a/src/patch.h
+++ b/src/patch.h
@@ -10,5 +10,7 @@ DWORD CountOpcodeBytes(FARPROC fn, DWORD minBytes);
PCHAR BuildTrampoline(DWORD fn, DWORD prefixLen);
PVOID HookFunc(PVOID pfnProc, PVOID pvTargetProc);
PVOID HookProc(HMODULE hModule, LPCSTR szName, PVOID pfnTargetProc);
+PVOID BuildThiscallToStdcallThunk(PVOID pfnProc);
+PVOID BuildStdcallToThiscallThunk(PVOID pfnProc);
#endif
diff --git a/src/patch_usa_852.c b/src/patch_usa_852.c
deleted file mode 100644
index 37c1b90..0000000
--- a/src/patch_usa_852.c
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "patch_usa_852.h"
-
-typedef struct _stMsgObject {
- void* m_pIActor;
- uint32_t m_id;
- uint32_t m_com[5];
- uint32_t m_time;
-} stMsgObject;
-
-inline stMsgObject MakeMsgObject(void* _pIActor, uint32_t _id, uint32_t _c0, uint32_t _c1, uint32_t _c2, uint32_t _c3, uint32_t _c4) {
- return (stMsgObject) { _pIActor, _id, _c0, _c1, _c2, _c3, _c4, 0u };
-}
-
-#define MAKEPROTOTYPETHISFUNCTION(_return_, _fnPrototype_, _type_this_, ...) typedef _return_ (__thiscall *_fnPrototype_)(_type_this_, uint32_t/*register EDX*/, __VA_ARGS__)
-#define CALLTHISFUNCTION(_func_, _this_, ...) _func_(_this_, 0u/*register EDX*/, __VA_ARGS__)
-
-#define MAKEVIRTUALCALL(_fnPrototype_, _addr_, _this_) (*(_fnPrototype_*)(*((uint8_t**)(_this_)) + (_addr_)))
-#define CALLTHISVIRTUALCALL(_fnPrototype_, _addr_, _this_, ...) CALLTHISFUNCTION(MAKEVIRTUALCALL(_fnPrototype_, _addr_, _this_), _this_, __VA_ARGS__)
-
-#define GETTHISPOINTERMEMBER(_type_, _addr_, _this_) (_type_*)(((uint8_t*)(_this_)) + (_addr_))
-
-typedef void* (__cdecl *PFNMAKEINSTANCEFRLOGINRSDLG)(void);
-typedef const char* (__fastcall *PFNBRASILTRANSLATESTRINGPROC)(const char* _str);
-typedef void(__fastcall *PFNFRLOGINRSDLGSETSTATEPROC)(uint32_t _state);
-
-MAKEPROTOTYPETHISFUNCTION(void*, PFNFRFORM_INITPROC, void*, void*, void*, const char*, void*);
-MAKEPROTOTYPETHISFUNCTION(void*, PFNIOBJECTDYNAMICCASTPROC, void*, const void*);
-MAKEPROTOTYPETHISFUNCTION(void*, PFNFRFORMLOGINRSDLGSCALARDELETINGDESTRUCTORPROC, void*, uint32_t);
-
-MAKEPROTOTYPETHISFUNCTION(uint64_t, PFNCSHAREDDOCISCONTROLSERVERSERVICEPROC, void*, uint64_t);
-MAKEPROTOTYPETHISFUNCTION(void, PFNVIRTUALIACTORHANDLEMSGPROC, void*, stMsgObject*);
-MAKEPROTOTYPETHISFUNCTION(void, PFNVIRTUALIACTORCLOSEALLDIALOGSPROC, void*);
-MAKEPROTOTYPETHISFUNCTION(BOOL, PFNWNETWORKSYSTEMISCONNECTEDPROC, void*, uint32_t);
-MAKEPROTOTYPETHISFUNCTION(BOOL, PFNWNETWORKSYSTEMINITPROC, void*, uint32_t);
-MAKEPROTOTYPETHISFUNCTION(BOOL, PFNWNETWORKSYSTEMSENDMESSAGEAPROC, void*, uint32_t, uint32_t);
-MAKEPROTOTYPETHISFUNCTION(void, PFNCONSTRUCTORWSENDPACKETPROC, void*, uint32_t);
-MAKEPROTOTYPETHISFUNCTION(void, PFNDESTRUCTORWSENDPACKETPROC, void*);
-MAKEPROTOTYPETHISFUNCTION(void, PFNWSENDPACKETSENDPROC, void*, uint32_t);
-MAKEPROTOTYPETHISFUNCTION(void, PFNCLOBBYMAINCLEARTOOLTIPPROC, void*, void*);
-MAKEPROTOTYPETHISFUNCTION(BOOL, PFNFRLOGINRSDLGONLOGINRSDLGRESULTPROC, void*, int32_t, void*);
-MAKEPROTOTYPETHISFUNCTION(BOOL, PFNFRFORMOPENPROC, void*, PFNFRLOGINRSDLGONLOGINRSDLGRESULTPROC, uint32_t, uint32_t, uint32_t, uint32_t);
-
-void* CreateFormFrLoginRsDlg(void* _pFrWndManager, void* _pFrCmdTarget, const char* _name, void* _pFrWnd) {
-
- static void* g_pFrLoginRsDlgObject = NULL;
-
- PFNMAKEINSTANCEFRLOGINRSDLG pMakeInstanceFrLoginRsDlg = (PFNMAKEINSTANCEFRLOGINRSDLG)0x00AC4680u;
- PFNFRFORM_INITPROC p_Init = (PFNFRFORM_INITPROC)0x00BCDD40u;
- PFNIOBJECTDYNAMICCASTPROC pDynamicCast = (PFNIOBJECTDYNAMICCASTPROC)0x0047EFF0u;
-
- const void* pFrLoginRsDlg_m_RTTI = (const void*)0x00ECA148u;
-
- void* pFrLoginRsDlgObject = pMakeInstanceFrLoginRsDlg();
-
- if (pFrLoginRsDlgObject == NULL)
- return NULL;
-
- void* pFrLoginRsDlgObjectAfter = CALLTHISFUNCTION(p_Init, pFrLoginRsDlgObject, _pFrWndManager, _pFrCmdTarget, _name, _pFrWnd);
-
- if (pFrLoginRsDlgObjectAfter != NULL) {
-
- // Test to see if it saves the value in tls as it is in pangya
- g_pFrLoginRsDlgObject = pFrLoginRsDlgObjectAfter;
-
- return CALLTHISFUNCTION(pDynamicCast, pFrLoginRsDlgObjectAfter, pFrLoginRsDlg_m_RTTI);
- }
-
- if (pFrLoginRsDlgObject != NULL)
- CALLTHISVIRTUALCALL(PFNFRFORMLOGINRSDLGSCALARDELETINGDESTRUCTORPROC, 0x04u, pFrLoginRsDlgObject, 1u);
-
- return NULL;
-}
-
-BOOL __thiscall OnLoginRsDlgResult(void* _this, uint32_t _EDX, int32_t exit_code/*I think*/, void* _pFrForm) {
- (_EDX); // UNREFERENCED_PARAMETER
-
- if (_this != NULL)
- *GETTHISPOINTERMEMBER(void*, 0x160u, _this) = NULL;
-
- return TRUE;
-}
-
-void __thiscall OnUnderBar_RankingUp(void* _this) {
-
- PFNCSHAREDDOCISCONTROLSERVERSERVICEPROC pIsControlServerService = (PFNCSHAREDDOCISCONTROLSERVERSERVICEPROC)0x0062E4A0;
- PFNBRASILTRANSLATESTRINGPROC pBrasilTranslateString = (PFNBRASILTRANSLATESTRINGPROC)0x00B3A7E0u;
- PFNWNETWORKSYSTEMISCONNECTEDPROC pIsConnected = (PFNWNETWORKSYSTEMISCONNECTEDPROC)0x00A3AEB0u;
- PFNWNETWORKSYSTEMINITPROC pInit = (PFNWNETWORKSYSTEMINITPROC)0x00A3AD40u;
- PFNWNETWORKSYSTEMSENDMESSAGEAPROC pSendMessageA = (PFNWNETWORKSYSTEMSENDMESSAGEAPROC)0x00A3ADB0u;
- PFNCONSTRUCTORWSENDPACKETPROC pConstructorWSendPacket = (PFNCONSTRUCTORWSENDPACKETPROC)0x00A3BEE0u;
- PFNDESTRUCTORWSENDPACKETPROC pDestructorWSendPacket = (PFNDESTRUCTORWSENDPACKETPROC)0x00A3BCD0u;
- PFNWSENDPACKETSENDPROC pSend = (PFNWSENDPACKETSENDPROC)0x00A3B340u;
- PFNCLOBBYMAINCLEARTOOLTIPPROC pClearToolTip = (PFNCLOBBYMAINCLEARTOOLTIPPROC)0x00656770u;
- PFNFRLOGINRSDLGSETSTATEPROC pSetState = (PFNFRLOGINRSDLGSETSTATEPROC)0x00AC4380u;
-
- const char* gRankingDisabledServiceMsg = (const char*)0x00D244E8u;
- void* gCSharedDocInstance = (*(void**)0x00E10FACu);
- void* gWNetworkSystemInstance = (*(void**)0x00E3CFD0);
- void* gFresh = (*(void**)0x00EC9640);
-
- if (CALLTHISFUNCTION(pIsControlServerService, gCSharedDocInstance, 0x10000u) != 0u) {
-
- if (_this == NULL)
- return;
-
- stMsgObject msg = MakeMsgObject(_this, 0x23u, (uint32_t)pBrasilTranslateString(gRankingDisabledServiceMsg), 0u, 0u, 0u, 0u);
-
- CALLTHISVIRTUALCALL(PFNVIRTUALIACTORHANDLEMSGPROC, 0x2Cu, _this, &msg);
-
- return;
- }
-
- CALLTHISVIRTUALCALL(PFNVIRTUALIACTORCLOSEALLDIALOGSPROC, 0x3Cu, _this);
-
- if (CALLTHISFUNCTION(pIsConnected, gWNetworkSystemInstance, 0) == FALSE) {
-
- CALLTHISFUNCTION(pInit, gWNetworkSystemInstance, 3);
- CALLTHISFUNCTION(pSendMessageA, gWNetworkSystemInstance, 3, 0);
-
- }else {
-
- uint8_t WSendPacketObject[40u];
-
- CALLTHISFUNCTION(pConstructorWSendPacket, (void*)WSendPacketObject, 0x47u);
- CALLTHISFUNCTION(pSend, (void*)WSendPacketObject, 0);
- CALLTHISFUNCTION(pDestructorWSendPacket, (void*)WSendPacketObject);
- }
-
- void** FormWndObject = GETTHISPOINTERMEMBER(void*, 0x160u, _this);
-
- if (*FormWndObject == NULL) {
-
- *FormWndObject = CreateFormFrLoginRsDlg(*GETTHISPOINTERMEMBER(void*, 0x40u, gFresh), (void*)GETTHISPOINTERMEMBER(void*, 0x18, _this), "login_gs", NULL);
-
- pSetState(1u);
-
- CALLTHISVIRTUALCALL(PFNFRFORMOPENPROC, 0x64u, *FormWndObject, OnLoginRsDlgResult, 0xFFFFFFE8u, 0, 0, 0x41);
- }
-
- CALLTHISFUNCTION(pClearToolTip, _this, NULL);
-
- return;
-}
diff --git a/src/patch_usa_852.h b/src/patch_usa_852.h
deleted file mode 100644
index 23b3b5a..0000000
--- a/src/patch_usa_852.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef PATCH_USA_852_H
-#define PATCH_USA_852_H
-
-#include "common.h"
-#include
-
-// C not have __thiscall
-#define __thiscall __fastcall
-
-void __thiscall OnUnderBar_RankingUp(void* _this);
-
-#endif