
Game and Address Discovery Packets

for Descent Registered v1.0.
Robert Huebner

The following information is provided for informational 
purposes only.  Parallax and Interplay make no guarantees as to 
the completeness or accuracy of this information, and the 
information is subject to change in future versions of Descent 
with no guarantee of updating this document.  This is not an 
official document of either company and is inteded simply as an 
aid to the Descent user community in developing useful 
utilities.

Note that the format described here is not valid for Shareware 
versions of Descent.  The two versions use a different network 
packet structure and different socket numbers, so an 
application written to work with registered versions of Descent 
will not work with shareware ones.

Overview:

Because discovery of active games and so on uses IPX broadcast 
packets, this opens the door for home-brew programs to display 
active games and so on.  And because there is actually more 
information in these discovery packets than is currently used 
in the game itself, there is a great deal of interesting 
information that can be displayed about an active game.  Some 
examples of info that could be displayed are:

current game scores (kills, killed, points, etc)
players in an active game (callsigns)
level the game is on
mission the game is using
time spent in the current level
IPX addresses for all the active players
team membership

All this information can also be shown for closed games.

fix types are 32-bit fixed point values with 16-bit mantissa.

All packets sent/received are assumed to contain a standard ECB 
and IPX header.  In addition, the first 4 bytes are a packet 
sequence number not of interest to this specification.  
Therefore each structure described here begins on the 5th byte 
of the data portion of the packet, or 32 bytes from the start 
of the packet.

The game information is stored in a structure referred to 
internally as Netgame_info.  Here is the structure of 
netgame_info:

WARNING: Do not flood the network with broadcast packets in 
order to get this game information.  It will slow down the 
games and generally irritate everyone on the network.  If you 
don't know how to add a sleep time to the polling loop of a 
network application, please stop reading and leave the coding 
to someone else!  Playing with raw IPX broadcasts is not a good 
way to introduce yourself to network programming.

The following struct is used as an element in the two basic 
structures needed to implement this system:

typedef struct netplayer_info {
	char		callsign[9]; 
	ubyte		server[4];  (these are not the local target addresses)
	ubyte		node[6];
	ushort		socket;
	byte 		connected;
} netplayer_info;

Values for 'connected' field:
#define CONNECT_DISCONNECTED		0	(Player was in game but left)
#define CONNECT_PLAYING			1	(Player is in game and playing)
#define CONNECT_WAITING			2	(Player is waiting to start the next level)
#define CONNECT_DIED_IN_MINE		3	(Player died in mine)
#define CONNECT_FOUND_SECRET		4	(Player exited mine via secret exit)
#define CONNECT_ESCAPE_TUNNEL		5	(Player is flying thru escape tunnel)
#define CONNECT_END_MENU		6	(Player is looking at the kill list or bonus)

typedef struct netgame_info {
	ubyte		type; // Always 37 decimal for this packet type
	char		game_name[16];
	char		team_name[2][9];
	ubyte		gamemode; (see NETGAME_XXX defines)
	ubyte		difficulty; (0-4)
	ubyte 		game_status;
	ubyte		numplayers; // how many active players
	ubyte		max_numplayers; (4 or 8, depending on mode)
	ubyte		game_flags; (see NETGAME_FLAG_XXX defines)
	netplayer_info	players[8];
	int		locations[8]; // starting locations (not always valid)
	short		kills[8][8]; // array of who-killed-who
	int		levelnum; // -1 = secret #1
	ubyte		protocol_version; // 2 for Registered
	ubyte		team_vector; // bitvector, 0 = blue, 1 = red.
	ushort		segments_checksum;
	short		team_kills[2];
	short		killed[8];
	short		kills[8];
	fix		level_time;
	fix		control_invul_time; // while level time < this, no damage to controlcen
	int 		monitor_vector; // which monitors are exploded, 32-bit bitvector
	int		player_score[8]; // valid only during coop games
	ubyte		player_flags[8]; // can get info about keys players have
	char		mission_name[9]; // filename of mission
	char		mission_title[22]; // title of mission
} netgame_info;

// Values for game_status field:
#define NETSTAT_MENU		0
#define NETSTAT_PLAYING		1
#define NETSTAT_BROWSING	2
#define NETSTAT_WAITING		3
#define NETSTAT_STARTING	4
#define NETSTAT_ENDLEVEL	5

// Values for game_flags field
#define NETGAME_FLAG_CLOSED 	1
#define NETGAME_FLAG_SHOW_ID	2 // Not currently in use
#define NETGAME_FLAG_SHOW_MAP 	4

// Values for gamemode field
#define NETGAME_ANARCHY		0
#define NETGAME_TEAM_ANARCHY	1
#define NETGAME_ROBOT_ANARCHY	2
#define NETGAME_COOPERATIVE	3

Obtaining a netgame packet:

To obtain a netgame packet for each active network game, the 
program must broadcast a packet the says "Tell me about your 
netgame".  A representative from each actively running or 
forming netgame will reply (not broadcast) the structure shown 
above to the requestor.  Also, when game information changes or 
when a new game is started, the netgame structure will be 
broadcast on the socket.

Socket numbers begin at a default of  hex 5100, adding the 
value of the -socket command line param to this base for 
alternate sockets.

To request netgame_info packets, your application needs to send 
a filled-in "sequence_packet".  To broadcast a packet on IPX 
you can send to local target 0xff, 0xff, 0xff, 0xff, 0xff, 
0xff.  My suggestion is do this no more than once every minute 
or so to avoid loading the network and burdening the machines 
playing the game.  Or better yet do it only once on-demand.  
After you broadcast this packet you should get between 0 and 4 
replies from active netgames within 1 or 2 seconds.

typedef struct sequence_packet {
	ubyte			type; // 36 decimal for this situation!
	netplayer_info		player;
} sequence_packet;

Fields that should be filled in are player.node, and 
player.server.  The node are server must be filled in since the 
reply is not broadcast.   Type must be set to 36 decimal.  
Player.callsign can be ignored.

Make sure all fields in this broadcast are set correctly to 
avoid problems!

Once again, let me restate the risks of crashing netgames or 
entire networks by improper use of IPX primatives.  Don't 
experiment with programs using this specification on live
sockets or networks.  We disclaim all responsibility for 
improper use of this specification.

For more information on IPX interrupts, headers, etc, I'd
recommend "C Programmers Guide to NetBIOS, SPX, and IPX"
published by Sams.

Happy hacking.

