reman3/Rayman_X/cpa/tempgrp/NET/L0DPlay.c

1489 lines
49 KiB
C

/*
* L0DPlay.c
*
* universal multiplayer library level 0 implementation file
* transport layer: DirectPlay lobby aware PC-windows 95
*/
/*
* Author: Christophe Roguet
*
* Creation Date: 04/08/97
*
*/
#include "warnings.h"
#include <stdlib.h>
/*
* we need this one to fill the interface structure
* with pointers to the correct functions
*/
#include "PrivNetDef.h"
#include "l0GlDef.h"
#include "NetMemCo.h"
#include "NetEnd.h"
#include "PrivNetSer.h"
#include <NET\Netdebug.h>
#include <NET\l0DPlay.h>
#define IDIRECTPLAY2_OR_GREATER
#include <dplobby.h>
#define DPLAY_MAXBUF 250
static char gs_bL0PCWin95DPlayInitState;
#pragma pack(push)
#pragma pack(1)
typedef struct
{
DPID DPlayPlayerId; /* DPlay ID of the local player*/
NetLib_tduxPlayerId uxNetLibPlayerId; /* NetLib ID of the local 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 eL0PCWin95DPlayEngine. */
static unsigned long SendMaxRate; /* Maximum rate. */
static unsigned short NbrPlayer; /* Number of player. */
static NetLib_tdstInfoPlayer *TabPlayer; /* Table of player. */
typedef struct {
NetLib_tduxPlayerId uxNetLibPlayerId;
DPID DPlayPlayerId;
NetLib_tdstAddPlayerDesc *pstPlDesc;
char *pcDPlayPlayerName;
} tdstConvLine;
typedef struct {
unsigned short uwMaxSize;
unsigned short uwSize;
tdstConvLine *dastConv;
} tdstConvTable;
static tdstConvTable gs_stConvTable;
typedef struct stFIFO
{
struct stFIFO *next; /* Next message of FIFO. */
unsigned long size; /* Size of message. */
DPID DPlayIdFrom; /* Direct Play ID of sender. */
NetLib_tduxPlayerId uxSenderId; /* NetLib 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;
unsigned long uxDPlaySpecific:2;
} DPlayHead;
typedef enum {
NetLib_ePureNetLib, NetLib_eNewPlayerId, NetLib_eIdTable
} tdeDPlayMsgType;
typedef struct {
DPID DPlayPlayerId;
NetLib_tduxPlayerId uxNetLibPlayerId;
} tdstConversionMsg;
enum { NetLib_DPlayWaiting, NetLib_DPlayGo };
#pragma pack(pop)
static LPDIRECTPLAY3 glpDP; /* directplay object pointer*/
static LPDPLCONNECTION glpdplConnection; /* connection settings*/
static LPDIRECTPLAYLOBBY2 glpDPL; /* lobby object pointer*/
static DPID pidLocalPlayer; /* Id of local player*/
static NetLib_tduxPlayerId gs_uxPlayerIdGen; /* used to generate player ids */
BOOL FAR PASCAL NewPlayerCallback(DPID PlayerId, DWORD dwPlayerType, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext);
void NetLib_RegisterNewPlayer1(DPID PlayerId, char *lpName);
void NetLib_RegisterNewPlayer2(DPID DPlayPlayerId, NetLib_tduxPlayerId uxNetLibPlayerId);
void NetLib_InitConversionTable(unsigned short uwMaxSize);
void NetLib_DeinitConversionTable();
void NetLib_AddConversionEntry(DPID DPlayPlayerId, NetLib_tdstAddPlayerDesc *pstPlDesc, char *);
void NetLib_SuppressConversionEntry(DPID DPlayerId);
DPlayHead *NetLib_BuildConversionMsg(DPID IdTo, unsigned short *);
DPID NetLib_NetLibToDPlay(NetLib_tduxPlayerId uxNetLibPlayerId);
NetLib_tduxPlayerId NetLib_DPlayToNetLib(DPID DPlayPlayerId);
NetLib_tduxPlayerId GeneratePlayerId(void);
void NetLib_DPlayHandleNewMsg(FIFO *pstFIFOCell, DPID IdTo);
void NetLib_DPlayHandleNewPlayerMsg(FIFO *pstFIFOCell, DPID IdTo);
void NetLib_DPlayHandlePlayerLeftMsg(FIFO *pstFIFOCell, DPID IdTo);
void NetLib_DPlayHandleSpecificMsg(FIFO *pstFIFOCell, DPID IdTo);
/******************************************************************************************/
/*
* DPLobbyCreate
*
* Wrapper for DirectPlayLobby DirectPlayLobbyCreate API.
*/
HRESULT DPLobbyCreate(void)
{
HRESULT hr=E_FAIL;
LPDIRECTPLAYLOBBY local_lpDPL; /* directplay object pointer*/
hr = DirectPlayLobbyCreate(NULL, &local_lpDPL, NULL, NULL, 0);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyCreate : DPLCreate : error %lx", hr);
#endif
return hr;
}
hr = IDirectPlayLobby_QueryInterface(local_lpDPL, &IID_IDirectPlayLobby2A, (LPVOID *)&glpDPL);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyCreate : DPLQueryInterface : error %lx", hr);
#endif
return hr;
}
hr = IDirectPlayLobby_Release(local_lpDPL);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyCreate : DPLRelease : error %lx", hr);
#endif
}
return hr;
}
/******************************************************************************************/
/*
* DPClose
*
* Wrapper for DirectPlay Close API
*/
HRESULT DPClose(void)
{
HRESULT hr=E_FAIL;
/* release the direct play object*/
if (glpDP)
{
hr = IDirectPlay3_Close(glpDP);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPClose : error %lx", hr);
#endif
}
}
return hr;
}
/******************************************************************************************/
/*
* DPRelease
*
* Wrapper for DirectPlay Release API
*/
HRESULT DPRelease(void)
{
HRESULT hr=E_FAIL;
/* release the lobby object*/
if (glpDP)
{
hr = IDirectPlay3_Release(glpDP);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPRelease : error %lx", hr);
#endif
}
glpDP = NULL;
}
return hr;
}
/******************************************************************************************/
/*
* DPLobbyRelease
*
* Wrapper for DirectPlayLobby Release API
*/
HRESULT DPLobbyRelease(void)
{
HRESULT hr=E_FAIL;
/* free our connection settings*/
if (glpdplConnection)
{
vFree(glpdplConnection);
glpdplConnection = NULL;
}
/* release the lobby object*/
if (glpDPL)
{
hr = IDirectPlayLobby_Release(glpDPL);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyRelease : DPLRelease : error %lx", hr);
#endif
}
glpDPL = NULL;
}
return hr;
}
/******************************************************************************************/
/*
* DPLobbyGetConnectionSettings
*
* Wrapper for DirectPlayLobby GetConnectionSettings API
*/
HRESULT DPLobbyGetConnectionSettings(void)
{
HRESULT hr=E_FAIL;
DWORD dwSize;
if (glpDPL)
{
/* get size for the connection settings structure*/
hr = IDirectPlayLobby_GetConnectionSettings(glpDPL, 0, NULL, &dwSize);
if (DPERR_BUFFERTOOSMALL == hr)
{
/* if we already have one, free it*/
if (glpdplConnection)
{
vFree(glpdplConnection);
glpdplConnection = NULL;
}
/* allocate memory for the new one*/
glpdplConnection = (LPDPLCONNECTION) pMalloc(dwSize);
/* get the connection settings*/
if (glpdplConnection)
hr = IDirectPlayLobby_GetConnectionSettings(glpDPL, 0, glpdplConnection, &dwSize);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyGetConnectionSettings : DPLGetConnectionSettings : error %lx", hr);
#endif
}
} else if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyGetConnectionSettings : DPLGetConnectionSettings : error %lx", hr);
#endif
}
}
return hr;
}
/******************************************************************************************/
/*
* DPLobbyConnect
*
* Wrapper for DirectPlayLobby Connect API.
*/
HRESULT DPLobbyConnect(void)
{
HRESULT hr=E_FAIL;
static LPDIRECTPLAY2 local_lpDP; /* directplay object pointer*/
if(glpDPL) {
/* connect and retrieve a DirectPlay2 interface */
hr = IDirectPlayLobby_Connect(glpDPL, 0, &local_lpDP, NULL) ;
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyConnect : DPLConnect : error %lx", hr);
#endif
}
hr = IDirectPlayLobby_Release(glpDPL);
glpDPL=NULL;
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLConnect : DPLRelease : error %lx", hr);
#endif
}
/* retrieve a DirectPlay3 interface from the DirectPlay2 interface */
if(local_lpDP) {
hr = IDirectPlay2_QueryInterface(local_lpDP, &IID_IDirectPlay3A, (LPVOID *)&glpDP);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLConnect : DP2QueryInterface : error %lx", hr);
#endif
}
hr = IDirectPlay2_Release(local_lpDP);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLConnect : DP2Release: error %lx", hr);
#endif
}
}
}
return hr;
}
/******************************************************************************************/
/*
* DPCreatePlayer
* wrapper for CreatePlayer
*/
HRESULT DPCreatePlayer(void)
{
HRESULT hr=E_FAIL;
if(glpDP) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPCreatePlayer : ConnectionSettings");
vDebugFormat(Net_C_Debug_DPlay, "dwFlags: %lx", glpdplConnection->dwFlags);
if(glpdplConnection->dwFlags==DPLCONNECTION_CREATESESSION)
vDebugFormat(Net_C_Debug_DPlay, "DPLCONNECTION_CREATESESSION");
if(glpdplConnection->dwFlags==DPLCONNECTION_JOINSESSION)
vDebugFormat(Net_C_Debug_DPlay, "DPLCONNECTION_JOINSESSION");
vDebugFormat(Net_C_Debug_DPlay, "PlayerName: %s", glpdplConnection->lpPlayerName->lpszShortNameA);
#endif
hr = IDirectPlay3_CreatePlayer(glpDP, &pidLocalPlayer, glpdplConnection->lpPlayerName, NULL, NULL, 0, 0);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPCreatePlayer : error %lu", hr);
#endif
}
if(glpdplConnection->dwFlags==DPLCONNECTION_CREATESESSION)
gs_JoinType=NetLib_Join_Create;
else if(glpdplConnection->dwFlags==DPLCONNECTION_JOINSESSION)
gs_JoinType=NetLib_Join_Join;
}
return hr;
}
/******************************************************************************************/
/*
* DPEnumPlayers
* wrapper for DPEnumPlayers
*/
HRESULT DPEnumPlayers(void)
{
HRESULT hr=E_FAIL;
if(glpDP) {
hr = IDirectPlay3_EnumPlayers(glpDP, NULL, (LPDPENUMPLAYERSCALLBACK2)NewPlayerCallback, 0, 0);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPEnumPlayers : DP3EnumPLayers : error %lx", hr);
#endif
}
}
return hr;
}
/******************************************************************************************/
BOOL FAR PASCAL NewPlayerCallback(DPID PlayerId, DWORD dwPlayerType, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
{
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"NewPlayerCallBack : %lx", PlayerId);
#endif
if (PlayerId == pidLocalPlayer) {
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_DPlay,"Is me");
#endif
gs_InfoLocal.DPlayPlayerId = PlayerId;
gs_InfoLocal.joinType = gs_JoinType;
gs_uwCallBack|=1;
}
NetLib_RegisterNewPlayer1(PlayerId, lpName->lpszShortNameA);
/* if we are the session host, we can finish registering ourself */
if (gs_JoinType==NetLib_Join_Create)
NetLib_RegisterNewPlayer2(PlayerId, GeneratePlayerId());
return TRUE; /* request next player */
}
/******************************************************************************/
void NetLib_RegisterNewPlayer1(DPID PlayerId, char *lpName)
{
NetLib_tdstAddPlayerDesc *pstPlDesc;
char *acDPlayPlayerName;
/* register a new player: first part */
/* add an entry to the conversion table */
/* and wait for the NetLib Player Id */
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Register New Player 1: %lx / %s", PlayerId, lpName);
#endif
pstPlDesc=(NetLib_tdstAddPlayerDesc *)pMalloc(sizeof(NetLib_tdstAddPlayerDesc));
pstPlDesc->m_tduxPlayerId=C_uxNetInvalidId;
pstPlDesc->m_pPlayerDescriptionData=C_pNull; /* at first, let's not deal with player description */
pstPlDesc->m_uxPlayerDesciptionLength=0;
pstPlDesc->m_stL1AddPlayerDesc.m_eProtocol=E_Net_pr_Windows95DPlayProtocol;
pstPlDesc->m_stL1AddPlayerDesc.m_vL0Param=NULL;
pstPlDesc->IsYou=PlayerId == pidLocalPlayer;
pstPlDesc->JoinType=gs_JoinType;
pstPlDesc->Options=NULL;
acDPlayPlayerName=strdup(lpName);
NetLib_AddConversionEntry(PlayerId, pstPlDesc, acDPlayPlayerName);
}
/******************************************************************************/
void NetLib_RegisterNewPlayer2(DPID DPlayPlayerId, NetLib_tduxPlayerId uxNetLibPlayerId)
{
/* register a new player: part 2 */
/* complete the conversion table entry */
/* and transmit the information to higher levels */
unsigned short i;
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Register New Player 2: %lx / %lu", DPlayPlayerId, uxNetLibPlayerId);
#endif
if(DPlayPlayerId==gs_InfoLocal.DPlayPlayerId)
gs_InfoLocal.uxNetLibPlayerId = uxNetLibPlayerId;
for(i=0; i<gs_stConvTable.uwSize; i++)
if(gs_stConvTable.dastConv[i].DPlayPlayerId == DPlayPlayerId) {
gs_stConvTable.dastConv[i].uxNetLibPlayerId=uxNetLibPlayerId;
if(gs_stConvTable.dastConv[i].pstPlDesc) {
gs_stConvTable.dastConv[i].pstPlDesc->m_tduxPlayerId=uxNetLibPlayerId;
NetLib_eAddNewPlayer(gs_stConvTable.dastConv[i].pstPlDesc);
vFree(gs_stConvTable.dastConv[i].pstPlDesc);
gs_stConvTable.dastConv[i].pstPlDesc=(NetLib_tdstAddPlayerDesc *)C_pNull;
NbrPlayer++;
} else {
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Register New Player 2: no description for %lx / (i=%hu) ???", DPlayPlayerId, i);
#endif
}
}
}
/******************************************************************************/
void NetLib_InitConversionTable(unsigned short uwMaxSize)
{
gs_stConvTable.uwSize=0;
gs_stConvTable.uwMaxSize=uwMaxSize;
gs_stConvTable.dastConv=(tdstConvLine *)pMalloc(gs_stConvTable.uwMaxSize*sizeof(tdstConvLine));
}
/******************************************************************************/
void NetLib_DeinitConversionTable()
{
unsigned short i;
for(i=0; i<gs_stConvTable.uwSize; i++)
if(gs_stConvTable.dastConv[i].pstPlDesc != (NetLib_tdstAddPlayerDesc*)C_pNull) {
vFree(gs_stConvTable.dastConv[i].pstPlDesc);
gs_stConvTable.dastConv[i].pstPlDesc=(NetLib_tdstAddPlayerDesc*)C_pNull;
}
vFree(gs_stConvTable.dastConv);
gs_stConvTable.dastConv=(tdstConvLine *)C_pNull;
gs_stConvTable.uwSize=gs_stConvTable.uwMaxSize=0;
}
/******************************************************************************/
void NetLib_AddConversionEntry(DPID DPlayPlayerId, NetLib_tdstAddPlayerDesc *pstPlDesc, char *pcDPlayPlayerName)
{
tdstConvLine *pstConvLine;
tdstConvLine *pstConvTable;
if(gs_stConvTable.uwSize==gs_stConvTable.uwMaxSize) {
/* reallocate table */
pstConvTable=(tdstConvLine *)pRealloc(gs_stConvTable.dastConv, (gs_stConvTable.uwSize+1)*sizeof(tdstConvLine));
if(pstConvTable != (tdstConvLine *)C_pNull) {
gs_stConvTable.uwMaxSize++;
gs_stConvTable.dastConv=pstConvTable;
} else
return;
}
pstConvLine=&gs_stConvTable.dastConv[gs_stConvTable.uwSize];
pstConvLine->uxNetLibPlayerId=C_uxNetInvalidId;
pstConvLine->DPlayPlayerId=DPlayPlayerId;
pstConvLine->pstPlDesc=pstPlDesc;
pstConvLine->pcDPlayPlayerName=pcDPlayPlayerName;
gs_stConvTable.uwSize++;
}
/******************************************************************************/
void NetLib_SuppressConversionEntry(DPID DPlayPlayerId)
{
unsigned short i;
for(i=0; i<gs_stConvTable.uwSize; i++)
if(gs_stConvTable.dastConv[i].DPlayPlayerId == DPlayPlayerId) {
if(gs_stConvTable.dastConv[i].pstPlDesc != (NetLib_tdstAddPlayerDesc *)C_pNull)
vFree(gs_stConvTable.dastConv[i].pstPlDesc);
vFree(gs_stConvTable.dastConv[i].pcDPlayPlayerName);
memmove(&gs_stConvTable.dastConv[i],
&gs_stConvTable.dastConv[i+1],
(gs_stConvTable.uwMaxSize-gs_stConvTable.uwSize)*sizeof(tdstConvLine));
gs_stConvTable.uwSize--;
}
}
/*****************************************************************************/
DPlayHead *NetLib_BuildConversionMsg(DPID IdTo, unsigned short *p_uxSize)
{
tdstConversionMsg *ConversionInfo;
DPlayHead *pstSpecificMsg;
unsigned short i;
/* build a message that contains the conversion info for all players except the adressee */
/* the adressee is normally the last entry in the conversion table */
*p_uxSize=sizeof(DPlayHead)+sizeof(tdstConversionMsg)*(gs_stConvTable.uwSize-1);
pstSpecificMsg=(DPlayHead *)pMalloc(*p_uxSize);
if(pstSpecificMsg != (DPlayHead *)C_pNull) {
pstSpecificMsg->uxDPlaySpecific=NetLib_eIdTable;
ConversionInfo=(tdstConversionMsg *)(pstSpecificMsg+1);
for(i=0; i<gs_stConvTable.uwSize-1; i++) /*if(gs_stConvTable.dastConv[i].DPlayPlayerId != IdTo)*/ {
ConversionInfo->DPlayPlayerId=gs_stConvTable.dastConv[i].DPlayPlayerId;
ConversionInfo->uxNetLibPlayerId=gs_stConvTable.dastConv[i].uxNetLibPlayerId;
ConversionInfo++;
}
}
return pstSpecificMsg;
}
/******************************************************************************/
DPID NetLib_NetLibToDPlay(NetLib_tduxPlayerId uxNetLibPlayerId)
{
unsigned short i;
for(i=0; i<gs_stConvTable.uwSize; i++)
if(gs_stConvTable.dastConv[i].uxNetLibPlayerId == uxNetLibPlayerId)
return gs_stConvTable.dastConv[i].DPlayPlayerId;
return DPID_UNKNOWN;
}
/******************************************************************************/
NetLib_tduxPlayerId NetLib_DPlayToNetLib(DPID DPlayPlayerId)
{
unsigned short i;
for(i=0; i<gs_stConvTable.uwSize; i++)
if(gs_stConvTable.dastConv[i].DPlayPlayerId == DPlayPlayerId)
return gs_stConvTable.dastConv[i].uxNetLibPlayerId;
return C_uxNetInvalidId;
}
/******************************************************************************/
NetLib_tduxPlayerId GeneratePlayerId(void)
{
if(gs_uxPlayerIdGen==127) { /* hope this never happens ... */
gs_uxPlayerIdGen=0;
return 0;
}
return gs_uxPlayerIdGen++;
}
/*****************************************************************************/
int CheckPlayerNbr()
{
if(NbrPlayer < glpdplConnection->lpSessionDesc->dwMaxPlayers)
return NetLib_DPlayWaiting;
else
return NetLib_DPlayGo;
}
/*****************************************************************************/
/*****************************************************************************
* Description: vL0PCWin95DPlayCloseChannel
* frees a slot in the channel table
*****************************************************************************
* Input: identifier of the channel
* Output: none
*****************************************************************************/
void vL0PCWin95DPlayCloseChannel(tduwNetChannel uwChannel)
{
}
/*****************************************************************************
* Description: uwL0PCWin95DPlayStartChannelScan
* returns the identification number of the first channel for the protocol
*****************************************************************************
* Input: none
* Output: 0
*****************************************************************************/
tduwNetChannel uwL0PCWin95DPlayStartChannelScan(void)
{
if(!(gs_bL0PCWin95DPlayInitState&0x02))
return C_uwNetInvalidChannel;
return 0;
}
/*****************************************************************************
* Description: uwL0PCWin95DPlayNextChannel
* returns the identification number of the channel following the last
*****************************************************************************
* Input: uwLastScannedChannel, index returned by the previous call
* Output: C_uwNetInvalidChannel
*****************************************************************************/
tduwNetChannel uwL0PCWin95DPlayNextChannel(tduwNetChannel uwLastScannedChannel)
{
return C_uwNetInvalidChannel;
}
/*****************************************************************************
* Description: uwL0PCWin95DPlayStartBroadcastChannelScan
* returns the identification number of the first broadcast channel
* for the protocol
*****************************************************************************
* Input: none
* Output: 0
*****************************************************************************/
tduwNetChannel uwL0PCWin95DPlayStartBroadcastChannelScan(void)
{
if(!(gs_bL0PCWin95DPlayInitState&0x02))
return C_uwNetInvalidChannel;
return 1;
}
/*****************************************************************************
* Description: uwL0PCWin95DPlayNextBroadcastChannel
* 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 uwL0PCWin95DPlayNextBroadcastChannel(tduwNetChannel uwLastScannedChannel)
{
return C_uwNetInvalidChannel;
}
/*****************************************************************************
* Description: wL0PCWin95DPlayGetMessage
*****************************************************************************
* Input: ppData, address of the pointer to retrieve a full message if
* necessary.
* Output: return 1 if getting a message and 0 otherwise.
*****************************************************************************/
short wL0PCWin95DPlayGetMessage(tdstNetMessage **ppMes)
{
FIFO *currentFIFOCell;
tdstNetMessage *pstMessage;
DPlayHead *pstDPlayHead;
if (FIFObegin==NULL)
{
*ppMes=NULL;
return 0;
}
else
{
/* avant tout, tester si l'expediteur est connu pour NetLib */
/* (et si on connait son propre id NetLib en local) */
pstMessage=(tdstNetMessage *)pMalloc(FIFObegin->size+sizeof(tdstNetMessage)-sizeof(DPlayHead));
pstDPlayHead=(DPlayHead *)(FIFObegin+1);
if (pstMessage==NULL) {
*ppMes=NULL;
return -1;
}
pstMessage->m_uxReadReceiptId=pstDPlayHead->m_ulReadReceiptId;
pstMessage->uxPriority=pstDPlayHead->uxPriority;
pstMessage->uxReplace=pstDPlayHead->uxReplace;
pstMessage->uxReplaceType=pstDPlayHead->uxReplaceType;
pstMessage->eMessageType=pstDPlayHead->eMessageType;
pstMessage->uxHeadBigEndian=pstDPlayHead->uxHeadBigEndian;
pstMessage->uxBodyBigEndian=pstDPlayHead->uxBodyBigEndian;
pstMessage->uwMessageSizeInBytes=(unsigned short)(FIFObegin->size-sizeof(DPlayHead));
pstMessage->uxSessionId=0;
pstMessage->uxSenderId=FIFObegin->uxSenderId;
pstMessage->uxRecipientId=gs_InfoLocal.uxNetLibPlayerId;
memcpy(pstMessage+1, pstDPlayHead+1, pstMessage->uwMessageSizeInBytes);
pstMessage->ulReserved=M_ulMakeReserved(M_uwProcessCheckSum(pstMessage),
M_uwProcessCheckSumBody(pstMessage));
currentFIFOCell=FIFObegin->next;
vFree((char *)FIFObegin);
FIFObegin=currentFIFOCell;
if (currentFIFOCell==NULL) FIFOend=&FIFObegin;
*ppMes=pstMessage;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "GetMessage(): Type %d, Size %d, Recipient %d",
pstMessage->eMessageType,
pstMessage->uwMessageSizeInBytes,
pstMessage->uxRecipientId);
#endif /* NET_USE_DEBUG */
return 1;
}
}
/*****************************************************************************
* Description: eL0PCWin95DPlayReadData
*****************************************************************************
* 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 eL0PCWin95DPlayReadData(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=wL0PCWin95DPlayGetMessage((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: eL0PCWin95DPlaySendData
*****************************************************************************
* Input: uwChannel, channel to send the message into.
* pData, pointer on the block to send
* Output: an error condition.
*****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95DPlaySendData(tduwNetChannel uwChannel, tdpPointer pData)
{
unsigned long ulBytestoSend;
tdstNetMessage *pMes=(tdstNetMessage *)pData;
DPlayHead *pSend;
unsigned long NewTime;
DPID DPlayDestinationId;
DWORD dwFlags;
HRESULT hr;
/* verify that the system has been initialized */
if(!(gs_bL0PCWin95DPlayInitState&0x02))
return NetLib_E_es_ProtocolNotInitialized;
/* verify the validity of the Channel */
if(uwChannel>1)
{
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Invalid channel %ud", uwChannel);
#endif
return NetLib_E_es_InvalidChannel;
}
if (pMes->uxRecipientId==C_uxNetBroadcastId) uwChannel=1;
ulBytestoSend= pMes->uwMessageSizeInBytes + sizeof(DPlayHead);
NewTime=GetTickCount();
SendBufSize-=((NewTime-LastTime)*(float)SendMaxRate)/1000;
LastTime=NewTime;
if (SendBufSize<0) SendBufSize=0;
if (SendBufSize>=DPLAY_MAXBUF) {
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_DPlay,"limiting throughput");
#endif
return NetLib_E_es_BufferIsFull;
}
SendBufSize+=ulBytestoSend+20;
pSend=(DPlayHead *)pMalloc(ulBytestoSend);
if (!pSend) {
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_DPlay,"out of memory");
#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;
pSend->uxDPlaySpecific=NetLib_ePureNetLib;
if (uwChannel!=1) {
DPlayDestinationId=NetLib_NetLibToDPlay(pMes->uxRecipientId);
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Send to one player. Type %d, Size %d, Recipient %d / %lx", pMes->eMessageType, pMes->uwMessageSizeInBytes, pMes->uxRecipientId, DPlayDestinationId);
#endif
dwFlags=DPSEND_GUARANTEED | DPSEND_OPENSTREAM;
} else {
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Send to all players. Type %d, Size %d, Recipient %d", pMes->eMessageType, pMes->uwMessageSizeInBytes, pMes->uxRecipientId);
#endif
DPlayDestinationId=DPID_ALLPLAYERS;
dwFlags=DPSEND_GUARANTEED;
}
hr=E_FAIL;
if(glpDP) {
hr=IDirectPlay3_Send( glpDP,
gs_InfoLocal.DPlayPlayerId,
DPlayDestinationId,
dwFlags,
(LPVOID)pSend,
ulBytestoSend);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "SendData : DP3Send : error %lx", hr);
#endif
}
}
vFree((char *)pSend);
if (hr==DPERR_BUSY)
{
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"emission failure: send queue is full");
#endif
return NetLib_E_es_BufferIsFull;
} else if(hr<0) {
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"emission failure: %lx", hr);
#endif
return NetLib_E_es_UnknownError;
}
/* free the message buffer */
vFree(pData);
return NetLib_E_es_NoError;
}
/*****************************************************************************
* Description: eL0PCWin95DPlayQueryChannelStatus
* returns the current status of the channel
*****************************************************************************
* Input: uwChannel, channel to query
* Output: an error condition.
*****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95DPlayQueryChannelStatus(tduwNetChannel uwChannel)
{
return NetLib_E_es_NoError;
}
/*****************************************************************************
* Description: eL0PCWin95DPlayEngine
*****************************************************************************
* Input: none
* Output: none
*****************************************************************************/
void eL0PCWin95DPlayEngine(void)
{
DPID IdFrom, IdTo;
unsigned long ulBytesToRead;
FIFO *pstFIFOCell;
HRESULT hr;
if(!(gs_bL0PCWin95DPlayInitState&0x02))
return;
if(!glpDP)
return;
do {
hr=IDirectPlay3_Receive(glpDP,
&IdFrom, &IdTo,
DPRECEIVE_ALL | DPRECEIVE_PEEK,
NULL,
&ulBytesToRead);
if(hr==DPERR_BUFFERTOOSMALL) {
pstFIFOCell=(FIFO *)pMalloc(ulBytesToRead+sizeof(FIFO));
if(pstFIFOCell==(FIFO *)C_pNull)
return;
hr=IDirectPlay3_Receive(glpDP,
&IdFrom, &IdTo,
DPRECEIVE_ALL,
pstFIFOCell+1,
&ulBytesToRead);
pstFIFOCell->size=ulBytesToRead;
pstFIFOCell->DPlayIdFrom=IdFrom;
pstFIFOCell->next=(FIFO *)C_pNull;
NetLib_DPlayHandleNewMsg(pstFIFOCell, IdTo);
} else if(hr != DPERR_NOMESSAGES) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay,"reception failure: %lx", hr);
#endif /* NET_USE_DEBUG */
}
} while(hr==DP_OK); /* introduire une limite sur le nombre de messages lus par appel */
}
/*****************************************************************************/
void NetLib_DPlayHandleNewMsg(FIFO *pstFIFOCell, DPID IdTo)
{
DPlayHead *pstDPlayMsg;
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"HandleNewMsg()");
#endif
/* first, handle Direct Play system messages */
if(pstFIFOCell->DPlayIdFrom==DPID_SYSMSG) {
switch(((LPDPMSG_GENERIC)(pstFIFOCell+1))->dwType) {
case DPSYS_CREATEPLAYERORGROUP:
NetLib_DPlayHandleNewPlayerMsg(pstFIFOCell, IdTo);
break;
case DPSYS_DESTROYPLAYERORGROUP:
NetLib_DPlayHandlePlayerLeftMsg(pstFIFOCell, IdTo);
break;
default:
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"HandleNewMsg() : unhandled system message %lx", ((LPDPMSG_GENERIC)(pstDPlayMsg+1))->dwType);
#endif
;
}
vFree(pstFIFOCell);
} else {
pstDPlayMsg=(DPlayHead *)(pstFIFOCell+1);
if(pstDPlayMsg->uxDPlaySpecific != NetLib_ePureNetLib) {
/* this is a message specific to the Direct Play subsystem: interpret it */
NetLib_DPlayHandleSpecificMsg(pstFIFOCell, IdTo);
vFree(pstFIFOCell);
} else {
/* this is a normal NetLib message: */
/* translate the player Id and enqueue the message */
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"Received: Type %lu, Size %lu, Source %lx",
pstDPlayMsg->eMessageType,
pstFIFOCell->size-sizeof(DPlayHead),
pstFIFOCell->DPlayIdFrom);
#endif
pstFIFOCell->uxSenderId=NetLib_DPlayToNetLib(pstFIFOCell->DPlayIdFrom);
*FIFOend=pstFIFOCell;
FIFOend=&(pstFIFOCell->next);
}
}
}
/*****************************************************************************/
void NetLib_DPlayHandleNewPlayerMsg(FIFO *pstFIFOCell, DPID IdTo)
{
HRESULT hr;
LPDPMSG_CREATEPLAYERORGROUP pSysMsg;
NetLib_tduxPlayerId uxNetLibPlayerId;
tdstConversionMsg *ConversionInfo;
DPlayHead *pstSpecificMsg;
unsigned short uxSize;
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"HandleNewPlayerMsg()");
#endif
pSysMsg = (LPDPMSG_CREATEPLAYERORGROUP) (pstFIFOCell+1);
/* if we host the session, then we have to generate a NetLib identifier for this player */
/* send this identifier to all other players */
/* and then send the list of all identifiers to this new player */
/* if we don't host the session, we remember that a new play has come */
/* and wait for a message from the host to know its NetLib identifier */
NetLib_RegisterNewPlayer1(pSysMsg->dpId, pSysMsg->dpnName.lpszShortNameA);
if(gs_InfoLocal.joinType==NetLib_Join_Create) {
/* we host the session: generate a new identifier for this player */
uxNetLibPlayerId=GeneratePlayerId();
NetLib_RegisterNewPlayer2(pSysMsg->dpId, uxNetLibPlayerId);
/* send the new NetLib id to everyone */
pstSpecificMsg=(DPlayHead *)pMalloc(sizeof(DPlayHead)+sizeof(tdstConversionMsg));
if(pstSpecificMsg) {
pstSpecificMsg->uxDPlaySpecific=NetLib_eNewPlayerId;
ConversionInfo=(tdstConversionMsg *)(pstSpecificMsg+1);
ConversionInfo->DPlayPlayerId=pSysMsg->dpId;
ConversionInfo->uxNetLibPlayerId=uxNetLibPlayerId;
hr=IDirectPlay3_Send( glpDP,
gs_InfoLocal.DPlayPlayerId,
DPID_ALLPLAYERS,
DPSEND_GUARANTEED,
(LPVOID)pstSpecificMsg,
sizeof(DPlayHead)+sizeof(tdstConversionMsg));
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "HandleNewPlayerMsg : DP3Send : error %lx", hr);
#endif
}
}
/* send all NetLib ids to the new player */
pstSpecificMsg=NetLib_BuildConversionMsg(pSysMsg->dpId, &uxSize);
if(pstSpecificMsg) {
hr=IDirectPlay3_Send( glpDP,
gs_InfoLocal.DPlayPlayerId,
pSysMsg->dpId,
DPSEND_GUARANTEED,
(LPVOID)pstSpecificMsg,
uxSize);
if(hr != DP_OK) {
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "HandleNewPlayerMsg : DP3Send : error %lx", hr);
#endif
}
}
}
}
/*****************************************************************************/
void NetLib_DPlayHandlePlayerLeftMsg(FIFO *pstFIFOCell, DPID IdTo)
{
LPDPMSG_DELETEPLAYERFROMGROUP pSysMsg;
pSysMsg=(LPDPMSG_DELETEPLAYERFROMGROUP)(pstFIFOCell+1);
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"HandlePlayerLeftMsg(): Player %lx", pSysMsg->dpIdPlayer);
#endif
NetLib_SuppressConversionEntry(pSysMsg->dpIdPlayer);
NbrPlayer--;
/* in normal conditions (i.e. the remote player made a call to DisconnectFromSession() */
/* the higher levels already have suppressed this player upon reception of the */
/* disconnection message */
}
/*****************************************************************************/
void NetLib_DPlayHandleSpecificMsg(FIFO *pstFIFOCell, DPID IdTo)
{
DPlayHead *pstMsg;
tdstConversionMsg *pstConversionMsg;
unsigned int i, uwNbrOfLines;
#if defined(NET_USE_DEBUG)
vDebugFormat(Net_C_Debug_DPlay,"HandleSpecificMsg()");
#endif
pstMsg=(DPlayHead *)(pstFIFOCell+1);
switch(pstMsg->uxDPlaySpecific) {
case NetLib_eNewPlayerId:
pstConversionMsg=(tdstConversionMsg *)(pstMsg+1);
NetLib_RegisterNewPlayer2(pstConversionMsg->DPlayPlayerId,
pstConversionMsg->uxNetLibPlayerId);
break;
/* the message contains the NetLib ID of a new player */
case NetLib_eIdTable:
pstConversionMsg=(tdstConversionMsg *)(pstMsg+1);
uwNbrOfLines=(pstFIFOCell->size - sizeof(DPlayHead)) / sizeof(tdstConversionMsg);
for(i=0; i<uwNbrOfLines; i++)
NetLib_RegisterNewPlayer2(pstConversionMsg[i].DPlayPlayerId,
pstConversionMsg[i].uxNetLibPlayerId);
break;
/* the message contains a table of the NetLib IDs for all players except the local player */
}
}
/*****************************************************************************
* Description : vL0PCWin95DPlayCloseProtocol(void)
* DPlay-Level 0 closing function
*****************************************************************************
* Input : none
* Output : none
*****************************************************************************/
void vL0PCWin95DPlayCloseProtocol(void)
{
FIFO *p;
while (FIFObegin)
{
p=FIFObegin->next;
vFree((char*)FIFObegin);
FIFObegin=p;
}
FIFObegin=NULL;
FIFOend=&FIFObegin;
vLevel1RemoveProtocol(E_Net_pr_Windows95DPlayProtocol);
}
/*****************************************************************************
* Description: vL0PCWin95DPlayAddNewPlayer
*****************************************************************************
* Input: pChanel : adress of returned chanel.
* par : extern parameter.
* Output: error code.
*****************************************************************************/
NetLib_tdeErrorStatus vL0PCWin95DPlayAddNewPlayer(tduwNetChannel *pChannel,void *par)
{
*pChannel=0;
return NetLib_E_es_NoError;
}
/*****************************************************************************
* Description: vL0PCWin95DPlayOpenProtocol
* 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_ vL0PCWin95DPlayOpenProtocol(void)
{
tdstNetProtocolInterface *p_stProtocolInterface;
#if defined(NET_USE_DEBUG)
vDebugClear(Net_C_Debug_DPlay);
vDebugS(Net_C_Debug_DPlay,"SetupInterface");
#endif
p_stProtocolInterface=pstLevel1AddProtocol();
FIFObegin=NULL;
FIFOend=&FIFObegin;
/* logical identification of the protocol */
p_stProtocolInterface->eProtocol = E_Net_pr_Windows95DPlayProtocol;
/* setup the function pointers */
p_stProtocolInterface->fn_uwStartChannelScan = uwL0PCWin95DPlayStartChannelScan;
p_stProtocolInterface->fn_uwStartBroadcastChannelScan= uwL0PCWin95DPlayStartBroadcastChannelScan;
p_stProtocolInterface->fn_uwNextChannel= uwL0PCWin95DPlayNextChannel;
p_stProtocolInterface->fn_uwNextBroadcastChannel= uwL0PCWin95DPlayNextBroadcastChannel;
p_stProtocolInterface->fn_eReadData= eL0PCWin95DPlayReadData;
p_stProtocolInterface->fn_eSendData= eL0PCWin95DPlaySendData;
p_stProtocolInterface->fn_eQueryChannelStatus= eL0PCWin95DPlayQueryChannelStatus;
p_stProtocolInterface->fn_vLevel0NetEngine = eL0PCWin95DPlayEngine;
p_stProtocolInterface->fn_vCloseChannel = vL0PCWin95DPlayCloseChannel;
p_stProtocolInterface->fn_vLevel0CloseProtocol = vL0PCWin95DPlayCloseProtocol;
p_stProtocolInterface->fn_eAddNewPlayer = vL0PCWin95DPlayAddNewPlayer;
gs_bL0PCWin95DPlayInitState = 0x01;
gs_uxPlayerIdGen=0;
NetLib_InitConversionTable(8);
}
/*****************************************************************************
* Description: eL0PCWin95DPlayStart
* Start a game with DPlay
*****************************************************************************
* Input: ppGameOptions : Adresse of a pointer wich receive the adresse of
* game options.
* Output: join type.
*****************************************************************************/
_NET_EXPORT_ NetLib_tduwJoinType _NET_CALLING_CONV_ eL0PCWin95DPlayStart(char cMode)
{
int Status;
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_DPlay,"Start");
#endif
SendMaxRate=1000L;
NbrPlayer=0;
SendBufSize=0;
TabPlayer=NULL;
LastTime=GetTickCount();
FIFObegin=NULL;
FIFOend=&FIFObegin;
/* obtain a directplay lobby interface*/
if(DPLobbyCreate() != DP_OK)
return -1;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyCreate: OK");
#endif
/* retrieve the session information */
if(DPLobbyGetConnectionSettings() != DP_OK)
return -1;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyGetConnectionSettings: OK");
#endif
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "session name : %s", glpdplConnection->lpSessionDesc->lpszSessionNameA);
vDebugFormat(Net_C_Debug_DPlay, "max # players : %ld", glpdplConnection->lpSessionDesc->dwMaxPlayers);
vDebugFormat(Net_C_Debug_DPlay, "current # players : %ld", glpdplConnection->lpSessionDesc->dwCurrentPlayers);
#endif
/* connect to the session */
if(DPLobbyConnect() != DP_OK)
return -1;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPLobbyConnect: OK");
#endif
/* create the local player */
if(DPCreatePlayer() != DP_OK)
return -1;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPCreatePlayer: OK");
#endif
/* wait for other players ? or not ? */
if(DPEnumPlayers() != DP_OK)
return -1;
#ifdef NET_USE_DEBUG
vDebugFormat(Net_C_Debug_DPlay, "DPEnumPlayers: OK");
#endif
if(cMode==NetLib_DPlayClosed)
/* wait for all players to arrive*/
do {
eL0PCWin95DPlayEngine();
Status=CheckPlayerNbr();
} while(Status==NetLib_DPlayWaiting);
gs_bL0PCWin95DPlayInitState|=0x02;
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_DPlay,"Start: returning");
#endif
return gs_JoinType;
}
/*****************************************************************************
* Description: eL0PCWin95DPlayFinish
* Finish a game with DPlay.
*****************************************************************************
* Input: none
* Output: none
*****************************************************************************/
_NET_EXPORT_ void _NET_CALLING_CONV_ eL0PCWin95DPlayFinish(void)
{
FIFO *p;
#if defined(NET_USE_DEBUG)
vDebugS(Net_C_Debug_DPlay,"Finish");
#endif
vFree((char *)TabPlayer);
while (FIFObegin)
{
p=FIFObegin->next;
vFree((char*)FIFObegin);
FIFObegin=p;
}
FIFObegin=NULL;
FIFOend=&FIFObegin;
gs_bL0PCWin95DPlayInitState&=~0x02;
NetLib_eFlushSendingList(500);
NetLib_vDisconnectAllRemotePlayers();
DPClose();
DPRelease();
DPLobbyRelease();
}
/*****************************************************************************/
NetLib_tdeErrorStatus eL0PCWin95DPlayGetPlayerName(NetLib_tduxPlayerId uxPlayerId, char *pcString, unsigned short uwSize)
{
unsigned short i;
for(i=0; i<gs_stConvTable.uwSize; i++)
if(gs_stConvTable.dastConv[i].uxNetLibPlayerId == uxPlayerId) {
strncpy(pcString, gs_stConvTable.dastConv[i].pcDPlayPlayerName, uwSize-1);
pcString[uwSize]='\0';
return NetLib_E_es_NoError;
}
return NetLib_E_es_UnknownPlayerId;
}
/*****************************************************************************
* Description : eL0PCWin95DPlayIsProtocolSet
* Check if the protocol is correctly initialize or not
*****************************************************************************
* Input : none
* Output : NetLib_E_es_True
*****************************************************************************/
NetLib_tdeErrorStatus _NET_CALLING_CONV_ eL0PCWin95DPlayIsProtocolSet(void)
{
if(!(gs_bL0PCWin95DPlayInitState&0x01)) return NetLib_E_es_ProtocolNotInitialized;
return NetLib_E_es_True;
}
/*****************************************************************************
* Description : eL0PCWin95DPlayIsProtocolAvailable
* 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_ eL0PCWin95DPlayIsProtocolAvailable(void)
{
if(!(gs_bL0PCWin95DPlayInitState&0x01)) return NetLib_E_es_ProtocolNotInitialized;
return NetLib_E_es_True;
}