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.