[comp.lang.pascal] TSR and Interrupt programs in Turbo Pascal 4.0

lowey@sask.UUCP (Kevin Lowey) (02/17/88)

Hi,

  A while ago I asked if anyone knew the format for the Turbo Pascal .BGI
files.  I wanted this so I could implement a version of the Borland 
Graphics Interface for the DEC VAXmate computer.  I didn't find the .BGI
format, but I DID find a solution for my problem.

  The following programs are written in Turbo Pascal 4.0.  They demonstrate
the new facilities provided in Turbo 4.0 for Interrupt handlers and TSR
programs.  It shows how to create your own interrupt handler, how to move
an existing interrupt from one location to another, how to add your own
functions to an existing interrupt, and how to make the program Terminate
and Stay Resident.  Notice that there is NO assembler or inline code 
required.  Everything is done using just Turbo Pascal.  I know the programs 
would be better done in assembler, so no flames please about wasted memory, 
etc.  Its a demo of Turbo Pascal.

  The EMULATT program makes the DEC VAXmate computer 640x400x2 graphics
mode look like the AT&T 6300 (olivetti) graphics mode.  This allows programs
which support the AT&T 6300 to also support the VAXmate.  See the comments
below for more details.

  The EMATTSET program tells the loaded EMULATT program whether it should
report that it is in the DEC graphics mode (for compatibility with the 
DEC graphics.com) or it is in AT&T graphics mode (for compatibility with
programs which expect to see the AT&T as they run, like the AT&T 
graphics.com).  The DEC mode is the default.

  If there are enough requests for the executables, I'll post them.

  I've posted in this newsgroup rather than COMP.SYS.DEC.MICRO because I
thought the TSR example would be useful.

Kevin Lowey


=================  EMULATT.PAS =========================================

{$R-,S-,I-,D-,T-,F+,V-,B+,N-,L+ }
{$M 1024,0,0}

program EmulATT;
uses dos;
{ Copyright 1988 University of Saskatchewan Computing Services }
{ All rights reserved                                          }


{**************************************************************************}
{ Program Name : EMULATT                                                   }
{ VERSION:       1.00c (Completed)                                         }
{ DATE:          02 February 1988                                          }
{ Author:        Kevin Lowey                                               }
{                Department of Computing Services                          }
{                Room 56 Physics Building                                  }
{                University of Saskatchewan                                }
{                Saskatoon Saskatchewan                                    }
{                S7N 0W0                                                   }
{                                                                          }
{                LOWEY@SASK.BITNET                                         }
{                ...!ihnp4!sask!lowey.uucp                                 }
{                Phone: (306) 966-4826                                     }
{                                                                          }
{ Description:                                                             }
{                                                                          }
{ This program is a memory resident (TSR) utility which makes the VAXmate  }
{ 640x400x2 graphics mode emulate the AT&T 640x400x2 graphics mode.  The   }
{ only difference between the AT&T and VAXmate is that the mode number used}
{ by the SET MODE function (Interrupt $10 function $00) and the REPORT MODE}
{ function (Interrupt $10 function $F0) is $D0 in the VAXmate and $40 in   }
{ the AT&T 6300 (Olivetti). The memory map, etc. are all identical.        }
{                                                                          }
{ This emulation allows software which supports the AT&T computer to use   }
{ the high resolution 640x400x2 mode on the VAXmate, even if the VAXmate   }
{ is not supported by the software.  Simply tell the software it is using  }
{ an AT&T graphics display.                                                }
{                                                                          }
{ This program finds an empty interrupt vector, and moves interrupt $10    }
{ into this unused vector.  It then places its own procedure (INT10HANDLER)}
{ into interrupt $10.  INT10HANDLER passes all $10 interrupt calls to the  }
{ "real" interrupt $10.  If function $00 or $F0 is called, INT10HANDLER    }
{ substitutes the VAXmate $D0 graphics mode for the AT&T $40 mode number.  }
{                                                                          }
{ This can cause problems if software expecting to see the AT&T mode number}
{ (like the AT&T graphics.com program) receives the VAXmate mode number.   }
{ Thus I also implemented the following extra functions for interrupt $10  }
{                                                                          }
{  Registers                          Description                          }
{  AX = $FF00      Signature function.  Returns $FF42 if EMULATT is loaded }
{  AX = $FF01      Makes function $F0 return the AT&T $40 mode, not $D0    }
{  AX = $FF02      Makes function $F0 return the VAXmate $D0, not $40      }
{                  This is the default setting                             }
{  AX = $FF03      Returns AX=$FF40 if ATTMODE set, AX=$FFD0 if not set    }
{                                                                          }
{ The companion program EMATTSET uses the above interrupts to change how   }
{ EMULATT behaves.                                                         }
{**************************************************************************}

