#ifndef __WINE_PROTOCOL_H
#define __WINE_PROTOCOL_H

#include "dplay8.h"
#include "dplobby8.h"

#include "pshpack1.h"

/* message type magic numbers */

#define DP8P_ENUMHOSTS 0x00
#define DP8P_CONNECT 0x88
#define DP8P_SETPEERINFO 0x7F
#define DP8P_MESSAGEDATA 0x37
#define DP8P_MESSAGEDATA_UNKNOWN 0x3D
#define DP8P_MESSAGEDATA_GUARANTEED 0x3F
#define DP8P_ACK 0x80

/* ENUMHOSTS */

#define DP8P_ENUMHOSTS_SEND 0x02
#define DP8P_ENUMHOSTS_RESPONSE 0x03

typedef struct dp8pmsg_EnumHostsSend
{
    BYTE protocol_magic;
    BYTE enum_type; /* ENUMHOST_SEND. */
    BYTE packet_count;
    BYTE unknown_03; /* 0x82 */
    BYTE unknown_04; /* 0x01 */
    GUID guidApp;
} dp8pmsg_EnumHostsSend;

typedef struct dp8pmsg_EnumHostsResponse
{
    BYTE protocol_magic;
    BYTE enum_type; /* ENUMHOST_RESPONSE. */
    BYTE packet_count;
    BYTE unknown_03; /* 0x82 */
    BYTE unknown_04; /* 0x00 */
    BYTE unknown_05[7]; /* 0x00 */
    BYTE unknown_12; /* ed */
    BYTE unknown_13; /* 8f */
    BYTE unknown_14; /* f0 */
    BYTE unknown_15; /* b7 */
    DWORD unknown_16; /* 0x00 */
    DWORD max_players;
    DWORD current_players; /* ?? unconfirmed */
    DWORD unknown_28; /* 0x58 */
    DWORD unknown_32; /* 0x12 */
    BYTE unknown_36[24]; /* 0x00 */
    GUID guidUnknown;
    GUID guidApp;
    WCHAR game_name[0]; /* null terminate wide string */
} dp8pmsg_EnumHostsResponse;

/* ACK */
/* response to message data (3f):   80 06 01 00 04 [05] 00 00 76 13 D8 04
 *                          (3f):   80 06 01 00 02 [02] 00 00 8e a7 6c 00    ( same session as below )   ( at time = 1.751872 )
 * response to server connect (88): 80 02 01 00 02 [00] 01 00 d9 11 36 6b 81 a7 6c 00  (at time = 1.729208)
 *                                                 pid  - sometimes its +1, odd. hrm, just seen it as +2, gah.
 *                                     type. not really sure. (doesnt change from packet to packet)
 *                                              player id, to/from?
 */
typedef struct dp8pmsg_Ack
{
    BYTE protocol_magic;
    BYTE reply_type;
    BYTE unknown_03; /* 01 */
    BYTE unknown_04; /* 00 */
    BYTE unknown_05; /* player ID maybe? */
    BYTE orig_packet_count; /* packet count of the one we are replying to, kinda */
    BYTE unknown_07;
    BYTE unknown_08;
    BYTE data[0];
    /* so far always includes:
     * DWORD time_recieved; (from GetTickCount()) at end
     * has also included another DWORD in connect replies, this dword is the same
     * as the one we send out in 'connect' packets */
} dp8pmsg_Ack;

/* CONNECT */

/* go 1:
 connect   : 88 01 00 00 02 00 01 00 41 44 fe 72 a3 c7 14 00
 sresponse : 88 02 00 00 05 00 01 00 41 44 fe 72 ea a9 10 00
    --- Server recieves DPN_MSGID_INIDCATE_CONNECT here (after response)... odd
 cresponse : 80 02 01 00 02 00 01 00 41 44 fe 72 ab c7 14 00 (ack)
 */
/* go 2:
 connect   : 88 01 00 00 02 00 01 00 c1 61 74 00 79 b2 4c 00
 sresponse : 88 02 00 00 05 00 01 00 c1 61 74 00 9b 94 48 00
 cresponse : 80 02 01 00 02 00 01 00 c1 61 74 00 80 b2 4c 00
 */

typedef struct dp8pmsg_Connect
{
    BYTE protocol_magic;
    BYTE connect_type; /* 01 = connect, 02 = reply && connect to non-host peers. */
    BYTE packet_count; /* if so, it resets at 0. */
    BYTE unknown_04; /* 0x00 */
    BYTE unknown_05; /* 0x02 */
    BYTE unknown_06; /* 0x00 */
    BYTE unknown_07; /* 0x01 */
    BYTE unknown_08; /* 0x00 */
    /* FIXME: this unknown below MIGHT MATTER.. if so, I need to find out why?? */
    DWORD unknown_09; /* ... */ /* probably a dword of something... */
    DWORD time_sent; /* from GetTickCount() */
} dp8pmsg_Connect;

