📄 multi.c
字号:
// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman// Ken Silverman's official web site: "http://www.advsys.net/ken"// See the included license file "BUILDLIC.TXT" for license info.// This file has been modified from Ken Silverman's original release#include <stdio.h>#include <stdlib.h>#include <string.h>#include "platform.h"extern long getcrc(char *buffer, short bufleng);extern void processreservedmessage(short tempbufleng, char *datempbuf);extern void initcrc(void);extern int comon(void);extern void comoff(void);extern int neton(void);extern void netoff(void);extern void startcom(void);extern int netinitconnection (long newconnectnum, char *newcompaddr);extern void installbicomhandlers(void);extern void uninstallbicomhandlers(void);#define COMBUFSIZ 16384#define COMCODEBYTES 384#define COMCODEOFFS 14#define NETCODEBYTES 384#define MAXPLAYERS 16#define ESC1 0x83#define ESC2 0x8f#define NETBACKPACKETS 4#define MAXIPXSIZ 546#define updatecrc16(crc,dat) crc = (((crc<<8)&65535)^crctable[((((unsigned short)crc)>>8)&65535)^dat])char syncstate = 0, hangup = 1;static char multioption = 0, comrateoption = 0; //COM & NET variablesshort numplayers = 0, myconnectindex = 0;short connecthead, connectpoint2[MAXPLAYERS];char syncbuf[MAXIPXSIZ];long syncbufleng, outbufindex[128], outcnt;long myconnectnum, otherconnectnum, mypriority;long crctable[256]; //COM ONLY variableslong comnum, comvect, comspeed, comtemp, comi, comescape, comreset;#ifdef PLATFORM_DOS // !!! this is a real mess. --ryan.static void interrupt far comhandler(void);static unsigned short orig_pm_sel, orig_rm_seg, orig_rm_off;static unsigned long orig_pm_off;#endifvolatile unsigned char *inbuf, *outbuf, *comerror, *incnt, *comtype;volatile unsigned char *comresend;volatile short *inbufplc, *inbufend, *outbufplc, *outbufend, *comport;#ifdef PLATFORM_DOS // !!! this is a real mess. --ryan.static char rmbuffer[COMCODEBYTES] = //See realcom.asm{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x50,0x53,0x66,0x51,0x52,0x2e, 0x8b,0x16,0x08,0x00,0x83,0xc2,0x02,0xec,0x24,0x07, 0x8a,0xe0,0x80,0xfc,0x02,0x74,0x08,0x80,0xfc,0x04, 0x74,0x62,0xe9,0x89,0x00,0x2e,0x8b,0x16,0x08,0x00, 0x2e,0x8a,0x0e,0x0a,0x00,0x80,0xe9,0x01,0x78,0x7a, 0x2e,0x80,0x3e,0x0c,0x00,0x01,0x7c,0x10,0x74,0x04, 0xb0,0x83,0xeb,0x02,0xb0,0x8f,0xee,0x2e,0xfe,0x0e, 0x0c,0x00,0xeb,0xe3,0x2e,0x80,0x3e,0x0b,0x00,0x01, 0x7c,0x12,0x74,0x04,0xb0,0x83,0xeb,0x04,0x2e,0xa0, 0x0d,0x00,0xee,0x2e,0xfe,0x0e,0x0b,0x00,0xeb,0xc9, 0x2e,0x8b,0x1e,0x04,0x00,0x2e,0x3b,0x1e,0x06,0x00, 0x74,0x3c,0x2e,0x8a,0x87,0x80,0x41,0xee,0x43,0x81, 0xe3,0xff,0x3f,0x2e,0x89,0x1e,0x04,0x00,0xeb,0xab, 0x2e,0x8b,0x16,0x08,0x00,0xec,0x2e,0x8b,0x1e,0x02, 0x00,0x2e,0x88,0x87,0x80,0x01,0x43,0x81,0xe3,0xff, 0x3f,0x2e,0x89,0x1e,0x02,0x00,0x2e,0x80,0x3e,0x0a, 0x00,0x10,0x75,0x08,0x83,0xc2,0x05,0xec,0xa8,0x01, 0x75,0xd6,0xf6,0xc4,0x01,0x0f,0x84,0x56,0xff,0xb0, 0x20,0xe6,0x20,0x5a,0x66,0x59,0x5b,0x58,0xcf,};#endif //NET ONLY variablesshort socket = 0x4949;char compaddr[MAXPLAYERS][12], mycompaddr[12];char netincnt[MAXPLAYERS], netoutcnt[MAXPLAYERS];char getmess[MAXIPXSIZ];char omessout[MAXPLAYERS][NETBACKPACKETS][MAXIPXSIZ];short omessleng[MAXPLAYERS][NETBACKPACKETS];short omessconnectindex[MAXPLAYERS][NETBACKPACKETS];short omessnum[MAXPLAYERS];long connectnum[MAXPLAYERS], rmoffset32, rmsegment16, neti;volatile char *ecbget, *ecbput, *ipxin, *ipxout, *messin, *messout;volatile char *tempinbuf, *tempoutbuf, *rmnethandler, *netinbuf;volatile short *netinbufplc, *netinbufend;static char rmnetbuffer[NETCODEBYTES] ={ 0xfb,0x2e,0x8a,0x26,0x62,0x00,0x2e,0xa0,0x63,0x00, 0x83,0xe8,0x1e,0x2e,0x8b,0x1e,0xe2,0x06,0x2e,0x88, 0x87,0xe4,0x06,0x43,0x81,0xe3,0xff,0x3f,0x2e,0x88, 0xa7,0xe4,0x06,0x43,0x81,0xe3,0xff,0x3f,0x33,0xf6, 0x2e,0x8a,0x8c,0xa0,0x00,0x46,0x2e,0x88,0x8f,0xe4, 0x06,0x43,0x81,0xe3,0xff,0x3f,0x3b,0xf0,0x72,0xec, 0x2e,0x89,0x1e,0xe2,0x06,0xbb,0x04,0x00,0x8c,0xc8, 0x8e,0xc0,0xbe,0x00,0x00,0xcd,0x7a,0xcb,};static long my7a = 0;#ifdef PLATFORM_DOS#pragma aux koutp =\ "out dx, al",\ parm [edx][eax]\#pragma aux kinp =\ "in al, dx",\ parm [edx]#endiflong convalloc32 (long size){#ifdef PLATFORM_DOS union REGS r; r.x.eax = 0x0100; //DPMI allocate DOS memory r.x.ebx = ((size+15)>>4); //Number of paragraphs requested int386(0x31,&r,&r); if (r.x.cflag != 0) return ((long)0); //Failed return ((long)((r.x.eax&0xffff)<<4)); //Returns full 32-bit offset#else fprintf (stderr, "%s, line %d; convalloc32() called\n", __FILE__, __LINE__); return 0;#endif }#ifdef PLATFORM_DOS#pragma aux fixregistersaftersimulate =\ "cld",\ "push ds",\ "pop es",\static struct rminfo{ long EDI, ESI, EBP, ESP, EBX, EDX, ECX, EAX; short flags, ES, DS, FS, GS, IP, CS, SP, SS;} RMI;#endiflong simulateint(char intnum, long daeax, long daebx, long daecx, long daedx, long daesi, long daedi){#ifdef PLATFORM_DOS union REGS regs; struct SREGS sregs; memset(&RMI,0,sizeof(RMI)); // Set up real-mode call structure memset(&sregs,0,sizeof(sregs)); RMI.EAX = daeax; RMI.EBX = daebx; RMI.ECX = daecx; RMI.EDX = daedx; RMI.ESI = daesi-rmoffset32; RMI.EDI = daedi-rmoffset32; RMI.DS = rmsegment16; RMI.ES = rmsegment16; regs.w.ax = 0x0300; // Use DMPI call 300h to issue the DOS interrupt regs.h.bl = intnum; regs.h.bh = 0; regs.w.cx = 0; sregs.es = FP_SEG(&RMI); regs.x.edi = FP_OFF(&RMI); int386x(0x31,®s,®s,&sregs); fixregistersaftersimulate(); return(RMI.EAX);#else fprintf(stderr, "%s line %d; simulateint() called\n",__FILE__,__LINE__); return 0;#endif }void initmultiplayers(char damultioption, char dacomrateoption, char dapriority){ long i; multioption = damultioption; comrateoption = dacomrateoption; connecthead = 0; for(i=MAXPLAYERS-1;i>=0;i--) connectpoint2[i] = -1, connectnum[i] = 0x7fffffff; mypriority = dapriority; initcrc(); if ((multioption >= 1) && (multioption <= 4)) { comnum = multioption; switch(dacomrateoption&15) { case 0: comspeed = 2400; break; case 1: comspeed = 4800; break; case 2: comspeed = 9600; break; case 3: comspeed = 14400; break; case 4: comspeed = 19200; break; case 5: comspeed = 28800; break; } comon(); } if (multioption >= 5) { if ((i = neton()) != 0) { if (i == -1) printf("IPX driver not found\n"); if (i == -2) printf("Socket could not be opened\n"); exit(0); } } numplayers = 1;}void uninitmultiplayers(){ if (numplayers > 0) { if ((multioption >= 1) && (multioption <= 4)) comoff(); if (multioption >= 5) netoff(); //Uninstall before timer }}int neton(void){ long i, j; if ((simulateint(0x2f,(long)0x7a00,0L,0L,0L,0L,0L)&255) != 255) return(-1); if (*(long *)(0x7a<<2) == 0) {#ifdef PLATFORM_DOS printf("Faking int 0x7a to call IPX entry at: %4x:%4x\n",RMI.ES,RMI.EDI&65535); my7a = convalloc32(16L); *(short *)((0x7a<<2)+0) = (my7a&15); *(short *)((0x7a<<2)+2) = (my7a>>4); *(char *)(my7a+0) = 0x2e; //call far ptr [L1] *(char *)(my7a+1) = 0x9a; *(long *)(my7a+2) = 7L; *(char *)(my7a+6) = 0xcf; //iret *(short *)(my7a+7) = (RMI.EDI&65535); //L1: ipxoff *(short *)(my7a+9) = RMI.ES; // ipxseg#endif } //Special stuff for WATCOM C if ((rmoffset32 = convalloc32(1380L+NETCODEBYTES+COMBUFSIZ)) == 0) { printf("Can't allocate memory for IPX\n"); exit; } rmsegment16 = (rmoffset32>>4); i = rmoffset32; ecbget = (char *)i; i += 48; ecbput = (char *)i; i += 48; ipxin = (char *)i; i += 32; ipxout = (char *)i; i += 32; messin = (char *)i; i += 560; messout = (char *)i; i += 560; tempinbuf = (char *)i; i += 16; tempoutbuf = (char *)i; i += 80; rmnethandler = (char *)i; i += NETCODEBYTES; netinbufplc = (short *)i; i += 2; netinbufend = (short *)i; i += 2; netinbuf = (char *)i; i += COMBUFSIZ; memcpy((void *)rmnethandler,(void *)rmnetbuffer,NETCODEBYTES); simulateint(0x7a,0L,(long)0x1,0L,(long)socket,0L,0L); //Closesocket if ((simulateint(0x7a,(long)0xff,0L,0L,(long)socket,0L,0L)&255) != 0) return(-2); //Opensocket simulateint(0x7a,0L,9L,0L,0L,(long)tempoutbuf,0L); //Getinternetworkaddress memcpy((void *)&mycompaddr[0],(void *)&tempoutbuf[0],10); mycompaddr[10] = (socket&255); mycompaddr[11] = (socket>>8); myconnectnum = ((long)tempoutbuf[6])+(((long)tempoutbuf[7])<<8)+(((long)(tempoutbuf[8]^tempoutbuf[9]))<<16)+(((long)mypriority)<<24); netinitconnection(myconnectnum,mycompaddr); ecbget[8] = 1; ecbput[8] = 0; *netinbufplc = 0; *netinbufend = 0; for(i=MAXPLAYERS-1;i>=0;i--) netincnt[i] = 0, netoutcnt[i] = 0; for(i=0;i<MAXPLAYERS;i++) { omessnum[i] = 0; for(j=NETBACKPACKETS-1;j>=0;j--) { omessleng[i][j] = 0; omessconnectindex[i][j] = 0; } } //Netlisten for(i=0;i<30;i++) ipxin[i] = 0; for(i=0;i<48;i++) ecbget[i] = 0; ecbget[4] = (char)(((long)rmnethandler-rmoffset32)&255), ecbget[5] = (char)(((long)rmnethandler-rmoffset32)>>8); ecbget[6] = (char)(rmsegment16&255), ecbget[7] = (char)(rmsegment16>>8); ecbget[10] = (socket&255), ecbget[11] = (socket>>8); ecbget[34] = 2, ecbget[35] = 0; ecbget[36] = (char)(((long)ipxin-rmoffset32)&255), ecbget[37] = (char)(((long)ipxin-rmoffset32)>>8); ecbget[38] = (char)(rmsegment16&255), ecbget[39] = (char)(rmsegment16>>8); ecbget[40] = 30, ecbget[41] = 0; ecbget[42] = (char)(((long)messin-rmoffset32)&255), ecbget[43] = (char)(((long)messin-rmoffset32)>>8); ecbget[44] = (char)(rmsegment16&255), ecbget[45] = (char)(rmsegment16>>8); ecbget[46] = (MAXIPXSIZ&255), ecbget[47] = (MAXIPXSIZ>>8); simulateint(0x7a,0L,(long)0x4,0L,0L,(long)ecbget,0L); //Receivepacket return(0);}int comon(){ long divisor, cnt; short *ptr; if ((comnum < 1) || (comnum > 4)) return(-1); //comvect = 0xb+(comnum&1); comvect = ((comrateoption>>4)+0x8+2); installbicomhandlers(); *incnt = 0; outcnt = 0; *inbufplc = 0; *inbufend = 0; *outbufplc = 0; *outbufend = 0; ptr = (short *)(0x400L+(long)((comnum-1)<<1)); *comport = *ptr; if (*comport == 0) { switch(comnum) { case 1: *comport = 0x3f8; break; case 2: *comport = 0x2f8; break; case 3: *comport = 0x3e8; break; case 4: *comport = 0x2e8; break; } if ((inp((*comport)+5)&0x60) != 0x60) { *comport = 0; return(-1); } } if ((comspeed <= 0) || (comspeed > 115200)) return(-1); // Baud-Setting,?,?,Parity O/E,Parity Off/On, Stop-1/2,Bits-5/6/7/8 // 0x0b is odd parity,1 stop bit, 8 bits#ifdef PLATFORM_DOS _disable();#endif koutp((*comport)+3,0x80); //enable latch registers divisor = 115200 / comspeed; koutp((*comport)+0,divisor&255); //# = 115200 / bps koutp((*comport)+1,divisor>>8); koutp((*comport)+3,0x03); //0x03 = n,8,1 koutp((*comport)+2,0x87); //check for a 16550 0=1,64=4,128=8,192=14 if ((kinp((*comport)+2)&0xf8) == 0xc0) { *comtype = 16; } else { *comtype = 1; koutp((*comport)+2,0); } cnt = *comtype; //Clear any junk already in FIFO while (((kinp((*comport)+5)&0x1) > 0) && (cnt > 0)) { kinp(*comport); cnt--; } koutp((*comport)+4,0x0b); //setup for interrupts (modem control) koutp((*comport)+1,0); //com interrupt disable koutp(0x21,kinp(0x21)&(255-(1<<(comvect&7)))); //Unmask vector kinp((*comport)+6); kinp((*comport)+5); kinp((*comport)+0); kinp((*comport)+2); koutp((*comport)+1,0x03); //com interrupt enable koutp(0x20,0x20); comescape = 0; comreset = 0; *comerror = 0; *comresend = 0;#ifdef PLATFORM_DOS _enable();#endif syncbufleng = 0; return(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -