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

    {
     STG>Does anyone know off hand if I can be in text mode and window in a
     STG>window and put the wondow only in graphics mode?
     STG>I have a program that I need to have a graph in.  Does anyone have some
     STG>code for using the PLOT procedure to plot variables.  The values for
     STG>the Y axis are from 1 - 2000, and for the X axis from 1 - 24.

            Yes, it's possible... sort of.   If you have a VGA (or
    EGA) you can have 2 separate character sets on screen at once.
    Use one character set for text, and redefine the other for your
    graphics window.  The only problem is that your graphics window
    can only be composed of 256 characters total.  So, a 16 X 16
    character square would only give you a vertical resolution of 256
    pixels and a horizontal resolution of 128 pixels.  The following
    code is an example of how one would do this.

                                                    Dave

    }

    Program GraphicsInTextModeExample;

    {================================================

             Graphics In Text Mode Example
                Programmed by David Dahl
                        12/24/93
        This program and source are PUBLIC DOMAIN

     ------------------------------------------------

       This example uses a second font as a pseudo-
       graphics window.  This program requires VGA.

     ================================================}

    Uses  CRT;

    Const { Dimentions of The Graphics Window in Characters }
          ChrSizeX = 32;
          ChrSizeY = 256 DIV ChrSizeX;
          { Dimentions of The Graphics Window in Pixels }
          MaxX     = ChrSizeX * 8;
          MaxY     = ChrSizeY * 16;

    {-[ Set Character Width to 8 Pixels ]-------------------------------------}
    Procedure SetCharWidthTo8; Assembler;
    Asm
       { Change To 640 Horz Res }
       MOV DX, $3CC
       IN  AL, DX
       AND AL, Not(4 OR 8)
       MOV DX, $3C2
       OUT DX, AL
       { Turn Off Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 0
       OUT DX, AL
       { Reset Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 3
       OUT DX, AL
       { Switch To 8 Pixel Wide Fonts }
       MOV DX, $3C4
       MOV AL, 1
       OUT DX, AL
       MOV DX, $3C5
       IN  AL, DX
       OR  AL, 1
       OUT DX, AL
       { Turn Off Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 0
       OUT DX, AL
       { Reset Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 3
       OUT DX, AL
       { Center Screen }
       MOV DX, $3DA
       IN  AL, DX
       MOV DX, $3C0
       MOV AL, $13 OR 32
       OUT DX, AL
       MOV AL, 0
       OUT DX, AL
    End;
    {-[ Turn On Dual Fonts ]--------------------------------------------------}
    Procedure SetDualFonts; Assembler;
    ASM
       { Set Fonts 0 & 1 }
       MOV BL, 4
       MOV AX, $1103
       INT $10
    END;
    {-[ Turn On Access To Font Memory ]---------------------------------------}
    Procedure SetAccessToFontMemory; Assembler;
    ASM
       { Turn Off Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 1
       OUT DX, AL
       { Reset Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 3
       OUT DX, AL
       { Change From Odd/Even Addressing to Linear }
       MOV DX, $3C4
       MOV AL, 4
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 7
       OUT DX, AL
       { Switch Write Access To Plane 2 }
       MOV DX, $3C4
       MOV AL, 2
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 4
       OUT DX, AL
       { Set Read Map Reg To Plane 2 }
       MOV DX, $3CE
       MOV AL, 4
       OUT DX, AL
       MOV DX, $3CF
       MOV AL, 2
       OUT DX, AL
       { Set Graphics Mode Reg }
       MOV DX, $3CE
       MOV AL, 5
       OUT DX, AL
       MOV DX, $3CF
       MOV AL, 0
       OUT DX, AL
       { Set Misc. Reg }
       MOV DX, $3CE
       MOV AL, 6
       OUT DX, AL
       MOV DX, $3CF
       MOV AL, 12
       OUT DX, AL
    End;
    {-[ Turn On Access to Text Memory ]---------------------------------------}
    Procedure SetAccessToTextMemory; Assembler;
    ASM
       { Turn Off Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 1
       OUT DX, AL
       { Reset Sequence Controller }
       MOV DX, $3C4
       MOV AL, 0
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 3
       OUT DX, AL
       { Change To Odd/Even Addressing }
       MOV DX, $3C4
       MOV AL, 4
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 3
       OUT DX, AL
       { Switch Write Access }
       MOV DX, $3C4
       MOV AL, 2
       OUT DX, AL
       MOV DX, $3C5
       MOV AL, 3  {?}
       OUT DX, AL
       { Set Read Map Reg }
       MOV DX, $3CE
       MOV AL, 4
       OUT DX, AL
       MOV DX, $3CF
       MOV AL, 0
       OUT DX, AL
       { Set Graphics Mode Reg }
       MOV DX, $3CE
       MOV AL, 5
       OUT DX, AL
       MOV DX, $3CF
       MOV AL, $10
       OUT DX, AL
       { Set Misc. Reg }
       MOV DX, $3CE
       MOV AL, 6
       OUT DX, AL
       MOV DX, $3CF
       MOV AL, 14
       OUT DX, AL
    End;
    {-[ Clear The Pseudo-Graphics Window by Clearing Font Definition ]--------}
    Procedure ClearGraphicsWindow;
    Begin
         SetAccessToFontMemory;
         FillChar (MEM[$B800:$4000], 32 * 256, 0);
         SetAccessToTextMemory;
    End;
    {-[ Turn The Cursor Off ]-------------------------------------------------}
    Procedure TurnCursorOff; Assembler;
    ASM
       MOV DX, $3D4
       MOV AL, $0A
       OUT DX, AL
       MOV DX, $3D5
       IN  AL, DX
       OR  AL, 32
       OUT DX, AL
    End;
    {-[ Turn The Cursor On ]--------------------------------------------------}
    Procedure TurnCursorOn; Assembler;
    ASM
       MOV DX, $3D4
       MOV AL, $0A
       OUT DX, AL
       MOV DX, $3D5
       IN  AL, DX
       AND AL, Not(32)
       OUT DX, AL
    End;
    {-[ Set Up The Pseudo-Graphics Window ]-----------------------------------}
    Procedure SetGraphicsWindow (XCoord, YCoord    : Byte;
                                 Color, BackGround : Byte);
    Var CounterX,
        CounterY  : Byte;
    Begin
         For CounterY := 0 to (ChrSizeY-1) do
             For CounterX := 0 to (ChrSizeX-1) do
                 MEMW[$B800:CounterX*2 + XCoord*2 + (YCoord * 80 * 2) +
                     (CounterY * 80 * 2)] :=
                       (CounterX + CounterY * ChrSizeX) OR
                       (((Color OR 8) OR ((BackGround AND 15) SHL 4)) SHL 8);
    End;
    {-[ Plot a Pixel in The Pseudo-Graphics Window ]--------------------------}
    Procedure PutPixel (Xin, Yin : Word);
    Var RealY,
        RealX      : Word;
    Begin
         If (Xin < MaxX) AND
            (Yin < MaxY)
         Then
         Begin
              RealX := (Xin DIV 8) * 32;
              RealY := (Yin MOD 16) + ((Yin DIV 16) * (32 * ChrSizeX));
              SetAccessToFontMemory;
              MEM[$B800:$4000 + RealX + RealY] :=
                  MEM[$B800:$4000 + RealX + RealY] OR (128 SHR (Xin MOD 8));
              SetAccessToTextMemory;
         End;
    End;
    {-[ Draw A Line ]---------------------------------------------------------}
    { OCTANT DDA Subroutine converted from the BASIC listing on pages 26 - 27 }
    { from the book _Microcomputer_Displays,_Graphics,_ And_Animation_ by     }
    { Bruce A. Artwick                                                        }
    Procedure Line (XStart, YStart, XEnd, YEnd : Word);
    Var StartX,
        StartY,
        EndX,
        EndY    : Word;
        DX,
        DY      : Integer;
        CNTDWN  : Integer;
        Errr    : Integer;
        Temp    : Integer;
        NotDone : Boolean;
    Begin
         NotDone := True;
         StartX := XStart;
         StartY := YStart;
         EndX   := XEnd;
         EndY   := YEnd;
         If EndX < StartX Then
         Begin
              { Mirror Quadrants 2,3 to 1,4 }
              Temp   := StartX;
              StartX := EndX;
              EndX   := Temp;
              Temp   := StartY;
              StartY := EndY;
              EndY   := Temp;
         End;
         DX := EndX - StartX;
         DY := EndY - StartY;
         If DY < 0 Then
         Begin
              If -DY > DX Then
              Begin
                   { Octant 7 Line Generation }
                   CntDwn := -DY + 1;
                   ERRR   := -(-DY shr 1);   {Fast Divide By 2}
                   While NotDone do
                   Begin
                        PutPixel (StartX, StartY);
                        Dec (CntDwn);
                        If CntDwn <= 0
                        Then NotDone := False
                        Else
                        Begin
                             Dec(StartY);
                             Inc(Errr, DX);
                             If Errr >= 0 Then
                             Begin
                                  Inc(StartX);
                                  Inc(Errr, DY);
                             End;
                        End;
                   End;
              End
              Else
              Begin
                   { Octant 8 Line Generation }
                   CntDwn := DX + 1;
                   ERRR   := -(DX shr 1);   {Fast Divide By 2}
                   While NotDone do
                   Begin
                        PutPixel (StartX, StartY);
                        Dec (CntDwn);
                        If CntDwn <= 0
                        Then NotDone := False
                        Else
                        Begin
                             Inc(StartX);
                             Dec(Errr, DY);
                             If Errr >= 0 Then
                             Begin
                                  Dec(StartY);
                                  Dec(Errr, DX);
                             End;
                        End;
                   End;
              End;
         End
         Else If DY > DX Then
              Begin
                   { Octant 2 Line Generation }
                   CntDwn := DY + 1;
                   ERRR   := -(DY shr 1);   {Fast Divide By 2}
                   While NotDone do
                   Begin
                        PutPixel (StartX, StartY);
                        Dec (CntDwn);
                        If CntDwn <= 0
                        Then NotDone := False
                        Else
                        Begin
                             Inc(StartY);
                             Inc(Errr, DX);
                             If Errr >= 0 Then
                             Begin
                                  Inc(StartX);
                                  Dec(Errr, DY);
                             End;
                        End;
                   End;
              End
              Else
              { Octant 1 Line Generation }
              Begin
                   CntDwn := DX + 1;
                   ERRR   := -(DX shr 1);   {Fast Divide By 2}
                   While NotDone do
                   Begin
                        PutPixel (StartX, StartY);
                        Dec (CntDwn);
                        If CntDwn <= 0
                        Then NotDone := False
                        Else
                        Begin
                             Inc(StartX);
                             Inc(Errr, DY);
                             If Errr >= 0 Then
                             Begin
                                  Inc(StartY);
                                  Dec(Errr, DX);
                             End;
                        End;
                   End;
              End;
    End;
    {-[ Draw A Circle ]-----------------------------------------------------}
    { Algorithm based on the Pseudocode from page 83 of the book _Advanced  }
    { Graphics_In_C_ by Nelson Johnson                                      }
    Procedure Circle (XCoord, YCoord, Radius : Integer);
    Var   d     : Integer;
          X, Y  : Integer;
        Procedure Symmetry (xc, yc, x, y : integer);
        Begin
             PutPixel ( X+xc,  Y+yc);
             PutPixel ( X+xc, -Y+yc);
             PutPixel (-X+xc, -Y+yc);
             PutPixel (-X+xc,  Y+yc);
             PutPixel ( Y+xc,  X+yc);
             PutPixel ( Y+xc, -X+yc);
             PutPixel (-Y+xc, -X+yc);
             PutPixel (-Y+xc,  X+yc);
        End;
    Begin
         x := 0;
         y := abs(Radius);
         d := 3 - 2 * y;
         While (x < y) do
         Begin
              Symmetry (XCoord, YCoord, x, y);
              if (d < 0) Then
                 inc(d, (4 * x) + 6)
              else
              Begin
                   inc (d, 4 * (x - y) + 10);
                   dec (y);
              End;
              inc(x);
         End;
         If x = y then
            Symmetry (XCoord, YCoord, x, y);
    End;
    {-[ Draw A Rectangle ]----------------------------------------------------}
    Procedure Rectangle (X1, Y1, X2, Y2 : Word);
    Begin
         { Draw Top Of Box }
         Line (X1, Y1, X2, Y1);
         { Draw Right Side Of Box }
         Line (X2, Y1, X2, Y2);
         { Draw Left Side Of Box }
         Line (X1, Y1, X1, Y2);
         { Draw Botton Of Box }
         Line (X1, Y2, X2, Y2);
    End;
    {=[ Main Program ]========================================================}

    Var C : Word;
        Key : Char;
    Begin

         TextMode (C80);
         TurnCursorOff;
         SetCharWidthTo8;
         SetDualFonts;
         ClearGraphicsWindow;
         TextColor(LightGray);
         ClrScr;

         SetGraphicsWindow (40, 0, White, Blue);   {X, Y, Color, BGColor}

         Writeln ('Graphics In Text Mode Example');
         Writeln ('Programmed by David Dahl');
         Writeln ('This is PUBLIC DOMAIN');
         Writeln;
         Writeln ('The graphics window to the right is');
         Writeln ('made up of custom characters of the');
         Writeln ('second font.');
         Writeln;
         Writeln ('There are four graphics primitives');
         Writeln ('available in this example program.');
         Writeln ('Circle, Line, PutPixel, and ');
         Writeln ('Rectangle are avaiable for your own');
         Writeln ('use.');
         Writeln;

         Randomize;
         For C := 1 to 10 do
         Begin
              Line (Random(MaxX), Random(MaxY),
                    Random(MaxX), Random(MaxY));

              Circle (Random(MaxX), Random(MaxY), Random(30));

              Rectangle (Random(MaxX), Random(MaxY),
                         Random(MaxX), Random(MaxY));
         End;

         Writeln ('Press [RETURN] to exit.');
         Readln;
         TurnCursorOn;
         TextMode (C80);
    End.

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