Skip to content

DAT — Multiplayer Network Configuration (.DAT)

NET.DAT, MODEM.DAT, and SERIAL.DAT are binary files that store FA's multiplayer network settings — three loose files in the FA install directory, none packed into any LIB archive. All three share the same 3,552-byte CN_INFO format and are read/written by the same CN_ReadConfig/CN_WriteConfig functions.

File Purpose
NET.DAT Active transport selection; IPX/TCP/IP addresses and direct-connect info
MODEM.DAT Modem phone book (8 player name + phone number pairs) and COM port selection
SERIAL.DAT Serial (RS-232) COM port and baud rate preferences

Tools

fx

fx dat info <NET.DAT|MODEM.DAT|SERIAL.DAT>   # dump CN_INFO + round-trip check

dat_read/dat_write type every documented field; the stored checksum, the 8-byte gap after the transport dword, and the unmapped [0x8f9]–[0xdab] region (gap #54) pass through verbatim — byte-identical round-trip, verified against the install's live NET.DAT by an FX_FA_ROOT-gated test. (Editing fields would need CfigChecksum recomputed; that lands with a write verb when something needs one.)

File Layout

All multi-byte integers are little-endian.

Each file is 3,552 bytes (0xDE0): a 4-byte checksum + 3,548-byte CN_INFO struct, written by CN_WriteConfig (0x47f930) via fwrite(param_1, 0xddc, 1, file). The filename is passed as a second parameter so the same function handles all three files. The struct stores all transport configurations simultaneously (IPX, TCP/IP, serial, modem) in one unified layout — the active transport is selected at runtime by field [0x54]; all sub-blocks are always persisted.

Session name is NOT stored in NET.DAT. The multiplayer lobby session/game name comes from IP.CFG (/n= flag — see CFG.md), which is passed to IP.EXE at launch. NET.DAT only holds transport configuration and the Janes.net online identity.

Phone book in MODEM.DAT: RunModemConfigurationScreen reads/writes MODEM.DAT separately from NET.DAT. It manages 8 phone-book slots (player name + phone number pairs) stored in CN_INFO [0xd0][0x5cf]. In NET.DAT these bytes are always zeroed.

All file offsets below = CN_INFO struct offset + 4 (checksum header).

File off.  CN_INFO  Size  Field
---------  -------  ----  -----
0x0000        —       4   checksum (CfigChecksum over CN_INFO block; length = 0xddc/0xdd8/0xdb0 for v3/v2/v1)
0x0004      [0x0]     4   version dword — must be 3 (current); 2 and 1 are migrated on read
0x0008      [0x4]    80   callsign / Janes.net online name (null-terminated, 80-byte field)
                           — seeded from _janesOnlineName by CN_SetFactoryDefaults and CN_ReadConfig
                           — also passed directly as name to SER_ExchangeNames in serial mode
0x0058      [0x54]    4   transport type dword — selects active protocol:
                             2 = modem (set by RunModemConfigurationScreen; confirmed by MODEM.DAT diff)
                             3 = serial / RS-232 (SER_Initialize2_5 checks for == 3)
                             4 = TCP/IP (doConfigurationScreen checks for == 4)
                             other values used by NetSetProtocol for IPX/NetBEUI
0x0064      [0x60]    4   baud rate index dword (factory default: 10)
                             7=9600 · 8=19200 · 9=38400 · 10=57600 · 11=57600 · 12=28800 · 13=115200
                             (SER_Initialize4 switch; also used by MOD_InitPortAndModem)
0x0068      [0x64]    4   serial COM port index dword (factory default: 0 = COM1; range 0–3)
                             — read by SER_Initialize1; written by MOD_FindModemAndInit autodetect
0x006C      [0x68]   84   modem phone number / mode string (null-terminated, 84-byte field)
                             — dial mode (param_2==0): holds dial number, passed to _Dial_12
                             — listen mode (param_2≠0): RunModemConfigurationScreen writes "LISTEN"
0x00C0      [0xbc]    4   modem COM port index dword (factory default: 8 = autodetect)
                             0–7 = COM1–COM8 (explicit); 8 = autodetect (MOD_Initialize1 scans registry)
                             range valid: 0–8 checked by MOD_Initialize
0x00C4      [0xc0]  0x280 phone book player names: 8 × 0x50-byte null-terminated strings (slots 0–7)
                           — MODEM.DAT only; zeroed in NET.DAT; edited by RunModemConfigurationScreen
                           — slot n starts at CN_INFO[0xc0 + n×0x50]; stride confirmed by differential save
0x0344      [0x340] 0x280 phone book phone numbers: 8 × 0x50-byte null-terminated strings (slots 0–7)
                           — MODEM.DAT only; zeroed in NET.DAT; edited by RunModemConfigurationScreen
                           — slot n starts at CN_INFO[0x340 + n×0x50]; stride confirmed by differential save
0x05C4      [0x5c0] 0x324 (unused padding) — all-zero in every tested MODEM.DAT capture (0–8
                           phone-book entries, callsign set, transport set to modem, Call and
                           Answer modes both exercised). FA's modem config screen has no Advanced
                           Setup dialog; no UI path writes to this range. Confirmed unreachable.
0x08E8      [0x8e4]   8   IP address hex string — 8 ASCII hex chars, e.g. "c0a80101" for 192.168.1.1
                           (null-checkable; if [0x8e4]==0 then IP/MAC binary fields are zeroed)
0x08F0      [0x8ec]  13   MAC/IPX node hex string — 12 ASCII hex chars + null, e.g. "001122334455"
                   ~~~~  [0x8f9]–[0xdab]: ~1,203 bytes reserved/unused padding — all-zero in every
                             tested NET/MODEM.DAT capture; no traced accessor across the modem,
                             serial, TCP, and IPX config screens, the modem-init path, or the
                             config load/save (the bracketing hex-string and appIO/binary fields are
                             written, this gap is not) — the same result as the [0x5c0] padding above.
                             Carried verbatim by the byte-identical codec.
0x0DB0      [0xdac]   4   appIO callback function pointer — set by SER/MOD/NET_Initialize from CN_INFO;
                           used for status dialogs during connection setup
0x0DB4      [0xdb0]   ?   CN_INFO_TCP sub-block start (added in v2; initialized by NetSetFactoryTCP)
                           — first 12 bytes (3 dwords) zeroed/set via protocol vtable slot +0x66
0x0DCA      [0xdc6]   4   local IPX/SPX network number — written by spxinit via getsockname()
0x0DCE      [0xdca]   4   local IPX/SPX node address bytes 0–3 — written by spxinit via getsockname()
0x0DD2      [0xdce]   2   local IPX/SPX node address bytes 4–5 — written by spxinit via getsockname()
0x0DD4      [0xdd0]   4   remote address field A — dual-use:
                           TCP/IP context: IP address binary (4 bytes decoded from hex string at [0x8e4] via _atohb(…,8))
                           IPX context: direct-connect target IPX network number (user-entered in RunIPXOptionsDialog)
0x0DD8      [0xdd4]   4   remote address field B (first 4 bytes) — dual-use:
                           TCP/IP: MAC address bytes 0–3
                           IPX: direct-connect target IPX node address bytes 0–3
0x0DDC      [0xdd8]   2   remote address field B (last 2 bytes) — dual-use:
                           TCP/IP: MAC address bytes 4–5
                           IPX: direct-connect target IPX node address bytes 4–5
0x0DDE      [0xdda]   1   remote address validity/flag — dual-use:
                           TCP/IP: 1 = IP+MAC fields successfully decoded; 0 = invalid
                           IPX: 1 = direct-connect address manually entered by user; 0 = not set
0x0DDF      [0xddb]   1   (padding / unused; end of v3 struct)

Version migration (CN_ReadConfig)

File version Action
v3, size 0xddc Accepted as-is; _janesOnlineName overwrites [0x4] if set
v2, size 0xdd8 Upgraded: version set to 3; TCP sub-block re-initialized; IP/MAC binary decoded from hex strings at [0x8e4]/[0x8ec]
v1, size 0xdb0 Upgraded: same as v2 migration
corrupt / missing Factory defaults applied via CN_SetFactoryDefaults

Engine Notes

Confirmed Functions

Function VA Lines Role
CN_ReadConfig 0x47f7a0 98888 Reads config file (NET.DAT / MODEM.DAT / SERIAL.DAT); populates CN_INFO; applies _janesOnlineName at [4]
CN_WriteConfig 0x47f930 99014 Writes 4-byte checksum + 0xddc-byte CN_INFO to named config file
CN_SetFactoryDefaults 0x47f6d0 98785 Zeroes CN_INFO; sets version=3; seeds [4] from _janesOnlineName; calls NetSetFactoryTCP
CfigChecksum 0x47f740 98851 Checksums CN_INFO; length driven by version dword: 0xddc/0xdd8/0xdb0
NetSetFactoryTCP 0x4b0700 139845 Writes 3 zero dwords to TCP sub-block start via protocol vtable slot +0x66
SER_Initialize 0x44cb20 57979 Serial connection setup; reads [0x54], [0x60], [0x64]
SER_Initialize4 0x44c990 57902 Maps [0x60] baud rate index → internal timing constant
MOD_InitPortAndModem 0x49a7d0 Opens COM port at [0x64]; sends modem AT attention + init; called by MOD_FindModemAndInit
MOD_FindModemAndInit 0x49a850 Scans HKLM\System\CurrentControlSet\Services for attached modem; writes autodetected COM port to [0x64]
MOD_FindModemAndInitPCMCIA 0x49a9b0 Same as above but scans HKLM\Enum\PCMCIA for a PCMCIA modem
MOD_Initialize1 0x49ad00 Tries MOD_InitPortAndModem ([0xbc]), then FindModemAndInit, then FindModemAndInitPCMCIA
MOD_DoConnect 0x49ad70 Dials [0x68] phone number or waits for incoming call; decodes carrier speed → baud index
MOD_InitializeAndConnect 0x49af30 Calls MOD_Initialize1 then MOD_DoConnect
MOD_Initialize 0x49aff0 118822 Top-level modem setup; called by MP_Initialize (0x494bc0); reads [0x68], [0xbc]
MOD_Shutdown 0x49b0d0 Hangs up modem and releases COM port
RunSerialConfigurationScreen 0x49b1d0 Serial config UI; reads/writes SERIAL.DAT; edits callsign [0x4], COM port [0x64], baud [0x60]
RunModemAdvSetupDialog 0x49c260 Advanced modem setup dialog (CN_INFO* param); symbol confirmed, not yet decompiled
RunModemConfigurationScreen 0x49c780 Modem config UI; reads/writes MODEM.DAT; edits callsign, phone book [0xd0][0x5cf], COM port
NET_Initialize 0x4b0830 140115 TCP/IP connection setup; reads [0x54] for NetSetProtocol, [0xdac] for appIO
NET_StartQuery 0x4b0940 Starts SAP session scan; calls proto_ptr+0x42 (sapopensocket), registers SAP callback at 0x4b22a0
spxinit 0x496f40 Creates/binds SPX socket; writes local IPX address to [0xdc6][0xdce] via getsockname
spxinit2 0x497000 Protocol init stub; sets NET_PROTOCOL+0xb = 1; does not access CN_INFO
spxbuildaddress 0x497290 Builds NET_ADDRESS from local SPX address at [0xdc6][0xdce]
spxlisten 0x497010 Creates server-side SPX socket; binds to socket 0x87ec
spxconnect 0x497150 Connects SPX socket to a NET_ADDRESS
sapopensocket 0x4874c0 Creates IPX SAP socket for session discovery; reads direct-connect address from [0xdd0][0xdda]
FUN_004b22a0 0x4b22a0 SAP response callback; dispatches received packets to FUN_004b23f0
FUN_004b23f0 0x4b23f0 SAP packet dispatcher; handles type 0x2 (session ad), 0x14 (player ad), 0x18 (disconnect)
RunIPXOptionsDialog 0x493780 IPX options UI; reads/writes direct-connect address at [0xdd0][0xdda]

NET_PROTOCOL Struct (spx_proto)

The global ?spx_proto@@3UNET_PROTOCOL@@A at 0x00501408 is the SPX protocol implementation selected by NetSetProtocol when the connection type is IPX/SPX. _proto_ptr points to it after FUN_004b21f0 selects the matching entry from the protocol list at PTR_PTR_0050c6cc.

The struct is a flat array of function pointers (C-style interface, not a C++ vtable):

Offset Value Function
+0x04 0x0001 Protocol type short (1 = SPX)
+0x0a flag Initialized flag — set to return value of +0x3a during protocol selection
+0x0b flag Init flag — set to 1 by spxinit2
+0x3a 0x00496f40 spxinit — creates/binds SPX socket, writes local IPX address
+0x3e 0x00497000 spxinit2 — protocol init stub (called by NET_Initialize)
+0x42 0x004874c0 sapopensocket — creates SAP socket for session discovery (called by NET_StartQuery)
+0x46 0x00487670 Session connect function (called in SAP callback when a session is found)
+0x4a Packet processor (vtable; called in SAP callback for multi-packet responses)
+0x4e Post-query setup (called by NET_StartQuery after sapopensocket)
+0x5a Address extractor (called in SAP callback before NETIsAddrLocal check)

Source file (from error strings): E:\atf95\multi\sap.cpp, E:\atf95\multi\ipx.cpp

Formats: CFG — general game configuration (EA.CFG) and the IP.CFG launcher flags that carry the session name.

Engine: network.md — the full multiplayer protocol and transport documentation these files configure.