                        
                        Pascal FastMem Unit (PFU) 
                              Version 3.2
                                  by 
                     Robert Rothenburg Walking-Owl
                 Copyright (c)1994 All Rights Reserved

  
  These routines allow a programmer to write software which is usable on
  any Intel i86 machine, yet is "intelligent" enough to identify the CPU
  and use faster code for 32-bit machines like the 386.

  This software may only be used for non-commercial/non-profit purposes.
  No guarantees or warrantees are made for the use of this software, nor
  will the author be held responsible for damages resulting from the use
  of this software package.  In other words, USE AT YOUR OWN RISK.

  Individuals have the right to distribute executables including this
  software so long as the FastMem code (including the embedded copyright
  notice) is not modified.

  This unit should be compatible with Turbo Pascal v(s)4.0 and later.
  (It has been tested with v5.0 and seems to work with no problems.)

  If you have any questions or comments, I can be reached electronically:

        robert.rothenburg@asb.com
        rrothenb@ic.sunysb.edu
  
  Note that some routines in previous versions of FastMem (GetVar,GetArg)
  inadvertantly used 386-branch instructions in the 16-bit portions, thus
  causing software that used them to crash on 16-bit machines.  This has
  been fixed, but similar bugs may still exist in other routines.
  
  ------------------------------------------------------------------------
  
  If many of these routines seem to fulfill "arcane" needs, it is because
  those are my needs.  Chances are a couple of the routines will be of
  general use.  (Also remember that Turbo Pascal uses "smart" linking,
  so unused routines should not be included in the final executable.)
  
  The procedures in the unit are as follows:

  procedure IdentifyCpu;

    This is the initialization routine for the FastMem unit. It identif-
    fies the processor and sets up some internal variables.  Because the
    CPU identification routine can damage the stack frame, it must be
    called only ONCE, as the FIRST statement in a program. (Note: for
    version 3.2, fixes have been made to minimize the possible damage.)

  function  GetCpu: Word;
  procedure SetCpu(Cpu: Word);

    These routines get and set the CpuId value respectively.  They allow
    you to write other routines which use this value, or notify the user
    what processor is being used.  You MUST use the constants defined in
    the unit (Cpu86 through Cpu486).

    Use SetCpu(Cpu86) to allow users to disable 32-bit code, in odd cases
    where processors do not ID correctly.

    Note: you may initially want to SetCpu(Cpu86) and re-SetCpu() to the
    identified value to give users the option to disable 32-bit code, in
    case there are problems.

function  MemComp(var Block1, Block2; Size: Word): Boolean;
procedure MemCopy(var Source, Dest; Size: Word);
procedure MemFill(var Block; Size: Word; Ch: Byte);

    These routines Compare, Copy and Fill blocks of memory. Note that the
    MemCopy and MemFill routines are equivalent to the Move and FillChar
    routines in Turbo Pascal - with the advantage that they can run from
    30-50% faster using 32-bit code.

    Note that for comparing two strings, MemComp is slower that Pascal's
    '=' if the strings are small and inequal, but faster (even in Cpu86)
    when the strings are equal, or when most of the initial characters
    are equal.

function  GetArg(Num: Integer): String;

    This function is somewhat equivalent to ParamStr in Turbo Pascal,
    however it allows command line arguments to be defined with quotes,
    thus allowing users to enter arguments with spaces.  One extention
    is that GetArg(-1) will return the entire argument line as one string,
    including the leading and trailing spaces.

function  GetVar(S: String): String;

    Equivalent to GetEnv in Turbo Pascal.  Returns the value of an envir-
    onment variable.  Note that the parameter must be in Uppercase. To be
    honest this routine seems slower than GetEnv, although one usually
    doesn't call GetEnv several-thousand times in a program for there to
    be a noticable difference.

function  SpaceOf(Len: Byte): String;

    Returns a string of Len spaces.

function  NumStr(X: LongInt): String;

    Translates X (as an UNSIGNED long integer) into a string.

function  NumVal(S: String): LongInt;

    Returns the value of S (an UNSIGNED long interger), the functional 
    opposite of NumStr.

function XNumVal(S: String): LongInt;

    Also returns the value of S like NumVal, however XNumVal accepts non-
    decimal numbers in C-format: numbers beginning with '0' are assued to
    be octal (base-8).  Numbers beginning with '0x' are assumed to be
    hexidecimal (base-16) and numbers beginning with '0b' are assumed to
    be binary.

    Note: if you want signed long integers, make the appropriate adjust-
    ments.  For most of my purposes, I need unsigned long ints.

function  SubStr(Main: String; Loc, Len: Word): String;

    Equivalent to the Copy function in Pascal, though it runs slightly
    faster using 32-bit instructions: the speed improvement is minor
    because smaller amounts are copied.

function  CatStr(First,Second: String): String;

    Concatenates two strings, equivalent to the ConCat function in
    Pascal, although it can only take two arguments.

function  PosStr(Sub,Main: String): Word;

    Equivalent to the Pos function in Pascal, though it runs about the
    same speed for small substrings.  For large substrigns PosStr runs
    much faster, even in Cpu86 mode.

function PascalStr(var S): String;
function AsciiZ(var A; S: String): Pointer;

    Similar to some functions in the Turbo Pascal Strings unit. PascalStr 
    converts an ASCIIZ string to one usable by Pascal; AsciiZ converts a
    Pascal string to an ASCIIZ string usage by DOS/BIOS functions.

function  SwapLong(X: LongInt): LongInt;

    Translates Motorola BigEndian numbers into Intel LittleEndian numbers.
    Uses the 486 bwsap instruction, which should be 2/3 faster in theory,
    though my own tests have shown it to be about the same.

procedure NixToDos( DTR: DateTime; X: LongInt);

    Translates a Unix-style date-time-stamp into a Pascal DateTime record,
    which can then be easily Packed into a DOS date-time-stamp. Useful for
    handling many Unix-file formats. (A DosToNix function may be added in
    future versions.)

function PackDate( DTR: DateTime ): LongInt;

    The equivalent of Pascal's PackTime, except that it works as a function
    and uses 286-instructions if applicable.

function CurrentDate: LongInt;

    Returns the current system date-time as a DOS packed-time-stamp.

function  FetchTime: LongInt;
procedure DecodeTime(var Time: TimeRec; Fetched: LongInt);

    Useful for timer functions: Fetchtime returns the current time as the
    number of 100ths/sec since midnight: thus allowing you to use simple
    subtraction (StopTime-StartTime) to determine the time difference.
    (An EncodeTime function may be added in future versions.)

