/* * Seven Kingdoms: Ancient Adversaries * * Copyright 1997,1998 Enlight Software Ltd. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ // Filename : OERRCTRL.H // Description : Error control for dplay #ifndef __OERRCTRL_H #define __OERRCTRL_H #include #include #include struct EcMsgHeader { char func_id; // FIRST_SEND / RE_SEND / ACKNOW / NEGACK char sender_id; // 1 to MAX_NATION (ecPlayerId) char frame_id; void init( char funcId, char senderId, char frameId ) { func_id = funcId; sender_id = senderId; frame_id = frameId; } }; class MultiPlayerType; class ErrorControl { enum { FIRST_SEND, RE_SEND, ACKNOW, NEGACK }; #ifdef AMPLUS // enum { MAX_PLAYER = MAX_NATION, MAX_QUEUE = 12, MAX_RECV_QUEUE = 48 }; enum { MAX_PLAYER = MAX_NATION, MAX_QUEUE = 18, MAX_RECV_QUEUE = 72 }; #else enum { MAX_PLAYER = MAX_NATION, MAX_QUEUE = 8, MAX_RECV_QUEUE = 32 }; #endif // MAX_QUEUE/2 > Remote::MAX_PROCESS_FRAME_DELAY // MAX_RECV_QUEUE > MAX_QUEUE/2 * MAX_PLAYER private: MultiPlayerType *mp_ptr; int connecting_player_count; // no. of peers char self_ec_player_id; char send_head; // queue_head == queue_tail, empty char send_tail; // queue_tail == queue_head -1, full VLenQueue send_queue[MAX_QUEUE]; // include EcMsgHeader and 8-bit CRC char ack_flag[MAX_QUEUE][MAX_PLAYER]; unsigned long send_time[MAX_QUEUE]; unsigned long re_send_after[MAX_QUEUE]; unsigned long dp_id[MAX_PLAYER]; // directPlay playerid, 0 if not valid char wait_to_receive[MAX_PLAYER]; char recv_flag[MAX_PLAYER][MAX_QUEUE]; // char next_send[MAX_PLAYER]; // char next_ack_send[MAX_PLAYER]; // char retrans_state[MAX_PLAYER]; char recv_head; char recv_tail; VLenQueue receive_queue[MAX_RECV_QUEUE]; // include EcMsgHeader and 8-bit CRC private: static inline void inc_frame_id(char &frameId) { if(++frameId >= MAX_QUEUE) frameId = 0; } static inline char next_frame_id(char frameId) { return frameId >= MAX_QUEUE-1 ? 0 : frameId+1 ; } static inline char prev_frame_id(char frameId) { return frameId <= 0 ? MAX_QUEUE-1 : frameId-1 ; } static int is_between(int low, int t, int high) { return low <= high ? (low <= t && t < high) : (low <= t || t < high); } int is_send_empty(); int is_send_full(); int send_queue_space(); int en_send_queue(); // return frameId void de_send_queue(); // free send_head int is_recv_empty(); int is_recv_full(); void en_recv_queue(void *dataPtr, unsigned long dataLen); int recv_queue_space(); // functions on ack_flag int is_waiting_ack(char ecPlayerId, char frameId); void set_ack(char ecPlayerId, char frameId); void clear_ack(char frameId); int are_all_acked(char frameId); void clear_acked_frame(); // functions on recv_flag int is_waiting_receive(char ecPlayerId, char frameId); void set_recv_flag(char ecPlayerId, char frameId); void clear_recv_flag(char ecPlayerId, char frameId); void mark_send_time(char frameId, unsigned long duration); int need_re_send(char frameId, int promptFactor); public: void init(MultiPlayerType *, char ecPlayerId ); void deinit(); void set_dp_id(char ecPlayerId, unsigned long dpPlayerId ); char get_ec_player_id( unsigned long dpPlayerId ); int send(char ecPlayerId, void *dataPtr, unsigned long dataLen); char *receive(char *sendEcPlayerId, unsigned long *dataLen); void de_recv_queue(); // get the content from recv_queue[recv_head] before de_recv_queue int is_player_valid(char ecPlayerId); void set_player_lost(char ecPlayerId); void yield(); void re_transmit(int promptFactor=1); }; extern ErrorControl ec_remote; #endif