⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 net_ipx.c

📁 quake1 dos源代码最新版本
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
Copyright (C) 1996-1997 Id Software, Inc.

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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// net_ipx.c

#include <stdio.h>
#include <stdlib.h>
#include <dpmi.h>

#include "quakedef.h"
#include "dosisms.h"
#include "net_ipx.h"

#define	EIO		 		5	/* I/O error */

#define AF_NETWARE 		64

#define IPX_OPEN					0
#define IPX_CLOSE					1
#define IPX_GETROUTE				2
#define IPX_SEND					3
#define IPX_LISTEN					4
#define IPX_SCHEDULEEVENT			5
#define IPX_CANCEL					6
#define IPX_SCHEDULESPECIALEVENT	7
#define IPX_GETINTERVALMARKER		8
#define IPX_GETADDRESS				9
#define IPX_RELINQUISH				10

#define PTYPE_UNKNOWN				0
#define PTYPE_RIP					1
#define PTYPE_ECHO					2
#define PTYPE_ERROR					3
#define PTYPE_IPX					4
#define PTYPE_SPX					5

#pragma pack(1)

typedef struct
{
	byte	network[4];
	byte	node[6];
	short	socket;
} IPXaddr;

struct sockaddr_ipx
{
    short			sipx_family;
	IPXaddr			sipx_addr;
    char			sipx_zero[2];
};
#define sipx_port sipx_addr.socket

typedef struct
{
	short			checkSum;
	short			length;
	byte			transportControl;
	byte			type;
	IPXaddr			destination;
	IPXaddr			source;
} IPXheader;

typedef struct ECBStructure
{
	struct ECBStructure *link;
	unsigned short	ESR_off;
	unsigned short	ESR_seg;
	byte	inUse;
	byte	completionCode;
	short	socket;
	byte	IPXWorkspace[4];
	byte	driverWorkspace[12];
	byte	immediateAddress[6];
	short	fragCount;
	short	fragOff;
	short	fragSeg;
	short	fragSize;
} ECB;

#pragma pack()

typedef struct
{
	ECB			ecb;
	IPXheader	header;
	int			sequence;
	char		data[NET_DATAGRAMSIZE];
} ipx_lowmem_buffer_t;

#define LOWMEMSIZE		(100 * 1024)
#define LOWMEMSAVE		256
#define IPXBUFFERS		((LOWMEMSIZE - LOWMEMSAVE)/ sizeof(ipx_lowmem_buffer_t))
#define IPXSOCKBUFFERS	5
#define IPXSOCKETS		(IPXBUFFERS / IPXSOCKBUFFERS)

// each socket's socketbuffer 0 is used for sending, the others for listening

typedef struct
{
	char				reserved[LOWMEMSAVE];
	ipx_lowmem_buffer_t	socketbuffer[IPXSOCKETS][IPXSOCKBUFFERS];
} ipx_lowmem_area_t;


static int ipxsocket[IPXSOCKETS];
static ECB *readlist[IPXSOCKETS];
static int sequence[IPXSOCKETS];
static int handlesInUse;
static ipx_lowmem_area_t *lma;
static char *lowmem_buffer;
static int lowmem_bufseg;
static int lowmem_bufoff;
static unsigned short ipx_cs;
static unsigned short ipx_ip;
static int net_acceptsocket = -1;
static int net_controlsocket;

static void IPX_PollProcedure(void);
static PollProcedure pollProcedure = {NULL, 0.0, IPX_PollProcedure};

//=============================================================================

static void IPX_GetLocalAddress(IPXaddr *addr)
{
	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_GETADDRESS;
	regs.x.es = lowmem_bufseg;
	regs.x.si = lowmem_bufoff;
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
	Q_memcpy(addr, lowmem_buffer, 10);
}

//=============================================================================

static int IPX_GetLocalTarget(IPXaddr *addr, byte *localTarget)
{
	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_GETROUTE;
	regs.x.es = lowmem_bufseg;
	regs.x.si = lowmem_bufoff;
	regs.x.di = lowmem_bufoff + sizeof(IPXaddr);
	Q_memcpy(lowmem_buffer, addr, sizeof(IPXaddr));
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
	if (regs.h.al)
		return -1;
	Q_memcpy(localTarget, lowmem_buffer + sizeof(IPXaddr), 6);
	return 0;
}

//=============================================================================

static void IPX_ListenForPacket(ECB *ecb)
{
	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_LISTEN;
	regs.x.es = ptr2real(ecb) >> 4;
	regs.x.si = ptr2real(ecb) & 0xf;
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
}

//=============================================================================

static void IPX_RelinquishControl(void)
{
	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_RELINQUISH;
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
}


void IPX_PollProcedure(void)
{
	IPX_RelinquishControl();
	SchedulePollProcedure(&pollProcedure, 0.01);
}

//=============================================================================

