[Back to SAVESCRN SWAG index]  [Back to Main SWAG index]  [Original]

{
:   Is there a way to save the current text screen so you can call it
: up later? (ie: Either save the screen so you can display something else
: in text, then bring back the first page, or to display graphics, then
: bring back the old text screen.)  Also, is there a way to dumb the screen
: to disk?

Here's the stuff i use... (It works from TP 4.0 and up)
}

Type
    ScreenRecord =
      Record
        X, Y: Byte; {x,y coord. of cursor}
        Screen: Pointer
      End;

  Var
    OriginalScreen: ScreenRecord;


Function QueryAdapterType: AdapterType;

  Var
    Code: Byte;
    Regs: Registers;

  Begin
    Regs.AH := $1A; { Attempt to call VGA Identify Adapter Function }
    Regs.AL := $00; { Must clear AL to 0 ... }
    Intr($10, Regs);
    If Regs.AL = $1A then { ...so that If $1A comes back in AL... }
      Begin { ...we know a PS/2 video BIOS is out there. }
      Case Regs.BL of { Code comes back in BL }
        $00:
          QueryAdapterType := None;
        $01:
          QueryAdapterType := MDA;
        $02:
          QueryAdapterType := CGA;
        $04:
          QueryAdapterType := EGAColor;
        $05:
          QueryAdapterType := EGAMono;
        $07:
          QueryAdapterType := VGAMono;
        $08:
          QueryAdapterType := VGAColor;
        $0A, $0C:
          QueryAdapterType := MCGAColor;
        $0B:
          QueryAdapterType := MCGAMono
        else
          QueryAdapterType := CGA
        End { Case }
      End
    else
    { Next we have to check for the presence of an EGA BIOS: }
      Begin
      Regs.AH := $12; { Select Alternate Function service }
      Regs.BX := $10; { BL=$10 means return EGA information }
      Intr($10, Regs); { Call BIOS VIDEO }
      If Regs.BX <> $10 then { BX unchanged means EGA is NOT there...}
        Begin
        Regs.AH := $12; { Once we know Alt Function exists... }
        Regs.BL := $10; { ...we call it again to see If it's... }
        Intr($10, Regs); { ...EGA color or EGA monochrome. }
        If Regs.BH = 0 then
          QueryAdapterType := EGAColor
        else
          QueryAdapterType := EGAMono
        End
      else { Now we know we have an EGA or MDA: }
        Begin
        Intr($11, Regs); { Equipment determination service }
        Code := (Regs.AL and $30) Shr 4;
        Case Code of
          1:
            QueryAdapterType := CGA;
          2:
            QueryAdapterType := CGA;
          3:
            QueryAdapterType := MDA
          else
            QueryAdapterType := CGA
          End { Case }
        End
      End
  End;


Function DeterminePoints: Integer;

  Var
    Regs: Registers;

  Begin
    Case QueryAdapterType of
      CGA:
        DeterminePoints := 8;
      MDA:
        DeterminePoints := 14;
      EGAMono, { These adapters may be using any of }
      EGAColor, { several different font cell heights, }
      VGAMono, { so we need to query the BIOS to find }
      VGAColor, { out which is currently in use. }
      MCGAMono, MCGAColor:
        Begin
        With Regs do
          Begin
          AH := $11; { EGA/VGA Information Call }
          AL := $30;
          BL := 0
          End;

        Intr($10, Regs);
        DeterminePoints := Regs.CX
        End
      End { Case }
  End;


Procedure SaveScreen(Var StashPtr: Pointer);

  Type
    VidPtr = ^VidSaver;
    VidSaver =
      Record
        Base, Size: Word;
        BufStart: Byte
      End;

  Var
    VidVector: VidPtr;
    StashBuf: VidSaver;
    VidBuffer: Pointer;
    Adapter: AdapterType;

  Begin
    Adapter := QueryAdapterType;
    With StashBuf do
      Begin
      Case Adapter of
        MDA, EGAMono, VGAMono, MCGAMono:
          Base := $B000
        else
          Base := $B800
        End; { Case }
      Case DeterminePoints of
        8:
          Case Adapter of
            CGA:
              Size := 4000; { 25-line screen }
            EGAMono, EGAColor:
              Size := 6880 { 43-line screen }
            else
              Size := 8000 { 50-line screen }
            End; { Case }
        14:
          Case Adapter of
            EGAMono, EGAColor:
              Size := 4000; { 25-line screen }
            else
              Size := 4320 { 27-line screen }
            End; { Case }
        16:
          Size := 4000
        End; { Case }
      VidBuffer := Ptr(Base, 0)
      End;

    { Allocate heap for whole shebang }
    GetMem(StashPtr, StashBuf.Size + 16);
    { Here we move *ONLY* the VidSaver Record (5 bytes) to the heap: }
    Move(StashBuf, StashPtr^, Sizeof(StashBuf));
    { This casts StashPtr, a generic pointer, to a pointer to a VidSaver: }
    VidVector := StashPtr;
      { Now we move the video buffer itself to the heap.  The vide data is
        written starting at the BufStart byte in the VidSaver Record, and
        goes on for Size bytes to fit the whole buffer.  Messy but hey,
        this is PC land! }
    Move(VidBuffer^, VidVector^.BufStart, StashBuf.Size);
  End;


Procedure RestoreScreen(StashPtr: Pointer);

  Type
    VidPtr = ^VidSaver;
    VidSaver =
      Record
        Base, Size: Word;
        BufStart: Byte
      End;

  Var
    DataSize: Word;
    VidVector: VidPtr;
    VidBuffer: Pointer;

  Begin
    VidVector := StashPtr; { Cast generic pointer onto VidSaver pointer }
    DataSize := VidVector^.Size;
    { Create a pointer to the base of the video buffer: }
    VidBuffer := Ptr(VidVector^.Base, 0);
    { Move the buffer portion of the data on the heap to the video buffer: }
    Move(VidVector^.BufStart, VidBuffer^, VidVector^.Size);
    FreeMem(StashPtr, DataSize + 16)
  End;
(*

Here's how you save a screen...

      With OriginalScreen do
        Begin
        X := WhereX; {save the x,y cursor positions...}
        Y := WhereY - 1;
        SaveScreen(Screen) {then the screen}
        End;

Here's how you restore a screen...

    With OriginalScreen do
      Begin
      RestoreScreen(Screen); {restore the screen}
      GotoXY(X, Y) {go back to the orig. cursor position}
      End;

:   While we're at it, I might as well get all my questions out of my
: system :)  First, is there a way to stop the program from crashing if
: someone enters a character instead of an integer (or any incompatible
: data types?)  I've been looking around but havn't found anything...

The best way is to read the number in as a string (characters), then use
the procedure Val(), to convert it from a character string to numeric.

: And lastly, how do you stop the program from crashing if a user enters
: a filename to load, and it doesn't exist?  I think this has something
: to do with the doserror (is that the function name?  Don't recall offhand)
: but I couldn't get it to work.

Check to see if the file exists, before you open it (Reset)...  Here's a
quick function..

Function Exists(FileName: String): Boolean;

  Begin
    Exists := FSearch(FileName, '') <> ''
  End;
*)

[Back to SAVESCRN SWAG index]  [Back to Main SWAG index]  [Original]