Skip to content

lotr2_net_msg — application network message frame#

Header: lotr2_net_msg.h

Summary#

Game-level multiplayer messages are framed as a 4-byte header plus a fixed-length payload, then transported inside DirectPlay 3 Send / Receive. This is a Sierra/Impressions custom payload, not a DirectPlay structure. The full opcode catalog is ../protocols/dplay-app-messages.md.

  • Confidence: likely (inferred from client code; no on-wire capture yet)
  • Endianness: little-endian (x86)
  • Total frame size: length + 4, capped at 0x104 (260) bytes

Header offset table#

Offset Size Field Type Description
0x00 1 opcode uint8 Index into the per-opcode length table and the send/recv handler tables
0x01 1 length uint8 Payload length; validated to equal the expected length for opcode
0x02 1 checksum uint8 8-bit additive sum of the payload bytes (offsets 0x04..0x04+length-1)
0x03 1 seq_flags uint8 bits 0-5 = rolling send-slot/sequence; 0x40/0x80 = reliable retransmit pass
0x04 length payload bytes Opcode-specific body

Evidence#

Claim Level Source
Header is 4 bytes; payload starts at +0x04 inferred from client code lotr2_net_checksum starts summing at offset 4 (local_8 = 4) // was FUN_00448c6c @ 0x00448c6c
opcode at +0x00 indexes handler tables inferred from client code (*(code *)(&PTR_LAB_004f0820)[lotr2_net_recv_frame])() in lotr2_net_dispatch_app_message
length at +0x01 must equal lotr2_net_opcode_len[opcode] inferred from client code (&DAT_004f0988)[lotr2_net_recv_frame] == lotr2_net_recv_length check
checksum at +0x02 over payload inferred from client code lotr2_net_recv_checksum == cVar2 where cVar2 = lotr2_net_checksum(len, base)
seq_flags low 6 bits = slot; 0x40/0x80 = retry inferred from client code lotr2_net_send_message sets | 0x40 then | 0x80 across three sends
Slot stride 0x104; max frame 0x104 inferred from client code iVar1 = lotr2_net_send_slot * 0x104; Receive(..., 0x104)
Send slot index wraps 1..0x27 inferred from client code if (0x27 < lotr2_net_send_slot) lotr2_net_send_slot = 1
Reliable messages sent three times; opcode 10 once inferred from client code if (param_1 == 10) ... else { send; |0x40 send; |0x80 send; }

Builders / parsers#

  • Build: lotr2_net_send_message // was FUN_00448641 @ 0x00448641 (writes header, calls the opcode's pack handler from PTR_LAB_004f06b8[], computes checksum, then lotr2_net_dp_send).
  • Low-level send: lotr2_net_dp_send // was FUN_004d39d5 @ 0x004d39d5 (IDirectPlay3::Send, vtable +0x68).
  • Receive/poll: lotr2_net_poll_messages // was FUN_004d36f0 @ 0x004d36f0 (IDirectPlay3::Receive, vtable +0x64; routes system vs app messages).
  • App dispatch: lotr2_net_dispatch_app_message // was FUN_00448362 @ 0x00448362 (validates length + checksum, dedupes by slot, calls unpack handler from PTR_LAB_004f0820[]).
  • Payload cursors: lotr2_net_payload_write // was FUN_00448dee @ 0x00448dee, lotr2_net_payload_read // was FUN_00448e2a @ 0x00448e2a (cursors: lotr2_net_payload_write_ptr, lotr2_net_payload_read_ptr).
  • Sync checksum helpers: lotr2_net_partial_checksum // was FUN_00448d8e @ 0x00448d8e, lotr2_net_buffer_checksum, lotr2_net_strided_checksum.

Frame buffer globals (pass 28)#

Symbol Address Role
lotr2_net_recv_frame 0x52d490 Receive frame buffer (header at +0..+3, payload from +4)
lotr2_net_recv_length 0x52d491 Received payload length byte
lotr2_net_recv_checksum 0x52d492 Received checksum byte
lotr2_net_recv_seq_flags 0x52d493 Received sequence / resend flags
lotr2_net_payload_write_ptr 0x52d488 Payload write cursor
lotr2_net_payload_read_ptr 0x52d460 Payload read cursor
lotr2_net_send_slots 0x52d5a0 Send slot array base, stride 0x104

Handler tables (not yet renamed as globals)#

Symbol Address Role
DAT_004f0988 0x4f0988 Per-opcode payload length table
PTR_LAB_004f06b8 0x4f06b8 Per-opcode send (pack) handler table
PTR_LAB_004f0820 0x4f0820 Per-opcode receive (unpack) handler table

Open questions#

  • Exact checksum width and overflow behaviour (appears to be 8-bit truncated sum).
  • Whether length is ever a sentinel (-1/0xFF marks a "skip" opcode in the parser).
  • Replace source-only TBD opcode rows with an authoritative table dump from bin/LORDS2.EXE.

Captures needed#

  • LAN trace between two stock clients to confirm byte order and checksum on the wire.