[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]

{
-----------------------------------------------------------------------------
Program BMPView;  { by Barry Naujok, 1993, written in TP7 }
        { This information was completely derived on my own (ALL of it). }
        { If there are any errors or omisions, please let me know at ... }
        {          a1357665@cfs01.cc.monash.edu.au                       }
        { Currently only supports 3-256 colours (not monochrome or true colour) }
        { My opinion: As can be seen from decoding a BitMaP, I truly believe }
        {    that Microsoft is a bit backwards! :) (other opinions welcome) }

Uses VESA,Crt,Dos,Strings;

Const bufsize=32000; { my optimal buffer size, could be bigger for other drives }
                     { Has to be even for the RLE decompression }
Type THeader=Record
       ID    : Word;     { 'BM' for a Windows BitMaP }
       FSize : LongInt;  { Size of file }
       Ver   : LongInt;  { BMP version (?), currently 0 }
       Image : LongInt;  { Offset of image into file }
       Misc  : LongInt;  { Unknown, appears to be 40 for all files }
       Width : LongInt;  { Width of image }
       Height: LongInt;  { Height of image }
       Num   : Word;     { Not sure, possibly number of images or planes (1) }
       Bits  : Word;     { Number of bits per pixel }
       Comp  : LongInt;  { Type of compression, 0 for uncompressed, 1,2 for RLE }
       ISize : LongInt;  { Size of image in bytes }
       XRes  : LongInt;  { X dots per metre (not inches! for US, unbelievable!) }
       YRes  : LongInt;  { Y dots per metre }
       PSize : LongInt;  { Palette size (number of colours) if not zero }
       Res   : LongInt;  { Probably reserved, currently 0 }
     End;  { 54 bytes }

     PByte = ^Byte;

     TPalette = Record
       b,g,r,x : Byte;   { BMP uses a fourth byte for the palette, not used }
     End;

Var  fl     : File;
     header : THeader;
     buffer : PByte;

Procedure BlankPalette;
Var pal : Array[0..767] Of Byte;
    r   : Registers;
Begin
  FillChar(pal,768,0);
  r.ax:=$1012;
  r.bx:=0;
  r.cx:=256;
  r.dx:=Ofs(pal);
  r.es:=Seg(pal);
  Intr($10,r);
End;

Procedure SetPalette;
Const Pal16:Array[0..15]Of Byte=(0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63);
Var palette : TPalette;  { ^ Actual BIOS palette numbers for 16 colour modes }
    BIOSpal : Array[0..767] Of Byte;
    i       : Byte;
    r       : Registers;
Begin
  For i:=0 To header.PSize-1 Do Begin
    BlockRead(fl,palette,4);
    If header.PSize>16 Then Begin
      BIOSpal[i*3]:=palette.r Shr 2;
      BIOSpal[i*3+1]:=palette.g Shr 2;
      BIOSpal[i*3+2]:=palette.b Shr 2;
    End Else Begin
      BIOSpal[Pal16[i]*3]:=palette.r Shr 2;
      BIOSpal[Pal16[i]*3+1]:=palette.g Shr 2;
      BIOSpal[Pal16[i]*3+2]:=palette.b Shr 2;
    End;
  End;
  r.ax:=$1012;
  r.bx:=0;
  r.cx:=256;
  r.dx:=Ofs(BIOSpal);
  r.es:=Seg(BIOSpal);
  Intr($10,r);
End;

