Back

Developer Network
  File Specs
  Source codes
  Tables
  Mailing lists
  Knowledge Base

Other Games

 

 

Descent Developer Network
Descent 1/2

IPX Programming Starter's Guide

Introduction

Purpose: I wrote this article out of guilt for not answering all those people who ask me questions, because I didn't have the time. Also, I think this information is really needed, as there is very little information out there on programming for IPX. Therefore, my goal is to get enough information to get people started, so that they can explore this protocol, and learn how easy it really is to use. I will only cover the basic IPX functions, maybe later I will add more advanced information.

Prerequisites: This guide is written assuming that you have some understanding of programming fundamentals, and in particular, the C language. I would recommend getting some knowledge of networking, and network protocols in general before trying to do any serious programming on networks.

Disclaimer: The author provides this information purely out of the goodness of his heart, with no warranty implied. Use this information at your own risk, because I assume no responsibility for anything that you do (good or bad) with this information. Remember that when programming with network protocols, you have the ability to affect all machines hooked up to the network that you are programming on, so a bug in your code can cause problems in everyone else's computer. All example code listed is just an example, you may need to tweak it to make it work, but for the most part, it has been tested.

eMail author: Kevin Bentley

 

Terminology

There are some terms that you will need to know to get started, here is a basic (not official) definition for some of them.

Socket: Think of a machine with IPX as a power line. As many things as you plug into it, the same powerline provides power for them all. But, they connect to different sockets. The same concept can be used for IPX. One IPX driver might have several applications using it, and each has it's own socket, so the IPX driver knows who to send the data it receives to.

ECB: (Event Control Block) This is a sort of intelligent buffer used for sending and receiving data via IPX. It specifies all the information about the data to be sent (or data that has been received). The ECB is always supplied by the application, and the driver fills in certain parts of it. An ECB is defined in Table 1.

ESR: (Event Service Routine) This is a somewhat advanced topic, but and ESR is a function that you specify for the IPX driver to call, to notify you that a packet has arrived. Each ECB must either specify NULL, or a pointer to a function. Unless you are writing a very high speed game, or a program where you cannot check the status of the ECB within an idle loop, you won't need an ESR for now.

Fragment In an ECB, you may have multiple parts of a packet in different memory locations. For example, the first fragment is always an IPX header. The next fragment will be the actual data you want to send (or buffer to receive data).

 

Fundamentals
  • Application Startup
    Before you do anything with IPX, you need to call IPXInitialize(). This tells the driver you intend to use it.
    Next, you need to choose a socket, and open the socket. If you are only sending data, you can 0 for the socket number, and IPX will find a socket, and assign it to you. Most the time, you will need to choose a socket yourself, I would recommend that you use something higher than 0x8000. To open a socket, call IPXOpenSocket(). The return code is the socket that was opened, or –1 in case of an error.

  • Sending Data
    In order to send data, you need to allocate a buffer big enough for the ECB. You will also need a buffer for the IPX header.
    You need to initialize several members of the ECB, and the IPX header before you send the packet. Refer to Table 1, you will see the required fields in boldface for the ECB. It is important that the FragmentDescriptor[1] be filled in with the pointer to your data that you intend to send, as well as the size of the data that you want to send.
    Table 2 lists the IPX header, and again, the required fields are in boldface. Note that the value for PacketType should almost always be 4. If you want to send a broadcast packet (to everyone on your network) fill in the immediate address, and the destination address with the value 0xFF in every byte of those fields. In order to get the value to put in the ImmediateAddress field, call IPXGetLocalTarget() with the IPX address, and a pointer to the ImmediateAddress. It will figure out the ImmediateAddress, and fill it in for you.

    Once the ECB and the packet header are complete, you can call IPXSendPacket() with a pointer to the filled ECB. Your program can then monitor the ECB's CompletionCode, and InUseFlag variables, to know when the packet has been sent. It is up to the application to free this memory (or, you can re-use it for the next send). The IPX driver will simply send the data, then change the completion codes. Tables 3 and 4 list the values for InUseFlag, and CompletionCode.

  • Receiving Data
    In order to receive data, you must allocate memory for an ECB, the IPX header, and any data that you expect to receive (FragmentDescriptor[1]) as well as the ESR (in most cases, set the ESR to NULL). Then call IPXListenForPacket() with a pointer to the ECB, where the IPX driver will put the received data, and fill in the IPX header.
    You can now watch the CompletionCode of the ECB that you prepared, and when it is 0x00, you can retrieve the data, and reuse that ECB for the next incoming packet. For most cases, if you are receiving much data, I find it safe to use more than one ECB to listen for data. If you don't have an ECB available when the packet arrives, you won't get the packet.

  • Cleaning up
    When you are done, first use IPXCancelEvent() for any ECBs that are pending (You called IPXListenForPacket() but it never received a packet) and then call IPXCloseSocket() for any sockets you have opened.

  • Misc. IPX Information
    If you want to know your own IPX address, call IPXGetInternetworkAddress(), with pointer to a buffer, and it will fill the buffer with your own IPX address.

