From 64376e726318c0bcab2be7a7a07e80ef26fd8e10 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 01:44:38 +0000 Subject: [PATCH] Decompile 9 functions in Source/Client/Mode/LoginMode.cpp, Source/Client/Mode/CLoginMode.h Batch #4181 by youko: 4 byte-identical, 5 confirmed by peer review. - fn_22265 CLoginMode::SubD8D4F0: byte-identical - fn_22270 GetClientType: logic confirmed by peer review - fn_22272 CLoginMode::GetMaxCharacterSlot: logic confirmed by peer review - fn_22273 GetUserCountText: logic confirmed by peer review - fn_22274 CLoginMode::ReceiveCharacterSlots: logic confirmed by peer review - fn_22276 CLoginMode::SubD8EDC0: byte-identical - fn_22279 CLoginMode::SubD8F560: byte-identical - fn_22280 CLoginMode::ReceiveCharacterList: logic confirmed by peer review - fn_22288 CLoginMode::SubD91780: byte-identical Peer-reviewed-by: Yommy, superintelligence, tayoba Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). Adds to the build: Source/Client/Mode/LoginMode.cpp --- Source/Client/Mode/CLoginMode.h | 65 +++++++++ Source/Client/Mode/LoginMode.cpp | 227 +++++++++++++++++++++++++++++++ data/compile.json | 1 + 3 files changed, 293 insertions(+) create mode 100644 Source/Client/Mode/CLoginMode.h create mode 100644 Source/Client/Mode/LoginMode.cpp diff --git a/Source/Client/Mode/CLoginMode.h b/Source/Client/Mode/CLoginMode.h new file mode 100644 index 00000000..4860bba5 --- /dev/null +++ b/Source/Client/Mode/CLoginMode.h @@ -0,0 +1,65 @@ +#ifndef RAGNAROK_SOURCE_CLIENT_MODE_CLOGINMODE_H +#define RAGNAROK_SOURCE_CLIENT_MODE_CLOGINMODE_H + +#include "Client/Mode/CMode.h" + +#include +#include + +struct CharacterListPacket; +struct CharacterSlotsPacket; + +#pragma pack(push, 1) +struct CharacterInfo { + /* 0000 */ std::uint32_t gid; + /* 0004 */ unsigned char unknown_0004[0x86]; + /* 008A */ unsigned char slot; + /* 008B */ unsigned char unknown_008B[0x24]; +}; + +struct CharacterSlotExtension { + /* 0000 */ unsigned char unknown_0000; + /* 0001 */ std::uint32_t unknown_0001; + /* 0005 */ std::uint32_t unknown_0005; + /* 0009 */ std::uint32_t unknown_0009; + /* 000D */ unsigned char unknown_000D[7]; +}; +#pragma pack(pop) + +class CLoginMode : public CMode { +public: + /* 0058 */ unsigned char unknown_0058[0x174]; + /* 01CC */ int characterCount; + /* 01D0 */ unsigned char unknown_01D0[0x8]; + /* 01D8 */ int unknown_01D8; + /* 01DC */ int unknown_01DC; + /* 01E0 */ unsigned char unknown_01E0[0x3E88]; + /* 4068 */ CharacterInfo characters[68]; + /* 6EE4 */ unsigned char unknown_6EE4[0x18]; + /* 6EFC */ CharacterSlotExtension slotExtension; + /* 6F10 */ unsigned char unknown_6F10[0x6C]; + + void SubD8D4F0(int); + int GetMaxCharacterSlot(); + void ReceiveCharacterSlots(const CharacterSlotsPacket* packet); + void SubD8EDC0(int); + void SubD8F560(int); + void ReceiveCharacterList(const CharacterListPacket* packet); + void SubD91780(int); +}; + +int GetClientType(); +const char* GetUserCountText(unsigned short userCount); + +#if defined(_WIN32) && !defined(_WIN64) +static_assert(sizeof(CharacterInfo) == 0xAF); +static_assert(offsetof(CharacterInfo, slot) == 0x8A); +static_assert(sizeof(CharacterSlotExtension) == 0x14); +static_assert(offsetof(CLoginMode, characterCount) == 0x1CC); +static_assert(offsetof(CLoginMode, unknown_01D8) == 0x1D8); +static_assert(offsetof(CLoginMode, characters) == 0x4068); +static_assert(offsetof(CLoginMode, slotExtension) == 0x6EFC); +static_assert(sizeof(CLoginMode) == 0x6F7C); +#endif + +#endif diff --git a/Source/Client/Mode/LoginMode.cpp b/Source/Client/Mode/LoginMode.cpp new file mode 100644 index 00000000..dc672a85 --- /dev/null +++ b/Source/Client/Mode/LoginMode.cpp @@ -0,0 +1,227 @@ +#include "Client/Mode/CLoginMode.h" +#include "Client/Session.h" +#include "Contents/Configuration/ServiceConfiguration.h" +#include "Contents/MessageTable.h" + +#include +#include +#include +#include +#include + +#pragma pack(push, 1) +struct CharacterSlotsPacket { + /* 0000 */ std::int16_t id; + /* 0002 */ std::uint16_t length; + /* 0004 */ unsigned char normalSlots; + /* 0005 */ unsigned char premiumSlots; + /* 0006 */ unsigned char billingSlots; + /* 0007 */ unsigned char producibleSlots; + /* 0008 */ unsigned char validSlots; + /* 0009 */ CharacterSlotExtension extension; +}; + +struct CharacterListPacket { + /* 0000 */ std::int16_t id; + /* 0002 */ std::uint16_t length; + /* 0004 */ CharacterInfo characters[1]; +}; +#pragma pack(pop) + +static_assert(sizeof(CharacterSlotsPacket) == 0x1D); + +// OFFSET: 0x00D8D4F0 +// FUNCTION: fn_22265 +void CLoginMode::SubD8D4F0(int) { +} + +// OFFSET: 0x00D8E1D0 +// FUNCTION: fn_22270 +int GetClientType() { + switch (g_serviceMode) { + case 1: + switch (g_serviceType) { + case 1: + return 14; + case 2: + return 9; + case 3: + return 4; + case 4: + return 5; + case 5: + return 7; + case 6: + return 13; + case 7: + return 18; + case 8: + return 16; + case 9: + return 17; + case 10: + return 20; + case 11: + return 21; + case 12: + return 22; + case 13: + return 23; + case 14: + return 25; + case 15: + return 33; + case 19: + return 35; + case 20: + return 36; + default: + return 2; + } + + case 5: + switch (g_serviceType) { + case 2: + return 28; + case 5: + return 29; + case 6: + return 34; + case 7: + return 27; + case 15: + return 32; + default: + return 0; + } + + default: + switch (g_serviceType) { + case 1: + return 1; + case 2: + return 3; + case 3: + return 4; + case 4: + return 5; + case 5: + return 7; + case 6: + return 12; + case 7: + return 15; + case 8: + return 16; + case 9: + return 17; + case 10: + return 20; + case 11: + return 21; + case 12: + return 22; + case 13: + return 23; + case 14: + return 25; + case 15: + return 26; + case 17: + return 30; + case 18: + return 31; + case 19: + return 35; + case 20: + return 36; + default: + return 0; + } + } +} + +// OFFSET: 0x00D8E700 +// FUNCTION: fn_22272 +int CLoginMode::GetMaxCharacterSlot() { + if (this == nullptr) { + return 0; + } + + int maxSlot = -1; + for (long long i = 0; i < 68; ++i) { + if (this->characters[i].gid == 0) { + break; + } + + maxSlot = std::max(maxSlot, static_cast(this->characters[i].slot)); + } + + return maxSlot; +} + +// OFFSET: 0x00D8E770 +// FUNCTION: fn_22273 +const char* GetUserCountText(unsigned short userCount) { + if (userCount <= 1000) { + return LookupMessage(825); + } + + if (userCount <= 3000) { + return LookupMessage(826); + } + + if (userCount <= 6000) { + return LookupMessage(827); + } + + if (userCount <= 10000) { + return LookupMessage(828); + } + + return LookupMessage(829); +} + +// OFFSET: 0x00D8E990 +// FUNCTION: fn_22274 +void CLoginMode::ReceiveCharacterSlots(const CharacterSlotsPacket* packet) { + g_session.unknown_59C0 = packet->normalSlots; + g_session.unknown_59C4 = packet->premiumSlots; + g_session.unknown_59C8 = packet->billingSlots; + g_session.unknown_59CC = packet->validSlots; + g_session.unknown_59D4 = packet->producibleSlots; + + SecureZeroMemory(this->characters, sizeof(this->characters)); + g_session.unknown_59BC = 0; + this->unknown_01D8 = 0; + this->unknown_01DC = 0; + + this->slotExtension = packet->extension; + this->slotExtension.unknown_0001 = htonl(this->slotExtension.unknown_0001); + this->slotExtension.unknown_0005 = htonl(this->slotExtension.unknown_0005); + this->slotExtension.unknown_0009 = htonl(this->slotExtension.unknown_0009); +} + +// OFFSET: 0x00D8EDC0 +// FUNCTION: fn_22276 +void CLoginMode::SubD8EDC0(int) { +} + +// OFFSET: 0x00D8F560 +// FUNCTION: fn_22279 +void CLoginMode::SubD8F560(int) { +} + +// OFFSET: 0x00D8F8E0 +// FUNCTION: fn_22280 +void CLoginMode::ReceiveCharacterList(const CharacterListPacket* packet) { + this->characterCount = (packet->length - 4) / sizeof(CharacterInfo); + g_session.unknown_59BC = this->characterCount; + memcpy_s(this->characters, sizeof(this->characters), packet->characters, this->characterCount * sizeof(CharacterInfo)); + this->pendingCursorType = 7; +} + +// OFFSET: 0x00D91780 +// FUNCTION: fn_22288 +void CLoginMode::SubD91780(int) { +} diff --git a/data/compile.json b/data/compile.json index d3330048..4cb74bea 100644 --- a/data/compile.json +++ b/data/compile.json @@ -260,6 +260,7 @@ "Source/Client/Mode/GameModeNotices.cpp": 0, "Source/Client/Mode/GameModePackets.cpp": 0, "Source/Client/Mode/GameModeProtocol.cpp": 0, + "Source/Client/Mode/LoginMode.cpp": 0, "Source/Client/Mode/ModeCursor.cpp": 0, "Source/Client/Mode/ModeDragState.cpp": 2, "Source/Client/Mode/ModeLifetime.cpp": 0,