/* SETPEERINFO */

/*
                               7f 00 01 00 c1 00              ......
00 00 04 00 00 00 02 00  00 00 50 00 00 00 10 00   ........ ..P.....
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
00 00 b6 5d c1 46 26 50  f5 44 95 51 f4 bd af 3b   ...].F&P .D.Q...;
11 c1 36 30 6a 87 d7 ff  bc 46 92 09 b4 2f 61 7b   ..60j... .F.../a{
9b e7 4d 00 61 00 72 00  69 00 73 00 69 00 61 00   ..M.a.r. i.s.i.a.
00 00                                              ..

*/
/*
                               7f 00 01 02 c2 00   ........ !.......
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
00 00 00 00 00 00 03 00  00 00 f8 01 00 00 12 00   ........ ........
00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ........ ........
00 00 00 00 00 00 00 00  00 00 d2 e9 04 2e c5 30   ........ .......0
f2 42 b5 28 93 ea 11 b0  55 ab 36 30 6a 87 d7 ff   .B.(.... U.60j...
bc 46 92 09 b4 2f 61 7b  9b e7|d6 e9 54 2e 05 00   .F.../a{ ....T...
00 00 00 00 00 00 03 00  00 00 00 00 00 00|d0 e9   ........ ........
24 2e 00 00 00 00 02 01  00 00 02 00 00 00 00 00   $....... ........   -- host
00 00 06 00 00 00 ea 01  00 00 0e 00 00 00 00 00   ........ ........
00 00 00 00 00 00 00 00  00 00 00 00 00 00|d1 e9   ........ ........
34 2e 00 00 00 00 00 01  00 00 03 00 00 00 00 00   4....... ........   -- other player
00 00 06 00 00 00 d6 01  00 00 14 00 00 00 00 00   ........ ........
00 00 00 00 00 00 74 01  00 00 62 00 00 00|d6 e9   ......t. ..b.....
54 2e 00 00 00 00 00 01  00 00 05 00 00 00 00 00   T....... ........
00 00 02 00 00 00 5e 01  00 00 16 00 00 00 00 00   ......^. ........   -- us ?
00 00 00 00 00 00 fc 00  00 00 62 00 00 00|78 2d   ........ ..b...x-
64 69 72 65 63 74 70 6c  61 79 3a 2f 70 72 6f 76   directpl ay:/prov
69 64 65 72 3d 25 37 42  45 42 46 45 37 42 41 30   ider=%7B EBFE7BA0
2d 36 32 38 44 2d 31 31  44 32 2d 41 45 30 46 2d   -628D-11 D2-AE0F-
30 30 36 30 39 37 42 30  31 34 31 31 25 37 44 3b   006097B0 1411%7D;   -- 120 (78) is len of uri + name
68 6f 73 74 6e 61 6d 65  3d 31 39 32 2e 31 36 38   hostname =192.168   -- 98  (62) is len of uri
2e 30 2e 31 39 3b 70 6f  72 74 3d 32 33 30 32 00   .0.19;po rt=2302.
54 00 65 00 73 00 74 00  50 00 6c 00 61 00 79 00   T.e.s.t. P.l.a.y.   -- 22  (16) is len of name
65 00 72 00 00 00 78 2d  64 69 72 65 63 74 70 6c   e.r...x- directpl
61 79 3a 2f 70 72 6f 76  69 64 65 72 3d 25 37 42   ay:/prov ider=%7B
45 42 46 45 37 42 41 30  2d 36 32 38 44 2d 31 31   EBFE7BA0 -628D-11
44 32 2d 41 45 30 46 2d  30 30 36 30 39 37 42 30   D2-AE0F- 006097B0   -- 118 (76) is len of uri + name
31 34 31 31 25 37 44 3b  68 6f 73 74 6e 61 6d 65   1411%7D; hostname   -- 98  (62) is len of uri
3d 31 39 32 2e 31 36 38  2e 30 2e 32 37 3b 70 6f   =192.168 .0.27;po
72 74 3d 32 33 30 33 00  43 00 6c 00 69 00 65 00   rt=2303. C.l.i.e.   -- 20  (14) is len of name
6e 00 74 00 54 00 77 00  6f 00 00 00 43 00 6c 00   n.t.T.w. o...C.l.   
69 00 65 00 6e 00 74 00  00 00 54 00 65 00 73 00   i.e.n.t. ..T.e.s.   -- 14  ( e) is len of name
74 00 47 00 61 00 6d 00  65 00 00 00               t.G.a.m. e...       -- 18  (12) is len of game name

*/
typedef struct dp8pmsg_SetPeerInfo_Local
{
    BYTE protocol_magic;
    BYTE unknown_02;
    BYTE packet_count;
    BYTE unknown_04; /* 00 */ /* -- peer type ID? */
    DWORD unknown_05; /* 0xc1 */
    DWORD unknown_09; /* 0x04 */
    DWORD unknown_13; /* 0x02 */
    DWORD unknown_17; /* 0x50, civ3 has 0x58 - perhaps offset to name or something? */
    DWORD player_name_len;

    DWORD unknown_21; /* 00 */
    DWORD unknown_25;
    DWORD unknown_29;
    DWORD unknown_33;
    DWORD unknown_37; /* 0x50 for civ3 */
    DWORD connect_data_len;
    DWORD unknown_45;
    DWORD unknown_49;
    GUID guidUnknown;
    GUID guidApp;
    BYTE data[0];
} dp8pmsg_SetPeerInfo_Local;