There are many other aspects to IPX programming, but the ones I have mentioned should be enough to get most people going. I have written many IPX programs using the code listed in Table 5. Feel free to use it, but you may have to tweak it to get your compiler to accept it. It originally was written for Borland C, but should be portable with a few modifications.

If you are programming under Windows 95, you might want to look at using Winsock IPX. If you have ever used Winsock for TCPIP, you will find that it is almost exactly the same using IPX as it is using TCPIP. The only difference is how you specify the address. The Microsoft Win32 SDK has an example application that uses Winsock IPX, take a look at it for your 32bit IPX development needs.

Please send me feedback, and if you have anything to add, send it to me, I will be glad to post it, and give you due credit!

Send feedback to: Kevin Bentley

 

Table 5

//********************************************
//********************************************
//begin DOSIPX.H
//********************************************
//********************************************

#include <dos.h>

typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long LONG;

union REGS regs;
struct SREGS sregs;

typedef struct IPXAddress {
    BYTE Network[4]; //Big-Endian
    BYTE Node[6]; //Big-Endian
    BYTE Socket[2]; //Big-Endian
}IPXAddress;


typedef struct IPXHeader {
    WORD CheckSum;
    WORD Length;
    BYTE TransportControl;
    BYTE PacketType;
    IPXAddress Destination;
    IPXAddress Source;
}IPXHeader;

typedef struct ECB {
    void far *linkAddress;
    void (far *ESRAddress)();
    BYTE InUseFlag;
    BYTE CompletionCode;
    WORD SocketNumber; //Big-Endian
    BYTE IPXWorkspace[4];
    BYTE DriverWorkspace[12];
    BYTE ImmediateAddress[6];
    WORD FragmentCount;
    ECBFragment FragmentDescriptor[4];
}ECB;

typedef struct ECBFragment {
    void far *address;
    WORD size;
}ECBFragment;



BYTE IPXInitialize (void)
{
    BYTE rvalue;
    asm {
        mov ax,0x7a00;
        int 0x2f;
        mov rvalue,al;
    }
    return rvalue;

}


int IPXOpenSocket(short SocketNumber)
{

    BYTE rvalue1;
    short rvalue2;

    asm {
        mov bx,0;
        mov al,0;
        mov dx, SocketNumber;
        int 0x7a;
        mov rvalue1,al;
        mov rvalue2,dx;
    }
    if (rvalue1) return -1;
    else return rvalue2;
}


void IPXCloseSocket(short SocketNumber)
{

    asm {
    mov bx,1;
    mov dx, SocketNumber;
    int 0x7a;
    }

}

int IPXListenForPacket(ECB *ecb)

    BYTE rvalue1;
    short ECBSEG,ECBOFS;
    ECBSEG=FP_SEG(ecb);
    ECBOFS=FP_OFF(ecb);

    asm {
        mov si,ECBOFS;
        mov es,ECBSEG;
        mov bx,4;
        int 0x7a;
        mov rvalue1,al;
    }
    if (rvalue1) return 1;
    else return 0;

}


int IPXGetInternetworkAddress (BYTE far *Address)
{


    short ADDRSEG,ADDROFS;
    BYTE rvalue;
    ADDRSEG=FP_SEG(Address);
    ADDROFS=FP_OFF(Address);

    asm {
        mov si,ADDROFS;
        mov es,ADDRSEG;
        mov bx,9;
        int 0x7a;
        mov al,rvalue;
    }
    if (rvalue) return 1;
    else return 0;
}

void IPXSendPacket(ECB *ecb) {

    short ECBSEG,ECBOFS;
    ECBSEG=FP_SEG(ecb);
    ECBOFS=FP_OFF(ecb);

    asm {
        mov si,ECBOFS;
        mov es,ECBSEG;
        mov bx,3;
        int 0x7a;
    }

}

void IPXGetLocalTarget(BYTE far * TargetAddr,BYTE far *immediateAddress,int *XportTime)
{

    short TGTADDROFS,TGTADDRSEG,IMMEDOFS;
    TGTADDRSEG=FP_SEG(TargetAddr);
    TGTADDROFS=FP_OFF(TargetAddr);
    IMMEDOFS=FP_OFF(immediateAddress);

    asm {
        mov si,TGTADDROFS;
        mov es,TGTADDRSEG;
        mov di,IMMEDOFS;
        mov bx,2;
        int 0x7a;
        mov *XportTime,cx;
    }
    return;

}

void IPXCancelEvent(ECB *ecb) {


    short ECBSEG,ECBOFS;
    ECBSEG=FP_SEG(ecb);
    ECBOFS=FP_OFF(ecb);

    asm {
        mov si,ECBOFS;
        mov es,ECBSEG;
        mov bx,6;
        int 0x7a;
    }
    return;

}

//********************************************
//********************************************
//end DOSIPX.H
//********************************************
//********************************************

 

 

All pages (C) 1996-2000 Descent Network Team
Everything taken from the Descent, FreeSpace, Red Faction and Summoner series games are
Copyright Interplay Productions , THQ Inc. , Parallax Software , Volition Inc. and/or Outrage Entertainment