[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]