typedef struct dp8pmsg_SetPeerInfo_Game
{
    BYTE protocol_magic;
    BYTE unknown_02;
    BYTE packet_count;
    BYTE unknown_04; /* 02 */ /* -- peer type ID? */
    DWORD unknown_05; /* c2 */ /* also possibly peer type ID, maybe flags? */
    DWORD unknown_09; /* saw 0x78 01 00 00 when we had data, could be offset? */
    DWORD reply_data_len;
    BYTE unknown_17[12];
    DWORD player_count; /* FIXME: or our player number */
    DWORD len_unknown_01; /* offset? length of something. its rather odd */
    DWORD game_name_len;
    BYTE unknown_x1[24];
    GUID guidUnknown;
    GUID guidApp;
    DWORD unknown_x2;
    DWORD our_player_number;
    DWORD unknown_x4; /* 0 */
    DWORD player_count_2; /* FIXME: or our player number */
    DWORD unknown_x5; /* 0 */
    BYTE data[0]; /* dp8pmsg_part_PeerInfo_Player * number of players. +
                   * (uri + player name) * number of players +
                   * game name
                   */
} dp8pmsg_SetPeerInfo_Game;

typedef struct dp8pmsg_part_PeerInfo_Player
{
    DPNID player_id;
    DWORD unknown_05; /* 0 */
    DWORD unknown_09; /* something rather interesting, indeed */
    DWORD player_number; /* player number, internal? unique in a session */
    DWORD unknown_17; /* 0 */
    DWORD unknown_21; /* 06 for other? 02 for the person recieving the message? */
    DWORD unknown_25; /* some kind of count, odd really */
    DWORD player_name_len;
    DWORD unknown_33; /* 0 */
    DWORD player_data_len;
    DWORD unknown_41; /* something rather high, normally */
    DWORD uri_len;
} dp8pmsg_part_PeerInfo_Player;

typedef struct dp8pmsg_SetPeerInfo_Unknown
/* I'm not sure why this is used, I need more testing.
 * I'm thinking it may be for sending "hello" to each peer? */
{
    BYTE protocol_magic;
    BYTE unknown_02;
    BYTE packet_count;
    BYTE unknown_04; /* 02 */
    BYTE unknown_05; /* c3 to send. c5 to recieve rejected, c6 to recieve ok */
    BYTE unknown_06; /* 00 */
    BYTE unknown_07; /* 00 */
    BYTE unknown_08; /* 00 */
} dp8pmsg_SetPeerInfo_Unknown;

typedef struct dp8pmsg_SetPeerInfo_Connected
{ /* probably shouldn't be called SetPeerInfo */
    BYTE protocol_magic;
    BYTE unknown_02;
    BYTE packet_count;
    BYTE unknown_04;
    DWORD unknown_05; /* c5 = rejected, c6 = accepted */
    DWORD unknown_09; /* 0x80158260 */
    DWORD unknown_13; /* 0 (sample) or 0xc (civ3 rejected) */
    DWORD data_size; /* 0 or 0x21  == length of data */
    BYTE data[0];
} dp8pmsg_SetPeerInfo_Connected;

/* MESSAGEDATA */

typedef struct dp8pmsg_MessageData
{
    BYTE protocol_magic;
    BYTE unknown_02; /* 00 */
    BYTE packet_count;
    BYTE unknown_04;
    BYTE data[0];
} dp8pmsg_MessageData;

#include "poppack.h"

#endif

