Pascal IPX routines
Pascal
Download (.zip)
Unit NewIpx; {This unit contains ipx routines used in NetMaze - Zaifrun} Interface
Const MainSocket : word = $8765; {869Ch = doom} MaxDataSize = 1800; ipxHeaderSize = 30; transfersize:word = 546; ClockDelay:word = 18; {clock ticks between activity} {all signals are started with $EE,$EE,$EE} Signal_ConnectOk = $10; Signal_EndTransferOK = $11; Signal_BeginTransferOK = $12; Signal_SendNextpacket = $13; Signal_NodeIdentify = $14; Signal_FileNameFollows = $15; {not as only data in packet} Signal_SuggestpacketSize = $16; {not as only data in packet - { next word is transfer rate in bytes} Signal_Synchronize = $17; Signal_Addplayer = $18; {not as only data in packet} {next data is relevant player info} Signal_SubPlayer = $19; {not as only data in packet} {next data is relevant player info} Signal_updatePlayer = $1A; {not as only data in packet} {next data is relevant player info} Signal_ImDead = $1B; {not as only data in packet} {next data is relevant player info} Signal_UpdateAllPlayers = $1C; {not as only data in packet} {next data is relevant player info} Signal_NewPlayerJoins = $1D; {not as only data in packet} {next data is relevant player info} Signal_PlayerAccepted = $1E; {not as only data in packet} {next data is relevant player info} Signal_MasterTransfer = $1F; {not as only data in packet} {next data is relevant player info} Signal_WantInfo = $20; Signal_SignUp = $21; signal_GiveItToNeNow = $22; Signal_UpdateAllPlayersScore = $23; {not as only data in packet} {next data is relevant player info} Signal_NewplayerJoinsScore = $24; {not as only data in packet} {next data is relevant player info} Signal_MasterChange = $25; {not as only data in packet} {next data is relevant player info} Signal_TerminatedByMaster = $26;
Type address = array[0..1] of word; {farpointer 32 bit} NetWorkType = array[1..4] of byte; NodeType = array[1..6] of byte; NetAddrType = record Network:NetWorkType; Node:NodeType; Socket:word; end;
ECBType = record {48 bytes} link : address; { Pointer to next ECB? } ESR : address; { Event Service Routine 00000000h if none } inUse : byte; { In use flag } complete : byte; { Completeing flag } socket : word; { Big endian socket number } IPXwork : array[1..4] of byte; { IPX work space } Dwork : array[1..12] of byte; { Driver work space } immedAddr : nodeType; { Immediate local node address } fragCount : word; { Fragment count } fragData : address; { Pointer to data fragment } fragSize : word; { Size of data fragment } end; IPXheader = record {30 bytes} check : word; { big endian checksum } length : word; { big endian length in bytes } tc : byte; { transport control } packetType : byte; { packet type } dest : netAddrtype; { destination network address } src : netAddrtype; { source network address } end; Packet = record ecb : ECBType; IPX : IPXheader; data : array[1..MaxDataSize] of byte; {data : string;} end;
const BroadCast : NodeType = ($FF,$FF,$FF,$FF,$FF,$FF); { n386 : nodetype = (0,64,51,56,207,20); n486 : nodetype = (0,64,51,56,214,64);}
Var LocalAddr:NetAddrType; IPXEntry : Pointer; {brug IKKE denne pointer - Det virker bare ikke!!} MaxPacketSize : word; IPXmajorversion,IPXminorversion:byte; MaxConnections,AvailConnections:word; Signal:byte;
Function DetectIpx:Boolean; Procedure GetIPXInfo; procedure GetOwnAddress; Function OpenSocket(var socket:word):byte; Procedure CloseSocket(socket:word); function IPXlistenForPacket(var E : ECBtype):byte; procedure ImIdle; procedure IPXsendPacket(var E : ECBtype); procedure SetPacketSize(var ecb:ecbtype;size:word); Function GetPacketSize(ecb:ecbtype):word; Procedure SetTargetNode(var ecb:ecbtype;var ipx:ipxheader;target:nodetype); Procedure GetTargetNode(var ecb:ecbtype;var ipx:ipxheader;var target:nodetype); Function CheckSignal(var x):boolean; Function Sizeofpacket(var ipx:ipxheader):word; Function IntervalMarker:word; {kald kun en gang} procedure InitReceivePacket(var ecb : ecbType; var ipx : ipxHeader;rut:address); procedure InitSendPacket(var ecb : ecbType; var ipx : ipxHeader; size:word;Target:nodetype); Procedure SetServiceInt(var ecb:ecbtype;service:pointer);
Implementation
uses dos;
var regs:registers;
Procedure SetServiceInt(var ecb:ecbtype;service:pointer); begin if service=nil then begin ecb.esr[0]:=0; ecb.esr[1]:=0; end else begin ecb.esr[0]:=memw[seg(service):ofs(service)]; ecb.esr[1]:=memw[seg(service):ofs(service)+2]; end; end;
Function sizeofpacket(var ipx:ipxheader):word; begin sizeofpacket:=swap(ipx.length)-ipxheadersize; end;
Function CheckSignal(var x):boolean; type artype = array[1..10] of byte; var ar:artype absolute x; begin checksignal:=false; if (ar[1]=$EE) and (ar[2]=$EE) and (ar[3]=$EE) then begin checksignal:=true; signal:=ar[4]; end; end;
Function IntervalMarker:word; begin regs.bx:=8; intr($7A,regs); IntervalMarker:=regs.ax; end;
{ Tell the IPX driver that we aren't doing anything at the moment } procedure ImIdle; begin regs.bx:=$000A; intr($7A,regs); end;
{ Listen for an IPX packet PARAMS: var E = an initialize Event Control Block RETURNS: 0 for OK, nonzero for an error ????} function IPXlistenForPacket(var E : ECBtype):byte; begin regs.bx:=$0004; regs.es:=seg(E); regs.SI:=ofs(E); intr($7A,regs); IPXlistenForPacket:=regs.al; end;
{ Send an IPX packet PARAMS: var E = an initialized Event Control Block } procedure IPXsendPacket(var E : ECBtype); begin regs.bx:=$0003; regs.es:=seg(E); regs.SI:=ofs(E); intr($7A,regs); end;
{ Set up the fields in a recieve IPX record } procedure InitReceivePacket(var ecb : ecbType; var ipx : ipxHeader;rut:address); begin fillChar(ecb,sizeOf(ecb),#0); fillChar(ipx,sizeOf(ipx),#0); with ecb do begin inUse:=$1d; { ???? } ESR:=Rut; socket:=localaddr.socket; { Big endian socket number } fragCount:=1; { Fragment count } fragData[0]:=ofs(IPX); { Pointer to data fragment } fragData[1]:=seg(IPX); fragSize:=sizeof(IPX)+maxdatasize;{sizeof(string); } { Size of data fragment } end; if IPXlistenForPacket(ecb)<>0 then ; { Tell IPX to listen } end;
Procedure SetTargetNode(var ecb:ecbtype;var ipx:ipxheader;target:nodetype); begin ecb.immedaddr:=target; {ipx.dest.node:=target;} end;
Procedure GetTargetNode(var ecb:ecbtype;var ipx:ipxheader;var target:nodetype); begin target:=ecb.immedaddr; end;
procedure SetPacketSize(var ecb:ecbtype;size:word); begin ecb.fragsize:=sizeof(IPXHeader)+size; end;
Function GetPacketSize(ecb:ecbtype):word; begin GetPacketSize:=ecb.fragsize; end;
procedure InitSendPacket(var ecb : ecbType; var ipx : ipxHeader; size:word;Target:nodetype); begin fillChar(ecb,sizeOf(ecb),#0); {NO ESR} fillChar(ipx,sizeOf(ipx),#0); with ecb do begin socket:=localaddr.socket; { Big endian socket number } fragCount:=1; { Fragment count } fragData[0]:=ofs(IPX); { Pointer to data fragment } fragData[1]:=seg(IPX); fragSize:=sizeof(IPX)+size; { Size of data fragment } immedAddr:=target; { Needs to be BROADCAST?? } end; with ipx do begin check:=$ffff; { NO CHECKSUM } packettype:=4; { Packet exchange packet } dest.netWork:=localAddr.network; { Send to this network } dest.node:=target; { Send to everybody! } dest.socket:=localaddr.socket; { Send to my socket } src.network:=localAddr.network; { From this net } src.node:=localAddr.node; { From ME } src.socket:=localaddr.socket; { From my socket } end; end;
Function OpenSocket(var socket:word):byte; begin regs.bx:=0; regs.al:=0; regs.dx:=socket; intr($7A,regs); opensocket:=regs.al; socket:=regs.dx; localaddr.socket:=socket; end;
Procedure CloseSocket(socket:word); begin regs.bx:=1; regs.dx:=socket; intr($7A,regs); end;
Function DetectIpx:Boolean; begin regs.ax:=$7A00; intr($2f,regs); if regs.al=255 then begin DetectIpx:=true; IPXEntry:=ptr(regs.es,regs.di); end else DetectIpx:=false; end;
Procedure GetIPXInfo; begin regs.bx:=$1A; intr($7A,regs); MaxPacketSize:=regs.ax-ipxheadersize; regs.al:=$00; regs.bx:=$10; intr($7A,regs); if regs.al=$FF then begin MaxConnections:=regs.cx; AvailConnections:=regs.dx; Ipxmajorversion:=regs.bh; Ipxminorversion:=regs.bl; end; end;
procedure GetOwnAddress; begin regs.bx:=$0009; regs.es:=seg(localAddr); regs.si:=ofs(localAddr); {Socket number doesn't have to be specified} intr($7A,regs); end;
begin {init} end.
|