821 lines
28 KiB
C
821 lines
28 KiB
C
/*
|
||
* universal multiplayer library level 0 implementation file
|
||
* transport layer: TEN arena PC-windows 95
|
||
*/
|
||
|
||
/*
|
||
* Author: David Fournier
|
||
*
|
||
* Creation Date: 13/12/96
|
||
*
|
||
*/
|
||
|
||
|
||
#include "warnings.h"
|
||
|
||
#include <stdlib.h>
|
||
/*
|
||
* we need this one to fill the interface structure
|
||
* with pointers to the correct functions
|
||
*/
|
||
#include "Privl0ten.h"
|
||
#include "PrivNetDef.h"
|
||
#include "l0GlDef.h"
|
||
#include "NetMemCo.h"
|
||
#include "NetSock.h"
|
||
#include "NetEnd.h"
|
||
#include "PrivNetSer.h"
|
||
#include <NET\Netdebug.h>
|
||
|
||
#include <arena.h>
|
||
#include <button.h>
|
||
#include <debuglib.h>
|
||
#include <environ.h>
|
||
#include <tenutils.h>
|
||
|
||
#define TEN_MAXBUF 250
|
||
|
||
static char gs_bL0PCWin95TENInitState;
|
||
|
||
#pragma pack(1)
|
||
|
||
typedef struct
|
||
{
|
||
NetLib_tduxPlayerId pid; /* ID of the player. */
|
||
NetLib_tduwJoinType joinType; /* Create, Join or Watch. */
|
||
}NetLib_tdstInfoPlayer;
|
||
|
||
static NetLib_tdstInfoPlayer gs_InfoLocal; /* Informations of the local player. */
|
||
static long SendBufSize; /* Virtual buffer size. */
|
||
static unsigned long LastTime; /* Time for the last eL0PCWin95TENEngine. */
|
||
static unsigned long SendMaxRate; /* Maximum rate. */
|
||
static unsigned short NbrPlayer; /* Number of player. */
|
||
static NetLib_tdstInfoPlayer *TabPlayer; /* Table of player. */
|
||
|
||
typedef struct stFIFO
|
||
{
|
||
struct stFIFO *next; /* Next message of FIFO. */
|
||
unsigned long size; /* Size of message. */
|
||
NetLib_tduxPlayerId id; /* ID of sender. */
|
||
}FIFO;
|
||
|
||
static FIFO *FIFObegin; /* First message of file. */
|
||
static FIFO **FIFOend; /* Last pointer of the file. */
|
||
|
||
static unsigned short gs_uwCallBack;
|
||
static NetLib_tduwJoinType gs_JoinType;
|
||
|
||
typedef struct
|
||
{
|
||
NetLib_uxReadReceiptId m_ulReadReceiptId;
|
||
unsigned long uxPriority:7;
|
||
unsigned long uxReplaceType:7;
|
||
unsigned long uxReplace:1;
|
||
unsigned long eMessageType:5;
|
||
unsigned long uxHeadBigEndian:1;
|
||
unsigned long uxBodyBigEndian:1;
|
||
}TENHead;
|
||
|
||
#pragma pack()
|
||
|
||
/* Convert a bloc memory into a hexa string. */
|
||
void memtohexa(void *mem,unsigned short sizemem,char *hexa)
|
||
{
|
||
unsigned char *p=(unsigned char *)mem;
|
||
unsigned short c,i;
|
||
for (i=0;i<sizemem;i++)
|
||
{
|
||
c=((p[i]&0xF0)>>4);
|
||
if (c<10) hexa[i*2]=c+'0';
|
||
else hexa[i*2]=(c-10)+'A';
|
||
c=p[i]&0x0F;
|
||
if (c<10) hexa[i*2+1]=c+'0';
|
||
else hexa[i*2+1]=(c-10)+'A';
|
||
}
|
||
hexa[i*2]=0;
|
||
}
|
||
|
||
/* Convert a hexa string into a bloc memory. */
|
||
void hexatomem(void *mem,char *hexa)
|
||
{
|
||
unsigned char *p=(unsigned char *)mem;
|
||
unsigned short c,i,sizehexa;
|
||
sizehexa=strlen(hexa)/2;
|
||
for (i=0;i<sizehexa;i++)
|
||
{
|
||
p[i]=0;
|
||
c=hexa[i*2];
|
||
if ((c>='0') && (c<='9')) p[i]+=((c-'0')<<4);
|
||
else p[i]+=(((c-'A')+10)<<4);
|
||
c=hexa[i*2+1];
|
||
if ((c>='0') && (c<='9')) p[i]+=(c-'0');
|
||
else p[i]+=(c-'A')+10;
|
||
}
|
||
}
|
||
|
||
/* Process the maximum send rate. */
|
||
static void ProcMaxRate(void)
|
||
{
|
||
unsigned short i,nbrp=0;
|
||
unsigned long max=10000000L;
|
||
unsigned long rate;
|
||
for (i=0;i<NbrPlayer;i++)
|
||
{
|
||
if (TabPlayer[i].pid!=C_uxNetInvalidId)
|
||
{
|
||
size_t size=sizeof(long);
|
||
tenArGetPlayerInfo(TabPlayer[i].pid,kTenArPIBandwidth,&rate,&size);
|
||
if ((rate) && (max>rate)) max=rate;
|
||
nbrp++;
|
||
}
|
||
}
|
||
if (nbrp>1) SendMaxRate=max/(nbrp-1);
|
||
else SendMaxRate=10000000L;
|
||
SendMaxRate=5000;
|
||
}
|
||
|
||
/* Add a player info. */
|
||
static void AddPlayerInfo(NetLib_tduxPlayerId pid,NetLib_tduwJoinType joinType)
|
||
{
|
||
NetLib_tdstInfoPlayer *nTab;
|
||
unsigned short i;
|
||
if (pid+1>NbrPlayer)
|
||
{
|
||
nTab=(NetLib_tdstInfoPlayer *)pMalloc(sizeof(NetLib_tdstInfoPlayer)*(pid+1));
|
||
memcpy(nTab,TabPlayer,sizeof(NetLib_tdstInfoPlayer)*NbrPlayer);
|
||
for (i=NbrPlayer;i<pid;i++) TabPlayer[i].pid=C_uxNetInvalidId;
|
||
vFree((char *)TabPlayer);
|
||
TabPlayer=nTab;
|
||
NbrPlayer=pid+1;
|
||
}
|
||
TabPlayer[pid].pid=pid;
|
||
TabPlayer[pid].joinType=joinType;
|
||
ProcMaxRate();
|
||
}
|
||
|
||
/* Supprim a player info. */
|
||
static void SupPlayerInfo(NetLib_tduxPlayerId pid)
|
||
{
|
||
TabPlayer[pid].pid=C_uxNetInvalidId;
|
||
ProcMaxRate();
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: vL0PCWin95TENCloseChannel
|
||
* frees a slot in the channel table
|
||
*****************************************************************************
|
||
* Input: identifier of the channel
|
||
* Output: none
|
||
*****************************************************************************/
|
||
void vL0PCWin95TENCloseChannel(tduwNetChannel uwChannel)
|
||
{
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: uwL0PCWin95TENStartChannelScan
|
||
* returns the identification number of the first channel for the protocol
|
||
*****************************************************************************
|
||
* Input: none
|
||
* Output: 0
|
||
*****************************************************************************/
|
||
tduwNetChannel uwL0PCWin95TENStartChannelScan(void)
|
||
{
|
||
if(!(gs_bL0PCWin95TENInitState&0x02))
|
||
return C_uwNetInvalidChannel;
|
||
|
||
return 0;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: uwL0PCWin95TENNextChannel
|
||
* returns the identification number of the channel following the last
|
||
*****************************************************************************
|
||
* Input: uwLastScannedChannel, index returned by the previous call
|
||
* Output: C_uwNetInvalidChannel
|
||
*****************************************************************************/
|
||
tduwNetChannel uwL0PCWin95TENNextChannel(tduwNetChannel uwLastScannedChannel)
|
||
{
|
||
return C_uwNetInvalidChannel;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: uwL0PCWin95TENStartBroadcastChannelScan
|
||
* returns the identification number of the first broadcast channel
|
||
* for the protocol
|
||
*****************************************************************************
|
||
* Input: none
|
||
* Output: 0
|
||
*****************************************************************************/
|
||
tduwNetChannel uwL0PCWin95TENStartBroadcastChannelScan(void)
|
||
{
|
||
if(!(gs_bL0PCWin95TENInitState&0x02))
|
||
return C_uwNetInvalidChannel;
|
||
|
||
return 1;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: uwL0PCWin95TENNextBroadcastChannel
|
||
* returns the identification number of the broadcast channel following
|
||
* the specified one
|
||
*****************************************************************************
|
||
* Input: uwLastScannedChannel, index returned by the previous call
|
||
* Output: identification of the channel following the specified one
|
||
*****************************************************************************/
|
||
tduwNetChannel uwL0PCWin95TENNextBroadcastChannel(tduwNetChannel uwLastScannedChannel)
|
||
{
|
||
return C_uwNetInvalidChannel;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: L0PCWin95TENReadCallBack
|
||
*****************************************************************************
|
||
* Input: p_uwChannel, pointer on a field to store the identification of
|
||
* a new channel in case of access to a newly created broacast channel
|
||
* (irrelevant for the serial layer)
|
||
* ppData, address of the pointer to retrieve a full message if
|
||
* necessary.
|
||
* Output: an error condition.
|
||
*****************************************************************************/
|
||
static void L0PCWin95TENReadCallBack(int fromPid, void *buf, size_t size)
|
||
{
|
||
FIFO *cour;
|
||
#if defined(NET_USE_DEBUG)
|
||
TENHead *pSend=(TENHead *)buf;
|
||
vDebugSISISI(Net_C_Debug_Ten,"Receive Type",pSend->eMessageType,"Size",size-sizeof(TENHead),"Source",fromPid);
|
||
#endif
|
||
cour=(FIFO *)pMalloc(sizeof(FIFO)+size);
|
||
if (cour)
|
||
{
|
||
*FIFOend=cour;
|
||
cour->next=NULL;
|
||
cour->size=size;
|
||
cour->id=fromPid;
|
||
memcpy(cour+1,buf,size);
|
||
FIFOend=&(cour->next);
|
||
}
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: wL0PCWin95TENGetMessage
|
||
*****************************************************************************
|
||
* Input: ppData, address of the pointer to retrieve a full message if
|
||
* necessary.
|
||
* Output: return 1 if getting a message and 0 otherwise.
|
||
*****************************************************************************/
|
||
short wL0PCWin95TENGetMessage(tdstNetMessage **ppMes)
|
||
{
|
||
FIFO *cour;
|
||
tdstNetMessage *pMes;
|
||
TENHead *pSend;
|
||
if (FIFObegin==NULL)
|
||
{
|
||
*ppMes=NULL;
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
pMes=(tdstNetMessage *)pMalloc(FIFObegin->size+sizeof(tdstNetMessage)-sizeof(TENHead));
|
||
if (pMes==NULL)
|
||
{
|
||
*ppMes=NULL;
|
||
return -1;
|
||
}
|
||
pSend=(TENHead *)(FIFObegin+1);
|
||
memcpy(pMes+1,pSend+1,FIFObegin->size-sizeof(TENHead));
|
||
pMes->m_uxReadReceiptId=pSend->m_ulReadReceiptId;
|
||
pMes->uxPriority=pSend->uxPriority;
|
||
pMes->uxReplace=pSend->uxReplace;
|
||
pMes->uxReplaceType=pSend->uxReplaceType;
|
||
pMes->eMessageType=pSend->eMessageType;
|
||
pMes->uxHeadBigEndian=pSend->uxHeadBigEndian;
|
||
pMes->uxBodyBigEndian=pSend->uxBodyBigEndian;
|
||
pMes->uxSessionId=0;
|
||
pMes->uxSenderId=FIFObegin->id;
|
||
pMes->uxRecipientId=gs_InfoLocal.pid;
|
||
pMes->uwMessageSizeInBytes=(unsigned short)(FIFObegin->size-sizeof(TENHead));
|
||
pMes->ulReserved=M_ulMakeReserved(M_uwProcessCheckSum(pMes),
|
||
M_uwProcessCheckSumBody(pMes));
|
||
cour=FIFObegin->next;
|
||
vFree((char *)FIFObegin);
|
||
FIFObegin=cour;
|
||
if (cour==NULL) FIFOend=&FIFObegin;
|
||
*ppMes=pMes;
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENReadData
|
||
*****************************************************************************
|
||
* Input: p_uwChannel, pointer on a field to store the identification of
|
||
* a new channel in case of access to a newly created broacast channel
|
||
* (irrelevant for the serial layer)
|
||
* ppData, address of the pointer to retrieve a full message if
|
||
* necessary.
|
||
* Output: an error condition.
|
||
*****************************************************************************/
|
||
NetLib_tdeErrorStatus eL0PCWin95TENReadData(tduwNetChannel *p_uwChannel, tdpPointer *ppData)
|
||
{
|
||
short r;
|
||
/* verify the validity of the Channel */
|
||
if(*p_uwChannel>1) return NetLib_E_es_InvalidChannel;
|
||
|
||
/* no : try to get a message from the FIFO */
|
||
r=wL0PCWin95TENGetMessage((tdstNetMessage **)ppData);
|
||
if (r>0) return NetLib_E_es_NoError;
|
||
else if (r==0) return NetLib_E_es_FIFOIsEmpty;
|
||
else return NetLib_E_es_NotEnoughMemory;
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENSendData
|
||
*****************************************************************************
|
||
* Input: uwChannel, channel to send the message into.
|
||
* pData, pointer on the block to send
|
||
* Output: an error condition.
|
||
*****************************************************************************/
|
||
NetLib_tdeErrorStatus eL0PCWin95TENSendData(tduwNetChannel uwChannel, tdpPointer pData)
|
||
{
|
||
unsigned long ulBytestoSend;
|
||
tdstNetMessage *pMes=(tdstNetMessage *)pData;
|
||
int NumErr;
|
||
TENHead *pSend;
|
||
unsigned long NewTime;
|
||
|
||
/* verify the validity of the Channel */
|
||
if(uwChannel>1)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugS(Net_C_Debug_Ten,"Invalid channel");
|
||
#endif
|
||
return NetLib_E_es_InvalidChannel;
|
||
}
|
||
|
||
if (pMes->uxRecipientId==C_uxNetBroadcastId) uwChannel=1;
|
||
|
||
ulBytestoSend= pMes->uwMessageSizeInBytes + sizeof(TENHead);
|
||
|
||
NewTime=GetTickCount();
|
||
SendBufSize-=((NewTime-LastTime)*(float)SendMaxRate)/1000;
|
||
LastTime=NewTime;
|
||
if (SendBufSize<0) SendBufSize=0;
|
||
if (SendBufSize>=TEN_MAXBUF)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugS(Net_C_Debug_Ten,"Controle de flot.");
|
||
#endif
|
||
return NetLib_E_es_BufferIsFull;
|
||
}
|
||
SendBufSize+=ulBytestoSend+20;
|
||
|
||
pSend=(TENHead *)pMalloc(ulBytestoSend);
|
||
if (!pSend)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugS(Net_C_Debug_Ten,"Manque de m<>moire.");
|
||
#endif
|
||
return NetLib_E_es_NotEnoughMemory;
|
||
}
|
||
memcpy(pSend+1,pMes+1,pMes->uwMessageSizeInBytes);
|
||
|
||
pSend->m_ulReadReceiptId=pMes->m_uxReadReceiptId;
|
||
pSend->uxPriority=pMes->uxPriority;
|
||
pSend->uxReplace=pMes->uxReplace;
|
||
pSend->uxReplaceType=pMes->uxReplaceType;
|
||
pSend->eMessageType=pMes->eMessageType;
|
||
pSend->uxHeadBigEndian=pMes->uxHeadBigEndian;
|
||
pSend->uxBodyBigEndian=pMes->uxBodyBigEndian;
|
||
|
||
if (uwChannel!=1)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugSISISI(Net_C_Debug_Ten,"Send to one player. Type",pMes->eMessageType,"Size",pMes->uwMessageSizeInBytes,"Recipient",pMes->uxRecipientId);
|
||
#endif
|
||
NumErr=tenArSendToPlayer(pMes->uxRecipientId,pSend,ulBytestoSend);
|
||
}
|
||
else
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugSISISI(Net_C_Debug_Ten,"Send to all players. Type",pMes->eMessageType,"Size",pMes->uwMessageSizeInBytes,"Recipient",pMes->uxRecipientId);
|
||
#endif
|
||
NumErr=tenArSendToOtherPlayers(pSend,ulBytestoSend);
|
||
}
|
||
|
||
vFree((char *)pSend);
|
||
if (NumErr)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugSI(Net_C_Debug_Ten,"Emission en attente",NumErr);
|
||
#endif
|
||
return NetLib_E_es_BufferIsFull;
|
||
}
|
||
|
||
/* free the message buffer */
|
||
vFree(pData);
|
||
|
||
return NetLib_E_es_NoError;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENQueryChannelStatus
|
||
* returns the current status of the channel
|
||
*****************************************************************************
|
||
* Input: uwChannel, channel to query
|
||
* Output: an error condition.
|
||
*****************************************************************************/
|
||
NetLib_tdeErrorStatus eL0PCWin95TENQueryChannelStatus(tduwNetChannel uwChannel)
|
||
{
|
||
return NetLib_E_es_NoError;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENEngine
|
||
*****************************************************************************
|
||
* Input: none
|
||
* Output: none
|
||
*****************************************************************************/
|
||
void eL0PCWin95TENEngine(void)
|
||
{
|
||
tenArIdleArena();
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : vL0PCWin95TENCloseProtocol(void)
|
||
* TEN-Level 0 closing function
|
||
*****************************************************************************
|
||
* Input : none
|
||
* Output : none
|
||
*****************************************************************************/
|
||
void vL0PCWin95TENCloseProtocol(void)
|
||
{
|
||
FIFO *p;
|
||
while (FIFObegin)
|
||
{
|
||
p=FIFObegin->next;
|
||
vFree((char*)FIFObegin);
|
||
FIFObegin=p;
|
||
}
|
||
FIFObegin=NULL;
|
||
FIFOend=&FIFObegin;
|
||
|
||
vLevel1RemoveProtocol(E_Net_pr_Windows95TENProtocol);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: L0PCWin95TENNewPlayerCallBack
|
||
*****************************************************************************
|
||
* Input: none
|
||
* Output: none
|
||
*****************************************************************************/
|
||
static void L0PCWin95TENNewPlayerCallBack(int pid, int isYou, char *options,
|
||
char *termOptions, char *address, long uniqueId, char *joinType)
|
||
{
|
||
NetLib_tdstAddPlayerDesc PlDesc;
|
||
char typeToken[16];
|
||
char hexa[500],mem[250];
|
||
short j=-1;
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugSI(Net_C_Debug_Ten,"NewPlayerCallBack Pid",pid);
|
||
#endif
|
||
sscanf(joinType, "%s", typeToken); /* peel off the first word*/
|
||
if (!strcmp(typeToken, "create")) j=NetLib_Join_Create;
|
||
else if (!strcmp(typeToken, "join")) j=NetLib_Join_Join;
|
||
else if (!strcmp(typeToken, "watch")) j=NetLib_Join_Watch;
|
||
if (isYou)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugS(Net_C_Debug_Ten,"Is me");
|
||
#endif
|
||
gs_InfoLocal.pid = pid;
|
||
gs_InfoLocal.joinType = j;
|
||
gs_uwCallBack|=1;
|
||
}
|
||
PlDesc.m_tduxPlayerId=pid;
|
||
getStringParam(options,"NetlibOptions",hexa,sizeof(hexa));
|
||
hexatomem(mem,hexa);
|
||
PlDesc.m_pPlayerDescriptionData=mem;
|
||
PlDesc.m_uxPlayerDesciptionLength=strlen(hexa)/2;
|
||
PlDesc.m_stL1AddPlayerDesc.m_eProtocol=E_Net_pr_Windows95TENProtocol;
|
||
PlDesc.m_stL1AddPlayerDesc.m_vL0Param=NULL;
|
||
PlDesc.IsYou=isYou;
|
||
PlDesc.JoinType=j;
|
||
PlDesc.Options=options;
|
||
NetLib_eAddNewPlayer(&PlDesc);
|
||
AddPlayerInfo((NetLib_tduxPlayerId)pid,(NetLib_tduwJoinType)j);
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Description: L0PCWin95TENDoPlayerLeft
|
||
* A user has left the game.
|
||
*****************************************************************************
|
||
* Input: pid : ID of player who left the game.
|
||
* Output: none
|
||
*****************************************************************************/
|
||
static void L0PCWin95TENDoPlayerLeft(int pid)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugSI(Net_C_Debug_Ten,"DoPlayerLeft Pid",pid);
|
||
#endif
|
||
eNetDisconnectPlayer((NetLib_tduxPlayerId)pid,1);
|
||
SupPlayerInfo((NetLib_tduxPlayerId)pid);
|
||
}
|
||
|
||
#include <stdio.h>
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENDoAlert
|
||
* Callback receive the error messages.
|
||
*****************************************************************************/
|
||
static void eL0PCWin95TENDoAlert(int type, int err, char *msg)
|
||
{
|
||
printf("%s\n", msg);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENDebugMessage
|
||
* Callback for verifyNoErr.
|
||
*****************************************************************************/
|
||
static void eL0PCWin95TENDebugMessage(int msgLevel, char *msg)
|
||
{
|
||
fprintf(stderr, "%s", msg);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : eL0PCWin95TENSetGameOptions
|
||
* Set the game options.
|
||
*****************************************************************************
|
||
* Input : GameOptions : the game options.
|
||
* Output : none.
|
||
*****************************************************************************/
|
||
_NET_EXPORT_ void _NET_CALLING_CONV_ eL0PCWin95TENSetGameOptions(char *GameName,void *GameOptions,unsigned short SizeOptions)
|
||
{
|
||
char options[500],conv[500];
|
||
options[0]=0;
|
||
addStringParam(options,sizeof(options),"name",GameName);
|
||
memtohexa(GameOptions,SizeOptions,conv);
|
||
addStringParam(options,sizeof(options),"NetlibOptions",conv);
|
||
tenArRegisterGame(options);
|
||
NetLib_eSetSessionDescription((unsigned char)SizeOptions,(char *)GameOptions,0);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : eL0PCWin95TENSetPlayerOptions
|
||
* Set the player options.
|
||
*****************************************************************************
|
||
* Input : GameOptions : the game options.
|
||
* Output : none.
|
||
*****************************************************************************/
|
||
_NET_EXPORT_ void _NET_CALLING_CONV_ eL0PCWin95TENSetPlayerOptions(char *PlayerName,char *PlayerOptions,unsigned short SizeOptions)
|
||
{
|
||
char options[500],conv[500];
|
||
options[0]=0;
|
||
addStringParam(options,sizeof(options),"name",PlayerName);
|
||
memtohexa(PlayerOptions,SizeOptions,conv);
|
||
addStringParam(options,sizeof(options),"NetlibOptions",conv);
|
||
tenArRegisterPlayer(options);
|
||
do
|
||
{
|
||
tenArIdleArena();
|
||
}while (!((gs_uwCallBack&1) && ((gs_uwCallBack&4) || (gs_JoinType==NetLib_Join_Create))));
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENDoPregameHook
|
||
* Callback for verifyNoErr.
|
||
*****************************************************************************/
|
||
static void eL0PCWin95TENDoPregameHook(char *joinType, char *gameTermOptions,
|
||
char *playerTermOptions, char *name, char *alias, char *address)
|
||
{
|
||
char typeToken[16];
|
||
sscanf(joinType, "%s", typeToken); /* peel off the first word*/
|
||
if (!strcmp(typeToken, "create")) gs_JoinType=NetLib_Join_Create;
|
||
else if (!strcmp(typeToken, "join")) gs_JoinType=NetLib_Join_Join;
|
||
else if (!strcmp(typeToken, "watch")) gs_JoinType=NetLib_Join_Watch;
|
||
gs_uwCallBack|=2;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENDoGameOptions
|
||
* Callback for recept change of game options.
|
||
*****************************************************************************/
|
||
void eL0PCWin95TENDoGameOptions(char *options, char *termOptions)
|
||
{
|
||
char hexa[500],mem[250];
|
||
getStringParam(options,"NetlibOptions",hexa,sizeof(hexa));
|
||
hexatomem(mem,hexa);
|
||
NetLib_eSetSessionDescription((char)(strlen(hexa)/2),mem,0);
|
||
gs_uwCallBack|=4;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: vL0PCWin95TENAddNewPlayer
|
||
*****************************************************************************
|
||
* Input: pChanel : adress of returned chanel.
|
||
* par : extern parameter.
|
||
* Output: error code.
|
||
*****************************************************************************/
|
||
NetLib_tdeErrorStatus vL0PCWin95TENAddNewPlayer(tduwNetChannel *pChanel,void *par)
|
||
{
|
||
*pChanel=0;
|
||
return NetLib_E_es_NoError;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: vL0PCWin95TENOpenProtocol
|
||
* initialize the specified interface structure with the correct function
|
||
* pointers to enable a protocol-independent data transmission process.
|
||
*****************************************************************************
|
||
* Input: p_stProtocolInterface, pointer to the interface structure
|
||
* uwPortNumber, port number to bind the socket to
|
||
* Output: none
|
||
*****************************************************************************/
|
||
void _NET_CALLING_CONV_ vL0PCWin95TENOpenProtocol(void)
|
||
{
|
||
tdstNetProtocolInterface *p_stProtocolInterface;
|
||
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugClear(Net_C_Debug_Ten);
|
||
vDebugS(Net_C_Debug_Ten,"SetupInterface");
|
||
#endif
|
||
|
||
p_stProtocolInterface=pstLevel1AddProtocol();
|
||
|
||
FIFObegin=NULL;
|
||
FIFOend=&FIFObegin;
|
||
|
||
/* logical identification of the protocol */
|
||
p_stProtocolInterface->eProtocol = E_Net_pr_Windows95TENProtocol;
|
||
|
||
/* setup the function pointers */
|
||
p_stProtocolInterface->fn_uwStartChannelScan = uwL0PCWin95TENStartChannelScan;
|
||
p_stProtocolInterface->fn_uwStartBroadcastChannelScan= uwL0PCWin95TENStartBroadcastChannelScan;
|
||
p_stProtocolInterface->fn_uwNextChannel= uwL0PCWin95TENNextChannel;
|
||
p_stProtocolInterface->fn_uwNextBroadcastChannel= uwL0PCWin95TENNextBroadcastChannel;
|
||
p_stProtocolInterface->fn_eReadData= eL0PCWin95TENReadData;
|
||
p_stProtocolInterface->fn_eSendData= eL0PCWin95TENSendData;
|
||
p_stProtocolInterface->fn_eQueryChannelStatus= eL0PCWin95TENQueryChannelStatus;
|
||
p_stProtocolInterface->fn_vLevel0NetEngine = eL0PCWin95TENEngine;
|
||
p_stProtocolInterface->fn_vCloseChannel = vL0PCWin95TENCloseChannel;
|
||
p_stProtocolInterface->fn_vLevel0CloseProtocol = vL0PCWin95TENCloseProtocol;
|
||
p_stProtocolInterface->fn_eAddNewPlayer = vL0PCWin95TENAddNewPlayer;
|
||
|
||
gs_bL0PCWin95TENInitState = 0x01;
|
||
|
||
setDebugMsgRoutine(eL0PCWin95TENDebugMessage);
|
||
|
||
tenArSetPregameHookRoutine(eL0PCWin95TENDoPregameHook);
|
||
tenArSetGameOptionsRoutine(eL0PCWin95TENDoGameOptions);
|
||
tenArSetPlayerLeftRoutine(L0PCWin95TENDoPlayerLeft);
|
||
tenArSetPlayerEnteredRoutine(L0PCWin95TENNewPlayerCallBack);
|
||
tenArSetIncomingPacketRoutine(L0PCWin95TENReadCallBack);
|
||
tenArSetAlertMessageRoutine(eL0PCWin95TENDoAlert);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENStart
|
||
* Start a game with TEN
|
||
*****************************************************************************
|
||
* Input: ppGameOptions : Adresse of a pointer wich receive the adresse of
|
||
* game options.
|
||
* Output: join type.
|
||
*****************************************************************************/
|
||
_NET_EXPORT_ NetLib_tduwJoinType _NET_CALLING_CONV_ eL0PCWin95TENStart(void)
|
||
{
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugS(Net_C_Debug_Ten,"Start");
|
||
#endif
|
||
SendMaxRate=10000000L;
|
||
NbrPlayer=0;
|
||
SendBufSize=0;
|
||
TabPlayer=NULL;
|
||
LastTime=GetTickCount();
|
||
FIFObegin=NULL;
|
||
FIFOend=&FIFObegin;
|
||
verifyNoErr(tenArInitArena("Lobby"));
|
||
do
|
||
{
|
||
tenArIdleArena();
|
||
}while (!(gs_uwCallBack&2));
|
||
|
||
gs_bL0PCWin95TENInitState|=0x02;
|
||
|
||
return gs_JoinType;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENFinish
|
||
* Finish a game with TEN.
|
||
*****************************************************************************
|
||
* Input: none
|
||
* Output: none
|
||
*****************************************************************************/
|
||
_NET_EXPORT_ void _NET_CALLING_CONV_ eL0PCWin95TENFinish(void)
|
||
{
|
||
FIFO *p;
|
||
#if defined(NET_USE_DEBUG)
|
||
vDebugS(Net_C_Debug_Ten,"Finish");
|
||
#endif
|
||
vFree((char *)TabPlayer);
|
||
while (FIFObegin)
|
||
{
|
||
p=FIFObegin->next;
|
||
vFree((char*)FIFObegin);
|
||
FIFObegin=p;
|
||
}
|
||
FIFObegin=NULL;
|
||
FIFOend=&FIFObegin;
|
||
tenArExitArena();
|
||
gs_bL0PCWin95TENInitState&=~0x02;
|
||
NetLib_eFlushSendingList(500);
|
||
NetLib_vDisconnectAllRemotePlayers();
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENGamePrivate
|
||
* Refuse all new players in the game.
|
||
*****************************************************************************/
|
||
_NET_EXPORT_ void _NET_CALLING_CONV_ eL0PCWin95TENGamePrivate(void)
|
||
{
|
||
char options[20];
|
||
options[0]=0;
|
||
addStringParam(options,sizeof(options),"lock","y");
|
||
tenArSetGameState(options);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description: eL0PCWin95TENGamePublic
|
||
* Accept all new players in the game (if maximum number of player allow it).
|
||
*****************************************************************************/
|
||
_NET_EXPORT_ void _NET_CALLING_CONV_ eL0PCWin95TENGamePublic(void)
|
||
{
|
||
char options[20];
|
||
options[0]=0;
|
||
addStringParam(options,sizeof(options),"lock","n");
|
||
tenArSetGameState(options);
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : eL0PCWin95TENIsProtocolSet
|
||
* Check if the protocol is correctly initialize or not
|
||
*****************************************************************************
|
||
* Input : none
|
||
* Output :
|
||
* NetLib_E_es_ProtocolNotInitialized : the vLevel0SetupWin95PCTENInterface has not
|
||
* been called yet or it has failed, the application should call the level 2
|
||
* eInitializeGlobalData function.
|
||
* NetLib_E_es_InitialisationSocketError : the eLevel0InitWin95PCTEN function has not been
|
||
* called yet or it has failed, the application should call the level 2
|
||
* eInitializeGlobalData function
|
||
* NetLib_E_es_NoPortSelected : the eL0PCWin95TENAddPort has not been called yet. The
|
||
* protocol has been correctly initialised, it can be used, but it won't give any
|
||
* results since no port is avaible. The application should call it.
|
||
*****************************************************************************/
|
||
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95TENIsProtocolSet(void)
|
||
{
|
||
if(!(gs_bL0PCWin95TENInitState&0x01)) return NetLib_E_es_ProtocolNotInitialized;
|
||
return NetLib_E_es_True;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : eL0PCWin95TENIsProtocolAvailable
|
||
* Check if the protocol is avaible for use or not
|
||
*****************************************************************************
|
||
* Input : A port number to test
|
||
* Output : NetLib_E_es_True if the port is avaible
|
||
* An error code otherwise
|
||
*****************************************************************************/
|
||
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95TENIsProtocolAvailable(void)
|
||
{
|
||
if(!(gs_bL0PCWin95TENInitState&0x01)) return NetLib_E_es_ProtocolNotInitialized;
|
||
return NetLib_E_es_True;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : eL0PCWin95TENPlayerInfo
|
||
* Return player bandwith and latency.
|
||
* Return non null value if error.
|
||
*****************************************************************************/
|
||
int _NET_CALLING_CONV_ eL0PCWin95TENPlayerInfo(NetLib_tduxPlayerId PId,long *bandwhith,long *latency)
|
||
{
|
||
int r;
|
||
size_t size=sizeof(long);
|
||
r=tenArGetPlayerInfo(PId,kTenArPIBandwidth,bandwhith,&size);
|
||
if (r!=0) return r;
|
||
size=sizeof(long);
|
||
r=tenArGetPlayerInfo(PId,kTenArPIAveLatency,latency,&size);
|
||
return r;
|
||
}
|
||
|
||
/*****************************************************************************
|
||
* Description : eL0PCWin95TENLaunchTenClient
|
||
* Input : a quit callback function.
|
||
*****************************************************************************/
|
||
void _NET_CALLING_CONV_ eL0PCWin95TENLaunchTenClient(void (*rtn)(void))
|
||
{
|
||
tenBnSetExitRtn(rtn);
|
||
tenBnStart();
|
||
}
|