Skip to content

DirectPlay system messages#

Summary#

DirectPlay delivers system traffic from player id 0. Lords of the Realm 2 reads the first DWORD of the receive buffer as dwType and routes every DirectPlay 3 DPSYS_* message it recognizes to lotr2_net_handle_system_message. All claims here are inferred from client code unless otherwise noted.

Evidence#

Claim Level
System messages arrive with sender id 0 inferred from client code
dwType is read from receive buffer offset 0x00 inferred from client code
Eight DPSYS_* values are routed inferred from client code
Fields after dwType use stock DirectPlay 3 SDK layouts inferred from SDK layout; not verified on wire

Session Context#

System messages are processed inside lotr2_net_poll_messages after IDirectPlay3::Receive fills the shared receive buffer at DAT_0052d490. Messages from lotr2_net_local_player_id are treated as self-echoes and ignored. Messages from any other nonzero sender are custom app frames; see dplay-app-messages.md.

Message Routing#

dwType DirectPlay constant Internal index Client action
0x00000003 DPSYS_CREATEPLAYERORGROUP 1 Logs create; reads created DPID from DAT_0052d498.
0x00000005 DPSYS_DESTROYPLAYERORGROUP 2 Removes slot; before gameplay, broadcasts app opcode 3 roster sync.
0x00000007 DPSYS_ADDPLAYERTOGROUP 5 Logs only.
0x00000021 DPSYS_DELETEPLAYERFROMGROUP 6 Logs only.
0x00000031 DPSYS_SESSIONLOST 3 Logs session lost.
0x00000101 DPSYS_HOST 4 Logs host migration and sets lotr2_net_is_host = 1.
0x00000102 DPSYS_SETPLAYERORGROUPDATA 7 Logs only.
0x00000103 DPSYS_SETPLAYERORGROUPNAME 8 Logs only.

Generic Field Layouts#

DirectPlay system messages are standard DirectPlay payloads, not the custom lotr2_net_msg_header frame. The client only reads dwType in the receive loop and, for create/destroy, the DPID at offset 0x08.

DPSYS_CREATEPLAYERORGROUP (0x00000003)#

SDK payload: DPMSG_CREATEPLAYERORGROUP.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_CREATEPLAYERORGROUP.
dpId 0x04 4 uint32le Created player or group id.
dwPlayerType 0x08 4 uint32le DirectPlay player/group type.
lpData 0x0c 4 pointer Player data pointer in local process.
dwDataSize 0x10 4 uint32le Player data byte count.
dpnName 0x14 16 DPNAME DirectPlay name structure.
  • Direction: DirectPlay system -> client.
  • Trigger: another player or group is created in the session.
  • Handler (parse): lotr2_net_handle_system_message // was FUN_004480ef @ 0x004480ef.
  • Compatibility notes: the client's router passes DAT_0052d498, which is the DPID slot used by both create and destroy system messages in this export.

DPSYS_DESTROYPLAYERORGROUP (0x00000005)#

SDK payload: DPMSG_DESTROYPLAYERORGROUP.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_DESTROYPLAYERORGROUP.
dpId 0x04 4 uint32le Destroyed player or group id.
dwPlayerType 0x08 4 uint32le DirectPlay player/group type.
lpLocalData 0x0c 4 pointer Local player data pointer.
dwLocalDataSize 0x10 4 uint32le Local data size.
lpRemoteData 0x14 4 pointer Remote player data pointer.
dwRemoteDataSize 0x18 4 uint32le Remote data size.
dpnName 0x1c 16 DPNAME DirectPlay name structure.
  • Direction: DirectPlay system -> client.
  • Trigger: another player or group leaves or is destroyed.
  • Handler (parse): lotr2_net_handle_system_message // was FUN_004480ef @ 0x004480ef.
  • Compatibility notes: before the game reaches state DAT_0055c02c >= 3, the client rebroadcasts custom opcode 3 after removing the player slot.

DPSYS_ADDPLAYERTOGROUP (0x00000007)#

SDK payload: DPMSG_ADDPLAYERTOGROUP.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_ADDPLAYERTOGROUP.
dpIdGroup 0x04 4 uint32le Target group id.
dpIdPlayer 0x08 4 uint32le Added player id.
  • Direction: DirectPlay system -> client.
  • Trigger: a DirectPlay group membership changes.
  • Handler (parse): lotr2_net_handle_system_message.
  • Compatibility notes: the observed client only logs this message.

DPSYS_DELETEPLAYERFROMGROUP (0x00000021)#

SDK payload: DPMSG_DELETEPLAYERFROMGROUP.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_DELETEPLAYERFROMGROUP.
dpIdGroup 0x04 4 uint32le Target group id.
dpIdPlayer 0x08 4 uint32le Removed player id.
  • Direction: DirectPlay system -> client.
  • Trigger: a player leaves a DirectPlay group.
  • Handler (parse): lotr2_net_handle_system_message.
  • Compatibility notes: the observed client only logs this message.

DPSYS_SESSIONLOST (0x00000031)#

SDK payload: DPMSG_GENERIC.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_SESSIONLOST.
  • Direction: DirectPlay system -> client.
  • Trigger: the DirectPlay session is lost.
  • Handler (parse): lotr2_net_handle_system_message.
  • Compatibility notes: the handler logs; teardown is handled elsewhere in session control paths.

DPSYS_HOST (0x00000101)#

SDK payload: DPMSG_HOST.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_HOST.
dpIdNewHost 0x04 4 uint32le New DirectPlay host id.
  • Direction: DirectPlay system -> client.
  • Trigger: DirectPlay host migration.
  • Handler (parse): lotr2_net_handle_system_message.
  • Compatibility notes: the client does not compare dpIdNewHost; receiving the system message is enough to set lotr2_net_is_host = 1.

DPSYS_SETPLAYERORGROUPDATA (0x00000102)#

SDK payload: DPMSG_SETPLAYERORGROUPDATA.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_SETPLAYERORGROUPDATA.
dpId 0x04 4 uint32le Player or group id.
dwPlayerType 0x08 4 uint32le DirectPlay player/group type.
lpData 0x0c 4 pointer New data pointer.
dwDataSize 0x10 4 uint32le New data size.
  • Direction: DirectPlay system -> client.
  • Trigger: player or group data changes through DirectPlay.
  • Handler (parse): lotr2_net_handle_system_message.
  • Compatibility notes: the observed client only logs this message.

DPSYS_SETPLAYERORGROUPNAME (0x00000103)#

SDK payload: DPMSG_SETPLAYERORGROUPNAME.

Field Offset Size Type Description
dwType 0x00 4 uint32le DPSYS_SETPLAYERORGROUPNAME.
dpId 0x04 4 uint32le Player or group id.
dwPlayerType 0x08 4 uint32le DirectPlay player/group type.
dpnName 0x0c 16 DPNAME New DirectPlay name structure.
  • Direction: DirectPlay system -> client.
  • Trigger: player or group name changes through DirectPlay.
  • Handler (parse): lotr2_net_handle_system_message.
  • Compatibility notes: the observed client only logs this message.

Receive HRESULTs#

The receive loop treats DP_OK as success, returns quietly on the no-message HRESULT, and logs several DirectPlay error codes before returning. These are transport status values, not message types.

Open Questions#

  • Confirm exact DirectPlay SDK struct packing against a Win95 DirectX SDK.
  • Capture system traffic on a stock-host join and disconnect.

Captures Needed#

  • LAN trace covering create-player, host migration if possible, player destroy, and session lost.