From cd54b65ff6fa8e58e11f1dfb5d0f6b4cb37caab7 Mon Sep 17 00:00:00 2001 From: ragnarok-clanker Date: Fri, 30 Oct 2026 04:00:21 +0000 Subject: [PATCH] Decompile 10 functions in Source/Client/Mode/CGameMode.h, Source/Client/Mode/GameModePackets.cpp, ... Batch #4422 by eAthena: 3 byte-identical, 7 confirmed by peer review. - fn_21638 CGameMode::IgnoreRemovedPacket3: byte-identical - fn_21649 CGameMode::IgnoreRemovedPacket4: byte-identical - fn_21653 CGameMode::IgnoreRemovedPacket5: byte-identical - fn_21657 CGameMode::ReceiveUnknown05C4Result: logic confirmed by peer review - fn_21640 CGameMode::ReceiveItem1738Add: logic confirmed by peer review - fn_21644 CGameMode::ReceiveItem1740Add: logic confirmed by peer review - fn_21645 CGameMode::ReceiveItem1740AddOptions: logic confirmed by peer review - fn_21646 CGameMode::ReceiveItem1740AddGrade: logic confirmed by peer review - fn_21647 CGameMode::ReceiveItem1738AddOptions: logic confirmed by peer review - fn_21648 CGameMode::ReceiveItem1738AddGrade: logic confirmed by peer review Peer-reviewed-by: willerthal, KWDev, Qwenkler3.8 Accepted without human review: peers confirmed the logic ("same" ahead by at least 3, with 70% of the votes). --- Source/Client/Mode/CGameMode.h | 16 ++- Source/Client/Mode/GameModePackets.cpp | 67 +++++++++ Source/Contents/ClientItemLists.cpp | 189 +++++++++++++++++++++++++ 3 files changed, 271 insertions(+), 1 deletion(-) diff --git a/Source/Client/Mode/CGameMode.h b/Source/Client/Mode/CGameMode.h index bd92711f..6abaf000 100644 --- a/Source/Client/Mode/CGameMode.h +++ b/Source/Client/Mode/CGameMode.h @@ -42,7 +42,10 @@ public: /* 02EC */ std::string unknown_02EC; /* 0304 */ unsigned char unknown_0304[0x04]; /* 0308 */ ModeDragState drag; - /* 03C8 */ unsigned char unknown_03C8[0x208]; + /* 03C8 */ unsigned char unknown_03C8[0x1FC]; + /* 05C4 */ int unknown_05C4; + /* 05C8 */ int unknown_05C8; + /* 05CC */ unsigned char unknown_05CC[0x04]; /* 05D0 */ UIWindow* unknown_05D0; /* 05D4 */ unsigned char unknown_05D4[0x54]; /* 0628 */ std::unordered_set unknown_0628; @@ -123,6 +126,16 @@ public: void ReceivePackageSimulation(const unsigned char* packet); void ReceiveWindow154Result(std::int16_t value); void UpdateUnknown0628(int id, bool add); + void IgnoreRemovedPacket3(const unsigned char* packet); + void IgnoreRemovedPacket4(const unsigned char* packet); + void IgnoreRemovedPacket5(const unsigned char* packet); + void ReceiveItem1738Add(const unsigned char* packet); + void ReceiveItem1738AddOptions(const unsigned char* packet); + void ReceiveItem1738AddGrade(const unsigned char* packet); + void ReceiveItem1740Add(const unsigned char* packet); + void ReceiveItem1740AddOptions(const unsigned char* packet); + void ReceiveItem1740AddGrade(const unsigned char* packet); + void ReceiveUnknown05C4Result(const unsigned char* packet); }; #if defined(_WIN32) && !defined(_WIN64) @@ -136,6 +149,7 @@ static_assert(offsetof(CGameMode, camera) == 0xD0); static_assert(offsetof(CGameMode, nameCard) == 0x160); static_assert(offsetof(CGameMode, unknown_0294) == 0x294); static_assert(offsetof(CGameMode, drag) == 0x308); +static_assert(offsetof(CGameMode, unknown_05C4) == 0x5C4); static_assert(offsetof(CGameMode, unknown_05D0) == 0x5D0); static_assert(offsetof(CGameMode, unknown_0628) == 0x628); static_assert(sizeof(CGameMode) == 0x670); diff --git a/Source/Client/Mode/GameModePackets.cpp b/Source/Client/Mode/GameModePackets.cpp index 80a51127..2ba6a0ff 100644 --- a/Source/Client/Mode/GameModePackets.cpp +++ b/Source/Client/Mode/GameModePackets.cpp @@ -55,6 +55,17 @@ namespace { /* 002A */ int unknown_002A; /* 002E */ int count; }; + + struct NamedProgressPacket { + /* 0000 */ std::uint16_t packetType; + /* 0002 */ unsigned char result; + /* 0003 */ int first; + /* 0007 */ int second; + /* 000B */ std::uint16_t current; + /* 000D */ std::uint16_t total; + /* 000F */ unsigned char unknown_000F[4]; + /* 0013 */ char name[1]; + }; #pragma pack(pop) static_assert(sizeof(SimulationPacketHeader) == 0x24); @@ -62,6 +73,62 @@ namespace { static_assert(sizeof(PackageSimulationRecord) == 0x32); } +// OFFSET: 0x00D1F540 +// FUNCTION: fn_21638 +void CGameMode::IgnoreRemovedPacket3(const unsigned char*) { +} + +// OFFSET: 0x00D208F0 +// FUNCTION: fn_21649 +void CGameMode::IgnoreRemovedPacket4(const unsigned char*) { +} + +// OFFSET: 0x00D21210 +// FUNCTION: fn_21653 +void CGameMode::IgnoreRemovedPacket5(const unsigned char*) { +} + +// OFFSET: 0x00D21D00 +// FUNCTION: fn_21657 +void CGameMode::ReceiveUnknown05C4Result(const unsigned char* data) { + const auto* packet = reinterpret_cast(data); + char message[256]; + char name[51] = {}; + std::sprintf(name, "%s", packet->name); + this->unknown_05C4 = -1; + this->unknown_05C8 = -1; + + switch (packet->result) { + case 0: + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(LookupMessage(1223)), 0xFFFFFF, 0, 0, 0); + g_windowMgr.SendNotice(19, reinterpret_cast(LookupMessage(1223)), 0xFFFFFF, 0, 0, 0); + return; + case 1: + case 2: + this->unknown_05C4 = packet->first; + this->unknown_05C8 = packet->second; + if (packet->result != 2) { + return; + } + std::sprintf(message, LookupMessage(1225), name); + break; + case 3: + if (packet->current == 0 && packet->total == 1) { + std::sprintf(message, LookupMessage(1261), name); + } else { + std::sprintf(message, LookupMessage(1224), name, packet->current, packet->total); + } + break; + default: + return; + } + + g_windowMgr.SendNotice(3, 0, 0, 0, 0, 0); + g_windowMgr.SendNotice(1, reinterpret_cast(message), 0xFFFFFF, 0, 0, 0); + g_windowMgr.SendNotice(19, reinterpret_cast(message), 0xFFFFFF, 0, 0, 0); +} + // OFFSET: 0x00D230E0 // FUNCTION: fn_21660 void CGameMode::ReceiveColoredNotice(const unsigned char* packet) { diff --git a/Source/Contents/ClientItemLists.cpp b/Source/Contents/ClientItemLists.cpp index 5d4ddd0f..7b78d65f 100644 --- a/Source/Contents/ClientItemLists.cpp +++ b/Source/Contents/ClientItemLists.cpp @@ -35,6 +35,45 @@ namespace { /* 0002 */ std::int16_t value; /* 0004 */ unsigned char param; }; + + struct ItemAddPacket { + /* 0000 */ std::int16_t id; + /* 0002 */ std::int16_t index; + /* 0004 */ int amount; + /* 0008 */ int itemId; + /* 000C */ unsigned char type; + /* 000D */ unsigned char identified; + /* 000E */ unsigned char damaged; + /* 000F */ unsigned char refine; + /* 0010 */ std::uint32_t cards[4]; + }; + + struct ItemAddOptionsPacket { + /* 0000 */ std::int16_t id; + /* 0002 */ std::int16_t index; + /* 0004 */ int amount; + /* 0008 */ int itemId; + /* 000C */ unsigned char type; + /* 000D */ unsigned char identified; + /* 000E */ unsigned char damaged; + /* 000F */ unsigned char refine; + /* 0010 */ std::uint32_t cards[4]; + /* 0020 */ ItemRandomOption options[5]; + }; + + struct ItemAddGradePacket { + /* 0000 */ std::int16_t id; + /* 0002 */ std::int16_t index; + /* 0004 */ int amount; + /* 0008 */ int itemId; + /* 000C */ unsigned char type; + /* 000D */ unsigned char identified; + /* 000E */ unsigned char damaged; + /* 000F */ std::uint32_t cards[4]; + /* 001F */ ItemRandomOption options[5]; + /* 0038 */ unsigned char refine; + /* 0039 */ unsigned char grade; + }; #pragma pack(pop) bool IsSameItem(const ITEM_INFO& value, const ITEM_INFO& item) { @@ -76,6 +115,9 @@ namespace { #if defined(_WIN32) && !defined(_WIN64) static_assert(sizeof(ItemRandomOption) == 5); +static_assert(sizeof(ItemAddPacket) == 0x20); +static_assert(sizeof(ItemAddOptionsPacket) == 0x39); +static_assert(sizeof(ItemAddGradePacket) == 0x3A); #endif struct ClientItemLists { @@ -213,6 +255,153 @@ void __fastcall RefreshItemWindows(UIWindowMgr* mgr) { } } +// INLINED +static int CountItemOptions(const ItemRandomOption* options) { + int count = 0; + for (int index = 0; index < 5; ++index) { + if (options[index].id != 0) { + ++count; + } + } + return count; +} + +// OFFSET: 0x00D1F5A0 +// FUNCTION: fn_21640 +void CGameMode::ReceiveItem1738Add(const unsigned char* data) { + const ItemAddPacket packet = *reinterpret_cast(data); + ItemRandomOption options[5] = {}; + ITEM_INFO item; + item.unknown_0000[1] = packet.index; + item.quantity = packet.amount; + item.SetItemId(packet.itemId); + item.identified = packet.identified; + item.unknown_005D = packet.damaged; + item.unknown_0060 = packet.refine; + item.unknown_0000[0] = packet.type; + std::memcpy(item.unknown_001C, packet.cards, sizeof(packet.cards)); + item.unknown_0098 = CountItemOptions(options); + for (int index = 0; index < item.unknown_0098; ++index) { + reinterpret_cast(item.unknown_009C)[index] = options[index]; + } + item.unknown_0088 = 0; + reinterpret_cast(&g_session)->AddItem1738(item, 1); +} + +// OFFSET: 0x00D1FDA0 +// FUNCTION: fn_21644 +void CGameMode::ReceiveItem1740Add(const unsigned char* data) { + const ItemAddPacket packet = *reinterpret_cast(data); + ItemRandomOption options[5] = {}; + ITEM_INFO item; + item.unknown_0000[1] = packet.index; + item.quantity = packet.amount; + item.SetItemId(packet.itemId); + item.identified = packet.identified; + item.unknown_005D = packet.damaged; + item.unknown_0060 = packet.refine; + item.unknown_0000[0] = packet.type; + std::memcpy(item.unknown_001C, packet.cards, sizeof(packet.cards)); + item.unknown_0098 = CountItemOptions(options); + for (int index = 0; index < item.unknown_0098; ++index) { + reinterpret_cast(item.unknown_009C)[index] = options[index]; + } + item.unknown_0088 = 0; + reinterpret_cast(&g_session)->AddItem1740(item); +} + +// OFFSET: 0x00D1FF70 +// FUNCTION: fn_21645 +void CGameMode::ReceiveItem1740AddOptions(const unsigned char* data) { + const ItemAddOptionsPacket packet = *reinterpret_cast(data); + ItemRandomOption options[5]; + std::memcpy(options, packet.options, sizeof(options)); + ITEM_INFO item; + item.unknown_0000[1] = packet.index; + item.quantity = packet.amount; + item.SetItemId(packet.itemId); + item.identified = packet.identified; + item.unknown_005D = packet.damaged; + item.unknown_0060 = packet.refine; + item.unknown_0000[0] = packet.type; + std::memcpy(item.unknown_001C, packet.cards, sizeof(packet.cards)); + item.unknown_0098 = CountItemOptions(options); + for (int index = 0; index < item.unknown_0098; ++index) { + reinterpret_cast(item.unknown_009C)[index] = options[index]; + } + item.unknown_0088 = 0; + reinterpret_cast(&g_session)->AddItem1740(item); +} + +// OFFSET: 0x00D20180 +// FUNCTION: fn_21646 +void CGameMode::ReceiveItem1740AddGrade(const unsigned char* data) { + const ItemAddGradePacket packet = *reinterpret_cast(data); + ItemRandomOption options[5]; + std::memcpy(options, packet.options, sizeof(options)); + ITEM_INFO item; + item.unknown_0000[1] = packet.index; + item.quantity = packet.amount; + item.SetItemId(packet.itemId); + item.identified = packet.identified; + item.unknown_005D = packet.damaged; + item.unknown_0060 = packet.refine; + item.unknown_0000[0] = packet.type; + std::memcpy(item.unknown_001C, packet.cards, sizeof(packet.cards)); + item.unknown_0098 = CountItemOptions(options); + for (int index = 0; index < item.unknown_0098; ++index) { + reinterpret_cast(item.unknown_009C)[index] = options[index]; + } + item.unknown_0088 = packet.grade; + reinterpret_cast(&g_session)->AddItem1740(item); +} + +// OFFSET: 0x00D204B0 +// FUNCTION: fn_21647 +void CGameMode::ReceiveItem1738AddOptions(const unsigned char* data) { + const ItemAddOptionsPacket packet = *reinterpret_cast(data); + ItemRandomOption options[5]; + std::memcpy(options, packet.options, sizeof(options)); + ITEM_INFO item; + item.unknown_0000[1] = packet.index; + item.quantity = packet.amount; + item.SetItemId(packet.itemId); + item.identified = packet.identified; + item.unknown_005D = packet.damaged; + item.unknown_0060 = packet.refine; + item.unknown_0000[0] = packet.type; + std::memcpy(item.unknown_001C, packet.cards, sizeof(packet.cards)); + item.unknown_0098 = CountItemOptions(options); + for (int index = 0; index < item.unknown_0098; ++index) { + reinterpret_cast(item.unknown_009C)[index] = options[index]; + } + item.unknown_0088 = 0; + reinterpret_cast(&g_session)->AddItem1738(item, 1); +} + +// OFFSET: 0x00D206C0 +// FUNCTION: fn_21648 +void CGameMode::ReceiveItem1738AddGrade(const unsigned char* data) { + const ItemAddGradePacket packet = *reinterpret_cast(data); + ItemRandomOption options[5]; + std::memcpy(options, packet.options, sizeof(options)); + ITEM_INFO item; + item.unknown_0000[1] = packet.index; + item.quantity = packet.amount; + item.SetItemId(packet.itemId); + item.identified = packet.identified; + item.unknown_005D = packet.damaged; + item.unknown_0060 = packet.refine; + item.unknown_0000[0] = packet.type; + std::memcpy(item.unknown_001C, packet.cards, sizeof(packet.cards)); + item.unknown_0098 = CountItemOptions(options); + for (int index = 0; index < item.unknown_0098; ++index) { + reinterpret_cast(item.unknown_009C)[index] = options[index]; + } + item.unknown_0088 = packet.grade; + reinterpret_cast(&g_session)->AddItem1738(item, 1); +} + // OFFSET: 0x00DD43A0 // FUNCTION: fn_23232 EquipSlots EquipSlotDecoder::Decode(int mask) const {