From 8d49d2a8b76f1ee861d283e9d398b4149a523ef8 Mon Sep 17 00:00:00 2001 From: "[11EJ11]" Date: Wed, 5 Aug 2026 10:10:41 +1200 Subject: [PATCH 01/17] Add ConnectionClass --- ConnectionClass.h | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 ConnectionClass.h diff --git a/ConnectionClass.h b/ConnectionClass.h new file mode 100644 index 00000000..da850335 --- /dev/null +++ b/ConnectionClass.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +class ConnManClassVtbl; +class CommBufferClass; +class GlobalHeaderType; +class CommHeaderType; + +class ConnectionClass +{ +public: + ConnManClassVtbl* vtable; + CommBufferClass* Queue; + int __resends; + int __numlost; + int __percentlost; + int __missedoverall; + int __missedmagic; + DWORD MaxPacketLen; + GlobalHeaderType* PacketBuf; + WORD MagicNum; + DWORD RetryDelta; + DWORD MaxRetries; + DWORD Timeout; + int NumRecNoAck; + int NumRecAck; + int NumSendNoAck; + int NumSendAck; + int LastSeqID; + int LastReadID; +}; +static_assert(sizeof(ConnectionClass) == 0x4C); + +class SendQueueType +{ +public: + int Flags; + int FirstTime; + int LastTime; + int SendCount; + int BufLen; + CommHeaderType* Buffer; + int ExtraLen; + int ExtraBuffer; + __int16 owntalk_20; +}; +static_assert(sizeof(SendQueueType) == 0x24); From 602db14b0ec09dad6e4e972465e4f1caf0bb932d Mon Sep 17 00:00:00 2001 From: "[11EJ11]" Date: Wed, 5 Aug 2026 10:38:05 +1200 Subject: [PATCH 02/17] Update ConnectionClass Add TheirSync --- ConnectionClass.h | 32 ++++++++++++++++++++++++++++++-- TheirSync.h | 16 ++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 TheirSync.h diff --git a/ConnectionClass.h b/ConnectionClass.h index da850335..18af589d 100644 --- a/ConnectionClass.h +++ b/ConnectionClass.h @@ -4,8 +4,36 @@ class ConnManClassVtbl; class CommBufferClass; -class GlobalHeaderType; -class CommHeaderType; + +enum class ConnectionEnum : unsigned char +{ + PACKET_DATA_ACK = 0, + PACKET_DATA_NOACK = 1, +}; + +#pragma pack(push, 1) +struct CommHeaderType +{ + __int16 MagicNumber; + ConnectionEnum Code; + char forwardto; + int PacketID; + char field_8; + char field_9; + char field_A; + char field_B; + char field_C; + char field_D; +}; +#pragma pack(pop) +static_assert(sizeof(CommHeaderType) == 14); + +struct GlobalHeaderType +{ + CommHeaderType Header; + __int16 ProductID; +}; +static_assert(sizeof(GlobalHeaderType) == 16); class ConnectionClass { diff --git a/TheirSync.h b/TheirSync.h new file mode 100644 index 00000000..a56a4ea9 --- /dev/null +++ b/TheirSync.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +struct TheirSync +{ + DEFINE_ARRAY_REFERENCE(TheirSync, [8], Array, 0xAFA358) + + int frame; + int __send; + int __recv; + int timing_C; + int __router_resp; + int timing_14; +}; +static_assert(sizeof(TheirSync) == 0x18); From 79d242578df8f5c33aeaaa3a8f3162e83804697e Mon Sep 17 00:00:00 2001 From: "[11EJ11]" Date: Thu, 6 Aug 2026 15:52:02 +1200 Subject: [PATCH 03/17] Updates --- CommBufferClass.h | 120 +++++++++++++++++++++++++++++++++++++++++++ ConnectionClass.h | 100 +++++++++++++++++++++++++++--------- IPX.h | 21 ++++++++ IPXConnClass.h | 53 +++++++++++++++++++ IPXGlobalConnClass.h | 70 +++++++++++++++++++++++++ 5 files changed, 339 insertions(+), 25 deletions(-) create mode 100644 CommBufferClass.h create mode 100644 IPXConnClass.h create mode 100644 IPXGlobalConnClass.h diff --git a/CommBufferClass.h b/CommBufferClass.h new file mode 100644 index 00000000..ce15e44b --- /dev/null +++ b/CommBufferClass.h @@ -0,0 +1,120 @@ +#pragma once + +#include + +struct CommHeaderType; + +// Flag bits shared by both queue entry types. Westwood declared these as +// single-bit bitfields; the game reads and writes them as a plain int. +enum CommQueueFlags +{ + COMMQUEUE_IS_ACTIVE = 0x1, // this entry holds a packet and is ready to be processed + COMMQUEUE_IS_READ = 0x2, // send queue: ACK received. receive queue: caller has read it + COMMQUEUE_IS_ACK = 0x4, // an ACK has been sent for this packet +}; + +// One outgoing queue entry. +struct SendQueueType +{ + int Flags; + int FirstTime; // time this packet was first sent + int LastTime; // time this packet was last sent + int SendCount; // number of times this packet has been sent + int BufLen; // size of the packet stored in this entry + CommHeaderType* Buffer; + int ExtraLen; // size of the extra data (an IPXAddressClass, for global conns) + void* ExtraBuffer; + __int16 Port; // destination port this entry was queued for +}; +static_assert(sizeof(SendQueueType) == 0x24); + +// One incoming queue entry. Unlike RA's, YR's tracks the time the packet was +// received so IPXGlobalConnClass::Strip_Packets can age entries out. +struct ReceiveQueueType +{ + int Flags; + int Time; + int BufLen; + void* Buffer; + int ExtraLen; + void* ExtraBuffer; +}; +static_assert(sizeof(ReceiveQueueType) == 0x18); + +// Stores the packets sent and received by a single ConnectionClass. Entries +// are addressed through an index array rather than moved, so unqueueing an +// entry does not disturb the others. +class NOVTABLE CommBufferClass +{ +public: + virtual ~CommBufferClass() RX; + + // Clears both queues. Init_Send_Queue clears only the send queue, which + // is what a reconnect needs. + void Init() + { JMP_THIS(0x48B2A0); } + void Init_Send_Queue() + { JMP_THIS(0x48B390); } + + // Send queue. Queue_Send returns zero when the queue is full. + int Queue_Send(void* buf, int buflen, void* extrabuf, int extralen, __int16 port) + { JMP_THIS(0x48B410); } + int UnQueue_Send(void* buf, int* buflen, int index, void* extrabuf, int* extralen, __int16 port) + { JMP_THIS(0x48B570); } + SendQueueType* Get_Send(int index) + { JMP_THIS(0x48B720); } + int Num_Send() const + { return this->SendCount; } + int Max_Send() const + { return this->MaxSend; } + + // Receive queue. + int Queue_Receive(void* buf, int buflen, void* extrabuf, int extralen) + { JMP_THIS(0x48B750); } + int UnQueue_Receive(void* buf, int* buflen, int index, void* extrabuf, int* extralen) + { JMP_THIS(0x48B890); } + ReceiveQueueType* Get_Receive(int index) + { JMP_THIS(0x48B9E0); } + int Num_Receive() const + { return this->ReceiveCount; } + int Max_Receive() const + { return this->MaxReceive; } + + // Response time tracking. The caller feeds in a delay whenever it detects + // an outgoing message has been ACK'd; the class keeps a running mean. + void Add_Delay(DWORD delay) + { JMP_THIS(0x48BA10); } + DWORD Avg_Response_Time() + { JMP_THIS(0x48BA80); } + DWORD Max_Response_Time() + { JMP_THIS(0x48BA90); } + + // Properties +public: + int MaxSend; + int MaxReceive; + int MaxPacketSize; + int MaxExtraSize; + + DWORD DelaySum; + DWORD NumDelay; + DWORD MeanDelay; + DWORD MaxDelay; + + SendQueueType* SendQueue; + int SendCount; // number of entries currently queued + DWORD SendTotal; // total ever added, used as the outgoing packet ID + int* SendIndex; + + ReceiveQueueType* ReceiveQueue; + int ReceiveCount; + DWORD ReceiveTotal; + int* ReceiveIndex; + + int DebugOffset; + int DebugSize; + char** DebugNames; + int DebugNameStart; + int DebugNameCount; +}; +static_assert(sizeof(CommBufferClass) == 0x58); diff --git a/ConnectionClass.h b/ConnectionClass.h index 18af589d..db0cdd96 100644 --- a/ConnectionClass.h +++ b/ConnectionClass.h @@ -1,16 +1,34 @@ #pragma once #include +#include -class ConnManClassVtbl; -class CommBufferClass; +// A single "connection" with another system. This is a pure virtual base +// class; a derived class supplies Init (protocol-specific setup) and Send +// (the actual hardware-dependent transmit). +// +// Every packet the application sends is prefixed with a CommHeaderType. The +// header carries a magic number (unique per product, so foreign traffic can +// be rejected), a code saying whether this is data or an ACK, and a packet ID +// used to detect resends and to hand packets to the application in order. +// +// Service() drives the ACK/retry logic and must be polled as often as +// possible. Because a derived class can override Service_Send_Queue and +// Service_Receive_Queue, a protocol that already guarantees delivery can skip +// ACKing entirely. +// Values for CommHeaderType::Code. enum class ConnectionEnum : unsigned char { - PACKET_DATA_ACK = 0, - PACKET_DATA_NOACK = 1, + PACKET_DATA_ACK = 0, // a data packet requiring an ACK + PACKET_DATA_NOACK = 1, // a data packet not requiring an ACK + PACKET_ACK = 2, // an ACK for a packet + PACKET_COUNT = 3, // for computational purposes }; +// The header prefixed to every packet the connection sends. YR widened RA's +// 7-byte header to 14 bytes; `forwardto` holds the packet router forwarding +// mask and is only filled in for internet games routed via the packet router. #pragma pack(push, 1) struct CommHeaderType { @@ -28,6 +46,8 @@ struct CommHeaderType #pragma pack(pop) static_assert(sizeof(CommHeaderType) == 14); +// The header used by IPXGlobalConnClass. It adds a product ID so several +// applications can share one socket and still tell their own packets apart. struct GlobalHeaderType { CommHeaderType Header; @@ -35,42 +55,72 @@ struct GlobalHeaderType }; static_assert(sizeof(GlobalHeaderType) == 16); -class ConnectionClass +class NOVTABLE ConnectionClass { public: - ConnManClassVtbl* vtable; + virtual ~ConnectionClass() RX; + + virtual void Init() + { JMP_THIS(0x48BF10); } + + // Queues a packet for sending. `forwardto` is only written into the + // header when the game is an internet game running via the packet router. + virtual int Send_Packet(void* buf, int buflen, int ack_req, char forwardto) + { JMP_THIS(0x48BF40); } + + // Tells the connection a packet has arrived; the connection manager calls + // this after parsing an incoming datagram. + virtual int Receive_Packet(CommHeaderType* buf, int buflen) + { JMP_THIS(0x48C040); } + + // Pulls the next application packet out of the receive queue, stripping + // the CommHeaderType. Returns zero when nothing is ready. + virtual int Get_Packet(void* buf, int* buflen) + { JMP_THIS(0x48C320); } + + // The main polling routine. Should be called as often as possible. + virtual int Service() + { JMP_THIS(0x48C3B0); } + + // Returns the current time in 60ths of a second, which is the unit the + // retry logic works in. + static DWORD Time() + { JMP_STD(0x48C600); } + +protected: + // Drops send queue entries that have been ACK'd. The base implementation + // is a stub returning zero; IPXGlobalConnClass overrides it. + virtual int Purge_Send_Queue() + { JMP_THIS(0x48C590); } + + virtual int Service_Send_Queue() + { JMP_THIS(0x48C3E0); } + virtual int Service_Receive_Queue() + { JMP_THIS(0x48C5A0); } + + // Performs the hardware-dependent send. Pure virtual, and protected + // because only the ACK/retry logic calls it, never the application. + virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) = 0; + + // Properties +public: CommBufferClass* Queue; int __resends; int __numlost; int __percentlost; int __missedoverall; int __missedmagic; - DWORD MaxPacketLen; + DWORD MaxPacketLen; // includes the CommHeaderType GlobalHeaderType* PacketBuf; WORD MagicNum; - DWORD RetryDelta; + DWORD RetryDelta; // delay before a packet is re-sent DWORD MaxRetries; DWORD Timeout; int NumRecNoAck; int NumRecAck; int NumSendNoAck; int NumSendAck; - int LastSeqID; - int LastReadID; + int LastSeqID; // ID of the last consecutively-received packet + int LastReadID; // ID of the last PACKET_DATA_ACK packet read }; static_assert(sizeof(ConnectionClass) == 0x4C); - -class SendQueueType -{ -public: - int Flags; - int FirstTime; - int LastTime; - int SendCount; - int BufLen; - CommHeaderType* Buffer; - int ExtraLen; - int ExtraBuffer; - __int16 owntalk_20; -}; -static_assert(sizeof(SendQueueType) == 0x24); diff --git a/IPX.h b/IPX.h index 0fca4eb5..7d8c3f4c 100644 --- a/IPX.h +++ b/IPX.h @@ -1,7 +1,28 @@ #pragma once +// The four-byte network number and six-byte node (MAC) address that together +// identify a machine on an IPX network. Westwood declared these as raw array +// typedefs; they are wrapped in structs here so they can be used as members +// without decaying to pointers. +struct NetNumType +{ + unsigned char Value[4]; +}; +static_assert(sizeof(NetNumType) == 4); + +struct NetNodeType +{ + unsigned char Value[6]; +}; +static_assert(sizeof(NetNodeType) == 6); + class IPXAddressClass { +public: unsigned char NetworkNumber[4]; unsigned char NodeAddress[6]; + // YR carries UDP/IP endpoints in this struct as well as real IPX + // addresses, so the trailing two bytes are only meaningful in IP mode. + unsigned char field_A[2]; }; +static_assert(sizeof(IPXAddressClass) == 12); diff --git a/IPXConnClass.h b/IPXConnClass.h new file mode 100644 index 00000000..3c322632 --- /dev/null +++ b/IPXConnClass.h @@ -0,0 +1,53 @@ +#pragma once + +#include +#include +#include + +class NOVTABLE IPXConnClass : public ConnectionClass +{ +public: + enum IPXConnTag + { + CONN_NAME_MAX = 40 // max number of chars allowed for a connection name + }; + + DEFINE_REFERENCE(WORD, Socket, 0xAA0568) + DEFINE_REFERENCE(int, Configured, 0xAA05A4) + DEFINE_REFERENCE(int, SocketOpen, 0xAA05A8) + DEFINE_REFERENCE(int, Listening, 0xAA05AC) + + virtual void Init() override + { JMP_THIS(0x53F4E0); } + + static int __fastcall Open_Socket(WORD socket) + { JMP_THIS(0x53F5F0); } + static void __fastcall Close_Socket(WORD socket) + { JMP_THIS(0x53F630); } + + static int Start_Listening() + { JMP_STD(0x53F540); } + static int Stop_Listening() + { JMP_STD(0x53F5B0); } + + static int __fastcall Broadcast(void* buf, int buflen) + { JMP_THIS(0x53F830); } + +protected: + virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) override + { JMP_THIS(0x53F5D0); } + + virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, __int16 port) + { JMP_THIS(0x53F650); } + + // Properties +public: + IPXAddressClass Address; + NetNodeType ImmediateAddress; + PROTECTED_PROPERTY(BYTE, align_5E[0x2]); + + DWORD Immed_Set; + DWORD ID; + wchar_t Name[CONN_NAME_MAX]; +}; +static_assert(sizeof(IPXConnClass) == 0xB8); diff --git a/IPXGlobalConnClass.h b/IPXGlobalConnClass.h new file mode 100644 index 00000000..ccabcbb5 --- /dev/null +++ b/IPXGlobalConnClass.h @@ -0,0 +1,70 @@ +#pragma once + +#include +#include + +class NOVTABLE IPXGlobalConnClass : public IPXConnClass +{ +public: + enum GlobalConnectionEnum + { + GLOBAL_MAGICNUM = 0x1235, + COMMAND_AND_CONQUER = 0xaa01, + COMMAND_AND_CONQUER0 = 0xaa00 + }; + + virtual int Send_Packet(void* buf, int buflen, int ack_req, char forwardto) override + { JMP_THIS(0x540610); } + virtual int Receive_Packet(CommHeaderType* buf, int buflen) override + { JMP_THIS(0x540630); } + virtual int Get_Packet(void* buf, int* buflen) override + { JMP_THIS(0x540650); } + + virtual int Send_Packet(void* buf, int buflen, IPXAddressClass* address, int ack_req, __int16 port, int packet_id) + { JMP_THIS(0x53FBD0); } + + virtual int Receive_Packet(GlobalHeaderType* buf, int buflen, IPXAddressClass* address, __int16 port) + { JMP_THIS(0x53FCB0); } + + virtual int Get_Packet(void* buf, int* buflen, IPXAddressClass* address, WORD* product_id) + { JMP_THIS(0x53FF10); } + + virtual int Peek_Packet(int index, void* buf, int* buflen, IPXAddressClass* address, WORD* product_id, int* packet_id) + { JMP_THIS(0x53FFA0); } + + virtual int Mark_Packet_Read(int index) + { JMP_THIS(0x540030); } + + virtual int Purge_Send_Queue_To(IPXAddressClass* address, __int16 port) + { JMP_THIS(0x540340); } + + virtual void Strip_Packets(DWORD age) + { JMP_THIS(0x540110); } + + void Set_Bridge(NetNumType* bridge) + { JMP_THIS(0x5402B0); } + +protected: + virtual int Purge_Send_Queue() override + { JMP_THIS(0x5402D0); } + virtual int Service_Receive_Queue() override + { JMP_THIS(0x5400D0); } + virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) override + { JMP_THIS(0x540050); } + virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, __int16 port) override + { JMP_THIS(0x5403F0); } + +public: + __int16 ProductID; + + NetNumType BridgeNet; + NetNodeType BridgeNode; + int IsBridge; + bool field_C8; + PROTECTED_PROPERTY(BYTE, align_C9[0x3]); + IPXAddressClass* LastAddress; + int* LastPacketID; + int LastCount; + int LastRXIndex; +}; +static_assert(sizeof(IPXGlobalConnClass) == 0xDC); From ae9a8418ee618201d69ecc2b0124cc24ea0b6147 Mon Sep 17 00:00:00 2001 From: "[11EJ11]" Date: Thu, 6 Aug 2026 15:52:37 +1200 Subject: [PATCH 04/17] Update comment --- IPXConnClass.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/IPXConnClass.h b/IPXConnClass.h index 3c322632..881d963f 100644 --- a/IPXConnClass.h +++ b/IPXConnClass.h @@ -9,7 +9,7 @@ class NOVTABLE IPXConnClass : public ConnectionClass public: enum IPXConnTag { - CONN_NAME_MAX = 40 // max number of chars allowed for a connection name + CONN_NAME_MAX = 40 }; DEFINE_REFERENCE(WORD, Socket, 0xAA0568) @@ -40,7 +40,6 @@ class NOVTABLE IPXConnClass : public ConnectionClass virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, __int16 port) { JMP_THIS(0x53F650); } - // Properties public: IPXAddressClass Address; NetNodeType ImmediateAddress; From b103398312a74b7dee76a4882b83d03f6a55df7e Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:07:24 +1200 Subject: [PATCH 05/17] Rename ConnectionClass packet statistics fields --- ConnectionClass.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ConnectionClass.h b/ConnectionClass.h index db0cdd96..58c5a29c 100644 --- a/ConnectionClass.h +++ b/ConnectionClass.h @@ -105,11 +105,11 @@ class NOVTABLE ConnectionClass // Properties public: CommBufferClass* Queue; - int __resends; - int __numlost; - int __percentlost; - int __missedoverall; - int __missedmagic; + int NumResends; + int NumLost; + int PercentLost; + int MissedOverall; + int MissedMagic; DWORD MaxPacketLen; // includes the CommHeaderType GlobalHeaderType* PacketBuf; WORD MagicNum; From b88367afcc8c756f2a66a3a2652369b700c821de Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:07:44 +1200 Subject: [PATCH 06/17] Remove GlobalHeaderType --- ConnectionClass.h | 11 +---------- IPXGlobalConnClass.h | 2 +- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/ConnectionClass.h b/ConnectionClass.h index 58c5a29c..bee335bc 100644 --- a/ConnectionClass.h +++ b/ConnectionClass.h @@ -46,15 +46,6 @@ struct CommHeaderType #pragma pack(pop) static_assert(sizeof(CommHeaderType) == 14); -// The header used by IPXGlobalConnClass. It adds a product ID so several -// applications can share one socket and still tell their own packets apart. -struct GlobalHeaderType -{ - CommHeaderType Header; - __int16 ProductID; -}; -static_assert(sizeof(GlobalHeaderType) == 16); - class NOVTABLE ConnectionClass { public: @@ -111,7 +102,7 @@ class NOVTABLE ConnectionClass int MissedOverall; int MissedMagic; DWORD MaxPacketLen; // includes the CommHeaderType - GlobalHeaderType* PacketBuf; + CommHeaderType* PacketBuf; WORD MagicNum; DWORD RetryDelta; // delay before a packet is re-sent DWORD MaxRetries; diff --git a/IPXGlobalConnClass.h b/IPXGlobalConnClass.h index ccabcbb5..52010fa1 100644 --- a/IPXGlobalConnClass.h +++ b/IPXGlobalConnClass.h @@ -23,7 +23,7 @@ class NOVTABLE IPXGlobalConnClass : public IPXConnClass virtual int Send_Packet(void* buf, int buflen, IPXAddressClass* address, int ack_req, __int16 port, int packet_id) { JMP_THIS(0x53FBD0); } - virtual int Receive_Packet(GlobalHeaderType* buf, int buflen, IPXAddressClass* address, __int16 port) + virtual int Receive_Packet(void* buf, int buflen, IPXAddressClass* address, __int16 port) { JMP_THIS(0x53FCB0); } virtual int Get_Packet(void* buf, int* buflen, IPXAddressClass* address, WORD* product_id) From 6dc55706ae403ce9da910e532095f1df155661e2 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:08:03 +1200 Subject: [PATCH 07/17] Replace Windows types in ConnectionClass --- ConnectionClass.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ConnectionClass.h b/ConnectionClass.h index bee335bc..427a13a5 100644 --- a/ConnectionClass.h +++ b/ConnectionClass.h @@ -32,7 +32,7 @@ enum class ConnectionEnum : unsigned char #pragma pack(push, 1) struct CommHeaderType { - __int16 MagicNumber; + short MagicNumber; ConnectionEnum Code; char forwardto; int PacketID; @@ -75,7 +75,7 @@ class NOVTABLE ConnectionClass // Returns the current time in 60ths of a second, which is the unit the // retry logic works in. - static DWORD Time() + static unsigned int Time() { JMP_STD(0x48C600); } protected: @@ -91,7 +91,7 @@ class NOVTABLE ConnectionClass // Performs the hardware-dependent send. Pure virtual, and protected // because only the ACK/retry logic calls it, never the application. - virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) = 0; + virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, short port) = 0; // Properties public: @@ -101,12 +101,12 @@ class NOVTABLE ConnectionClass int PercentLost; int MissedOverall; int MissedMagic; - DWORD MaxPacketLen; // includes the CommHeaderType + unsigned int MaxPacketLen; // includes the CommHeaderType CommHeaderType* PacketBuf; - WORD MagicNum; - DWORD RetryDelta; // delay before a packet is re-sent - DWORD MaxRetries; - DWORD Timeout; + unsigned short MagicNum; + unsigned int RetryDelta; // delay before a packet is re-sent + unsigned int MaxRetries; + unsigned int Timeout; int NumRecNoAck; int NumRecAck; int NumSendNoAck; From 7b7e4abbae76293f695898e1c4b8a6c88d84c0b5 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:08:25 +1200 Subject: [PATCH 08/17] Replace Windows types in CommBufferClass --- CommBufferClass.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/CommBufferClass.h b/CommBufferClass.h index ce15e44b..2c33b15e 100644 --- a/CommBufferClass.h +++ b/CommBufferClass.h @@ -24,7 +24,7 @@ struct SendQueueType CommHeaderType* Buffer; int ExtraLen; // size of the extra data (an IPXAddressClass, for global conns) void* ExtraBuffer; - __int16 Port; // destination port this entry was queued for + short Port; // destination port this entry was queued for }; static_assert(sizeof(SendQueueType) == 0x24); @@ -57,9 +57,9 @@ class NOVTABLE CommBufferClass { JMP_THIS(0x48B390); } // Send queue. Queue_Send returns zero when the queue is full. - int Queue_Send(void* buf, int buflen, void* extrabuf, int extralen, __int16 port) + int Queue_Send(void* buf, int buflen, void* extrabuf, int extralen, short port) { JMP_THIS(0x48B410); } - int UnQueue_Send(void* buf, int* buflen, int index, void* extrabuf, int* extralen, __int16 port) + int UnQueue_Send(void* buf, int* buflen, int index, void* extrabuf, int* extralen, short port) { JMP_THIS(0x48B570); } SendQueueType* Get_Send(int index) { JMP_THIS(0x48B720); } @@ -82,11 +82,11 @@ class NOVTABLE CommBufferClass // Response time tracking. The caller feeds in a delay whenever it detects // an outgoing message has been ACK'd; the class keeps a running mean. - void Add_Delay(DWORD delay) + void Add_Delay(unsigned int delay) { JMP_THIS(0x48BA10); } - DWORD Avg_Response_Time() + unsigned int Avg_Response_Time() { JMP_THIS(0x48BA80); } - DWORD Max_Response_Time() + unsigned int Max_Response_Time() { JMP_THIS(0x48BA90); } // Properties @@ -96,19 +96,19 @@ class NOVTABLE CommBufferClass int MaxPacketSize; int MaxExtraSize; - DWORD DelaySum; - DWORD NumDelay; - DWORD MeanDelay; - DWORD MaxDelay; + unsigned int DelaySum; + unsigned int NumDelay; + unsigned int MeanDelay; + unsigned int MaxDelay; SendQueueType* SendQueue; - int SendCount; // number of entries currently queued - DWORD SendTotal; // total ever added, used as the outgoing packet ID + int SendCount; // number of entries currently queued + unsigned int SendTotal; // total ever added, used as the outgoing packet ID int* SendIndex; ReceiveQueueType* ReceiveQueue; int ReceiveCount; - DWORD ReceiveTotal; + unsigned int ReceiveTotal; int* ReceiveIndex; int DebugOffset; From 3f4a1c53260622456fb314db2f8a5e474794fced Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:08:35 +1200 Subject: [PATCH 09/17] Replace Windows types in IPXConnClass --- IPXConnClass.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/IPXConnClass.h b/IPXConnClass.h index 881d963f..6b42dbf7 100644 --- a/IPXConnClass.h +++ b/IPXConnClass.h @@ -12,7 +12,7 @@ class NOVTABLE IPXConnClass : public ConnectionClass CONN_NAME_MAX = 40 }; - DEFINE_REFERENCE(WORD, Socket, 0xAA0568) + DEFINE_REFERENCE(unsigned short, Socket, 0xAA0568) DEFINE_REFERENCE(int, Configured, 0xAA05A4) DEFINE_REFERENCE(int, SocketOpen, 0xAA05A8) DEFINE_REFERENCE(int, Listening, 0xAA05AC) @@ -20,9 +20,9 @@ class NOVTABLE IPXConnClass : public ConnectionClass virtual void Init() override { JMP_THIS(0x53F4E0); } - static int __fastcall Open_Socket(WORD socket) + static int __fastcall Open_Socket(unsigned short socket) { JMP_THIS(0x53F5F0); } - static void __fastcall Close_Socket(WORD socket) + static void __fastcall Close_Socket(unsigned short socket) { JMP_THIS(0x53F630); } static int Start_Listening() @@ -34,10 +34,10 @@ class NOVTABLE IPXConnClass : public ConnectionClass { JMP_THIS(0x53F830); } protected: - virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) override + virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, short port) override { JMP_THIS(0x53F5D0); } - virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, __int16 port) + virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, short port) { JMP_THIS(0x53F650); } public: From 0f867bde209fbe65d03509ca6e9f63b5f1d93113 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:08:44 +1200 Subject: [PATCH 10/17] Use int for IPXConnClass Immed_Set and ID --- IPXConnClass.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IPXConnClass.h b/IPXConnClass.h index 6b42dbf7..4520bec4 100644 --- a/IPXConnClass.h +++ b/IPXConnClass.h @@ -45,8 +45,8 @@ class NOVTABLE IPXConnClass : public ConnectionClass NetNodeType ImmediateAddress; PROTECTED_PROPERTY(BYTE, align_5E[0x2]); - DWORD Immed_Set; - DWORD ID; + int Immed_Set; + int ID; wchar_t Name[CONN_NAME_MAX]; }; static_assert(sizeof(IPXConnClass) == 0xB8); From cc0f08cd2890b7da3f77c9bf63b10a07c19bc04f Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:08:56 +1200 Subject: [PATCH 11/17] Remove explicit alignment padding --- IPXConnClass.h | 1 - IPXGlobalConnClass.h | 1 - 2 files changed, 2 deletions(-) diff --git a/IPXConnClass.h b/IPXConnClass.h index 4520bec4..4a48745c 100644 --- a/IPXConnClass.h +++ b/IPXConnClass.h @@ -43,7 +43,6 @@ class NOVTABLE IPXConnClass : public ConnectionClass public: IPXAddressClass Address; NetNodeType ImmediateAddress; - PROTECTED_PROPERTY(BYTE, align_5E[0x2]); int Immed_Set; int ID; diff --git a/IPXGlobalConnClass.h b/IPXGlobalConnClass.h index 52010fa1..0a83e750 100644 --- a/IPXGlobalConnClass.h +++ b/IPXGlobalConnClass.h @@ -61,7 +61,6 @@ class NOVTABLE IPXGlobalConnClass : public IPXConnClass NetNodeType BridgeNode; int IsBridge; bool field_C8; - PROTECTED_PROPERTY(BYTE, align_C9[0x3]); IPXAddressClass* LastAddress; int* LastPacketID; int LastCount; From 24f844ee9bb62980456fadc43ecff3116ce9bd8d Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:09:09 +1200 Subject: [PATCH 12/17] Replace Windows types in IPXGlobalConnClass --- IPXGlobalConnClass.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/IPXGlobalConnClass.h b/IPXGlobalConnClass.h index 0a83e750..f846d521 100644 --- a/IPXGlobalConnClass.h +++ b/IPXGlobalConnClass.h @@ -20,25 +20,25 @@ class NOVTABLE IPXGlobalConnClass : public IPXConnClass virtual int Get_Packet(void* buf, int* buflen) override { JMP_THIS(0x540650); } - virtual int Send_Packet(void* buf, int buflen, IPXAddressClass* address, int ack_req, __int16 port, int packet_id) + virtual int Send_Packet(void* buf, int buflen, IPXAddressClass* address, int ack_req, short port, int packet_id) { JMP_THIS(0x53FBD0); } - virtual int Receive_Packet(void* buf, int buflen, IPXAddressClass* address, __int16 port) + virtual int Receive_Packet(void* buf, int buflen, IPXAddressClass* address, short port) { JMP_THIS(0x53FCB0); } - virtual int Get_Packet(void* buf, int* buflen, IPXAddressClass* address, WORD* product_id) + virtual int Get_Packet(void* buf, int* buflen, IPXAddressClass* address, unsigned short* product_id) { JMP_THIS(0x53FF10); } - virtual int Peek_Packet(int index, void* buf, int* buflen, IPXAddressClass* address, WORD* product_id, int* packet_id) + virtual int Peek_Packet(int index, void* buf, int* buflen, IPXAddressClass* address, unsigned short* product_id, int* packet_id) { JMP_THIS(0x53FFA0); } virtual int Mark_Packet_Read(int index) { JMP_THIS(0x540030); } - virtual int Purge_Send_Queue_To(IPXAddressClass* address, __int16 port) + virtual int Purge_Send_Queue_To(IPXAddressClass* address, short port) { JMP_THIS(0x540340); } - virtual void Strip_Packets(DWORD age) + virtual void Strip_Packets(unsigned int age) { JMP_THIS(0x540110); } void Set_Bridge(NetNumType* bridge) @@ -49,13 +49,13 @@ class NOVTABLE IPXGlobalConnClass : public IPXConnClass { JMP_THIS(0x5402D0); } virtual int Service_Receive_Queue() override { JMP_THIS(0x5400D0); } - virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, __int16 port) override + virtual int Send(CommHeaderType* buf, int buflen, void* extrabuf, int extralen, bool isGlobalConn, short port) override { JMP_THIS(0x540050); } - virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, __int16 port) override + virtual int Send_To_Address(CommHeaderType* buf, int buflen, IPXAddressClass* address, NetNodeType* nodeOverride, bool isGlobalConn, short port) override { JMP_THIS(0x5403F0); } public: - __int16 ProductID; + unsigned short ProductID; NetNumType BridgeNet; NetNodeType BridgeNode; From 3a3ee66f9d36ee6026d2dfd91b095221afbfebe0 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:09:26 +1200 Subject: [PATCH 13/17] Expand the product ID enum --- IPXGlobalConnClass.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/IPXGlobalConnClass.h b/IPXGlobalConnClass.h index f846d521..8a56581d 100644 --- a/IPXGlobalConnClass.h +++ b/IPXGlobalConnClass.h @@ -9,7 +9,10 @@ class NOVTABLE IPXGlobalConnClass : public IPXConnClass enum GlobalConnectionEnum { GLOBAL_MAGICNUM = 0x1235, - COMMAND_AND_CONQUER = 0xaa01, + COMMAND_AND_CONQUER4 = 0xaa04, /// YR + COMMAND_AND_CONQUER3 = 0xaa03, /// RA2 + COMMAND_AND_CONQUER2 = 0xaa02, /// TS + COMMAND_AND_CONQUER1 = 0xaa01, COMMAND_AND_CONQUER0 = 0xaa00 }; From 04b15765ae21e3fbf4e2aedd8f3cb12897a0a324 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:09:39 +1200 Subject: [PATCH 14/17] Clean up TheirSync field names --- TheirSync.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/TheirSync.h b/TheirSync.h index a56a4ea9..6d958f0e 100644 --- a/TheirSync.h +++ b/TheirSync.h @@ -6,11 +6,11 @@ struct TheirSync { DEFINE_ARRAY_REFERENCE(TheirSync, [8], Array, 0xAFA358) - int frame; - int __send; - int __recv; - int timing_C; - int __router_resp; - int timing_14; + int Frame; + int CommandsSent; + int CommandsReceived; + int ResponseTime; + int RouterResponseTime; + int LastHeardTime; }; static_assert(sizeof(TheirSync) == 0x18); From f9792d9afa2d3d420c2295a5f23d23eb23fcc7f4 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:09:46 +1200 Subject: [PATCH 15/17] Fix TheirSync array size --- TheirSync.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TheirSync.h b/TheirSync.h index 6d958f0e..341005c1 100644 --- a/TheirSync.h +++ b/TheirSync.h @@ -4,7 +4,7 @@ struct TheirSync { - DEFINE_ARRAY_REFERENCE(TheirSync, [8], Array, 0xAFA358) + DEFINE_ARRAY_REFERENCE(TheirSync, [7], Array, 0xAFA358) int Frame; int CommandsSent; From 11b06bdf6a3df6524e7766f283be1b51b2a7f66f Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:09:56 +1200 Subject: [PATCH 16/17] Use exact field widths in CommHeaderType --- ConnectionClass.h | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/ConnectionClass.h b/ConnectionClass.h index 427a13a5..b4ca0e61 100644 --- a/ConnectionClass.h +++ b/ConnectionClass.h @@ -27,21 +27,17 @@ enum class ConnectionEnum : unsigned char }; // The header prefixed to every packet the connection sends. YR widened RA's -// 7-byte header to 14 bytes; `forwardto` holds the packet router forwarding +// 7-byte header to 14 bytes; `ForwardTo` holds the packet router forwarding // mask and is only filled in for internet games routed via the packet router. #pragma pack(push, 1) struct CommHeaderType { short MagicNumber; ConnectionEnum Code; - char forwardto; + char ForwardTo; int PacketID; - char field_8; - char field_9; - char field_A; - char field_B; - char field_C; - char field_D; + int field_8; + short field_C; }; #pragma pack(pop) static_assert(sizeof(CommHeaderType) == 14); From af29bc00c8a5310f551f92146bbda6962f8dde66 Mon Sep 17 00:00:00 2001 From: 11EJDE11 Date: Sun, 16 Aug 2026 15:10:03 +1200 Subject: [PATCH 17/17] Add the new headers to YRpp.props --- YRpp.props | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/YRpp.props b/YRpp.props index 37e1286b..80bbcff3 100644 --- a/YRpp.props +++ b/YRpp.props @@ -163,6 +163,8 @@ + + @@ -214,6 +216,8 @@ + + @@ -308,6 +312,7 @@ +