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
| 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
Captures needed
- LAN trace between two stock clients to confirm byte order and checksum on the wire.