UnitNewIpx;
{This unit contains ipx routines used inNetMaze-Zaifrun}
InterfaceConstMainSocket : 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; { EventServiceRoutine 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);}
VarLocalAddr:NetAddrType;
IPXEntry : Pointer; {brug IKKE denne pointer -Det virker bare ikke!!}
MaxPacketSize : word;
IPXmajorversion,IPXminorversion:byte;
MaxConnections,AvailConnections:word;
Signal:byte;
FunctionDetectIpx:Boolean;
ProcedureGetIPXInfo;
procedure GetOwnAddress;
FunctionOpenSocket(var socket:word):byte;
ProcedureCloseSocket(socket:word);
function IPXlistenForPacket(var E : ECBtype):byte;
procedure ImIdle;
procedure IPXsendPacket(var E : ECBtype);
procedure SetPacketSize(var ecb:ecbtype;size:word);
FunctionGetPacketSize(ecb:ecbtype):word;
ProcedureSetTargetNode(var ecb:ecbtype;var ipx:ipxheader;target:nodetype);
ProcedureGetTargetNode(var ecb:ecbtype;var ipx:ipxheader;var target:nodetype);
FunctionCheckSignal(var x):boolean;
FunctionSizeofpacket(var ipx:ipxheader):word;
FunctionIntervalMarker: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);
ProcedureSetServiceInt(var ecb:ecbtype;service:pointer);
Implementation
uses
dos;
var
regs:registers;
ProcedureSetServiceInt(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;
FunctionCheckSignal(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;
FunctionIntervalMarker: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;
{ Listenfor an IPX packet
PARAMS: varE= an initialize EventControlBlockRETURNS: 0forOK, 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: varE= an initialized EventControlBlock }
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;
ifIPXlistenForPacket(ecb)<>0 then ; { TellIPX to listen }
end;
ProcedureSetTargetNode(var ecb:ecbtype;var ipx:ipxheader;target:nodetype);
begin
ecb.immedaddr:=target;
{ipx.dest.node:=target;}
end;
ProcedureGetTargetNode(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;
FunctionGetPacketSize(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); {NOESR}
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; { NOCHECKSUM }
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; { FromME }
src.socket:=localaddr.socket; { From my socket }
end;
end;
FunctionOpenSocket(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;
ProcedureCloseSocket(socket:word);
begin
regs.bx:=1;
regs.dx:=socket;
intr($7A,regs);
end;
FunctionDetectIpx:Boolean;
begin
regs.ax:=$7A00;
intr($2f,regs);
if regs.al=255 then
begin
DetectIpx:=true;
IPXEntry:=ptr(regs.es,regs.di);
end elseDetectIpx:=false;
end;
ProcedureGetIPXInfo;
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.