{*/////////////////////////////////////
 *
 * _globals.pas
 *
 * Global definition file for
 *      MCBL.LIB
 *      EMSL.LIB
 *      XMSL.LIB 
 *      VML.LIB
 *
 */////////////////////////////////////}

unit    _Globals;

INTERFACE

const


{*
 * attribute define values
 *}

    BLACK=      0;
    BLUE=       1;
    GREEN=      2;
    CYAN=       3;
    RED=        4;
    MAGENTA=    5;
    BROWN=      6;
    WHITE=      15;
    NORMAL=     7;
    REVERSE=    112;

    ON_INTENSITY=  8;
    OFF_INTENSITY= 0;
    ON_BLINK=      128;
    OFF_BLINK=     0;

type
    DWord=      LongInt;
    StrPtr=    ^String;
    BytePtr=   ^Byte;
    CharPtr=   ^Char;
    WordPtr=   ^Word;
    DWordPtr=  ^DWord;

    SegOff_type = record
        offset:     Word;
        segment:    Word;
        end;

var
    errno:      Word;

function    hex(num: DWord; precision: Word): String;
function    even(num: DWord): DWord;
function    segOffToPhys(p: Pointer): DWord;
function    segToPhys(s: Word): DWord;
function    min(a: DWord; b: DWord) : DWord;
function    max(a: DWord; b: DWord) : DWord;
procedure   memset(p: Pointer; val: Word; len: Word);
procedure   getBigMem(var p: Pointer; len: DWord);
procedure   freeBigMem(var p: Pointer; len: DWord);

IMPLEMENTATION

(*
 *  hex     --  Translate a number to HEX
 *)
function    hex(num: DWord; precision: Word): String;

const
    digits: String= '0123456789ABCDEF';

var
    i:      Word;
    result: String;

begin
    result:= '';
    for i:= 1 to precision do begin
        result:= digits[(num and $F) + 1] + result;
        num:= num shr 4;
        end;

    hex:= result;
end;


(*
 *  Round to an even number.
 *)
function    even(num: DWord): DWord;

begin
    even:= (num + 1) and not 1;
end;

(*
 *  Define the translation from segment:offset to a physical address
 *)
function    segOffToPhys(p: Pointer) : DWord;

var
    segOff:     SegOff_type absolute p;

begin
    segOffToPhys:= (DWord(segOff.segment) shl 4) + DWord(segOff.offset);
end;

(*
 *  segToPhys --    Translates a segment # to a physical address
 *)
function    segToPhys(s: Word) : DWord;

begin
    segToPhys:= DWord(s) shl 4;
end;

(*
 *  Min and max --  The obvious min and max functions
 *)
function    min(a: DWord; b: DWord): DWord;
begin
    if a < b then begin
        min:= a;
        end
    else begin
        min:= b;
        end;
end;

function    max(a: DWord; b: DWord): DWord;
begin
    if a > b then begin
        max:= a;
        end
    else begin
        max:= b;
        end;
end;

(*
 *  memset --   Sets a block of memory to a given value.
 *)
{$L MEMSET}
procedure memset(p: Pointer; val: Word; len: Word); external;

(*
 *  getBigMem --    Get's a large (> 64K) block of memory.
 *)
procedure getBigMem(var p: Pointer; len: DWord);

const
    blockSize=          16384;

var
    block:              array[0..39] of DWord;
    currBlock:          Integer;
    currArea:           Integer;

    tmpPtr:             Pointer;
    toBeAllocated:      DWord;

begin
    (*
     *  Keep allocating blocks till we've got what we need;
     *)
    currBlock:= 0;
    currArea:= 0;
    toBeAllocated:= len;
    repeat
        GetMem(tmpPtr, blockSize);
        block[currBlock]:= segOffToPhys(tmpPtr);

        (*
         *  See if block is consecutive with previous
         *)
        if (currBlock > 0) and
                (block[currBlock] <> (block[currBlock-1] + blockSize)) then begin
            currArea:= currBlock;
            toBeAllocated:= len;
            end;

        toBeAllocated:= toBeAllocated - blockSize;
        currBlock:= currBlock + 1;

    until toBeAllocated = 0;

    (*
     *  We've got a run of blocks of suffucient size. Release all of
     *  the blocks we allocated before the run. Then return the block.
     *)
    for currBlock:= 0 to currArea-1 do begin
        tmpPtr:= Ptr(block[currBlock] shr 4, block[currBlock] and $F);
        FreeMem(tmpPtr, blockSize);
        end;

    p:= Ptr(block[currArea] shr 4, block[currArea] and $F);

end;

(*
 *  freeBigMem --   Free a big block of memory.
 *)
procedure   freeBigMem(var p: Pointer; len: DWord);

const
    blockSize=          16384;

var
    currBlock:          Integer;
    toBeFreed:          DWord;
    tmpPtr:             Pointer;

begin
    (*
     *  Keep freeing blocks till we've freed everything
     *)
    toBeFreed:= (len + blockSize - 1) and (not (blockSize-1));
    while toBeFreed <> 0 do begin
        tmpPtr:= p;
        FreeMem(p, blockSize);

        (*
         *  Bump p to next block
         *)
        p:= Ptr(Seg(p^) + (blockSize shr 4), Ofs(p^));

        (*
         *  Decrement toBeFreed:
         *)
        toBeFreed:= toBeFreed - blockSize;
        end;
end;


end.