static void ProcessReadyList(int s)
{
	int n;
	ECB *ecb;
	ECB *prev;

	for (n = 1; n < IPXSOCKBUFFERS; n++)
	{
		if (lma->socketbuffer[s][n].ecb.inUse == 0)
		{
			for (ecb = readlist[s], prev = NULL; ecb; ecb = ecb->link)
			{
				if (lma->socketbuffer[s][n].sequence < ((ipx_lowmem_buffer_t *) ecb)->sequence)
					break;
				prev = ecb;
			}
			if (ecb)
				lma->socketbuffer[s][n].ecb.link = ecb;
			else
				lma->socketbuffer[s][n].ecb.link = NULL;
			if (prev)
				prev->link = &lma->socketbuffer[s][n].ecb;
			else
				readlist[s] = &lma->socketbuffer[s][n].ecb;
			lma->socketbuffer[s][n].ecb.inUse = 0xff;
		}
	}
}

//=============================================================================

int IPX_Init(void)
{
	int s;
	int n;
	struct qsockaddr addr;
	char *colon;

	if (COM_CheckParm ("-noipx"))
		return -1;

	// find the IPX far call entry point
	regs.x.ax = 0x7a00;
	__dpmi_simulate_real_mode_interrupt (0x2f, (__dpmi_regs *)&regs);
	if (regs.h.al != 0xff)
	{
		Con_Printf("IPX not detected\n");
		return -1;
	}
	ipx_cs = regs.x.es;
	ipx_ip = regs.x.di;

	// grab a chunk of memory down in DOS land
	lowmem_buffer = dos_getmemory(LOWMEMSIZE);
	if (!lowmem_buffer)
	{
		Con_Printf("IPX_Init: Not enough low memory\n");
		return -1;
	}
	lowmem_bufoff = ptr2real(lowmem_buffer) & 0xf;
	lowmem_bufseg = ptr2real(lowmem_buffer) >> 4;

	// init socket handles & buffers
	handlesInUse = 0;
	lma = (ipx_lowmem_area_t *)lowmem_buffer;
	for (s = 0; s < IPXSOCKETS; s++)
	{
		ipxsocket[s] = 0;
		for (n = 0; n < IPXSOCKBUFFERS; n++)
		{
			lma->socketbuffer[s][n].ecb.link = NULL;
			lma->socketbuffer[s][n].ecb.ESR_off = 0;
			lma->socketbuffer[s][n].ecb.ESR_seg = 0;
			lma->socketbuffer[s][n].ecb.socket = 0;
			lma->socketbuffer[s][n].ecb.inUse = 0xff;
			lma->socketbuffer[s][n].ecb.completionCode = 0;
			lma->socketbuffer[s][n].ecb.fragCount = 1;
			lma->socketbuffer[s][n].ecb.fragOff = ptr2real(&lma->socketbuffer[s][n].header) & 0xf;
			lma->socketbuffer[s][n].ecb.fragSeg = ptr2real(&lma->socketbuffer[s][n].header) >> 4;
			lma->socketbuffer[s][n].ecb.fragSize = sizeof(IPXheader) + sizeof(int) + NET_DATAGRAMSIZE;
		}
	}

	if ((net_controlsocket = IPX_OpenSocket (0)) == -1)
	{
		dos_freememory(lowmem_buffer);
		Con_DPrintf ("IPX_Init: Unable to open control socket\n");
		return -1;
	}

	SchedulePollProcedure(&pollProcedure, 0.01);

	IPX_GetSocketAddr (net_controlsocket, &addr);
	strcpy(my_ipx_address,  IPX_AddrToString (&addr));
	colon = strrchr (my_ipx_address, ':');
	if (colon)
		*colon = 0;

	Con_Printf("IPX initialized\n");
	ipxAvailable = true;
	return net_controlsocket;
}

//=============================================================================

void IPX_Shutdown(void)
{
	IPX_Listen (false);
	IPX_CloseSocket (net_controlsocket);
	dos_freememory(lowmem_buffer);
}

//=============================================================================

void IPX_Listen (qboolean state)
{
	// enable listening
	if (state)
	{
		if (net_acceptsocket != -1)
			return;
		if ((net_acceptsocket = IPX_OpenSocket (net_hostport)) == -1)
			Sys_Error ("IPX_Listen: Unable to open accept socket\n");
		return;
	}

	// disable listening
	if (net_acceptsocket == -1)
		return;
	IPX_CloseSocket (net_acceptsocket);
	net_acceptsocket = -1;
}

//=============================================================================

int IPX_OpenSocket(int port)
{
	int handle;
	int n;
	unsigned short socket;

	if (handlesInUse == IPXSOCKETS)
		return -1;

	// open the IPX socket
	regs.x.cs = ipx_cs;
	regs.x.ip = ipx_ip;
	regs.x.bx = IPX_OPEN;
	regs.h.al = 0;
	regs.x.dx = htons(port);
	__dpmi_simulate_real_mode_procedure_retf((__dpmi_regs *)&regs);
	if (regs.h.al == 0xfe)
	{
		Con_DPrintf("IPX_OpenSocket: all sockets in use\n");
		return -1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -