Pascal IPX routines

IPX routines

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.