Procedure ShowImage256(name:PChar); Assembler;
Var dseg,width,height,bytes,rows,bank,handle,cp:Word;
Asm
        Mov     dseg,ds
        Mov     ax,header.Comp.Word[0]
        Mov     cp,ax
        Mov     ax,header.Width.Word[0]
        Test    ax,1
        Jz      @0I
        Inc     ax  { image is word aligned so adjust width if needed }
  @0I:  Mov     width,ax
        Mov     ax,header.Height.Word[0]
        Mov     height,ax
        Mov     di,ax
        Dec     di
        Mov     ax,VesaMode.Bytes
        Mov     bytes,ax
        Mov     ax,VesaMode.Height
        Mov     rows,ax
        Mov     es,VesaMode.SegA

        Mov     ax,$3D00
        Lds     dx,name
        Int     $21                     { Open the file for assembler }
        Mov     ds,dseg                 { Restore the data segment }
        Jc      @Ex
        Mov     handle,ax

        Mov     bx,ax
        Mov     ax,$4200
        Mov     cx,header.Image.Word[2]
        Mov     dx,header.Image.Word[0]
        Int     $21                     { Seek to image location }
        Call    @FR
        Jmp     @0N

  @FR:  Push    ax
        Push    cx
        Push    dx
        Mov     ds,dseg
        Mov     bx,handle
        Mov     cx,bufsize
        Lds     si,buffer
        Mov     dx,si
        Mov     ah,$3F
        Int     $21
        Mov     bx,ax                   { Bytes left to read from the buffer }
        Pop     dx
        Pop     cx
        Pop     ax
        RetN

  @0N:  Mov     ax,bytes
        Mul     di
        Mov     di,ax
        Mov     bank,dx
        Call    @B1                     { Set the last line & bank }
        Mov     dx,width

        Cmp     cp,0
        Je      @0S

        { RLE bitmap }
  @1S:  Xor     dx,dx                   { Set DX as the width count }
  @10:  Xor     ah,ah                   { Clear upper byte }
        Lodsb                           { Get "index" byte }
        Dec     bx                      { Decrement buffer count }
        Jnz     @11                     { Jump if not empty }
        Call    @FR                     { Reload buffer }
  @11:  Or      al,al
        Jz      @14                     { Jump if following is a string }
        { Repeat byte }
        Mov     cx,ax                   { else "index" is a repeat count }
        Add     dx,cx
        Lodsb                           { Load data to repeat "index" times }
        Dec     bx
        Jnz     @12                     { Jump if buffer isn't empty }
        Call    @FR
  @12:  Stosb                           { Draw byte to screen }
        Or      di,di                   { Check to see if line crosses bank }
        Jnz     @13
        Inc     bank                    { Change bank if crossed }
        Call    @B1
  @13:  Loop    @12                     { Store all repeated bytes }
        Jmp     @10
        { Dump string }
  @14:  Lodsb                           { Load "count", number of bytes in the string }
        Mov     cx,ax
        Add     dx,cx
        Dec     bx
        Jnz     @1T                     { Update buffer count (& buffer contents) }
        Call    @FR
  @1T:  Or      al,al
        Jz      @20
  @15:  Movsb                           { Transfer string to screen }
        Or      di,di
        Jnz     @16                     { bank checking }
        Inc     bank
        Call    @B1
  @16:  Dec     bx                      { Update buffer count, etc }
        Jnz     @17
        Call    @FR
  @17:  Loop    @15                     { Repeat for string }
        Test    al,1                    { See if there was an odd numbered count }
        Jz      @10                     { Jump if even }
        Lodsb                           { Clear extra byte, due to word alignment }
        Dec     bx
        Jnz     @10                     { Update buffer count, etc }
        Call    @FR
        Jmp     @10
  @20:  Sub     di,dx                   { Move screen pointer to start of line }
        Jnc     @21                     { Jump if not crossed bank }
        Dec     bank                    { Update bank if crossed }
        Call    @B1
  @21:  Sub     di,bytes                { Move to screen line above }
        Jnc     @23                     { Jump if not crossed bank }
        Dec     bank                    { Update bank if crossed }
        Call    @B1
  @23:  Dec     height                  { Update line count }
        Jnz     @1S                     { Jump to start if not end of the image }
        Jmp     @Ex                     { Exit if image drawn }

        { Un-compressed bitmap }
  @0S:  Mov     cx,dx
        Mov     ax,di
        Add     ax,cx
        Jc      @03                     { Jump if line crosses bank }
        Cmp     bx,cx
        Jle     @03                     { Jump if file buffer will run out }
        Sub     bx,cx                   { Update buffer counter }
        Shr     cx,1
        Jnc     @01
        Movsb
  @01:  Rep     Movsw                   { Show line }
        Sub     di,dx                   { Go to next line (above) }
        Sub     di,bytes
        Jnc     @02
        Dec     bank                    { See if line above is in another bank }
        Call    @B1
  @02:  Dec     height
        Jnz     @0S
        Jmp     @Ex
  @03:  Movsb
        Or      di,di
        Jnz     @04
        Inc     bank
        Call    @B1
  @04:  Dec     bx
        Jnz     @05
        Call    @FR
  @05:  Loop    @03
        Sub     di,dx
        Jnc     @06
        Dec     bank
        Call    @B1
  @06:  Sub     di,bytes
        Jnc     @07
        Dec     bank
        Call    @B1
  @07:  Dec     height
        Jnz     @0S
        Jmp     @Ex


        { Set bank }
  @B1:  Push    ax
        Push    ds
        Mov     ds,dseg
        Mov     al,vesaon
        Or      al,al
        Jz      @B3
        Push    bx
        Push    dx
        Mov     dx,bank
        Xor     bx,bx
        Mov     ax,64
        Mul     dx
        Div     VesaMode.Gran
        Mov     dx,ax
        Push    dx
        Call    VesaMode.WinFunc
        Pop     dx
        Inc     bx
        Call    VesaMode.WinFunc
        Pop     dx
        Pop     bx
  @B3:  Pop     ds
        Pop     ax
        RetN
  @Ex:  Mov     ds,dseg
        Mov     bx,handle              { Close the file }
        Mov     ah,$3E
        Int     $21
End;

Procedure ShowImage16(name:PChar); Assembler;
Var dseg,width,height,bytes,rows,bank,handle,cp,rc,bc:Word;
Asm
        Mov     dseg,ds
        Mov     ax,header.Comp.Word[0]
        Mov     cp,ax
        Mov     ax,header.Width.Word[0]
        Mov     width,ax
        Mov     ax,header.Height.Word[0]
        Mov     height,ax
        Mov     di,ax
        Dec     di
        Mov     ax,VesaMode.Bytes
        Mov     bytes,ax
        Mov     ax,VesaMode.Height
        Mov     rows,ax
        Mov     es,VesaMode.SegA

        Mov     ax,$3D00
        Lds     dx,name
        Int     $21                     { Open the file for assembler }
        Mov     ds,dseg                 { Restore the data segment }
        Jc      @Ex
        Mov     handle,ax

        Mov     bx,ax
        Mov     ax,$4200
        Mov     cx,header.Image.Word[2]
        Mov     dx,header.Image.Word[0]
        Int     $21                     { Seek to image location }
        Call    @FR
        Jmp     @0N

  @FR:  Push    ax
        Push    bx
        Push    cx
        Push    dx
        Mov     ds,dseg
        Mov     bx,handle
        Mov     cx,bufsize
        Lds     si,buffer
        Mov     dx,si
        Mov     ah,$3F
        Int     $21
        Mov     bc,ax                   { Bytes left to read from the buffer }
        Pop     dx
        Pop     cx
        Pop     bx
        Pop     ax
        RetN

  @0N:  Mov     ax,bytes
        Mul     di
        Mov     di,ax
        Mov     bank,dx
        Call    @B1                     { Set the last line & bank }
        Mov     dx,$3CE
        Mov     ax,$205
        Out     dx,ax                   { Set Write Mode 2 }
        Mov     ax,$8008                { Initial bit mask }

        Cmp     cp,0
        Je      @0S

        { RLE bitmap }
  @1S:  Mov     rc,0
        Mov     ax,$8008
  @10:  Xor     ch,ch                   { Clear upper byte }
        Mov     cl,[si]                 { Get "index" byte }
        Inc     si
        Dec     bc                      { Decrement buffer count }
        Jnz     @11                     { Jump if not empty }
        Call    @FR                     { Reload buffer }
  @11:  Or      cl,cl
        Jz      @14                     { Jump if following is a string }
        { Repeat byte }
        Shr     cl,1                    {   Divide the "index" by two }
        Mov     bl,[si]                 { Load data to repeat "index" times }
        Inc     si
        Dec     bc
        Jnz     @12                     { Jump if buffer isn't empty }
        Call    @FR
  @12:  Rol     bl,4
        Out     dx,ax
        Mov     bh,es:[di]
        Mov     es:[di],bl              { Update screen }
        Ror     ah,1
        Jnc     @1B
        Inc     di
        Jnc     @1B
        Inc     bank                    { Change bank if crossed }
        Call    @B1
  @1B:  Out     dx,ax
        Rol     bl,4
        Mov     bh,es:[di]
        Mov     es:[di],bl
        Ror     ah,1
        Jnc     @13
        Inc     di
        Inc     rc
        Jnc     @13
        Inc     bank                    { Change bank if crossed }
        Call    @B1
  @13:  Loop    @12                     { Store all repeated bytes }
        Jmp     @10
        { Dump string }
  @14:  Mov     cl,[si]                 { Load "count", number of bytes in the string }
        Inc     si
        Dec     bc
        Jnz     @1E                     { Update buffer count (& buffer contents) }
        Call    @FR
  @1E:  Or      cl,cl
        Jz      @20
        Shr     cl,1                    { Divide the "count" by 2 }
        Push    cx
  @15:  Mov     bl,[si]
        Inc     si
        Rol     bl,4
        Out     dx,ax
        Mov     bh,es:[di]
        Mov     es:[di],bl
        Ror     ah,1
        Jnc     @1A
        Inc     di
        Jnz     @1A                     { bank checking }
        Inc     bank
        Call    @B1
  @1A:  Out     dx,ax
        Rol     bl,4
        Mov     bh,es:[di]
        Mov     es:[di],bl
        Ror     ah,1
        Jnc     @16
        Inc     di
        Inc     rc
        Jnz     @16
        Inc     bank
        Call    @B1
  @16:  Dec     bc                      { Update buffer count, etc }
        Jnz     @17
        Call    @FR
  @17:  Loop    @15                     { Repeat for string }
        Pop     cx
        Test    cl,1                    { See if there was an odd numbered count }
        Jz      @10                     { Jump if even }
        Mov     cl,[si]                 { Clear extra byte, due to word alignment }
        Inc     si
        Dec     bc
        Jnz     @10                     { Update buffer count, etc }
        Call    @FR
        Jmp     @10
  @20:  Sub     di,rc                   { Move screen pointer to start of line }
        Jnc     @21                     { Jump if not crossed bank }
        Dec     bank                    { Update bank if crossed }
        Call    @B1
  @21:  Sub     di,bytes                { Move to screen line above }
        Jnc     @22                     { Jump if not crossed bank }
        Dec     bank                    { Update bank if crossed }
        Call    @B1
  @22:  Dec     height                  { Update line count }
        Jnz     @1S                     { Jump to start if not end of the image }
        Jmp     @Ex                     { Exit if image drawn }

        { Un-compressed bitmap }
  @0S:  Mov     ax,width
        Xor     bx,bx
        Mov     rc,ax                   { Initialize rowcount }
        Mov     ax,$8008
  @02:  Out     dx,ax                   { Update bit mask register }
        Mov     cl,[si]                 { Load a byte (2 pixels) }
        Inc     si                      { Update buffer pointer }
        Dec     bc                      { Updata buffer count }
        Jnz     @03
        Call    @FR                     { Reload buffer if necessary }
  @03:  Ror     cl,4                    { Move 1st pixel in low part of CL }
        Mov     ch,es:[di]              { Load latches }
        Mov     es:[di],cl              { Update latches }
        Ror     ah,1                    { Shift bit mask right a pixel }
        Out     dx,ax                   { Update bit mask register }
        Ror     cl,4                    { Move 2nd pixel in low part of CL }
        Mov     ch,es:[di]              { as above 3 steps }
        Mov     es:[di],cl              { ... }
        Sub     rc,2
        Jle     @04
        Ror     ah,1
        Jnc     @02
        Inc     di
        Inc     bx
        Jnc     @02
        Inc     bank
        Call    @B1
        Jmp     @02
  @04:  Mov     ax,si                   { Discard extra bytes for }
        Mov     cx,4                    { LongInt alignment (?) }
        And     ax,3
        Sub     cx,ax
        And     cx,3
        Add     si,cx
        Sub     bc,cx
        Sub     di,bx
        Jnc     @06
        Dec     bank
        Call    @b1
  @06:  Sub     di,bytes
        Jnc     @07
        Dec     bank
        Call    @b1
  @07:  Dec     height
        Jnz     @0S
        Jmp     @Ex

        { Set bank }
  @B1:  Push    ax
        Push    ds
        Mov     ds,dseg
        Mov     al,vesaon
        Or      al,al
        Jz      @B3
        Push    bx
        Push    dx
        Mov     dx,bank
        Xor     bx,bx
        Mov     ax,64
        Mul     dx
        Div     VesaMode.Gran
        Mov     dx,ax
        Push    dx
        Call    VesaMode.WinFunc
        Pop     dx
        Inc     bx
        Call    VesaMode.WinFunc
        Pop     dx
        Pop     bx
  @B3:  Pop     ds
        Pop     ax
        RetN
  @Ex:  Mov     ds,dseg
        Mov     bx,handle              { Close the file }
        Mov     ah,$3E
        Int     $21
End;
Procedure ShowBMP;
Var fn:Array[0..63]Of Char;
Begin
  StrPCopy(fn,ParamStr(1));
  GetMem(buffer,bufsize);
  Case header.PSize Of
    1..16: Begin
         Case header.Width Of
              0..640  : SetMode($12);
            641..800  : SetMode($102);
            801..1024 : SetMode($104);
           1025..9999 : SetMode($106);
         End;
         BlankPalette;
         ShowImage16(fn);
       End;
    17..256: Begin
         Case header.Width Of
              0..320  : SetMode($13);
            321..640  : SetMode($101);
            641..800  : SetMode($103);
            801..1024 : SetMode($105);
           1025..9999 : SetMode($107);
         End;
         BlankPalette;
         ShowImage256(fn);
       End;
  End;

  FreeMem(buffer,bufsize);
  SetPalette;
  Sound(660);
  Delay(100);
  Sound(880);
  Delay(50);
  Sound(440);
  Delay(75);
  NoSound;

  ReadKey;
  SetMode(3);
End;

Procedure SetPSize;
Begin
  If header.PSize=0 Then Case header.Bits Of
    1 : header.PSize:=2;  { These are the only valid bits in a BMP }
    4 : header.PSize:=16;
    8 : header.PSize:=256;
    24: header.PSize:=0;  { A 24 bit image does not have a palette }
  End;
End;

Begin
  If ParamCount>0 Then Begin
    Assign(fl,ParamStr(1));
    {$I-}
    Reset(fl,1);
    {$I+}
    If IOResult=0 Then Begin
      BlockRead(fl,header,54);
      If header.ID=$4D42 Then Begin
        SetPSize; { Set the PSize field in the header if not defined }
        Writeln;
        Writeln('Width  . . . . . ',header.Width,' pixels');
        Writeln('Height . . . . . ',header.Height,' pixels');
        Writeln('Bits per Pixel . ',header.Bits);
        Writeln('Palette Size . . ',header.PSize,' colours, ',header.PSize*4,' bytes');
        Write('Compression  . . type ',header.Comp);
        If header.Comp=0 Then Writeln(' (not compressed)')
          Else Writeln(' (RLE)');
        Writeln('Image Offset . . ',header.Image);
        Writeln('Image Size . . . ',header.ISize,' bytes');
        Writeln('X Resolution . . ',header.XRes,' D/m, ',header.XRes*254 Div 10000,' DPI');
        Writeln('Y Resolution . . ',header.YRes,' D/m, ',header.YRes*254 Div 10000,' DPI');
        Writeln;
        If ((header.Width<641)And(header.Height<481)And(header.PSize<17))
           Or((header.Width<321)And(header.Height<201))Or(IsVesa) Then
        If header.PSize>2 Then Begin
          Writeln('Press a key to show the image');
          ReadKey;
          ShowBMP;
        End Else Writeln('Cannot display the image without VESA graphics support');
        Close(fl);
      End Else Writeln('The file is not a Windows BitMaP file');
    End Else Writeln('File not found, try again');
  End Else Writeln('Usage: BMPVIEW <filename>');
End.
-----------------------------------------------------------------------------
Unit VESA;

Interface

Type ModeList=Array[1..32] Of Word;  { List of VESA mode numbers }

     TVesaMode=Record
       Attr     : Word;         { Mode Attributes                   }
       WinA     : Byte;         { Window A attributes               }
       WinB     : Byte;         { Window B attributes               }
       Gran     : Word;         { Window granularity in K bytes     }
       WinSiz   : Word;         { Size of window in K bytes         }
       SegA     : Word;         { Segment address of window A       }
       SegB     : Word;         { Segment address of window B       }
       WinFunc  : Procedure;    { Windows positioning function      }
       Bytes    : Word;         { Number of bytes per line          }
       Width    : Word;         { Number of horizontal pixels       }
       Height   : Word;         { Number of vertical pixels         }
       CharW    : Byte;         { Width of character cell           }
       CharH    : Byte;         { Height of character cell          }
       Planes   : Byte;         { Number of memory planes           }
       Bits     : Byte;         { Number of bits per pixel          }
       nBanks   : Byte;         { Number of banks        (not used) }
       Model    : Byte;         { Memory model type                 }
       Banks    : Byte;         { Size of bank           (not used) }
       Pages    : Byte;         { Number of image pages             }
       Reserved : Byte; { The following are for 15,16,24,32 bit colour modes }
       RedMaskSize   : Byte;    { Size of Red mask in bits          }
       RedFieldPos   : Byte;    { Bit position of LSB of Red mask   }
       GreenMaskSize : Byte;    { Size of Green mask in bits        }
       GreenFieldPos : Byte;    { Bit position of LSB of Green mask }
       BlueMaskSize  : Byte;    { Size of Blue mask in bits         }
       BlueFieldPos  : Byte;    { Bit position of LSB of Blue mask  }
       RsvdMaskSize  : Byte;    { Size of Reserved mask in bits     }
       RsvdFieldPos  : Byte;    { Bit pos. of LSB of Reserved mask  }
       DirColModeInf : Byte;    { Direct Colour mode attributes     }
       Filler   : Array[0..215] Of Byte; { Not used - filler        }
     End;

     TVesaInfo=Record
       Signature    : LongInt;   { Signature - "VESA"               }
       Version      : Word;      { VESA Version number              }
       OEMName      : PChar;     { Pointer to manufacturer name     }
       Capabilities : Longint;   { Capabilities       (Not used)    }
       List         : ^ModeList; { Pointer to list of VESA modes    }
       TotalMemory  : Word;      { Number of 64k memory blocks on card }
       Filler       : Array[1..238] of Byte;
     End; { 258 byte size due to bug in the Diamond SpeedStar 24X v1.01 BIOS }


Var  VesaMode : TVesaMode;
                { Contains all info needed for drawing on the screen }
     VesaInfo : TVesaInfo;
                { Contains info on the VESA BIOS Extensions }

     vesaon   : Byte;
                { Specifies whether a VESA mode is on or not      }

Function  IsVesa:Boolean;
          { Detects whether VESA support is present }
Procedure GetVesaInfo;
          { Get Information on VESA modes, etc }
Procedure GetVesaModeInfo(md:Word);
          { Get Information on a VESA mode (md) }
Function  SetMode(md:Word):Boolean;
          { Sets a video mode (OEM and VESA) }
Function  GetMode:Word;
          { Returns the current video mode }
Function  SizeOfVideoState:Word;
          { Returns the size of the buffer needed to save the video state }
Procedure SaveVideoState(Var buf);
          { Saves the SVGA video state in the buffer }
Procedure RestoreVideoState(Var buf);
          { Restores the SVGA video state from the buffer}
Procedure SetBank(bank:Word);
          { Set the video bank to draw on }
Function  GetBank:Word;
          { Gets the current active video bank }
Procedure SetLineLength(Var len:Word);
          { Sets the logical scan line length, returns the actual length set }
Function  GetLineLength:Word;
          { Returns the current logical scan line length }
Procedure SetDisplayStart(pixel,line:Word);
          { Sets the first pixel and line on the display }
Procedure GetDisplayStart(Var pixel,line:Word);
          { Returns the first pixel and line on the display }

{---------------------------------------------------------------------------}
{-----------------------------} Implementation {----------------------------}
{---------------------------------------------------------------------------}

Uses Dos;

Var  rp : Registers;

Function IsVesa:Boolean;
Begin
  rp.ax:=$4F03;
  Intr($10,rp);
  IsVesa:=(rp.al=$4F);
End;

Procedure GetVesaInfo;
Begin
  rp.ax:=$4F00;
  rp.di:=Ofs(VesaInfo);
  rp.es:=Seg(VesaInfo);
  Intr($10,rp);
End;

Procedure GetVesaModeInfo(md:Word);
Begin
  rp.ax:=$4F01;
  rp.cx:=md;
  rp.di:=Ofs(VesaMode);
  rp.es:=Seg(VesaMode);
  Intr($10,rp);
End;

Function SetMode(md:Word):Boolean;
Begin
  SetMode:=True; vesaon:=1;
  If md>$FF Then Begin
    rp.bx:=md;
    rp.ax:=$4F02;
    Intr($10,rp);
    If rp.ax<>$4F Then SetMode:=False Else GetVesaModeInfo(md);
  End Else Begin
    rp.ax:=md;
    Intr($10,rp);
    VesaMode.Gran:=64; vesaon:=0;
    VesaMode.SegA:=$A000;
    Case md Of  { OEM (standard) video modes }
      1..3,7 : Begin { Text modes }
                 VesaMode.Width:=80;  VesaMode.Height:=25;
                 If md=7 Then Begin
                   VesaMode.Bits:=1;  VesaMode.SegA:=$B000;
                 End Else Begin
                   VesaMode.Bits:=4;  VesaMode.SegA:=$B800;
                 End;
                 VesaMode.Bytes:=160; VesaMode.Model:=0;
               End;
      $13 : Begin  { 320 x 200 x 256 colours, VGA & MCGA }
              VesaMode.Width:=320; VesaMode.Height:=200;
              VesaMode.Bits:=8;    VesaMode.Model:=4;
              VesaMode.Bytes:=320;
            End;
      $12 : Begin  { 640 x 480 x 16 colours, VGA only }
              VesaMode.Width:=640; VesaMode.Height:=480;
              VesaMode.Bits:=4;    VesaMode.Model:=3;
              VesaMode.Bytes:=80;
            End;
      $10 : Begin  { 640 x 350 x 16 colours, VGA & EGA with 128k+ }
              VesaMode.Width:=640; VesaMode.Height:=350;
              VesaMode.Bits:=4;    VesaMode.Model:=3;
              VesaMode.Bytes:=80;
            End;
      $0E : Begin  { 640 x 200 x 16 colours, VGA & EGA }
              VesaMode.Width:=640; VesaMode.Height:=200;
              VesaMode.Bits:=4;    VesaMode.Model:=3;
              VesaMode.Bytes:=80;
            End;
      $0D : Begin  { 320 x 200 x 16 colours, VGA & EGA }
              VesaMode.Width:=320; VesaMode.Height:=200;
              VesaMode.Bits:=4;    VesaMode.Model:=3;
              VesaMode.Bytes:=40;
            End;
      Else SetMode:=False;
    End;
  End;
End;

Function GetMode:Word;
Begin
  rp.ax:=$4F03;
  Intr($10,rp);
  GetMode:=rp.bx;
End;

Function SizeOfVideoState:Word;
Begin  { Will save/restore all video states }
  rp.ax:=$4F04;
  rp.dl:=0;
  rp.cx:=$0F;  { hardware, BIOS, DAC & SVGA states }
  Intr($10,rp);
  SizeOfVideoState:=rp.bx;
End;

Procedure SaveVideoState(Var buf);
Begin
  rp.ax:=$4F04;
  rp.dl:=1;
  rp.cx:=$0F;
  rp.es:=Seg(buf);
  rp.bx:=Ofs(buf);
  Intr($10,rp);
End;

Procedure RestoreVideoState(Var buf);
Begin
  rp.ax:=$4F04;
  rp.dl:=2;
  rp.cx:=$0F;
  rp.es:=Seg(buf);
  rp.bx:=Ofs(buf);
  Intr($10,rp);
End;

Procedure SetBank(bank:Word);
Var winnum:Word;
Begin
  winnum:=bank*64 Div VesaMode.Gran;
  rp.ax:=$4F05;
  rp.bx:=0;
  rp.dx:=winnum;
  Intr($10,rp);
  rp.ax:=$4F05;
  rp.bx:=1;
  rp.dx:=winnum;
  Intr($10,rp);
End;

Function GetBank:Word;
Begin
  rp.ax:=$4F05;
  rp.bx:=$100;
  Intr($10,rp);
  GetBank:=rp.dx;
End;

Procedure SetLineLength(Var len:Word);
Begin
  rp.ax:=$4F06;
  rp.bl:=0;
  rp.cx:=len;
  Intr($10,rp); { dx:=maximum number of scan lines }
  len:=rp.cx;
End;

Function GetLineLength:Word;
Begin
  rp.ax:=$4F06;
  rp.bl:=1;
  Intr($10,rp); { dx:=maximum number of scan lines }
  GetLineLength:=rp.cx;
End;

Procedure SetDisplayStart(pixel,line:Word);
Begin
  rp.ax:=$4F07;
  rp.bx:=0;
  rp.cx:=pixel;
  rp.dx:=line;
  Intr($10,rp);
End;

Procedure GetDisplayStart(Var pixel,line:Word);
Begin
  rp.ax:=$4F07;
  rp.bx:=1;
  Intr($10,rp);
  pixel:=rp.cx;
  line:=rp.dx;
End;

End.

[Back to WIN-OS2 SWAG index]  [Back to Main SWAG index]  [Original]