home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / grafik / dc / svga.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-21  |  35.8 KB  |  1,330 lines

  1. {
  2.   Copyright 1992 by Digital Crime.
  3.  
  4.   All rights reserved.
  5.  
  6.   Permission to use, copy, modify, and distribute this software and its
  7.   documentation for any purpose and without fee is hereby granted,
  8.   provided that the above copyright notice appear in all copies and that
  9.   both that copyright notice and this permission notice appear in
  10.   supporting documentation, and that the name of the Digital Crime
  11.   not be used in advertising or publicity pertaining to distribution
  12.   of the software without specific, written  prior permission.
  13.  
  14.   DIGITAL CRIME DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  15.   SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  16.   AND FITNESS, IN NO EVENT SHALL DIGITAL CRIME BE LIABLE FOR ANY SPECIAL,
  17.   INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  18.   FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  19.   NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.   WITH THE USE OR PERFORMANCE OF THIS  SOFTWARE.
  21.  
  22.   s924683@minyos.xx.rmit.OZ.AU   Chandi.
  23.   s924698@minyos.xx.rmit.OZ.AU   Ed.
  24.  
  25.  
  26.  
  27. }
  28. {$R-}
  29.  
  30. Unit SVGA;
  31.  
  32. { This unit enables TP programs to utilize SVGA graphics. }
  33. { Nine types of cards are supported however not all have  }
  34. { tested.  Also included is a SVGA mouse driver.          }
  35. { References  - Programmer's Guide to the EGA & VGA Cards ( 2nd Ed.) }
  36. {               Richard F. Ferraro,  Addison-Wesley, 1990.           }
  37. {               ISBN 0-201-57025                                     }
  38. {             - Finn Theogersen  jesperf@daimi.aau.dk                }
  39. {             - Graphics Programming in Turbo Pascal 6.0             }
  40. {               Ben Ezzell, Addison-Wesley, 1991                     }
  41. {               ISBN 0-201-58119-1                                   }
  42. {             - Advanced Graphics Programming in Turbo Pascal        }
  43. {               Roger T. Stevens and Christopher D. Watkins,         }
  44. {               Prentice Hall, M & T Books, 1991.                    }
  45. {               ISBN 0-13-367145-3                                   }
  46.  
  47. INTERFACE
  48.  
  49. const
  50.    ButtonL = 0; ButtonR = 1; ButtonM = 2;
  51.    OFF      = 0;  ON       = 1;
  52.  
  53. Type
  54.   RGB = record
  55.         Red, Grn, Blu : byte
  56.         end;
  57.   PaletteRegister = array[0..255] of RGB;
  58.   SetTypes = ( FutureFont, StandardFont );
  59.   ResType = ( SVGAMED, SVGAHIGH );  { SVGAHIGH not installed as yet }
  60.   Position = record
  61.                BtnStatus,
  62.                opCount,
  63.                XPos, YPos : integer;
  64.              end;
  65.  
  66.   EventRec = record
  67.                Event,
  68.                BtnStatus,
  69.                XPos, YPos : word;
  70.              end;
  71.  
  72. var  Color : PaletteRegister;
  73.      Bytes_per_Line, GetMaxX, GetMaxY : integer;
  74.      mEvent : EventRec;
  75.      PresentSeg : byte;
  76.  
  77. procedure SetMode( Mode : Restype );
  78.   { Sets Graphics card to desired mode }
  79. procedure LoadWriteBank( Segment : byte );
  80.   { Loads particular bank for read/write operations }
  81. procedure Plot( x, y : integer; Color : byte );
  82.   { Plots a point to screen }
  83. procedure SetColor( PalNum: byte; Hue : RGB );
  84.   { Sets Color of a particular pallette }
  85. function  GetPixel( x, y : integer ) : byte;
  86.   { Returns color of a pixel }
  87. procedure SetPalette( Hue : PaletteRegister );
  88.   { Sets all 256 pallette registers to desired pallette }
  89. procedure CyclePalette;
  90.   { Rotates all colors in the pallette in repetitive cycle }
  91. procedure Circle( x, y, Radius : word; Color : byte );
  92.   { Draws a circle }
  93. procedure Line( xx1, yy1, xx2, yy2 : integer; Color : byte );
  94.   { Draws a line }
  95. procedure Rectangle( x1, y1, x2, y2 : word; Color : byte );
  96.   { Draws a rectangle outline i.e not solid }
  97. procedure RectFill( x1, y1, x2, y2 : integer; Color : byte );
  98.   { Draws a solid Rectangle }
  99. procedure ClearPort( x1, y1, x2, y2 : integer );
  100.   { Clears a Section of the screen }
  101. procedure OutTextXY( x, y : integer; word : string );
  102.   { Writes text to screen at point X, Y }
  103. procedure LoadFont( CharSetName: SetTypes );
  104.   { Loads a particular Font for use }
  105. procedure SetFont( Font : SetTypes );
  106.   { If two or more fonts are in memory this allows you to choose one }
  107. procedure SetFontColor( Color, BackCol : byte; Trans : boolean );
  108.   { Set forground & background color of text & transparent background or not }
  109.   { i.e write background to screen or skip it and only write letter          }
  110. procedure LoadPalette( PaletteName : string );
  111.   { Loads a particular pallette from disk }
  112. procedure ExitGraphics;
  113.   { Exits SVGA Graphics and returns to normal text mode }
  114.  
  115. type
  116.    GenMouse = object
  117.       procedure SetAccel( threshold : integer );
  118.         { Set Acceleration of mouse }
  119.       procedure Getposition( var BtnStatus, XPos, YPos : integer );
  120.         { Gets the Position of the mouse and returns button status }
  121.       procedure QueryBtnDn( button : integer; var mouse : Position );
  122.         { Checks if queried button was pressed }
  123.       procedure QueryBtnUp( button : integer; var mouse : Position );
  124.         { Checks if queried button is released }
  125.       procedure ReadMove( var XMove, YMove : integer );
  126.         { Reports absolute mouse movement since last call to ReadMove }
  127.       procedure Reset( var Status : boolean; var BtnCount : integer );
  128.         { Resets the mouse to default conditions }
  129.       procedure SetRatio( horPix, verPix : integer );
  130.         { Sets speed of mouse }
  131.       procedure SetLimits( XPosMin, YPosMin, XPosMax, YPosMax : integer );
  132.         { Creates View Port for which mouse can operate in }
  133.       procedure SetPosition( XPos, YPos : integer );
  134.         { Puts mouse to desired point on screen }
  135.    end;
  136.  
  137.   GraphicMouse = object( GenMouse )
  138.     procedure Initialize;
  139.       { Sets default conditons for graphics mouse }
  140.     procedure Show( ShowMouse : boolean );
  141.       { Either shows or hides the graphics mouse }
  142.     procedure CheckMouse;
  143.       { Checks if mouse has been moved since last call and moves mouse accordingly }
  144.     procedure ExitSVGA;
  145.       { Exits Graphics mouse and resets it back to text mode }
  146.   end;
  147.  
  148.  
  149. IMPLEMENTATION
  150.  
  151. Uses Dos, Crt;
  152.  
  153. const White = 255;
  154.       Black = 0;
  155.  
  156. type  FCharType = array[ 0..15, 0..12 ] of boolean;
  157.       FCharSetType = array[ 0..95 ] of FCharType;
  158.       SCharType = array[ 0..7, 0..9 ] of boolean;
  159.       SCharSetType = array[ 0..95 ] of SCharType;
  160.       CardType = ( AheadA, AheadB, ATI, ChipsTech, Everex, Genoa,
  161.                    Paradise, Trident, Tseng3000, Tseng4000, Video7 );
  162.       ImagePtrType = ^ImageType;
  163.       ImageType = array[ 0..120, 0..120 ] of byte;
  164.       NameType = string[30];
  165.  
  166. var
  167.   XRes, YRes, X, Y, OldX, OldY : integer;
  168.   regs : registers;
  169.   Future : ^FCharSetType;
  170.   Standard : ^SCharSetType;
  171.   Width, Height, FontColor, BackGroundColor : byte;
  172.   PresentSet : SetTypes;
  173.   Transparent, Sused, Fused : boolean;
  174.   Card : CardType;
  175.   MP, ColOld : array[ 0..3, 0..3 ] of byte;
  176.  
  177. function Ahead : NameType;
  178.  
  179.   begin
  180.     Portw[$3CE] := $200F;
  181.     if Port[$3CF] = $20 then Ahead := 'Ahead A'
  182.       else if Port[$3CF] = $21 then Ahead := 'Ahead B'
  183.         else Ahead := 'False';
  184.   end;
  185.  
  186. function AnATI : NameType;
  187.  
  188.   var s : NameType;
  189.       Temp : string;
  190.  
  191.   begin
  192.     s[0] := #9;
  193.     move(mem[$C000:$31],s[1],9);
  194.     if s = '761295520'then
  195.       begin
  196.         Temp := 'ATI';
  197.         if memw[$C000:$40] = $3331 then Temp := Temp + ' Super VGA';
  198.         Regs.AH := $12;
  199.         Regs.BX := $5506;
  200.         Regs.AL := $55;
  201.         Regs.BP := $FFFF;
  202.         Regs.SI := $0;
  203.         intr( $10, Regs );
  204.         if Regs.BP = $FFFF then Temp := Temp + ' Revision 1'
  205.           else Temp := Temp + ' Revision 2/3';
  206.         AnATI := Temp;
  207.       end
  208.     else AnATI := 'False';
  209.   end;
  210.  
  211. function AChipsTech : Nametype;
  212.  
  213.   var OldValue, Value : byte;
  214.       Temp : string;
  215.  
  216.   begin
  217.     Port[$3C3] := Port[$3C3] or 16;
  218.     if Port[$104] = $A5 then
  219.       begin
  220.         Temp:= 'Chips & Technologies';
  221.         Port[$3C3] := Port[$3C3] and $EF;
  222.         Port[$3D6] := 0;
  223.         case Port[$3D7] shr 4 of
  224.           2 : Temp := Temp + ' 82c455';
  225.           3 : Temp := Temp + ' 82c453';
  226.           5 : Temp := Temp + ' 82c456';
  227.           1 : begin
  228.                 Port[$3D6] := $3A;
  229.                 OldValue := Port[$3D7];
  230.                 Port[$3D7] := $AA;
  231.                 Value := Port[$3D7];
  232.                 Port[$3D7] := OldValue;
  233.                 if Value = $AA then Temp := Temp + ' 82c452'
  234.                   else Temp := Temp + ' 82c451';
  235.               end;
  236.           end;
  237.         AChipsTech := Temp;
  238.       end
  239.     else AChipsTech := 'False';
  240.   end;
  241.  
  242. function AnEverex : NameType;
  243.  
  244.   var Value : byte;
  245.       s : NameType;
  246.  
  247.   begin
  248.     Regs.AX := $7000;
  249.     Regs.BX := 0;
  250.     intr( $10, Regs );
  251.     if Regs.AL = $70 then
  252.       begin
  253.         Value := Regs.DX shr 4;
  254.         if Value = $678 then AnEverex := 'Everex Ev678'
  255.           else if Value = $236 then AnEverex := 'Everex Ev236'
  256.             else begin
  257.                    str( Value, s );
  258.                    AnEverex := 'Everex Ev'+ s;
  259.                  end;
  260.       end
  261.     else AnEverex := 'False';
  262.   end;
  263.  
  264. function AGenoa : Nametype;
  265.  
  266.   begin
  267.     if (meml[$C000:mem[$C000:$37]] and $FFFF00FF) = $66990077 then
  268.       begin
  269.         case mem[$C000:mem[$C000:$37] + 1] of
  270.           $33, $55 : AGenoa := 'Tseng ET3000';
  271.                $22 : AGenoa := 'Genoa 6100';
  272.                  0 : AGenoa := 'Genoa 6200/6300';
  273.                $11 : AGenoa := 'Genoa 6400/6600';
  274.           end;
  275.       end
  276.     else AGenoa := 'False';
  277.   end;
  278.  
  279. function AParadise : NameType;
  280.  
  281.   var OldValue, NewValue, New1, New2 : byte;
  282.       Base : word;
  283.       Temp : string;
  284.  
  285.    begin
  286.      if meml[$C000:$7D] = $3D414756 then
  287.        begin
  288.          Temp := 'Paradise';
  289.          if odd(Port[$3CC]) then Base:= $3D4
  290.            else Base := $3B4;
  291.          Port[Base] := $2B;  OldValue := Port[Base+1];
  292.          Port[Base+1] := $AA; NewValue := Port[Base+1];
  293.          Port[Base+1] := OldValue;
  294.          if NewValue <> $AA then Temp := Temp + ' PVGA1A'
  295.            else
  296.              begin
  297.                Port[$3C4] := $12; OldValue := Port[$3C5];
  298.                Port[$3C5] := OldValue and $BF; New1 := Port[$3C5] and 64;
  299.                Port[$3C5] := OldValue or $40;  New2 := Port[$3C5] and 64;
  300.                Port[$3C5] := OldValue;
  301.                if (New1 <> 0) or (New2 = 0) then Temp := Temp + ' WD90C00'
  302.                  else
  303.                    begin
  304.                      Port[$3C4] := $10; OldValue := Port[$3C5];
  305.                      Port[$3C5] := OldValue and $FB; New1 := Port[$3C5] and 4;
  306.                      Port[$3C5] := OldValue or 4;    New2 := Port[$3C5] and 4;
  307.                      Port[$3C5] := OldValue;
  308.                      if (New1 <> 0) or (New2 = 0) then Temp := Temp + ' WD90C10'
  309.                        else Temp := Temp + ' WD90C11';
  310.                    end;
  311.              end;
  312.          AParadise := Temp;
  313.        end
  314.      else AParadise := 'False';
  315.    end;
  316.  
  317. function ATrident : NameType;
  318.  
  319.    var OldValue, Value : byte;
  320.        Temp : string;
  321.  
  322.    begin
  323.      Port[$03C4] := $E;
  324.      OldValue := Port[$03C5];
  325.      Port[$03C5] := 0;
  326.      Value := Port[$03C5] AND $F;
  327.      Port[$03C5] := OldValue;
  328.      if Value = $2 then
  329.        begin
  330.          Temp := 'Trident';
  331.          Port[$3C4] := 11;
  332.          if Port[$3C5] >= 3 then Temp := Temp + ' 8900/9000'
  333.            else Temp := Temp + ' 8800';
  334.          ATrident := Temp;
  335.        end
  336.      else ATrident := 'False';
  337.   end;
  338.  
  339. function ATseng : NameType;
  340.  
  341.   var OldValue, NewValue, Value : byte;
  342.       Base : word;
  343.       Temp : string;
  344.  
  345.   begin
  346.     OldValue := Port[$3CD];
  347.     Port[$3CD] := $55;
  348.     NewValue := Port[$3CD];
  349.     Port[$3CD] := OldValue;
  350.     if NewValue = $55 then
  351.       begin
  352.         Temp := 'Tseng';
  353.         if odd( Port[$3CC] ) then Base := $3C4
  354.           else Base := $3B4;
  355.         Port[Base] := $33; OldValue := Port[Base+1];
  356.         NewValue := OldValue xor 15;
  357.         Port[Base+1] := NewValue;
  358.         Value := Port[Base+1];
  359.         Port[Base+1] := OldValue;
  360.         if Value = NewValue then Temp := Temp + ' ET4000'
  361.           else Temp := Temp + ' ET3000';
  362.         ATseng := Temp;
  363.       end
  364.     else ATseng := 'False';
  365.   end;
  366.  
  367. function AVideo7 : NameType;
  368.  
  369.   var Value, OldValue, NewValue : byte;
  370.       Base : word;
  371.       Temp : string;
  372.  
  373.   begin
  374.     if odd( Port[$3CC] ) then Base := $3D4
  375.       else Base := $3B4;
  376.     Port[Base] := 12; OldValue := Port[Base+1];
  377.     Port[Base+1] := $55; NewValue := Port[Base+1];
  378.     Port[Base] := $1F; Value := Port[Base+1];
  379.     Port[Base] := 12; Port[Base+1] := OldValue;
  380.     if Value = byte( $55 xor $EA ) then
  381.       begin
  382.         Temp := 'Video7';
  383.         Port[$3C4] := $8E;
  384.         case Port[$3C5] of
  385.           $80..$FF : Temp := Temp + ' VEGA VGA';
  386.           $70..$7F : Temp := Temp + ' V7VGA FASTWRITE/VRAM';
  387.           $50..$59 : Temp := Temp + ' V7VGA Version 5';
  388.           $41..$49 : Temp := Temp + ' 1024i';
  389.         end;
  390.         AVideo7 := Temp;
  391.       end
  392.     else AVideo7 := 'False';
  393.   end;
  394.  
  395. procedure SetMode( Mode : ResType );
  396.  
  397.   var ModeNum : byte;
  398.  
  399.   begin
  400.     TextColor( LightRed );  writeln; writeln;
  401.     if Ahead <> 'False' then
  402.       begin
  403.         if Mode = SVGAMED then ModeNum := $61;
  404.         if Ahead = 'Ahead A' then Card := AheadA
  405.           else Card := AheadB;
  406.         write( Ahead + ' Card Detected' );
  407.       end
  408.     else if AnATI <> 'False' then
  409.       begin
  410.         if Mode = SVGAMED then ModeNum := $62;
  411.         Card := ATI;
  412.         write( AnATI + 'Card Detected' );
  413.       end
  414.     else if AChipsTech <> 'False' then
  415.       begin
  416.         if (AChipsTech = 'Chips & Technologies 82c452') or
  417.            (AChipsTech = 'Chips & Technologies 82c453') then
  418.            begin
  419.              if Mode = SVGAMED then ModeNum := $79;
  420.              Card := ChipsTech;
  421.              write( AChipsTech + ' Card Detected' );
  422.            end
  423.         else
  424.           begin
  425.             write( AChipsTech + ' Card does not support 640*480 256 Color Mode ' );
  426.             Halt( 1 );
  427.           end
  428.       end
  429.     else if AnEverex <> 'False' then
  430.       begin
  431.         if Mode = SVGAMED then ModeNum := $30; { ??? How about Trident }
  432.         if (AnEverex = 'Everex Ev678') or (AnEverex = 'Everex Ev236') then
  433.           Card := Trident   { 678, 236 Chips use Trident }
  434.         else Card := Everex;
  435.         write( AnEverex + ' Card Detected' );
  436.       end
  437.     else if AGenoa <> 'False' then
  438.       begin
  439.         if AGenoa = 'Tseng 3000' then
  440.           begin
  441.             if Mode = SVGAMED then ModeNum := $2E;
  442.             Card := Tseng3000;
  443.           end
  444.         else
  445.           begin
  446.             if Mode = SVGAMED then ModeNum := $5C;
  447.             Card := Genoa;
  448.           end;
  449.         write( AGenoa + ' Card Detected' );
  450.       end
  451.     else if AParadise <> 'False' then
  452.       begin
  453.         if Mode = SVGAMED then ModeNum := $5F;
  454.         Card := Paradise;
  455.         write( AParadise + ' Card Detected' );
  456.       end
  457.     else if ATrident <> 'False'then
  458.       begin
  459.         if Mode = SVGAMED then ModeNum := $5D;
  460.         Card := Trident;
  461.         write( ATrident + ' Card Detected' );
  462.       end
  463.     else if ATseng <> 'False' then
  464.       begin
  465.         if Mode = SVGAMED then ModeNum := $2E;
  466.         if ATseng = 'Tseng ET3000' then Card := Tseng3000
  467.           else Card := Tseng4000;
  468.         write( ATseng + ' Card Detected' );
  469.       end
  470.     else if AVideo7 <> 'False' then
  471.       begin
  472.         if Mode = SVGAMED then ModeNum := $67;
  473.         Card := Video7;
  474.         write( AVideo7 + ' Card Detected' );
  475.       end
  476.     else
  477.       begin
  478.         write( 'Graphics card Unrecognizable......' );
  479.         Halt( 1 );
  480.       end;
  481.     Delay( 500 );
  482.     if Mode = SVGAMED then
  483.       begin
  484.         GetMaxX := 639;
  485.         GetMaxY := 479;
  486.         Bytes_per_line := 640;
  487.       end;
  488.     if Card <> Video7  then
  489.       begin
  490.         Regs.AH := 0;
  491.         Regs.AL := ModeNum;
  492.         intr( $10, Regs );
  493.       end;
  494.     if Card = ATI then                { Certain cards have to be  }
  495.       asm                             { initialized before use    }
  496.         push es
  497.         push bx
  498.         mov ax, 0c000h
  499.         mov es, ax
  500.         mov bx, 10h
  501.         mov dx, es:[bx]
  502.         pop bx
  503.         pop es
  504.         mov al, 0beh
  505.         out dx, al
  506.         inc dl
  507.         in al, dx
  508.         mov ah, al
  509.         and ah, 0f7h
  510.         dec dl
  511.         mov al, 0beh
  512.         out dx, ax
  513.       end;
  514.       if Card = ChipsTech then
  515.         asm
  516.           mov dx, 3d6h
  517.           mov al, 0bh
  518.           out dx, al
  519.           in al, dx
  520.           and al, 0fdh
  521.           out dx, al
  522.         end;
  523.       if Card = Paradise then
  524.         asm
  525.           mov dx, 3ceh
  526.           mov al, 0fh
  527.           mov ah, 05h
  528.           out dx, ax
  529.           add dx, 4
  530.           mov al, 29h
  531.           mov ah, 85h
  532.           out dx, ax
  533.           mov dx, 3c4h
  534.           mov al, 06h
  535.           mov ah, 48h
  536.           out dx, ax
  537.           mov dx, 3c4h
  538.           mov al, 11h
  539.           out dx, al
  540.           inc dx
  541.           in  al, dx
  542.           and al, 7fh
  543.           out dx, al
  544.           mov dx, 3ceh
  545.           mov al, 0bh
  546.           out dx, al
  547.           inc dx
  548.           in  al, dx
  549.           and al, 0f7h
  550.           out dx, al
  551.         end;
  552.       if Card = Video7 then
  553.          asm
  554.            mov bx, 67h
  555.            mov ax, 6f05h
  556.            int 10h
  557.            mov dx, 3c4h
  558.            mov al, 6
  559.            mov ah, 0eah
  560.            out dx, ax
  561.          end;
  562.   end;
  563.  
  564. procedure LoadWriteBank( Segment : byte );
  565.  
  566. { This is the main problem with SVGA graphics. }
  567. { Each card manufacturer have their own way of }
  568. { loading banks so each type of card must be   }
  569. { handled seperatly.                           }
  570.  
  571.   begin
  572.     PresentSeg := Segment;
  573.     if Card = Trident then
  574.         asm
  575.           mov bl, Segment
  576.           mov dx, 3c4h
  577.           mov al, 0eh
  578.           xor bl, 02
  579.           mov ah, bl
  580.           out dx, ax
  581.         end
  582.     else if Card = Tseng3000 then
  583.         asm
  584.           mov bl, Segment
  585.           mov dx, 3cdh
  586.           in  al, dx
  587.           and al, 0f8h
  588.           and bl, 07h
  589.           or  al, bl
  590.           out dx, al
  591.         end
  592.     else if Card = Tseng4000 then
  593.         asm
  594.           mov bl, Segment
  595.           mov dx, 3cdh
  596.           in  al, dx
  597.           and al, 0f0h
  598.           and bl, 0fh
  599.           or  al, bl
  600.           out dx, al
  601.         end
  602.       else if Card = Paradise then
  603.         asm
  604.           mov bl, Segment
  605.           mov dx, 3ceh
  606.           mov al, 09h
  607.           mov ah, bl
  608.           shl ah, 1
  609.           shl ah, 1
  610.           shl ah, 1
  611.           shl ah, 1
  612.           out dx, ax
  613.         end
  614.       else if Card = Genoa then
  615.         asm
  616.           mov bl, Segment
  617.           mov dx, 3c4h
  618.           mov al, 06h
  619.           out dx, al
  620.           inc dx
  621.           in  al, dx
  622.           and al, 0c7h
  623.           and bl, 07h
  624.           shl bl, 1
  625.           shl bl, 1
  626.           shl bl, 1
  627.           or  al, bl
  628.           out dx, al
  629.         end
  630.       else if Card = ChipsTech then
  631.         asm
  632.           mov bl, Segment
  633.           mov dx, 3d6h
  634.           mov al, 10h
  635.           mov ah, bl
  636.           shl ah, 1
  637.           shl ah, 1
  638.           out dx, ax
  639.         end
  640.       else if Card = ATI then
  641.         asm
  642.           mov bl, Segment
  643.           push es
  644.           push bx
  645.           mov ax, 0c000h
  646.           mov es, ax
  647.           mov bx, 10h
  648.           mov dx, es:[bx]
  649.           pop bx
  650.           pop es
  651.           mov al, 0b2h
  652.           out dx, al
  653.           inc dl
  654.           in al, dx
  655.           mov ah, al
  656.           and ah, 0e1h
  657.           shl bl, 1
  658.           or ah, bl
  659.           mov al, 0b2h
  660.           dec dl
  661.           out dx, ax
  662.         end
  663.       else if Card = Video7 then
  664.       { This is for the V7VGA Chip Versions 1-3 }
  665.       { Version 4 is different }
  666.         asm
  667.           mov bl, Segment
  668.           mov dx, 3c4h
  669.           mov ah, bl
  670.           and ah, 1
  671.           mov al, 0f9h
  672.           out dx, ax
  673.  
  674.           mov ah, bl
  675.           and ah, 2
  676.           shl ah, 1
  677.           shl ah, 1
  678.           shl ah, 1
  679.           shl ah, 1
  680.           mov dx, 3cch
  681.  
  682.           in  al, dx
  683.           and al, 0dfh
  684.           mov dx, 3c2h
  685.  
  686.           or  al, ah
  687.           out dx, al
  688.  
  689.           mov dx, 3c4h
  690.           mov al, 0f6h
  691.           out dx, al
  692.           inc dx
  693.           in  al, dx
  694.  
  695.           mov ah, al
  696.           and ah, 0fch
  697.           shr bl, 1
  698.  
  699.           shr bl, 1
  700.           and bl, 3
  701.           or  ah, bl
  702.           mov al, ah
  703.           out dx, al
  704.         end;
  705.   end;
  706.  
  707. procedure Plot( x, y : integer; Color : byte );
  708.  
  709.   var Segment : byte;
  710.  
  711.   begin
  712.     if (y = 102) AND (x < 256) then Segment := 0
  713.          else if (y = 204) AND (x < 512) then Segment := 1
  714.           else if (y = 307) AND (x < 128) then  Segment := 2
  715.            else if (y = 409) AND (x < 384) then Segment := 3
  716.             else if y < 102 then Segment := 0
  717.              else if y < 204 then Segment := 1
  718.               else if y < 307 then Segment := 2
  719.                else if y < 409 then Segment := 3
  720.                 else Segment := 4;
  721.    if Segment <> PresentSeg then LoadWriteBank( Segment );
  722.     asm
  723.       mov ax, Bytes_per_Line
  724.       mov bx, y
  725.       mul bx
  726.       add ax, x
  727.       mov di, ax
  728.       mov ax, 0a000h
  729.       mov es, ax
  730.       mov al, Color
  731.       mov es:[di], al
  732.     end;
  733.   end;
  734.  
  735. procedure SetColor( PalNum: byte; Hue : RGB );
  736.  
  737.   var reg : registers;
  738.  
  739.   begin
  740.     Color[ PalNum ] := Hue;
  741.     with reg do
  742.       begin
  743.         AX := $1010;
  744.         BX := PalNum;
  745.         CH := Hue.Grn;
  746.         CL := Hue.Blu;
  747.         DH := Hue.Red;
  748.       end;
  749.     intr( $10, reg );
  750.   end;
  751.  
  752. function GetPixel( x, y : integer ) : byte;
  753.  
  754.   var Segment : byte;
  755.  
  756.   begin
  757.     if (y = 102) AND (x < 256) then Segment := 0
  758.          else if (y = 204) AND (x < 512) then Segment := 1
  759.           else if (y = 307) AND (x < 128) then  Segment := 2
  760.            else if (y = 409) AND (x < 384) then Segment := 3
  761.             else if y < 102 then Segment := 0
  762.              else if y < 204 then Segment := 1
  763.               else if y < 307 then Segment := 2
  764.                else if y < 409 then Segment := 3
  765.                 else Segment := 4;
  766.     if Segment <> PresentSeg then LoadWriteBank( Segment );
  767.     Regs.AX := 3328;
  768.     Regs.DX := y;
  769.     Regs.CX := x;
  770.     Intr( $10, Regs );
  771.     GetPixel := Regs.AX AND 255;
  772.   end;
  773.  
  774. procedure SetPalette( Hue : PaletteRegister );
  775.  
  776.   begin
  777.     Color := Hue;
  778.     with Regs do
  779.       begin
  780.         AX := $1012;
  781.         BX := 0;
  782.         CX := 256;
  783.         ES := Seg( Hue );
  784.         DX := Ofs( Hue );
  785.       end;
  786.     intr( $10, Regs );
  787.   end;
  788.  
  789. procedure CyclePalette;
  790.  
  791.   var
  792.     i   : byte;
  793.     Tmp : RGB;
  794.  
  795.   begin
  796.     Tmp := Color[1];
  797.     for i := 2 to 251 do
  798.         Color[i-1] := Color[i];
  799.     Color[251] := Tmp;
  800.     SetPalette( Color )
  801.   end;
  802.  
  803. procedure Swap( var First, Second : integer );
  804.  
  805.   var
  806.     temp : integer;
  807.  
  808.   begin
  809.     temp   := first;
  810.     first  := second;
  811.     second := temp
  812.   end;
  813.  
  814.  
  815. procedure Circle( x, y, Radius : word; Color : byte );
  816.  
  817.   var
  818.     a, af, b, bf, target, r2 : integer;
  819.  
  820.   begin
  821.     target := 0;
  822.     a := radius;
  823.     b := 0;
  824.     r2 := Sqr( radius );
  825.     while a >= b do
  826.       begin
  827.         b := Round( Sqrt( r2 - sqr(a)));
  828.         Swap( target, b );
  829.         while b < target do
  830.           begin
  831.             af := (100*a) div 100;
  832.             bf := (100*b) div 100;
  833.             Plot( x+af, y+b, color );
  834.             Plot( x+bf, y+a, color );
  835.             Plot( x-af, y+b, color );
  836.             Plot( x-bf, y+a, color );
  837.             Plot( x-af, y-b, color );
  838.             Plot( x-bf, y-a, color );
  839.             Plot( x+af, y-b, color );
  840.             Plot( x+bf, y-a, color );
  841.             b := b + 1
  842.           end;
  843.         a := a - 1
  844.       end
  845.   end;
  846.  
  847. procedure Line( xx1, yy1, xx2, yy2 : integer; color : byte );
  848.  
  849.   var
  850.     LgDelta, ShDelta, Cycle, LgStep, ShStep, Dtotal : integer;
  851.  
  852.   begin
  853.     LgDelta := xx2 - xx1;
  854.     ShDelta := yy2 - yy1;
  855.     if LgDelta < 0 then
  856.       begin
  857.         LgDelta := -LgDelta;
  858.         LgStep := -1
  859.       end
  860.      else
  861.         LgStep := 1;
  862.     if ShDelta < 0 then
  863.       begin
  864.         ShDelta := -ShDelta;
  865.         ShStep := -1
  866.       end
  867.       else
  868.         ShStep := 1;
  869.     if ShDelta < LgDelta then
  870.       begin
  871.         Cycle := LgDelta shr 1;
  872.         while xx1 <> xx2 do
  873.           begin
  874.             Plot( xx1, yy1, color );
  875.             Cycle := Cycle + ShDelta;
  876.             if Cycle > LgDelta then
  877.               begin
  878.                 Cycle := Cycle - LgDelta;
  879.                 yy1 := yy1 + ShStep
  880.               end;
  881.             xx1 := xx1 + LgStep
  882.           end;
  883.         Plot( xx1, yy1, color )
  884.       end
  885.     else
  886.       begin
  887.         Cycle := ShDelta shr 1;
  888.         Swap( LgDelta, ShDelta );
  889.         Swap( LgStep, ShStep );
  890.         while yy1 <> yy2 do
  891.           begin
  892.             Plot( xx1, yy1, color );
  893.             Cycle := Cycle + ShDelta;
  894.             if Cycle > LgDelta then
  895.               begin
  896.                 Cycle := Cycle - LgDelta;
  897.                 xx1 := xx1 + ShStep
  898.               end;
  899.             yy1 := yy1 + LgStep
  900.           end;
  901.         Plot( xx1, yy1, color )
  902.       end;
  903.   end;
  904.  
  905. procedure Rectangle( x1, y1, x2, y2 : word; Color : byte );
  906.  
  907.   begin
  908.     Line( x1, y1, x2, y1, Color );
  909.     Line( x2, y1, x2, y2, Color );
  910.     Line( x2, y2, x1, y2, Color );
  911.     Line( x1, y2, x1, y1, Color );
  912.   end;
  913.  
  914. procedure RectFill( x1, y1, x2, y2 : integer; Color : byte );
  915.  
  916. { Special algorithm to speed up fill time }
  917.  
  918.   var i : integer;
  919.       Segment : byte;
  920.  
  921.   begin
  922.     if x2 < x1 then Swap( x1, x2 );
  923.     if y2 < y1 then Swap( y1, y2 );
  924.     repeat
  925.       if (y1 = 102) OR (y1 = 204) OR (y1 = 307) OR (y1 = 409) then
  926.         begin
  927.           Line( x1, y1, x2, y1, Color );
  928.           y1 := y1 + 1;
  929.         end
  930.       else
  931.         begin
  932.           if y1 < 102 then Segment := 0
  933.             else if y1 < 204 then Segment := 1
  934.               else if y1 < 307 then Segment := 2
  935.                 else if y1 < 409 then Segment := 3
  936.                   else Segment := 4;
  937.         if Segment <> PresentSeg then LoadWriteBank( Segment );
  938.         i := x1;
  939.           repeat
  940.             asm
  941.               mov ax, Bytes_per_Line
  942.               mov bx, y1
  943.               mul bx
  944.               add ax, x1
  945.               mov di, ax
  946.               mov ax, 0a000h
  947.               mov es, ax
  948.               mov al, Color
  949.               mov es:[di], al
  950.             end;
  951.           x1 := x1 + 1;
  952.         until x1 > x2;
  953.         x1 := i;
  954.         y1 := y1 + 1;
  955.       end;
  956.     until y1 > y2;
  957.   end;
  958.  
  959. procedure ClearPort( x1, y1, x2, y2 : integer );
  960.  
  961.   var i, j, Temp : integer;
  962.  
  963.   begin
  964.     if y1 > y2 then Swap( y1, y2 );
  965.     for i := 0 to 19 do
  966.       for j := 0 to 23 do
  967.         begin
  968.           Temp := y1+i+j*20;
  969.           if Temp <= y2 then
  970.             RectFill( x1, Temp, x2, Temp, 0 );
  971.         end;
  972.   end;
  973.  
  974.  
  975. procedure ExitGraphics;
  976.  
  977.   begin
  978.     Sound(1300); Delay(200); NoSound;
  979.     Regs.AH := 0;
  980.     Regs.AL := 3;
  981.     intr( $10, Regs );
  982.     if Fused then dispose( Future );
  983.     if Sused then dispose( Standard );
  984.   end;
  985.  
  986. procedure OutTextXY( x, y : integer; word : string );
  987.  
  988.   var i, j, k, symbol : byte;
  989.       LetterX, LetterY, xx, yy : integer;
  990.  
  991.   begin
  992.     LetterX := x;
  993.     LetterY := y;
  994.     if PresentSet = FutureFont then
  995.       begin
  996.          for i := 1 to length( word ) do
  997.            begin
  998.              symbol := ord(word[i])-ord(' ');
  999.              for j := 0 to Width do
  1000.                for k := 0 to Height do
  1001.                    if Future^[symbol][j,k] then
  1002.                          Plot( LetterX+j, LetterY+k, FontColor )
  1003.                    else if not Transparent then
  1004.                          Plot( LetterX+j, LetterY+k, BackGroundColor );
  1005.              LetterX := LetterX + Width + 2;
  1006.            end;
  1007.       end;
  1008.     if PresentSet = StandardFont then
  1009.       begin
  1010.          for i := 1 to length( word ) do
  1011.            begin
  1012.              symbol := ord(word[i])-ord(' ');
  1013.              for j := 0 to Width do
  1014.                for k := 0 to Height do
  1015.                    if Standard^[symbol][j,k] then
  1016.                          Plot( LetterX+j, LetterY+k, FontColor )
  1017.                    else if not Transparent then
  1018.                          Plot( LetterX+j, LetterY+k, BackGroundColor );
  1019.              LetterX := LetterX + Width + 2;
  1020.            end;
  1021.       end;
  1022.   end;
  1023.  
  1024. procedure LoadFont( CharSetName: SetTypes );
  1025.  
  1026.   var Sfil : file of SCharSetType;
  1027.       Ffil : file of FCharSetType;
  1028.       Color : byte;
  1029.  
  1030.   begin
  1031.     if CharSetName = FutureFont then
  1032.       begin
  1033.         GetMem( Future, 19968 );
  1034.         assign( Ffil, 'future.chr' );
  1035.         reset( Ffil );
  1036.         Read( Ffil, Future^ );
  1037.         Close( Ffil );
  1038.         Fused := True;
  1039.       end;
  1040.     if CharSetName = StandardFont then
  1041.       begin
  1042.         GetMem( Standard, 7680 );
  1043.         assign( Sfil, 'standard.chr' );
  1044.         reset( Sfil );
  1045.         Read( Sfil, Standard^ );
  1046.         Close( Sfil );
  1047.         Sused := True;
  1048.       end;
  1049.   end;
  1050.  
  1051. procedure SetFont( Font : SetTypes );
  1052.  
  1053.   begin
  1054.     if Font = FutureFont then
  1055.       begin
  1056.         Width := 15;
  1057.         Height := 12;
  1058.         PresentSet := FutureFont;
  1059.       end;
  1060.     if Font = StandardFont then
  1061.       begin
  1062.         Width := 7;
  1063.         Height := 9;
  1064.         PresentSet := StandardFont;
  1065.       end;
  1066.   end;
  1067.  
  1068. procedure SetFontColor( Color, BackCol : byte; Trans : boolean );
  1069.   begin
  1070.     FontColor := Color;
  1071.     BackGroundColor := BackCol;
  1072.     Transparent := Trans;
  1073.   end;
  1074.  
  1075. procedure LoadPalette( PaletteName : string  );
  1076.  
  1077.   var Fil : File of PaletteRegister;
  1078.  
  1079.   begin
  1080.     assign( fil, PaletteName );
  1081.     reset( fil );
  1082.     read( fil, Color );
  1083.     Close( fil );
  1084.     SetPalette( Color );
  1085.   end;
  1086.  
  1087. function Lower( n1, n2 : integer ) : integer;
  1088.    begin
  1089.       if n1 < n2 then Lower := n1
  1090.                  else Lower := n2;
  1091.    end;
  1092.  
  1093. function Upper( n1, n2 : integer ) : integer;
  1094.    begin
  1095.       if n1 > n2 then Upper := n1
  1096.                  else Upper := n2;
  1097.    end;
  1098.  
  1099. procedure MouseHandler( Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP : word );
  1100.  
  1101.    INTERRUPT;
  1102.    begin
  1103.       mEvent.Event     := AX;
  1104.       mEvent.BtnStatus := BX;
  1105.       mEvent.xPos      := CX;
  1106.       mEvent.yPos      := DX;
  1107.       inline( $8B/$E5/$5D/$07/$1F/$5F/$5E/$5A/$59/$5B/$58/$CB );
  1108.    end;
  1109.  
  1110. procedure GenMouse.Reset( var Status : boolean; var BtnCount : integer );
  1111.    begin
  1112.       regs.AX := $00;
  1113.       intr($33,regs);
  1114.       Status   := regs.AX <> 0;
  1115.       BtnCount := regs.BX;
  1116.    end;
  1117.  
  1118. procedure GenMouse.SetAccel( threshold : integer );
  1119.    begin
  1120.       regs.AX := $13;
  1121.       regs.DX := threshold;
  1122.       intr($33,regs);
  1123.    end;
  1124.  
  1125. procedure GenMouse.GetPosition( var BtnStatus, XPos, YPos : integer );
  1126.    begin
  1127.       regs.AX := $03;
  1128.       intr($33,regs);
  1129.       Btnstatus := regs.BX;
  1130.       XPos := X; YPos := Y;
  1131.    end;
  1132.  
  1133. procedure GenMouse.SetPosition( XPos, YPos : integer );
  1134.    begin
  1135.       regs.AX := $04;
  1136.       regs.CX := XPos;
  1137.       regs.DX := YPos;
  1138.       intr($33,regs);
  1139.    end;
  1140.  
  1141. procedure GenMouse.SetRatio( horPix, verPix : integer );
  1142.   begin
  1143.      regs.AX := $0F;
  1144.      regs.CX := horPix;
  1145.      regs.DX := verPix;
  1146.      intr($33,regs);
  1147.   end;
  1148.  
  1149. procedure GenMouse.QueryBtnDn( button : integer; var mouse : Position );
  1150.    begin
  1151.       regs.AX := $05;
  1152.       regs.BX := button;
  1153.       intr($33,regs);
  1154.       mouse.BtnStatus := regs.AX;
  1155.       mouse.opCount := regs.BX;
  1156.       mouse.XPos    := regs.CX;
  1157.       mouse.YPos    := regs.DX;
  1158.    end;
  1159.  
  1160. procedure GenMouse.QueryBtnUp( button : integer; var mouse : Position );
  1161.    begin
  1162.       regs.AX := $06;
  1163.       regs.BX := button;
  1164.       intr($33,regs);
  1165.       mouse.BtnStatus := regs.AX;
  1166.       mouse.opCount := regs.BX;
  1167.       mouse.XPos    := regs.CX;
  1168.       mouse.YPos    := regs.DX;
  1169.    end;
  1170.  
  1171. procedure GenMouse.SetLimits( XPosMin, YPosMin, XPosMax, YPosMax : integer );
  1172.    begin
  1173.       regs.AX := $07;
  1174.       regs.CX := Lower(XPosMin,XPosMax);
  1175.       regs.DX := Upper(XPosMin,XPosMax);
  1176.       intr($33,regs);
  1177.       regs.AX := $08;
  1178.       regs.CX := Lower(YPosMin,YPosMax);
  1179.       regs.DX := Upper(YPosMin,YPosMax);
  1180.       intr($33,regs);
  1181.    end;
  1182.  
  1183. procedure GenMouse.ReadMove( var XMove, Ymove : integer );
  1184.    begin
  1185.       regs.AX := $0B;
  1186.       intr($33,regs);
  1187.       XMove := regs.CX;
  1188.       Ymove := regs.DX;
  1189.    end;
  1190.  
  1191. procedure MousePlot( x, y : integer; Color : byte );
  1192.  
  1193.   var Segment : byte;
  1194.  
  1195.   begin
  1196.     if (y = 102) AND (x < 256) then Segment := 0
  1197.          else if (y = 204) AND (x < 512) then Segment := 1
  1198.           else if (y = 307) AND (x < 128) then  Segment := 2
  1199.            else if (y = 409) AND (x < 384) then Segment := 3
  1200.             else if y < 102 then Segment := 0
  1201.              else if y < 204 then Segment := 1
  1202.               else if y < 307 then Segment := 2
  1203.                else if y < 409 then Segment := 3
  1204.                 else Segment := 4;
  1205.    LoadWriteBank( Segment );
  1206.     asm
  1207.       mov ax, Bytes_per_Line
  1208.       mov bx, y
  1209.       mul bx
  1210.       add ax, x
  1211.       mov di, ax
  1212.       mov ax, 0a000h
  1213.       mov es, ax
  1214.       mov al, Color
  1215.       mov es:[di], al
  1216.     end;
  1217.   end;
  1218.  
  1219. procedure MPlot( xx, yy : integer );
  1220.  
  1221.   var TX, TY, x, y : integer;
  1222.  
  1223.   begin
  1224.     for TY := 0 to 3 do
  1225.       begin
  1226.         y := yy + TY;
  1227.         if y < GetMaxY then
  1228.         for TX := 0 to 3 do
  1229.           begin
  1230.             x := xx + TX;
  1231.             if (MP[TX,TY] <> 0) AND (x < GetMaxX) then
  1232.                 MousePlot( x, y, MP[TX,TY] );
  1233.           end;
  1234.       end;
  1235.   end;
  1236.  
  1237. procedure GraphicMouse.Show( ShowMouse : boolean );
  1238.  
  1239.   var i, j, x, y : integer;
  1240.  
  1241.   begin
  1242.     if ShowMouse then
  1243.       begin
  1244.         for i := 0 to 3 do
  1245.           for j := 0 to 3 do
  1246.             ColOld[ i, j ] := GetPixel( OldX + i, OldY + j );
  1247.         MPlot( OldX, OldY );
  1248.       end
  1249.     else
  1250.       for i := 0 to 3 do
  1251.         begin
  1252.           x := OldX + i;
  1253.           for j := 0 to 3 do
  1254.             begin
  1255.               y := OldY + j;
  1256.               MousePlot( x, y, ColOld[i,j] );
  1257.             end;
  1258.         end;
  1259.   end;
  1260.  
  1261. procedure GraphicMouse.CheckMouse;
  1262.  
  1263.   var XNew, YNew, i, j : integer;
  1264.  
  1265.   begin
  1266.     ReadMove( XNew, YNew );
  1267.     if ((X+XNew) <> X) OR ((Y+YNew) <> Y) then
  1268.       begin
  1269.         if ((X + XNew) > GetMaxX-1) then X := GetMaxX-1
  1270.           else if ((X + XNew) < 0) then X := 0
  1271.             else X := X + XNew;
  1272.         if ((Y + YNew) > GetMaxY-1) then Y := GetMaxY-1
  1273.           else if ((Y + YNew) < 0) then Y := 0
  1274.             else Y := Y + YNew;
  1275.         Show( False );
  1276.         for i := 0 to 3 do
  1277.           for j := 0 to 3 do
  1278.             ColOld[ i, j ] := GetPixel( X + i, Y + j );
  1279.         MPlot( X, Y );
  1280.         OldX := X; OldY := Y;
  1281.       end;
  1282.   end;
  1283.  
  1284.  
  1285. procedure GraphicMouse.Initialize;
  1286.  
  1287.    var mStatus : boolean;
  1288.        Btn : integer;
  1289.  
  1290.    begin
  1291.       Reset( mStatus, Btn );
  1292.       if mStatus then
  1293.         begin
  1294.           X := GetMaxX div 2;
  1295.           Y := GetMaxY div 2;
  1296.           OldX := X; OldY := Y;
  1297.           SetLimits( 0, 0, GetMaxX, GetMaxY );
  1298.           SetPosition( X, Y );
  1299.           MP[0,0] := 255; MP[0,1] := 255;  {     0 1 2 3  }
  1300.           MP[0,2] := 255; MP[0,3] := 255;  {  0  # # # #  }
  1301.           MP[1,0] := 255; MP[1,1] := 1;    {  1  # * * #  }
  1302.           MP[1,2] := 1;   MP[1,3] := 255;  {  2  # *      }
  1303.           MP[2,0] := 255; MP[2,1] := 1;    {  3  # #      }
  1304.           MP[2,2] := 0;   MP[2,3] := 0;    { Mouse Pointer }
  1305.           MP[3,0] := 255; MP[3,1] := 255;
  1306.           MP[3,2] := 0;   MP[3,3] := 0;
  1307.           Show( True );                    { Transparent = 0 }
  1308.         end;                               { White = 255     }
  1309.    end;                                    { Black = 1       }
  1310.  
  1311. procedure GraphicMouse.ExitSVGA;
  1312.    begin
  1313.       SetLimits( lo(WindMin)*8, hi(WindMin)*8, lo(WindMax)*8, hi(WindMax)*8);
  1314.       regs.AX := $0A;
  1315.       regs.BX := 1;
  1316.       regs.CX := 6;
  1317.       regs.DX := 7;
  1318.       intr($33,regs);
  1319.       SetPosition( 0, 0 );
  1320.       regs.AX := $02;
  1321.       intr($33,regs);
  1322.    end;
  1323.  
  1324. begin
  1325.   SetFont( StandardFont );
  1326.   SetFontColor( 253, 0, True );
  1327.   PresentSeg := 0;
  1328.   Sused := False;
  1329.   Fused := False;
  1330. end.