var
    int10save : pointer;        {Saves a pointer to the old INT10 routine}
    regs      : registers;      {registers for INTR function}
    oldah     : byte;           {Stores AH so appropriate actions can be }
                                {taken after calling INT10               }

CONST
    newintr   : byte = $59;      {Starting interrupt to install in          }
    ATTmode   : boolean = FALSE; {True if function $0F returns AT&T mode $40}
                                 {False if function $0F returns DEC mode $D0}
    VERSION   = '1.00c';
    VERSDate  = '02 Feb. 1988';

procedure INT10HANDLER (FLAGS,CS,IP,AX,BX,CX,DX,SI,DI,DS,ES,BP:word);
interrupt;

begin {INT10HANDLER}
  { Process My extensions to the interrupt, function $FFxx }

  { Return signature }
  if AX = $FF00  then
    ax := $FF42 {Why 42? read Hitchiker's Guide to the Galaxy :-)}

  {Make function $0F (what mode are you in) say AT&T if applicable}
  else if AX = $FF01 then begin
    ATTMODE := TRUE;
    AX := $FFFF
  end

  {Make function $0F (what mode are you in) say VAXmate if applicable}
  else if AX = $FF02 then begin
    ATTMODE := false;
    AX := $FFFF;
  end

  else if AX = $FF03 then begin  {return current setting of ATTMODE}
    IF ATTMODE then
      AX := $FF40  {AT&T mode}
    else
      AX := $FFD0  {VAXmate mode}
  end

  { Call normal interrupt $10 routines }
  else begin

    {trap AT&T enter hires mode $40 interrupt and change to DEC's $D0}
    if ax = $0040 then begin {AT&T 640x400x2}
      regs.ax := $00D0 {Vaxmate AT&T compatible mode}
    end
    else {Don't do anything special}
      regs.aX := AX;

    {save the old function number so we can check for modification}
    {of returned parameters later}
    oldah := regs.ah;

    {Put the parameters into the registers}
    regs.bx := BX;
    regs.cx := CX;
    regs.dx := DX;
    regs.es := es;
    regs.bp := bp;

    {Call the interrupt}
    intr (newintr,regs);

    { If the function is $0F (what mode are you in), and we are in the DEC }
    { 640x200x2 mode, and the ATTMODE switch is set, then return $40, the  }
    { equivalent AT&T mode.  This is so programs which ask what mode you   }
    { are in, like GRAPHICS.COM, will operate properly.  The default is to }
    { return the DEC mode, so that DEC's GRAPHICS.COM program will work.   }

    if (ATTMODE) and (oldah = $0F) and (regs.al = $D0) then {Return AT&T}
      regs.al := $40;  {AT&T equivalent mode }

    {Move the register results back to the parameters}
    ax := regs.ax;
    bx := regs.bx;
    cx := regs.cx;
    dx := regs.dx;
  end; {else call old interrupt }
end; {INT10HANDLER}

begin {EMULATT}
  Writeln ('AT&T Graphic emulator for the Vaxmate');
  Writeln ('Version ',version,', ',versdate);
  writeln ('Copyright 1988 University of Saskatchewan');
  { Check to see if already installed }
  regs.ax := $FF00;
  intr($10,regs);
  if regs.ax = $FF42 then begin {Signature found}
    writeln ('EMULATT already installed, Aborting');
    halt(1);
  end
  else begin {install}
    {find a free interrupt}
    newintr := $5F; {first application available interrupt}
    repeat
      newintr := succ(newintr);
      getintvec(newintr,int10save);
    until byte(int10save^) = $CF; {interrupt return}

    getintvec ($10,int10save);
    setintvec (newintr,int10save);
    setintvec ($10,@int10handler);
    keep (0);
  end; {install}
end. {EmulATT}


=======================  EMATTSET.PAS ==================================
{$R-,S-,I-,D-,T-,F+,V-,B+,N-,L+ }
{$M 1024,0,0 }
program EmulATT;
uses dos;

var
    regs      : registers;      {registers for INTR function}
CONST
   Version = '1.00c'; 
   VERDATE = '02 February 1988';

begin {EMATTSET}
  Writeln ('EMATTSET: Version ',version,',  ',verdate);
  Writeln ('AT&T Graphics card Emulator for the DEC VAXmate computer');
  writeln ('       Copyright 1988 University of Saskatchewan');
  writeln;
  writeln ('         Written by Kevin Lowey');
  writeln ('         Department of Computing Services');
  writeln ('         Room 56 Physics Building');
  writeln ('         University of Saskatchewan');
  writeln ('         Saskatoon, Saskatchewan Canada S7N 0W0');
  writeln;
  writeln ('         LOWEY@SASK.BITNET');
  writeln ('         ...!ihnp4!sask!lowey.uucp');
  writeln ('         (306) 966-4826 SASK-TEL');
  writeln;

  { Check to see if already installed }
  regs.ax := $FF00;
  intr($10,regs);
  if NOT (regs.ax = $FF42) then begin {Signature found}
    writeln ('The program EMULATT is not currently installed');
    writeln ('Run EMULATT to make your VAXmate computer emulate');
    writeln ('the AT&T 6300 640x400x2 graphics mode along with the');
    writeln ('DEC VAXmate 640x400x2 graphics mode.');
    writeln ('Program aborting . . .');
    halt(1);
  end
  else begin {install}
    if paramstr(1) = '+' then begin
      regs.ax := $FF01;
      intr($10,regs);
      if regs.ax = $FFFF then begin
        writeln ('The AT&T emulator will now report to calling programs');
        writeln ('that it is using an AT&T graphics card, and NOT the');
        writeln ('VAXmate graphics card.  This is not the default setting.');
      end
      else begin
        writeln ('An error occured.  The AT&T graphics emulator will');
        writeln ('continue to report the current settings');
      end;
    end
    else if paramstr(1) = '-' then begin
      regs.ax := $FF02;
      intr($10,regs);
      if regs.ax = $FFFF then begin
        writeln ('The AT&T emulator will now report to calling programs');
        writeln ('that it is using the VAXmate graphics card, and NOT the');
        writeln ('AT&T graphics card.  This is the default setting.');
      end
      else begin
        writeln ('An error occured.  The AT&T graphics emulator will');
        writeln ('continue to report the current settings');
      end;
    end
    else begin {Unrecognised Parameter}
      writeln ('USAGE:  EMATTSET {+,-}');
      writeln (
        '  "EMATTSET +" makes EMULATT report that it is using an AT&T');
      writeln (
        '               graphics card for compatibility with AT&T software.');
      writeln;
      writeln (
        '  "EMATTSET -" makes EMULATT report that it is using a VAXmate');
      writeln (
        '               graphics card for compatibility with DEC software.');
      writeln;
      regs.ax := $FF03;
      intr($10,regs);
      if regs.AX = $FF40 then
        writeln ('EMULATT is currently set to "+"')
      else
        writeln ('EMULATT is currently set to "-"');
    end; {usage}
  end; {install}
end. {EMATTSET}