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).
This commit is contained in:
ragnarok-clanker 2026-10-30 04:00:21 +00:00
commit cd54b65ff6
3 changed files with 271 additions and 1 deletions

View file

@ -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<int> 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);

View file

@ -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<const NamedProgressPacket*>(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<std::intptr_t>(LookupMessage(1223)), 0xFFFFFF, 0, 0, 0);
g_windowMgr.SendNotice(19, reinterpret_cast<std::intptr_t>(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<std::intptr_t>(message), 0xFFFFFF, 0, 0, 0);
g_windowMgr.SendNotice(19, reinterpret_cast<std::intptr_t>(message), 0xFFFFFF, 0, 0, 0);
}
// OFFSET: 0x00D230E0
// FUNCTION: fn_21660
void CGameMode::ReceiveColoredNotice(const unsigned char* packet) {

View file

@ -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<const ItemAddPacket*>(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<ItemRandomOption*>(item.unknown_009C)[index] = options[index];
}
item.unknown_0088 = 0;
reinterpret_cast<ClientItemLists*>(&g_session)->AddItem1738(item, 1);
}
// OFFSET: 0x00D1FDA0
// FUNCTION: fn_21644
void CGameMode::ReceiveItem1740Add(const unsigned char* data) {
const ItemAddPacket packet = *reinterpret_cast<const ItemAddPacket*>(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<ItemRandomOption*>(item.unknown_009C)[index] = options[index];
}
item.unknown_0088 = 0;
reinterpret_cast<ClientItemLists*>(&g_session)->AddItem1740(item);
}
// OFFSET: 0x00D1FF70
// FUNCTION: fn_21645
void CGameMode::ReceiveItem1740AddOptions(const unsigned char* data) {
const ItemAddOptionsPacket packet = *reinterpret_cast<const ItemAddOptionsPacket*>(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<ItemRandomOption*>(item.unknown_009C)[index] = options[index];
}
item.unknown_0088 = 0;
reinterpret_cast<ClientItemLists*>(&g_session)->AddItem1740(item);
}
// OFFSET: 0x00D20180
// FUNCTION: fn_21646
void CGameMode::ReceiveItem1740AddGrade(const unsigned char* data) {
const ItemAddGradePacket packet = *reinterpret_cast<const ItemAddGradePacket*>(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<ItemRandomOption*>(item.unknown_009C)[index] = options[index];
}
item.unknown_0088 = packet.grade;
reinterpret_cast<ClientItemLists*>(&g_session)->AddItem1740(item);
}
// OFFSET: 0x00D204B0
// FUNCTION: fn_21647
void CGameMode::ReceiveItem1738AddOptions(const unsigned char* data) {
const ItemAddOptionsPacket packet = *reinterpret_cast<const ItemAddOptionsPacket*>(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<ItemRandomOption*>(item.unknown_009C)[index] = options[index];
}
item.unknown_0088 = 0;
reinterpret_cast<ClientItemLists*>(&g_session)->AddItem1738(item, 1);
}
// OFFSET: 0x00D206C0
// FUNCTION: fn_21648
void CGameMode::ReceiveItem1738AddGrade(const unsigned char* data) {
const ItemAddGradePacket packet = *reinterpret_cast<const ItemAddGradePacket*>(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<ItemRandomOption*>(item.unknown_009C)[index] = options[index];
}
item.unknown_0088 = packet.grade;
reinterpret_cast<ClientItemLists*>(&g_session)->AddItem1738(item, 1);
}
// OFFSET: 0x00DD43A0
// FUNCTION: fn_23232
EquipSlots EquipSlotDecoder::Decode(int mask) const {