| 1 |
/*************************************************************************** |
| 2 |
|
| 3 |
network.h |
| 4 |
|
| 5 |
***************************************************************************/ |
| 6 |
#ifdef MAME_NET |
| 7 |
|
| 8 |
#ifndef __NETWORK_H__ |
| 9 |
#define __NETWORK_H__ |
| 10 |
|
| 11 |
#include "osdepend.h" |
| 12 |
|
| 13 |
#define NET_ERROR (-1) |
| 14 |
|
| 15 |
#define NET_SPECTATOR -1 |
| 16 |
#define NET_MAX_PLAYERS 8 |
| 17 |
|
| 18 |
//TODO: figure out where to put these options if anywhere |
| 19 |
#define NET_DEF_LAN_TIMEOUT 500000 /* lan default timeout value in us (microseconds) */ |
| 20 |
#define NET_DEF_DUP_TIMEOUT 1000000 /* dial-up default timeout value in us (microseconds) */ |
| 21 |
/* see below for protocol defines */ |
| 22 |
|
| 23 |
//TODO: move this stuff to TCPIP.h as it is specific to TCP/IP implementation |
| 24 |
#define NET_ID_PLAYER_CLIENT 0 |
| 25 |
#define NET_ID_PLAYER_SERVER 1 |
| 26 |
#define NET_ID_HEADLESS_SERVER 2 |
| 27 |
#define NET_ID_SPECTATOR 3 |
| 28 |
#define NET_TEXT_SPECTATOR "Spectator" |
| 29 |
#define NET_TEXT_PLAYER_CLIENT "Player" |
| 30 |
#define NET_TEXT_PLAYER_SERVER "Player/Server" |
| 31 |
#define NET_TEXT_HEADLESS_SERVER "Headless server" |
| 32 |
|
| 33 |
#define NUM_UI_KEYS 4 |
| 34 |
/* UI Keys to synchronize: |
| 35 |
0 = KEYCODE_FAST_EXIT |
| 36 |
1 = KEYCODE_RESET_MACHINE |
| 37 |
2 = KEYCODE_PAUSE |
| 38 |
3 = KEYCODE_UNPAUSE |
| 39 |
*/ |
| 40 |
|
| 41 |
|
| 42 |
int net_init(); |
| 43 |
int net_exit( char type ); |
| 44 |
int net_game_init(); |
| 45 |
int net_game_exit(); |
| 46 |
int net_vers_check( int player ); |
| 47 |
int net_game_check( int player ); |
| 48 |
int net_sync( char type ); |
| 49 |
int net_input_sync( unsigned char input_port_value[], unsigned char input_port_default[], int num_ports ); |
| 50 |
int net_analog_sync( unsigned char input_port_value[], int port, int analog_player_port[], int default_player ); |
| 51 |
int net_send( int player, char type, unsigned char *msg, int size ); |
| 52 |
int net_recv( int player, char type, unsigned char *msg, int size ); |
| 53 |
int net_add_player(); |
| 54 |
int net_remove_player( int player ); |
| 55 |
int net_active(); |
| 56 |
int net_chat_send( unsigned char *buf, int *size ); |
| 57 |
int net_chat_recv(int player, unsigned char *buf, int *size ); |
| 58 |
|
| 59 |
/************************************************************************** |
| 60 |
NetMAME PROTOCOL DEFINITION |
| 61 |
|
| 62 |
Revision History |
| 63 |
|
| 64 |
Rev1 1998June15 Peter Eberhardy with feedback from Michael Adcock |
| 65 |
Preliminary spec identifying most synchronous mode commands. |
| 66 |
Rev2 1998June30 Peter Eberhardy |
| 67 |
Revised to begin support for asynchronous mode. |
| 68 |
Rev3 1998July08 Peter Eberhardy |
| 69 |
Implemented asynchronous (joining/leaving chat) mode. |
| 70 |
Rev4 1998July31 Michael Adcock |
| 71 |
Implemented analog control synchronizing. |
| 72 |
Rev5 1998August09 Michael Adcock |
| 73 |
Figured out the first generation chat dialog. |
| 74 |
Rev6 1998September7 Peter Eberhardy |
| 75 |
Implemented first generation virtual key synchronizing. |
| 76 |
Rev7 1998October20 Peter Eberhardy |
| 77 |
Brought NetMAME32 source in sync with .34b4 source base. |
| 78 |
Worked on more chat code. |
| 79 |
|
| 80 |
|
| 81 |
Introduction |
| 82 |
|
| 83 |
The protocol is really not all that necessary. All the information |
| 84 |
passed between the server and the remote players should be synchronized. |
| 85 |
So you should always expect the packet you receive except in specific |
| 86 |
circumstances. (Some have termed this a wire protocol) |
| 87 |
|
| 88 |
Chat mode data can be received asynchronously and is also used when |
| 89 |
entering the configuration/option menus in MAME. When exiting chat mode |
| 90 |
or configuration/option menus the server and remote players resume |
| 91 |
synchronous mode. |
| 92 |
|
| 93 |
When a packet is received that is not expected the synchronization may |
| 94 |
change modes or an error has been detected and network support will |
| 95 |
attempt to abort, possibly aborting emulation or hanging. (Technically |
| 96 |
hanging or a crash is failed error detection) |
| 97 |
|
| 98 |
|
| 99 |
Packet format |
| 100 |
|
| 101 |
+-+-+-----+ |
| 102 |
|X|Y| buf | |
| 103 |
+-+-+-----+ |
| 104 |
where XYZ is 2 byte header |
| 105 |
X=Packet Type (1 byte) |
| 106 |
Z=buf size (1 byte) |
| 107 |
buf=packet type specific message (NET_MAX_PACKET-NET_MAX_HEADER bytes) |
| 108 |
|
| 109 |
|
| 110 |
Porting guidelines |
| 111 |
|
| 112 |
Other TCP/IP implementations should be similar to the Win32 Winsock |
| 113 |
implementation. If time permits I'll port X-MAME as well. Cross-platform |
| 114 |
games should work just fine if these guidelines are followed. |
| 115 |
|
| 116 |
In general, I advise receiving the full packet data size everytime you |
| 117 |
try to receive data - including synchronous reads. This should afford |
| 118 |
better error handling. |
| 119 |
|
| 120 |
Non TCP/IP implementations should also be easy to implement. NetMAME |
| 121 |
really doesn't care about the underlying protocol only the NetMAME |
| 122 |
packets. As time permits I'll also look at doing an IPX implementation |
| 123 |
which utilizes broadcasts or a multi-cast TCP/IP implementation. |
| 124 |
|
| 125 |
|
| 126 |
|
| 127 |
Function notes |
| 128 |
|
| 129 |
//TODO: lots more detail here... |
| 130 |
|
| 131 |
int net_init(); |
| 132 |
This functon handles network specific initialization and will need to |
| 133 |
call osd_net_init to handle the OS specific network initialization. |
| 134 |
|
| 135 |
int net_exit(); |
| 136 |
int net_vers_check(); |
| 137 |
int net_sync( char type ); |
| 138 |
int net_input_sync( unsigned char input_port_value[], unsigned char input_port_default[], int num_ports ); |
| 139 |
int net_analog_sync( unsigned char input_port_value[], int port, int analog_player_port[], int default_player ); |
| 140 |
int net_send( int player, char type, char reserved, unsigned char *msg, int size ); |
| 141 |
int net_recv( int player, char type, char reserved, unsigned char *msg, int size ); |
| 142 |
int net_add_player(); |
| 143 |
int net_remove_player(); |
| 144 |
int net_active(); |
| 145 |
int net_chat_send( unsigned char buf[], int *size ); |
| 146 |
int net_chat_recv( unsigned char buf[], int *size ); |
| 147 |
|
| 148 |
To-Do |
| 149 |
|
| 150 |
I'd like to implement a generic packet transmission benchmark similar |
| 151 |
to the FPS counter. Currently (rev2) it is unknown how NetMAME will perform |
| 152 |
under conditions with less than 10Mbs Ethernet bandwidth available to |
| 153 |
each node. |
| 154 |
|
| 155 |
|
| 156 |
References |
| 157 |
|
| 158 |
Contact Peter (eberhardy@acm.org) or Michael for more information and code comments. |
| 159 |
|
| 160 |
Peter recommends _UNIX Network Programming_ by W. Richard Stevens as a |
| 161 |
wonderful source for understanding network programming in general and |
| 162 |
specifically TCP/IP programming over Berkeley-style sockets or Winsock. |
| 163 |
|
| 164 |
**************************************************************************/ |
| 165 |
|
| 166 |
/*TODO: register mame port number and use a more portable method for NET_MAX_HEAD-_TYPE and _SIZE */ |
| 167 |
#define NET_MAME_PORT 6263 /* need to register this */ |
| 168 |
#define NET_MAX_PACKET 256 /* full packet */ |
| 169 |
#define NET_MAX_HEAD_TYPE sizeof(char) /* needs to be 1 */ |
| 170 |
#define NET_MAX_HEAD_SIZE sizeof(int) /* needs to be 1 */ |
| 171 |
#define NET_MAX_HEADER (NET_MAX_HEAD_TYPE + NET_MAX_HEAD_SIZE) |
| 172 |
#define NET_MAX_DATA (NET_MAX_PACKET-NET_MAX_HEADER) /* leftover for data */ |
| 173 |
|
| 174 |
#define NET_BYTE unsigned char /* TODO: remove this...? */ |
| 175 |
|
| 176 |
/* Packet header defines */ |
| 177 |
#define NET_0NOT_USED 0x00 /* zero should be reserved, possible error condition if no data sent */ |
| 178 |
|
| 179 |
#define NET_INIT_INIT 0x01 /* Setup connection */ |
| 180 |
#define NET_INIT_VERS 0x02 /* MAME/network version checking */ |
| 181 |
/* char 0: start of mameversion string |
| 182 |
char 25: start of netversion string */ |
| 183 |
#define NET_INIT_GAME 0x03 /* Game/ROM version checking */ |
| 184 |
/* char 0: start of GameDriver->name */ |
| 185 |
|
| 186 |
#define NET_SYNC_INIT 0x10 /* Basic synchronization */ |
| 187 |
#define NET_SYNC_INPT 0x11 /* Sync basic input */ |
| 188 |
#define NET_SYNC_ANLG 0x12 /* Sync analog input */ |
| 189 |
#define NET_SYNC_USER 0x13 /* Sync user interface input (F3,F8,F10,F12,TAB,P,etc) */ |
| 190 |
#define NET_SYNC_BOOM 0x14 /* Sync RAM - reserved for save state restarting and debugging */ |
| 191 |
#define NET_SYNC_REDO 0x15 /* Machine reset!!! */ |
| 192 |
#define NET_SYNC_PAWS 0x16 /* Toggle pause */ |
| 193 |
|
| 194 |
#define NET_QUIT_QUIT 0x20 /* Normal termination */ |
| 195 |
#define NET_QUIT_ABRT 0x21 /* Abnormal termination */ |
| 196 |
#define NET_QUIT_OKAY 0x22 /* Peer initiated quit (this is actually a placeholder and doesn't get sent) */ |
| 197 |
|
| 198 |
#define NET_CHAT_INIT 0x30 /* Enter chat mode */ |
| 199 |
#define NET_CHAT_CHAT 0x31 /* Chat exchange */ |
| 200 |
#define NET_CHAT_QUIT 0x32 /* Exit chat mode */ |
| 201 |
|
| 202 |
#endif /* __NETWORK_H__ */ |
| 203 |
|
| 204 |
#endif /* MAME_NET */ |