home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l045 / 2.ddi / GRAFCGA.DVR < prev    next >
Encoding:
Text File  |  1987-12-23  |  16.4 KB  |  622 lines

  1. (********************************************************************)
  2. (*                         GRAPHIX TOOLBOX 4.0                      *)
  3. (*       Copyright (c) 1985, 87 by  Borland International, Inc.     *)
  4. (*                                                                  *)
  5. (*           Graphics module for IBM Color/Graphics Adapter         *)
  6. (********************************************************************)
  7.  
  8. unit GDriver;
  9.  
  10. interface
  11.  
  12. {$I Float.inc}  { Determines what type Float means. }
  13.  
  14. uses
  15.   Dos, Crt;
  16.  
  17. {$IFOPT N+}
  18. type
  19.   Float = Double; { 8 byte real, requires 8087 math chip }
  20.  
  21. {$ELSE}
  22. type
  23.   Float = real;   { 6 byte real, no math chip required }
  24.  
  25. {$ENDIF}
  26.  
  27. const
  28.   MaxWorldsGlb = 4;
  29.   MaxWindowsGlb = 16;
  30.   MaxPiesGlb = 10;
  31.   MaxPlotGlb = 100;
  32.   StringSizeGlb = 80;
  33.   HeaderSizeGlb = 10;
  34.   RamScreenGlb : boolean = true;
  35.   CharFile : string[StringSizeGlb] = '4x6.fon';
  36.   MaxProcsGlb = 27;
  37.   MaxErrsGlb = 7;
  38.   AspectFactor   = 0.44;           { Aspect ratio for a true circle }
  39.   ScreenSizeGlb  = 8191;           { Total size -1 of the screen in words }
  40.   HardwareGrafBase : word = $B800; { Location of the hardware screen }
  41.   XMaxGlb        = 79;             { Number of bytes -1 in one screen line }
  42.   XScreenMaxGlb  = 639;            { Number of pixels -1 in one screen line }
  43.   YMaxGlb        = 199;            { Number of lines -1 on the screen }
  44.   IVStepGlb      = 2;              { Initial value of VStepGlb }
  45.   MinForeground : word = 0;        { Lowest allowable foreground color }
  46.   MaxForeground : word = 15;       { Highest allowable foreground color }
  47.   MinBackground : word = 0;        { Lowest allowable background color }
  48.   MaxBackground : word = 0;        { Highest allowable background color }
  49. type
  50.   WrkString = string[StringSizeGlb];
  51.   WrkStringPtr = ^WrkString;
  52.   WorldType = record
  53.                 X1, Y1, X2, Y2 : Float;
  54.               end;
  55.   WindowType = record
  56.                  X1, Y1, X2, Y2 : integer;
  57.                  Header : WrkString;
  58.                  Drawn, Top : boolean;
  59.                  Size : word;
  60.                end;
  61.   Worlds = array[1..MaxWorldsGlb] of WorldType;
  62.   Windows = array[1..MaxWindowsGlb] of WindowType;
  63.   PlotArray = array[1..MaxPlotGlb, 1..2] of Float;
  64.   Character = array[1..3] of byte;
  65.   CharArray = array[32..126] of character;
  66.   PieType = record
  67.               Area : Float;
  68.               Text : WrkString;
  69.             end;
  70.   PieArray = array[1..MaxPiesGlb] of PieType;
  71.   BackgroundArray = array[0..7] of byte;
  72.   LineStyleArray = array[0..7] of boolean;
  73.   ScreenType        = array[0..ScreenSizeGlb] of word;
  74.   ScreenPointer     = ^ScreenType;
  75.   WindowStackRecord = record
  76.                         W : WindowType;
  77.                         Contents : ScreenPointer;
  78.                       end;
  79.   Stacks            = array[1..MaxWindowsGlb] of WindowStackRecord;
  80.  
  81. var
  82.   X1WldGlb, X2WldGlb, Y1WldGlb, Y2WldGlb, AxGlb, AyGlb, BxGlb, ByGlb : Float;
  83.   X1RefGlb, X2RefGlb, Y1RefGlb, Y2RefGlb : integer;
  84.   LinestyleGlb, MaxWorldGlb, MaxWindowGlb, WindowNdxGlb, WorldNdxGlb : integer;
  85.   X1Glb, X2Glb, Y1Glb, Y2Glb : integer;
  86.   XTextGlb, YTextGlb, VStepGlb : integer;
  87.   PieGlb, DirectModeGlb, ClippingGlb, AxisGlb, HatchGlb : boolean;
  88.   MessageGlb, BrkGlb, HeaderGlb, TopGlb, GrafModeGlb : boolean;
  89.   CntGlb, ColorGlb : byte;
  90.   ErrCodeGlb : integer;
  91.   LineStyleArrayGlb : LineStyleArray;
  92.   ErrorProc : array[0..MaxProcsGlb] of WrkStringPtr;
  93.   ErrorCode : array[0..MaxErrsGlb] of WrkStringPtr;
  94.   PcGlb : string[40];
  95.   AspectGlb : Float;
  96.   GrafBase : word;
  97.   World : Worlds;
  98.   GrafWindow : Windows;
  99.   CharSet : CharArray;
  100.   ScreenGlb : ScreenPointer;
  101.   Stack : Stacks;
  102.  
  103. function BaseAddress(Y : word) : word;
  104. { Calculate address of scanline Y }
  105.  
  106. procedure Error(ErrProc, ErrCode : integer);
  107.  
  108. function HardwarePresent : boolean;
  109. { Test for the presence of a graphics card }
  110.  
  111. procedure AllocateRAMScreen;
  112. { Allocates the RAM screen and makes sure that
  113.   ScreenGlb is on a segment (16 byte) boundary }
  114.  
  115. procedure LeaveGraphic;
  116. { Exit from graphics mode and clear the screen }
  117.  
  118. procedure DC(C : byte);
  119. { Draw the character C at the position XTextGlb, YTextGlb }
  120.  
  121. procedure SetIBMPalette(PaletteNumber, Color : word);
  122. { Set up the palette registers on the IBM CGA }
  123.  
  124. procedure SetForegroundColor(Color : word);
  125. { Set the foreground color }
  126.  
  127. procedure SetBackgroundColor(Color : word);
  128. { Set the background color }
  129.  
  130. procedure ClearScreen;
  131. { Clear the displayed screen }
  132.  
  133. procedure EnterGraphic;
  134. { Enter graphics mode }
  135.  
  136. procedure DP(X, Y : word);
  137. { Plot a pixel at (X, Y) }
  138.  
  139. function PD(X, Y : word) : boolean;
  140. { Return true if the color of the pixel at (X, Y) matches ColorGlb }
  141.  
  142. procedure SetBackground8(Background : BackgroundArray);
  143. { Fills the active display with the specified bit pattern }
  144.  
  145. procedure SetBackground(Byt : byte);
  146. { Determines the background pattern of the active window }
  147.  
  148. procedure DrawStraight(X1, X2, Y : word);
  149. { Draw a horizontal line from X1,Y to X2,Y }
  150.  
  151. procedure SaveScreen(FileName : WrkString);
  152. { Save the current screen on disk using FileName }
  153.  
  154. procedure LoadScreen(FileName : WrkString);
  155. { Load screen from file FileName }
  156.  
  157. procedure SwapScreen;
  158. { Exchanges the contents of the displayed
  159.   screen with the contents of the RAM screen  }
  160.  
  161. procedure CopyScreen;
  162. { Copies the active screen onto the inactive screen }
  163.  
  164. procedure InvertScreen;
  165. { Inverts the image on the active screen }
  166.  
  167. implementation
  168.  
  169.  
  170. const
  171.   GrafMode = $0006;   { BIOS Interrupt 10 AX register }
  172.  
  173.   FontLoaded         : boolean = false; { Has the font been loaded yet? }
  174.   ForegroundColorGlb : word = 15;
  175.  
  176. type
  177.   FontChar = array[0..7] of byte;
  178.   GrfFont  = array[0..255] of FontChar;
  179.  
  180. var
  181.   Font          : GrfFont;
  182.   DisplayType   : (IBMPCjr, IBMCGA, IBMEGA, NoDisplay);
  183.   SaveStateGlb  : word;
  184.  
  185. function BaseAddress{(Y : word) : word};
  186. { Calculate address of scanline Y }
  187. begin
  188.   BaseAddress:=(Y and 1) shl 13 + (Y and -2) shl 5 + (Y and -2) shl 3;
  189. end; { BaseAddress }
  190.  
  191. procedure Error{(ErrProc, ErrCode : integer)};
  192. var
  193.   XLoc, YLoc : integer;
  194.   Ch : char;
  195.  
  196. begin { Error }
  197.   if not (ErrProc in [0..MaxProcsGlb]) then
  198.   begin
  199.     LeaveGraphic;
  200.     WriteLn('FATAL Error 1: illegal procedure number ', ErrProc);
  201.     Halt;
  202.   end;
  203.   if not (ErrCode in [0..MaxErrsGlb]) then
  204.   begin
  205.     LeaveGraphic;
  206.     WriteLn('FATAL Error 2: illegal Error code ', ErrCode);
  207.     Halt;
  208.   end;
  209.   ErrCodeGlb := ErrCode;
  210.   if BrkGlb then
  211.     LeaveGraphic;
  212.   if MessageGlb or BrkGlb then
  213.   begin
  214.     XLoc := XTextGlb;
  215.     YLoc := YTextGlb;
  216.     GotoXY(1, 24);
  217.     ClrEOL;
  218.     WriteLn('Turbo Graphix Error #', ErrCode, ' in procedure #', ErrProc);
  219.     if MessageGlb then
  220.     begin
  221.       ClrEOL;
  222.       Write('(', ErrorCode[ErrCode]^, ' in ', ErrorProc[ErrProc]^, ')');
  223.     end;
  224.   end;
  225.   if BrkGlb then
  226.     Halt
  227.   else if MessageGlb then
  228.     begin
  229.       Write('.  Hit enter: ');
  230.       repeat
  231.         Ch := ReadKey;
  232.       until (Ch = ^M) or (Ch = ^C);
  233.       if Ch = ^C then
  234.       begin
  235.         LeaveGraphic;
  236.         Halt;
  237.       end;
  238.       GotoXY(XLoc, YLoc);
  239.     end;
  240. end; { Error }
  241.  
  242. function HardwarePresent{ : boolean};
  243. { Test for the presence of a graphics card }
  244. var
  245.   EquipFlag       : word;
  246.   Info, EGASwitch : byte;
  247.   HP              : boolean;
  248.   Regs            : Registers;
  249.  
  250. begin
  251.   HP := false;
  252.   DisplayType := NoDisplay;
  253.   with Regs do
  254.   begin
  255.     Intr($11, Regs);
  256.     EquipFlag := AX;
  257.     AH := $12;
  258.     BL := $10;
  259.     Intr($10, Regs);
  260.     EGASwitch := CL;
  261.     Info := BH;
  262.   end;
  263.  
  264.   if Mem[$F000:$FFFE] = $FD then                             { PCjr }
  265.     begin
  266.       MinForeground := 0;        { Actually only 0 and 15 are valid }
  267.       MaxForeground := 15;
  268.       MinBackground := 0;
  269.       MaxBackground := 15;
  270.       DisplayType := IBMPCjr;
  271.       HP := true;
  272.     end
  273.   else if ((EquipFlag and 52) in [0,16,32]) and (Info = 0) then
  274.     begin                       { EGA present, active, and in color }
  275.       MinForeground := 0;
  276.       MaxForeground := 15;
  277.       MinBackground := 0;
  278.       MaxBackground := 15;
  279.       DisplayType := IBMEGA;
  280.       HP := true;
  281.     end;
  282.   if not HP then
  283.     if ((EquipFlag and 48) in [16,32]) or                     { CGA }
  284.        (((EquipFlag and 52) = 4) and           { EGA but not active }
  285.        (EGASwitch in [4,5,10,11])) then               { EGA is mono }
  286.       begin
  287.         MinForeground := 0;
  288.         MaxForeground := 15;
  289.         MinBackground := 0;
  290.         MaxBackground := 0;
  291.         DisplayType := IBMCGA;
  292.         HP := true;
  293.       end;
  294.     HardwarePresent := HP;
  295. end; { HardwarePresent }
  296.  
  297. procedure AllocateRAMScreen;
  298. { Allocates the RAM screen and makes sure that
  299.   ScreenGlb is on a segment (16 byte) boundary }
  300. var
  301.   BytePtr : ^byte;
  302. begin
  303.   New(ScreenGlb);
  304.   while Ofs(ScreenGlb^) <> 0 do   { Make absolutely certain that ScreenGlb }
  305.   begin                           { is on a segment (16 byte) boundary!    }
  306.     Dispose(ScreenGlb);
  307.     New(BytePtr);
  308.     New(ScreenGlb);
  309.   end;
  310. end; { AllocateRAMScreen }
  311.  
  312. {$L GrafCGA.OBJ}
  313. procedure DC{(C : byte)}; external;
  314.  
  315. procedure DP{(X, Y : word)}; external;
  316.  
  317. procedure SwapScreen; external;
  318.  
  319. procedure InvertScreen; external;
  320.  
  321. {$F+}
  322. function WriteGrafChars(var F : TextRec) : integer;
  323. { Used to output graphics characters through the standard output channel. }
  324. const
  325.   BackSpace = #8;
  326.   LineFeed  = #10;
  327.   Return    = #13;
  328. var
  329.   I : integer;
  330. begin
  331.   with F do
  332.     if Mode = fmOutput then
  333.     begin
  334.       if BufPos > BufEnd then
  335.       begin
  336.         for I := BufEnd to Pred(BufPos) do  { Flush the output buffer }
  337.         begin
  338.           case BufPtr^[I] of
  339.             BackSpace : if XTextGlb > 1 then
  340.                           DEC(XTextGlb);
  341.  
  342.             LineFeed  : if YTextGlb < 25 then
  343.                           INC(YTextGlb);
  344.  
  345.             Return    : XTextGlb := 1;
  346.           else
  347.             DC(ORD(BufPtr^[I]));
  348.             if XTextGlb < 80 then
  349.               INC(XTextGlb);
  350.           end; { case }
  351.         end; { for }
  352.       end;
  353.       BufPos := BufEnd;
  354.     end; { if }
  355.   WriteGrafChars := 0;
  356. end; { WriteGrafChars }
  357.  
  358. function GrafCharZero(var F : TextRec) : integer;
  359. { Called when standard output is opened and closed }
  360. begin
  361.   GrafCharZero := 0;
  362. end; { GrafCharZero }
  363. {$F-}
  364.  
  365. var
  366.   OldOutput : Text; { Stores output I/O channel }
  367.  
  368. procedure GrafCharsON;
  369. { Redirects standard output to the WriteGrafChars function. }
  370. begin
  371.   Move(Output, OldOutput, SizeOf(Output));  { Save old output channel }
  372.   with TextRec(Output) do
  373.   begin
  374.     OpenFunc:=@GrafCharZero;       { no open necessary }
  375.     InOutFunc:=@WriteGrafChars;    { WriteGrafChars gets called for I/O }
  376.     FlushFunc:=@WriteGrafChars;    { WriteGrafChars flushes automatically }
  377.     CloseFunc:=@GrafCharZero;      { no close necessary }
  378.     Name[0]:=#0;
  379.   end;
  380. end; { GrafCharsON }
  381.  
  382. procedure GrafCharsOFF;
  383. { Restores original output I/O channel }
  384. begin
  385.   Move(OldOutput, Output, SizeOf(OldOutput));
  386. end; { GrafCharsOFF }
  387.  
  388. procedure LeaveGraphic;
  389. { Exit from graphics mode and clear the screen }
  390. var
  391.   Regs : Registers;
  392. begin
  393.   Regs.AX := SaveStateGlb;
  394.   Intr($10, Regs);
  395.   GrafCharsOFF;
  396.   GrafModeGlb := false;
  397. end; { LeaveGraphic }
  398.  
  399. procedure SetIBMPalette{(PaletteNumber, Color : word)};
  400. { Set up the palette registers on the IBM CGA }
  401. var
  402.   Regs : Registers;
  403. begin
  404.   with Regs do
  405.   begin
  406.     if PaletteNumber <> 2 then
  407.       begin
  408.         AH := $0B;
  409.         BL := Color;
  410.         BH := PaletteNumber;
  411.       end
  412.     else
  413.       begin
  414.         AX := $1000;
  415.         BL := 1;
  416.         BH := Color;
  417.       end;
  418.     Intr($10, Regs);
  419.   end;
  420. end; { SetIBMPalette }
  421.  
  422. procedure SetForegroundColor{(Color : word)};
  423. { Set the foreground color }
  424. begin
  425.   case DisplayType of
  426.     IBMPCjr : SetIBMPalette(1, 1 - (Color and 1));
  427.     IBMCGA  : SetIBMPalette(0, Color);
  428.     IBMEGA  : SetIBMPalette(2, Color);
  429.   end;
  430.   ForegroundColorGlb := Color;
  431. end; { SetForegroundColor }
  432.  
  433. procedure SetBackgroundColor{(Color : word)};
  434. { Set the background color }
  435. begin
  436.   case DisplayType of
  437.     IBMPCjr,
  438.     IBMEGA  : SetIBMPalette(0, Color);
  439.   end;
  440.   if DisplayType = IBMEGA then
  441.     SetIBMPalette(2, ForegroundColorGlb);
  442. end; { SetBackgroundColor }
  443.  
  444. procedure ClearScreen;
  445. { Clear the displayed screen }
  446. begin
  447.   FillChar(Mem[GrafBase:0000], ScreenSizeGlb shl 1, 0);
  448. end; { ClearScreen }
  449.  
  450. procedure EnterGraphic;
  451. { Enter graphics mode }
  452. var
  453.   Regs     : Registers;
  454.   FontFile : file of GrfFont;
  455. begin
  456.   if not FontLoaded then
  457.   begin
  458.     Assign(FontFile, '8x8.FON');
  459.     {$I-} Reset(FontFile); {$I+}
  460.     if IOresult = 0 then
  461.       begin
  462.         Read(FontFile, Font);
  463.         Close(FontFile);
  464.       end
  465.     else
  466.       FillChar(Font, SizeOf(Font), 0);
  467.     FontLoaded := true;
  468.   end;
  469.   SaveStateGlb := 10;
  470.   Regs.AX := $0F00;
  471.   Intr($10, Regs);
  472.   if (Regs.AL < 4) or (SaveStateGlb = 10) then
  473.     SaveStateGlb := Regs.AL;
  474.   Regs.AX := GrafMode;
  475.   Intr($10, Regs);
  476.   SetForegroundColor(MaxForeground);
  477.   if not GrafModeGlb then
  478.     GrafCharsON;
  479.   GrafModeGlb := true;
  480. end; { EnterGraphic }
  481.  
  482. function PD{(X, Y : word) : boolean};
  483. { Return true if the color of the pixel at (X, Y) matches ColorGlb }
  484. begin
  485.   PD := (ColorGlb = 0) xor (Mem[GrafBase:BaseAddress(Y) + X shr 3]
  486.                        and (128 shr (X and 7)) <> 0);
  487. end; { PD }
  488.  
  489. procedure SetBackground8{(Background : BackgroundArray)};
  490. { Fills the active display with the specified bit pattern }
  491. var
  492.   I : word;
  493. begin
  494.   for I := Y1RefGlb to Y2RefGlb do
  495.     FillChar(Mem[GrafBase:BaseAddress(I) + X1RefGlb], X2RefGlb - X1RefGlb + 1,
  496.              Background[I and 7]);
  497. end; { SetBackground8 }
  498.  
  499. procedure SetBackground{(Byt : byte)};
  500. { Determines the background pattern of the active window }
  501. var
  502.   Bk : BackgroundArray;
  503. begin
  504.   FillChar(Bk, 8, Byt);
  505.   SetBackground8(Bk);
  506. end; { SetBackground }
  507.  
  508. procedure DrawStraight{(X1, X2, Y : integer)};
  509. { Draw a horizontal line from X1,Y to X2,Y }
  510. var
  511.   I, X          : word;
  512.   DirectModeLoc : boolean;
  513. begin
  514.   if (not ((X1 < 0) or (X1 > XMaxGlb shl 3 + 7)) and not ((X2 < 0) or
  515.      (X2 > XMaxGlb shl 3 + 7)) and ((Y >= 0) and (Y <= YMaxGlb))) then
  516.   begin
  517.     DirectModeLoc := DirectModeGlb;
  518.     DirectModeGlb := true;
  519.     if X1 > X2 then
  520.     begin
  521.       X := X1;
  522.       X1 := X2;
  523.       X2 := X;
  524.     end;
  525.     if X2 - X1 < 16 then
  526.       for X := X1 to X2 do
  527.         DP(X, Y)
  528.     else
  529.       begin
  530.         X1 := X1 + 8;
  531.         for I := (X1 - 8) to (X1 and -8) do
  532.           DP(I, Y);
  533.         for I := (X2 and -8) to X2 do
  534.           DP(I, Y);
  535.         FillChar(Mem[GrafBase:BaseAddress(Y) + (X1 shr 3)],
  536.                 (X2 shr 3) - (X1 shr 3), ColorGlb);
  537.       end;
  538.     DirectModeGlb := DirectModeLoc;
  539.   end;
  540. end; { DrawStraight }
  541.  
  542. procedure SaveScreen{(FileName : WrkString)};
  543. { Save the current screen on disk using FileName }
  544. type
  545.   PicFile = file of ScreenType;
  546. var
  547.   Picture     : ScreenPointer;
  548.   PictureFile : PicFile;
  549.   IOErr       : boolean;
  550.  
  551. procedure IOCheck;
  552. begin
  553.   IOErr := IOresult <> 0;
  554.   if IOErr then
  555.     Error(27, 5);
  556. end; { IOCheck }
  557.  
  558. begin
  559.   if FileName <> '' then
  560.     begin
  561.       IOErr := false;
  562.       Picture := Ptr(GrafBase, 0);
  563.       Assign(PictureFile, FileName);
  564.       {$I-} Rewrite(PictureFile); {$I+}
  565.       IOCheck;
  566.       if not IOErr then
  567.       begin
  568.         {$I-} Write(PictureFile, Picture^); {$I+}
  569.         IOCheck;
  570.       end;
  571.       if not IOErr then
  572.       begin
  573.         {$I-} Close(PictureFile); {$I+}
  574.         IOCheck;
  575.       end;
  576.     end
  577.   else
  578.     Error(27, 5);
  579. end; { SaveScreen }
  580.  
  581. procedure LoadScreen{(FileName : WrkString)};
  582. { Load screen from file FileName }
  583. type
  584.   PicFile = file of ScreenType;
  585. var
  586.   Picture     : ScreenPointer;
  587.   PictureFile : PicFile;
  588. begin
  589.   if FileName <> '' then
  590.     begin
  591.       Picture := Ptr(GrafBase, 0);
  592.       Assign(PictureFile, FileName);
  593.       {$I-} Reset(PictureFile); {$I+}
  594.       if IOresult <> 0 then
  595.         Error(11, 5)
  596.       else
  597.         begin
  598.           Read(PictureFile, Picture^);
  599.           Close(PictureFile);
  600.         end;
  601.     end
  602.   else
  603.     Error(11, 5);
  604. end; { LoadScreen }
  605.  
  606. procedure CopyScreen;
  607. { Copies the active screen onto the inactive screen }
  608. var
  609.   ToBase : word;
  610. begin
  611.   if RamScreenGlb then
  612.   begin
  613.     if GrafBase = HardwareGrafBase then
  614.       ToBase := Seg(ScreenGlb^)
  615.     else
  616.       ToBase := HardwareGrafBase;
  617.     Move(Mem[GrafBase:0000], Mem[ToBase:0000], ScreenSizeGlb shl 1);
  618.   end;
  619. end; { CopyScreen }
  620.  
  621. end. { GDriver }
  622.