From ec32cf41f916fc34c03d2844684631bee39005ad Mon Sep 17 00:00:00 2001
From: Ian C <ianc@noddybox.co.uk>
Date: Thu, 9 Jun 2011 13:57:32 +0000
Subject: Added copies of old numbered releases.

---
 doc/porting.htm | 1318 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 1318 insertions(+)
 create mode 100644 doc/porting.htm

(limited to 'doc/porting.htm')

diff --git a/doc/porting.htm b/doc/porting.htm
new file mode 100644
index 0000000..99d3cf1
--- /dev/null
+++ b/doc/porting.htm
@@ -0,0 +1,1318 @@
+<html>
+
+<head>
+<meta http-equiv="Content-Type"
+content="text/html; charset=iso-8859-1">
+<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
+<title>viDOOM - Free Software DOOM editor</title>
+</head>
+
+<body>
+
+<h1 align="center">Porting viDOOM</h1>
+
+<p>This document is provided in case anyone wishes to port viDOOM
+to a new platform. Below is an indication of what OS dependent
+routines must be provided and what configuration needs to be
+done. It is requested that any ports are also released as Free
+Software.</p>
+
+<ul>
+    <li><a href="#MAKEFILE">Makefile configuration</a></li>
+    <li><a href="#INI">INI File</a></li>
+    <li><a href="#FILES">Files</a></li>
+    <li><a href="#MAIN">Main entry point</a></li>
+    <li><a href="#GFX_H">Graphics and input</a></li>
+    <li><a href="#PLATGUI_H">Platform GUI</a></li>
+    <li><a href="#FILE_H">File interface</a></li>
+    <li><a href="#MEM_H">Memory allocation</a></li>
+    <li><a href="#RUNCMD_H">External command execution</a></li>
+    <li><a href="#VSTRING_H">String functions</a></li>
+    <li><a href="#INSTALLATION">Installation script</a></li>
+    <li><a href="#DOCUMENTATION">Documentation</a></li>
+</ul>
+
+<hr>
+
+<h2><a name="MAKEFILE"></a>Makefile configuration</h2>
+
+<p><strong><u>makefile</u></strong></p>
+
+<p><a name="MAKEPLAT"></a>Set the variable <strong>MAKEPLAT</strong>
+to the name of your platform, eg.</p>
+
+<p><tt>MAKEPLAT=</tt><em><tt>OS</tt></em></p>
+
+<p>You will then need to create a matching file the <strong>make</strong>
+sub directory called <em>OS</em>.cfg. Also all the OS dependent C
+source should go into a sub directory defined in the following
+make config file by the <strong>PLATFORM</strong> variable. See
+the <a href="#FILES">Files</a> section for an overview of these
+files.</p>
+
+<p><a name="MAKE_CONFIG"></a><strong><u>make config file</u></strong></p>
+
+<p>The following values need to be set in the file <strong>make</strong><em><strong>/OS</strong></em><strong>.cfg</strong>:</p>
+
+<table border="1" cellpadding="3">
+    <tr>
+        <td valign="top" nowrap><strong><tt>CC</tt></strong></td>
+        <td valign="top">Set to the name of the C compiler.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>LD</tt></strong></td>
+        <td valign="top">The name of the linker.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><a name="PLATFORMVAR"></a><strong><tt>PLATFORM</tt></strong></td>
+        <td valign="top">The name of the D containing
+        the OS dependent C sources. The idea of defineing tdefining    here, rather than using the MAKEPLAT variable defined in
+        the top level makefile, is so that different
+        configurations can share sources. i.e. An X11 port may
+        use the same code for all the unix platforms, but each
+        machine may require slightly different configuration
+        (library search paths for example).</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>EXE_EXT</tt></strong></td>
+        <td valign="top">An extension to add to the executable
+        name, e.g.<br>
+        <tt>EXE_EXT=.EXE</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>OBJ_EXT</tt></strong></td>
+        <td valign="top">The extension used in this OS to denote
+        object files produced by the C compiler. Generally:<br>
+        <tt>OBJ_EXT=.o</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>LIBS</tt></strong></td>
+        <td valign="top">Any extra libraries to link in with
+        viDOOM for the OS dependent routines.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>EXRACF</tt></strong></td>
+        <td valign="top">Any extra C flags required when
+        compiling the sources. Use it to enable optimisation and
+        to include any extra include paths required by this OS.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>EXTRALF</tt></strong></td>
+        <td valign="top">Any extra flags required when linking
+        viDOOM. Use it to enable include any extra library paths
+        required by this OS.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>DIRSEP</tt></strong></td>
+        <td valign="top">The directory separator character for
+        this OS. The character must be included in quotes, e.g.<font
+        face="Courier New"><tt><br>
+        </tt></font><tt>DIRSEP=&quot;/&quot;</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>MATHLIB</tt></strong></td>
+        <td valign="top">The options required to include the
+        maths library when linking.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>TRACEFORM</tt></strong></td>
+        <td valign="top">This variable is a printf format string
+        and the arguments to the format. This string is used to
+        provide a tracing function used to track bugs in the
+        editor. A simple, portable example is:<br>
+        <tt>TRACEFORM=&quot;%s:%d&quot;,__FILE__,__LINE__</tt><p>It
+        can just be defined to an empty string if you are not
+        compiling the debug version.</p>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>EXEFLAG</tt></strong></td>
+        <td valign="top">The flag to provide to the linker to
+        generate an executable. The flag is used in a rule
+        something like this:<br>
+        <tt>$(LD) $(EXTRALF) $(EXEFLAG) vidoom$(EXE_EXT)
+        $(ALL+VIDOOM_OBJECTS)</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>OBJFLAG</tt></strong></td>
+        <td valign="top">The flag to provide to the C compiler to
+        generate an object file from the supplied C source. The
+        flag is used in a rule something like this:<br>
+        <tt>$(CC) $(EXTRACF) $(OBJFLAG) file.c</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>DEFINEFLAG</tt></strong></td>
+        <td valign="top">The flag to provide to the C compiler
+        with pre-processor definition from the command line. The
+        flag is used in a rule something like this (note no space
+        after the DEFINEFLAG - if there is a space between the
+        switch and the argument put it in this variable
+        definition):<br>
+        <tt>$(CC) $(EXTRACF) $(OBJFLAG) $(DEFINEFLAG)MACRO=value
+        file.c</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>INCFLAG</tt></strong></td>
+        <td valign="top">The flag to provide to the C compiler
+        with extra directories in which the pre-processor
+        searches for include files. The flag is used in a rule
+        something like this (note no space after the INCFLAG - if
+        there is a space between the switch and the argument put
+        it in this variable definition):<br>
+        <tt>$(CC) $(EXTRACF) $(OBJFLAG) $(INCFLAG)include_dir
+        file.c</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong><tt>MAKEINSTALL</tt></strong></td>
+        <td valign="top">The command used to execute the <strong>install</strong>
+        makefile as described in the <a href="#INSTALLATION">installation
+        script </a>section. The command must define the
+        INSTALLDIR variable for the makefile and invoke the first
+        rule in the install makefile.<p>For instance, using a
+        normal unix/GCC type make command, this would be:<br>
+        <tt>make INSTALL_DIR='$(INSTALL_DIR)' -f install</tt></p>
+        </td>
+    </tr>
+</table>
+
+<hr>
+
+<h2><a name="INI"></a>INI File</h2>
+
+<p>If your port requires or wants configuration to be set at
+tun-time from the INI file, it is best to place it a
+system-dependent section called the same as the <em>OS</em> value
+you set <a href="#MAKEPLAT">MAKEPLAT</a> to for this platform,
+e.g.</p>
+
+<p><tt>[</tt><em><tt>OS</tt></em><tt>]<br>
+guimode=3D</tt></p>
+
+<hr>
+
+<h2><a name="FILES"></a>Files</h2>
+
+<p>The following files are the minimum that must be provided by
+the platform:</p>
+
+<table border="1" cellpadding="3">
+    <tr>
+        <td valign="top" nowrap><strong>make/</strong><em><strong>OS</strong></em><strong>.cfg</strong></td>
+        <td valign="top">The make config file. Described in the <a
+        href="#MAKE_CONFIG">previous section</a>.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>main.c</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides the <a href="#MAIN">startup
+        code</a> for the operating system.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>gfx.c</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides the <a href="#GFX_H">low level
+        graphics and input</a>.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>platgui.c</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides the <a href="#PLATGUI_H">system
+        dependent GUI</a>.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>file.c</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides the portable part of the <a
+        href="#FILE_H">file system interface</a>.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>mem.c</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides the <a href="#MEM_H">memory
+        handling</a>.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>runcmd.c</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides the method for <a
+        href="#RUNCMD_H">running external commands</a>.</td>
+    </tr>
+    <tr>
+        <td><strong>vstring.c</strong></td>
+        <td>This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and provides functions for <a
+        href="#VSTRING_H">string comparisons</a>.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>install</strong></td>
+        <td valign="top">This goes in the <a href="#PLATFORMVAR">platform
+        directory</a> and is the makefile invoked to <a
+        href="#INSTALLATION">install viDOOM</a>.</td>
+    </tr>
+</table>
+
+<hr>
+
+<h2><a name="MAIN"></a>Main entry point</h2>
+
+<p><strong><u>main.c</u></strong></p>
+
+<p>The OS dependent code must provide it's own main (this is to
+allow for various non-standard environments where main() is not
+the standard entry point). The entry point must do any OS
+dependent initialisations then invoke the following entry point
+to start up viDOOM:</p>
+
+<p><tt>int viDOOM(int argv, char *argv[])</tt></p>
+
+<p>If the OS uses main() as an entry point the following example
+could be enough:</p>
+
+<pre>int main(int argc,char *argv[])
+{
+    return (viDOOM(argc,argv));
+}</pre>
+
+<hr>
+
+<h2><a name="GFX_H"></a>Graphics and input</h2>
+
+<p><strong><u>gfx.c</u></strong></p>
+
+<p>This provides the low-level graphics access and interfaces to
+keyboard and mouse. The GFX object is expected to work on a weak,
+semi-event driven basis for keyboard/mouse access. The following
+are the basic assumptions about the GFX interface:</p>
+
+<ul>
+    <li>A true, or hicolor, display.</li>
+    <li>A Fixed font.</li>
+    <li>Default origin is in the top left of the display, with X
+        positive along and Y positive down.</li>
+    <li>A buffered display. The screen contents should not change
+        until GFX_redraw() is called. If not honoured viDOOM
+        should still work up to a point, but it's use of the XOR
+        mode may not be apparent to the user.</li>
+    <li>Colours are represented using an int, with 8 bits each
+        for the red, green and blue component. The int used to
+        define the colour, when viewed in hex, would look like <tt>0xRRGGBB</tt>.
+        Some examples are:<ul type="disc">
+            <li><tt>0xFF0000</tt> - Red</li>
+            <li><tt>0x00FF00</tt> - Green</li>
+            <li type="disc"><tt>0x0000FF</tt> - Blue</li>
+            <li><tt>0xFFFFFF</tt> - White</li>
+            <li><tt>0x808080</tt> - 50% grey</li>
+            <li><tt>0x000000</tt> - Black</li>
+        </ul>
+    </li>
+</ul>
+
+<p>The following types are defined and used by the GFX object :</p>
+
+<table border="1" cellpadding="3">
+    <tr>
+        <td valign="top" nowrap><pre>typedef void *GFX_IMAGE; </pre>
+        </td>
+        <td valign="top">This is an opaque type provided to allow
+        the GFX object to provide whatever is required to
+        reference a bitmap on the machine.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    int           w;
+    int           h;
+    int           pal[256];
+    unsigned char *data;
+    } GFX_BITMAP; </pre>
+        </td>
+        <td valign="top">This type represents the bitmap objects
+        that viDOOM defines. These bitmaps are converted into
+        GFX_IMAGE prior to use. The fields are: <table border="0"
+        cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>w</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">width of bitmap</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>h</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">height of bitmap</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>pal[256]</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The palette used to define the
+                bitmap. Each bitmap pixel is an index into this
+                array of RGB values. Each entry is an integer,
+                that when represented in hex would define the RGB
+                triplet as 0xRRGGBB.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>*data</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">A pointer to the data of the
+                bitmap. This should be accessed using pointer
+                arithmetic as *(data+(x)+(y*w))</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    int    type;
+    int    shift;
+    int    ctrl;
+    int    alt;
+    char   ascii;
+    int    code;
+    } GFXKey;</pre>
+        </td>
+        <td valign="top">This defines an object for reporting key
+        presses. The fields are:<table border="0" cellpadding="3"
+        cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>type</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The type of event. This field is
+                just used to line up with the event union defined
+                later on. Should just hold GFX_KEY_EVENT.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>shift</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">TRUE if the Shift key is being
+                pressed.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>ctrl</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">TRUE if the Control key is being
+                pressed.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>alt</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">TRUE if the Alt key is being
+                pressed.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>ascii</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The ASCII code of the character
+                read. If the key is not an ASCII key (e.g. a
+                function key) this field should be zero.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>code</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">Holds the code for non-ASCII
+                keys, e.g. GFX_F1. This field should be set to
+                GFX_ASCII for key presses reported through the
+                ascii field.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct GFXMouse
+    {
+    int    type;
+    int    shift;
+    int    ctrl;
+    int    alt;
+    int    x;
+    int    y;
+    int    b;
+    } GFXMouse;</pre>
+        </td>
+        <td valign="top">This defines the type for reporting
+        mouse movements and button presses. The fields are:<table
+        border="0" cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>type</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The type of event. This field is
+                just used to line up with the event union defined
+                later on. Should just hold GFX_MOUSE_EVENT.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>shift</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">TRUE if the Shift key is being
+                pressed.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>ctrl</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">TRUE if the Control key is being
+                pressed.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>alt</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">TRUE if the Alt key is being
+                pressed.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>x</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The X co-ordinate of the mouse,
+                relative to the top left of the display.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>y</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The Y co-ordinate of the mouse,
+                relative to the top left of the display.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>b</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The currently pressed buttons.
+                This should be made up of a bit mask composed
+                from GFX_BUTLEFT, GFX_BUTMIDDLE and GFX_BUTRIGHT.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef union GFXEvent
+    {
+    int      type;
+    GFXKey   key;
+    GFXMouse mouse;
+    } GFXEvent;</pre>
+        </td>
+        <td valign="top">This defines the type for reporting
+        events (a combination of both mouse movements or key
+        presses). The fields are:<table border="0"
+        cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>type</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The type of event. This field is
+                just used to decide which of the other two fields
+                should be accessed to get the event information.
+                This field must be GFX_MOUSE_EVENT or
+                GFX_KEY_EVENT.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>key</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The GFXKey structure defining
+                the event if this is a GFX_KEY_EVENT.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>mouse</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The GFXMouse structure defining
+                the event if this is a GFX_MOUSE_EVENT.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+</table>
+
+<p>The following interfaces must be supplied by the GFX object:</p>
+
+<p><strong><tt>void GFX_init(void)</tt></strong></p>
+
+<blockquote>
+    <p>Initialises the GFX object. No other GFX interfaces are
+    called prior to this, with the possible (though current not
+    used) exception of <strong><tt>GFX_exit()</tt></strong>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_close(void)</tt></strong></p>
+
+<blockquote>
+    <p>Called when viDOOM is terminating. Note that other (none
+    system dependent) processing may go on between calling this
+    and then invoking <strong><tt>exit()</tt></strong> or <strong><tt>return()</tt></strong>.</p>
+</blockquote>
+
+<p><strong><tt>GFX_IMAGE GFX_create_image(GFX_BITMAP *bm)</tt></strong></p>
+
+<blockquote>
+    <p>Should create a GFX_IMAGE from the passed bitmap <em>bm</em>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_destroy_image(GFX_IMAGE img)</tt></strong></p>
+
+<blockquote>
+    <p>Release the bitmap object pointed to by <em>img</em>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_draw_image(GFX_IMAGE img, int x, int y)</tt></strong></p>
+
+<blockquote>
+    <p>Draws <em>img</em> with it's top-left co-ordinate
+    represented by <em>x,y</em>. This function should implement
+    any necessary clipping when drawing the bitmap.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_fill_screen(GFX_IMAGE img)</tt></strong></p>
+
+<blockquote>
+    <p>Should fill the screen with the image, scaled if
+    necessary. Note that this call is just used for the menu
+    backdrop, so if it cannot be honoured no harm will be done.</p>
+</blockquote>
+
+<p><a name="GFX_OPEN"></a><strong><tt>void GFX_open(int width,
+int height)</tt></strong></p>
+
+<blockquote>
+    <p>Opens the display (or window or whatever) with the
+    specified <em>width</em> and <em>height</em>. Note that
+    failures in here should terminate the program.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_clear(int col)</tt></strong></p>
+
+<blockquote>
+    <p>This clears the display to the passed colour <em>col</em>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_redraw(void)</tt></strong></p>
+
+<blockquote>
+    <p>This redraws the contents of the screen. All drawing
+    operations should not update the actual screen till this is
+    called (i.e. the display should be buffered).</p>
+</blockquote>
+
+<p><strong><tt>void GFX_line(int x1, int y1, int x2, int y2, int
+col)</tt></strong></p>
+
+<blockquote>
+    <p>Draw a line from <em>x1,y1</em> to <em>x2,y2</em> in
+    colour <em>col</em>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_plot(int x, int y, int col)</tt></strong></p>
+
+<blockquote>
+    <p>Plot the point <em>x,y</em> in colour <em>col</em>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_circle(int x, int y, int r, int col)<br>
+void GFX_fcircle(int x, int y, int r, int col)</tt></strong></p>
+
+<blockquote>
+    <p>Draw a circle centred on <em>x,y</em> with a radius <em>r</em>
+    and in colour <em>col</em>. The <strong>fcircle</strong>
+    version should draw a filled circle.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_rect(int x, int y, int w, int h, int col)<br>
+void GFX_frect(int x, int y, int w, int h, int col)</tt></strong></p>
+
+<blockquote>
+    <p>Draw a rectangle with one corner at <em>x,y</em> and the
+    other corner at <em>(x+w),(y+h)</em> in colour <em>col</em>.
+    Note that zero length and negative width and heights must be
+    allowed. The <strong>frect </strong>version should draw a
+    filled rectangle.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_set_XOR_mode(void)<br>
+void GFX_clear_XOR_mode(void)</tt></strong></p>
+
+<blockquote>
+    <p>This should set and clear XOR mode. Normally all GFX
+    operations should set the pixels to the colour specified, but
+    when XOR mode is enabled the pixel values should be XORed
+    into place.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_print(int x, int y, int col, char *fmt,
+...)</tt></strong></p>
+
+<blockquote>
+    <p>Print the printf style arguments (<em>fmt</em> and <em>...</em>)
+    with their top left corner at <em>x,y</em> in colour <em>col</em>.
+    Note that text should rendered transparently.</p>
+</blockquote>
+
+<p><strong><tt>int GFX_fh(void)<br>
+int GFX_fw(void)</tt></strong></p>
+
+<blockquote>
+    <p>Return the height (GFX_fh) and width (GFX_fw) of the fixed
+    width font used for display purposes.</p>
+</blockquote>
+
+<p><strong><tt>int GFX_mouse_buttons(void)</tt></strong></p>
+
+<blockquote>
+    <p>Returns the number of mouse buttons. This is just used as
+    check on initialisation as viDOOM expects at least 2 mouse
+    buttons.</p>
+</blockquote>
+
+<p><strong><tt>int GFX_mouse(int *x, int *y)</tt></strong></p>
+
+<blockquote>
+    <p>Return the current point position in <em>x</em> and <em>y</em>.
+    If any of the passed pointers are NULL that variable should
+    be ignored.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_waitkey(GFXKEy *key)</tt></strong></p>
+
+<blockquote>
+    <p>Waits for a <em>key</em> to be pressed and returns the key
+    press in <em>key</em>. If <em>key</em> is NULL simply wait
+    for a key press.</p>
+</blockquote>
+
+<p><strong><tt>int GFX_key(GFXKey *key)</tt></strong></p>
+
+<blockquote>
+    <p>Returns TRUE if a key has been pressed and returns the
+    keypress in <em>key</em>. Returns FALSE if there is no
+    outstanding keypresses, in which case the contents of <em>key</em>
+    are undefined.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_bounce(void)</tt></strong></p>
+
+<blockquote>
+    <p>Waits for all keys and mouse buttons to be released. On a
+    real event-driven system could be ignored, or flush any
+    outstanding events.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_await_input(GFXEvent *ev)</tt></strong></p>
+
+<blockquote>
+    <p>Waits for either a keypress or a mouse button to be
+    pressed and fills in <em>ev</em> accordingly.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_await_input_full(GFXEvent *ev)</tt></strong></p>
+
+<blockquote>
+    <p>Waits for either a keypress, a mouse button to be pressed
+    or the mouse to be moved and fills in <em>ev</em>
+    accordingly.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_exit(int code, char *fmt, ...)</tt></strong></p>
+
+<blockquote>
+    <p>This call should do any necessary tidying of the display
+    (switching from graphics mode, closing windows, whatever)
+    then display the printf style arguments (<em>fmt</em> and <em>...</em>)
+    and the exit with the passed return <em>code</em>.</p>
+</blockquote>
+
+<p><strong><tt>void GFX_save_screen(char *path)</tt></strong></p>
+
+<blockquote>
+    <p>This call need not be supported. It just allows screen
+    grabs to be captured when viDOOM is compiled with debug
+    information. If supported it should just save a bitmap in the
+    file pointed to by <em>path</em>.</p>
+</blockquote>
+
+<hr>
+
+<h2><a name="PLATGUI_H"></a>Platform GUI</h2>
+
+<p><strong><u>platgui.c</u></strong></p>
+
+<p>This provides access to the platform's GUI routines.</p>
+
+<p>The following types are defined and used by the PLATGUI object
+:</p>
+
+<table border="1" cellpadding="3">
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    char      *text;
+    GFX_IMAGE img;
+    int       client_index;
+    } PLAT_IMG_PICKLIST;</pre>
+        </td>
+        <td valign="top">This structure is used to define a
+        picklist that has graphical images and client defined
+        values attached to them. This is used for selection of
+        textures, flats and sprites (things) in viDOOM.<p>The
+        fields in the structure are:</p>
+        <table border="0" cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>text</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This defines the text for a
+                picklist entry. NULL marks the end of the list of
+                picklist entries.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>img</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The GFX_IMAGE to associate with
+                this entry. Can be NULL to indicate show no
+                image.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>client_index</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The value returned if this item
+                is selected.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    char   *text;
+    int    client_index;
+    } PLAT_PICKLIST;</pre>
+        </td>
+        <td valign="top">This structure is used to define a
+        picklist that has client defined values attached to the
+        entries.<p>The fields in the structure are:</p>
+        <table border="0" cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>text</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This defines the text for a
+                picklist entry. NULL marks the end of the list of
+                picklist entries.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>client_index</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The value returned if this item
+                is selected.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    char  *text;
+    int   client_index;
+    } PLAT_MENU;</pre>
+        </td>
+        <td valign="top">This structure is used to define menu
+        entries that have client defined values attached to them.<p>The
+        fields in the structure are:</p>
+        <table border="0" cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>text</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This defines the text for the
+                menu entry. NULL marks the end of the list of
+                menu entries.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>client_index</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The value returned if this item
+                is selected.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    char   *text;
+    int    client_index;
+    } PLAT_RADIO;</pre>
+        </td>
+        <td valign="top">This structure is used to define entries
+        for a radio style picklist (i.e. where only one option
+        can be chosen) that have client defined values attached
+        to them.<p>The fields in the structure are:</p>
+        <table border="0" cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>text</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This defines the text for the
+                radio button. NULL marks the end of the list of
+                radio button entries.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>client_index</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The value returned if this item
+                is selected.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><pre>typedef struct
+    {
+    char   *text;
+    int    type;
+    union /* Data */
+        {
+        int	i;
+        char	s[PLAT_DIAL_MAXSTRLEN+1];
+        double	d;
+        } data;
+    } PLAT_DIALOG;</pre>
+        </td>
+        <td valign="top">This structure is used to define entries
+        for a simple dialog.<p>The fields in the structure are:</p>
+        <table border="0" cellpadding="3" cellspacing="6">
+            <tr>
+                <td valign="top" nowrap>text</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This defines the text for this
+                field in the dialog. NULL marks the end of the
+                list of dialog entries.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>type</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">The type of field this is.
+                Possible values are PLAT_DIAL_STRING,
+                PLAT_DIAL_INTEGER and PLAT_DIAL_DOUBLE.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>data.i</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This is the field that is
+                displayed and updated on exit if the type is
+                PLAT_DIAL_INTEGER.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>data.s</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This is the field that is
+                displayed and updated on exit if the type is
+                PLAT_DIAL_STRING.</td>
+            </tr>
+            <tr>
+                <td valign="top" nowrap>data.d</td>
+                <td valign="top" nowrap>-</td>
+                <td valign="top">This is the field that is
+                displayed and updated on exit if the type is
+                PLAT_DIAL_DOUBLE.</td>
+            </tr>
+        </table>
+        </td>
+    </tr>
+</table>
+
+<p>Note that along with the types, the following predefined
+values are set (these are read from the INI file). Note that they
+should be considered to be unset until immediately prior to
+viDOOM's call to <strong><tt>GUI_setscreen()</tt></strong>:</p>
+
+<table border="1" cellpadding="3">
+    <tr>
+        <td valign="top" nowrap><strong>GUI_HI</strong></td>
+        <td valign="top">The brightest colour used to draw the 3D
+        looking interface.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>GUI_MID</strong></td>
+        <td valign="top">The medium colour used to draw the 3D
+        looking interface.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>GUI_LO</strong></td>
+        <td valign="top">The darkest colour used to draw the 3D
+        looking interface.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>GUI_TEXT</strong></td>
+        <td valign="top">The colour of text.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>GUI_TEXTSHADOW</strong></td>
+        <td valign="top">The colour of the shadow behind text.
+        This is only really used by viDOOM's own portable GUI
+        routines.</td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><strong>GUI_BOLD</strong></td>
+        <td valign="top">The colour of bold text (used for
+        titles).</td>
+    </tr>
+</table>
+
+<h3>Functions</h3>
+
+<p>The following interfaces are defined by the PLATGUI object.
+Note that all these calls are assumed to not destroy screen
+contents (ie. the screen should be restored after displaying the
+GUI object):</p>
+
+<p><strong><tt>void GUI_setscreen(int width, int height)</tt></strong></p>
+
+<blockquote>
+    <p>Once the display has been opened with <a href="#GFX_OPEN"><strong>GFX_open()</strong></a>
+    then this is called to inform the platform's GUI routines of
+    the display size.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_yesno(char *question)</tt></strong></p>
+
+<blockquote>
+    <p>Display an alert with <em>question</em> in it and <em>Yes</em>
+    and <em>No</em> buttons. Returns TRUE if <em>Yes</em> is
+    pressed and FALSE if <em>No</em> is pressed.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_menu(char *title, int x, int y, PLAT_MENU
+menu[], int defval)</tt></strong></p>
+
+<blockquote>
+    <p>Displays a menu with title <em>title</em> at position <em>x,y</em>.
+    The displayed items are taken from <em>menu</em>. The return
+    is the client_index field from the selected menu item, or <em>defval</em>
+    if the menu is cancelled.</p>
+</blockquote>
+
+<p><strong><tt>char *GUI_fsel(char *title, char *default_path,
+char filter)</tt></strong></p>
+
+<blockquote>
+    <p>Allows a file to be selected. The file selector should
+    have <em>title</em> for it's title and start selecting from
+    the <em>default_path</em>. If <em>filter </em>is NULL then
+    all files should be displayed, otherwise only files ending in
+    <em>filter</em>.</p>
+    <p>The return is NULL if the selector is cancelled. Otherwise
+    a pointer is returned containing the fully qualified path of
+    the selected file. This pointer must be dynamically allocated
+    and will be freed using <a href="#FRELEASE"><strong>FRelease()</strong></a>.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_picklist(char *title, char *opts[])</tt></strong></p>
+
+<blockquote>
+    <p>Displays a picklist with title <em>title</em>. The options
+    are taken from the array of character pointers <em>opts</em>.
+    The return value is the index of the selected item in <em>opts</em>
+    if selected, or -1 if the picklist is cancelled.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_client_picklist(char *title, PLAT_PICKLIST
+opts[], int defval)</tt></strong></p>
+
+<blockquote>
+    <p>Displays a picklist with title <em>title</em>. The text
+    items to display are taken from <em>opts</em>. The return is
+    the client_index field from the selected picklist item, or <em>defval</em>
+    if the picklist is cancelled.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_image_picklist(char *title,
+PLAT_IMG_PICKLIST opts[], int defval)</tt></strong></p>
+
+<blockquote>
+    <p>Displays a picklist with title <em>title</em>. The text
+    items and associated image to display are taken from <em>opts</em>.
+    The return is the client_index field from the selected
+    picklist item, or <em>defval</em> if the picklist is
+    cancelled.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_radio_box(char *title, PLAT_RADIO opts[],
+int current, int defval)</tt></strong></p>
+
+<blockquote>
+    <p>Displays a dialog containing radio buttons with title <em>title</em>.
+    The text to display is taken from <em>opts</em>. The selected
+    object when the the radio box is first displayed is the
+    option who's client_index field matches <em>current</em> (or
+    the first item if there is no match). The return is the
+    client_index field from the selected radio button, or <em>defval</em>
+    if the radio box is cancelled.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_multi_box(char *title, char *opts[], int
+*val)</tt></strong></p>
+
+<blockquote>
+    <p>Display a mutli-selection radio box. The items are
+    described <em>opts</em>, which terminates with a NULL
+    pointer. <em>Val</em> points to a value which is used to
+    enable/disable the options dependent on the integers bit
+    setting. The integer pointed to by <em>val</em> is updated on
+    exit of the multi-selection box if it is not cancelled.</p>
+    <p>Note that the bit patterns are matched bit number to opt
+    index. ie.</p>
+    <ul>
+        <li>val &amp; 0x0001 corresponds to opts[0]</li>
+        <li>val &amp; 0x0002 corresponds to opts[1] ...</li>
+        <li>val &amp; 0x0010 corresponds to opts[4] ...</li>
+        <li>val &amp; 0x0100 corresponds to opts[8] ...</li>
+        <li>val &amp; 0x8000 corresponds to opts[15]</li>
+    </ul>
+    <p>A maximum of 16 bits should be all that needs supporting
+    currently. The return is TRUE if the dialog is accepted,
+    otherwise FALSE.</p>
+</blockquote>
+
+<p><strong><tt>int GUI_dialog(char *title, int no, PLAT_DIALOG
+dial[])</tt></strong></p>
+
+<blockquote>
+    <p>Displays a dialog with the title <em>title</em>. The
+    fields for the dialog are extracted from <em>dial</em>, for
+    which there is expected to be <em>no</em> elements. The
+    return is TRUE if the dialog is accepted, or FALSE if it is
+    cancelled. On being cancelled the contents of the data union
+    within the <em>dial</em> elements is undefined.</p>
+</blockquote>
+
+<hr>
+
+<h2><a name="FILE_H"></a>File interface</h2>
+
+<p><strong><u>file.c</u></strong></p>
+
+<p>This provides access to various file system functions and also
+provides some filename manipulation routines. The following
+interfaces should be provided:</p>
+
+<p><strong><tt>char *Pwd(void)</tt></strong></p>
+
+<blockquote>
+    <p>This call should return the current working directory. The
+    return should be static.</p>
+</blockquote>
+
+<p><strong><tt>void Cd(char *path)</tt></strong></p>
+
+<blockquote>
+    <p>This call should change the current working directory to <em>path</em>.</p>
+</blockquote>
+
+<p><strong><tt>char *Dirname(char *path)</tt></strong></p>
+
+<blockquote>
+    <p>This call should return the directory part of <em>path</em>
+    if any. The return should be static.</p>
+</blockquote>
+
+<p><strong><tt>char *Basename(char *path)</tt></strong></p>
+
+<blockquote>
+    <p>This call should return the filename part of <em>path</em>.
+    The return should be static, or a pointer into the <em>path</em>
+    parameter.</p>
+</blockquote>
+
+<p><strong><tt>int FileExists(char *path)</tt></strong></p>
+
+<blockquote>
+    <p>This call should return TRUE if the file pointed to by <em>path</em>
+    exists.</p>
+</blockquote>
+
+<p><strong><tt>int FilenamesEqual(char *path1, char *path2)</tt></strong></p>
+
+<blockquote>
+    <p>This call should return TRUE if the file pointed to by <em>path1</em>
+    and <em>path2</em> are the same file. At it's most basic
+    (e.g. like in the DOS port) it can simply makes sure that
+    directory separators are in the same form and then does <strong>strcasecmp()</strong>
+    on the paths.</p>
+</blockquote>
+
+<hr>
+
+<h2><a name="MEM_H"></a>Memory allocation</h2>
+
+<p><strong><u>mem.c</u></strong></p>
+
+<p>This provides memory allocation. While memory allocation can
+generally be done portably using <tt>malloc()</tt> providing this
+library just covers for any possible OS dependent twist. Also
+these routines are expected to handle errors internally. In all
+the interfaces <em>file</em> and <em>line</em> parameters are
+included so that errors can be reported more accurately.</p>
+
+<p>The following interfaces should be provided:</p>
+
+<p><strong><tt>void *FGrab (char *file, int line, int len)</tt></strong></p>
+
+<blockquote>
+    <p>This call should allocate <em>len</em> bytes and return a
+    pointer to it. A <em>len</em> of zero is valid. Memory should
+    be initialised to zero. Failure to allocate the memory should
+    terminate the program.</p>
+</blockquote>
+
+<p><strong><tt>void *FReGrab (char *file, int line, void *ptr,
+int len)</tt></strong></p>
+
+<blockquote>
+    <p>This call should re-allocate the memory pointed to by <em>ptr</em>
+    and return a new memory area of <em>len</em> bytes. The
+    original data pointed to by <em>ptr</em> should be copied to
+    the new memory area. Failure to allocate the memory should
+    terminate the program.</p>
+</blockquote>
+
+<p><strong><tt>char *FStrdup (char *file, int line, char *str)</tt></strong></p>
+
+<blockquote>
+    <p>This call should allocate enough bytes to copy the nul
+    terminated <em>str</em> to it. The returned pointer should
+    point to the new copy of <em>str</em>.<em> </em>Failure to
+    allocate the memory should terminate the program.</p>
+</blockquote>
+
+<p><strong><tt>void *FCopy (char *file, int line, void *ptr, int
+len)</tt></strong></p>
+
+<blockquote>
+    <p>This call should allocate <em>len</em> bytes and copy <em>len</em>
+    bytes from <em>ptr</em> into the new area. The newly
+    allocated memory should be returned. Failure to allocate the
+    memory should terminate the program.</p>
+</blockquote>
+
+<p><a name="FRELEASE"></a><strong><tt>void FRelease (char *file,
+int line, void *ptr)</tt></strong></p>
+
+<blockquote>
+    <p>This call should release the memory pointed to by <em>ptr</em>,
+    which will have been allocated by FGrab, FReGrab, FStrdup or
+    FCopy.</p>
+</blockquote>
+
+<hr>
+
+<h2><a name="RUNCMD_H"></a>External command execution</h2>
+
+<p><strong><u>runcmd.c</u></strong></p>
+
+<p>Provides a mechanism to run an external command. The following
+interfaces should be provided:</p>
+
+<p><strong><tt>int RunCommand(char *argv[], char *path)</tt></strong></p>
+
+<blockquote>
+    <p>Run a command. The output from the command (if there is
+    any) should NOT disturb the screen contents. The call should
+    return TRUE if the call succeeds, FALSE otherwise.</p>
+    <p>The <em>argv</em> list is an array of pointers to various
+    sections of the command and it's arguments, terminated with a
+    NULL pointer. Note that arguments may contain more than one
+    argument in each line - the actual command is described
+    simply by concatenating all the pointers together, eg.</p>
+    <p><tt>argv[0]=&quot;bsp&quot;<br>
+    argv[1]=&quot;file.wad&quot;<br>
+    argv[2]=&quot;-o file.wad&quot;<br>
+    argv[3]=NULL</tt></p>
+    <p>The <em>path</em> argument is a place to copy the path to
+    a file where the output from the command has been stored. If
+    this is not supported then the empty string should be
+    assigned to it. viDOOM will <tt>remove()</tt> the file after
+    it has read it.</p>
+</blockquote>
+
+<hr>
+
+<h2><a name="VSTRING_H"></a>Portable String routines</h2>
+
+<p><strong><u>vstring.c</u></strong></p>
+
+<p>Provides common string functions that are not actually part of
+the ANSI standard:</p>
+
+<p><strong><tt>int StrCaseCmp(char *a, char *b)</tt></strong></p>
+
+<blockquote>
+    <p>Performs in exactly the same way as the ANSI <tt>strcmp()</tt>
+    function, save for the fact that the case of the strings
+    being compared is ignored.</p>
+</blockquote>
+
+<p><strong><tt>int StrNCaseCmp(char *a, char *b)</tt></strong></p>
+
+<blockquote>
+    <p>Performs in exactly the same way as the ANSI <tt>strncmp()</tt>
+    function, save for the fact that the case of the strings
+    being compared is ignored.</p>
+</blockquote>
+
+<hr>
+
+<h2><a name="INSTALLATION"></a>Installation script</h2>
+
+<p>Each platform should provide a makefile called <strong>install</strong>.
+This is invoked from the top level makefile like this:</p>
+
+<blockquote>
+    <p><tt>cd $(PLATFORM) ; $(MAKEINSTALL)</tt></p>
+</blockquote>
+
+<p>Note that the install makefile will be invoked with the <a
+href="#PLATFORMVAR">PLATFORM</a> directory as the current working
+directory.</p>
+
+<p>The following files must be copied (where $SRC represents
+the source build directory and $INSTALLDIR the install
+directory):</p>
+
+<table border="1" cellpadding="3">
+    <tr>
+        <td valign="top" nowrap><tt>$SRC/vidoom</tt></td>
+        <td valign="top"><tt>$INSTALLDIR/vidoom</tt><p>Note that
+        this file may have a system specific extension (e.g. .EXE
+        in DOS)</p>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><tt>$SRC/LICENSE</tt></td>
+        <td valign="top"><tt>$INSTALLDIR/LICENSE</tt><p>The GNU
+        GPL should be copied into the installation directory so that
+	binary distributions can be easily generated with the license
+	included.</p>
+        </td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><tt>$SRC/base.ini</tt></td>
+        <td valign="top"><tt>$INSTALLDIR/vidoom.ini</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><tt>$SRC/*.cfg</tt></td>
+        <td valign="top"><tt>$INSTALLDIR/*.cfg</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><tt>$SRC/doc/*.htm</tt></td>
+        <td valign="top"><tt>$INSTALLDIR/doc/*.htm</tt></td>
+    </tr>
+    <tr>
+        <td valign="top" nowrap><tt>$SRC/doc/*.png</tt></td>
+        <td valign="top"><tt>$INSTALLDIR/doc/*.png</tt></td>
+    </tr>
+</table>
+
+<p>Note that, obviously, any OS specific files should also be copied.</p>
+
+<hr>
+
+<h2><a name="DOCUMENTATION"></a>Documentation</h2>
+
+<p>If you release a port of viDOOM to any platform please update <a
+href="bugs.htm#CONTACTS">doc/bugs.htm</a> with a contact address
+for problems on that platform.</p>
+
+<hr>
+
+<p><a href="index.htm">Back to index</a></p>
+
+<p><tt>$Id: porting.htm,v 1.19 2000/08/13 00:46:22 dosuser Exp dosuser $</tt></p>
+</body>
+</html>
-- 
cgit v1.2.3