home *** CD-ROM | disk | FTP | other *** search
-
- program CGALoRes;
- uses crt, turbo3, graph3;
- (*--------------------------------------------------------------------------*)
- (* *)
- (* This low resolution graphics mode provides resolution *)
- (* of 160 horizontal by 100 vertical pixels in 16 colors. *)
- (* This mode is not directly supported by the IBM PC BIOS, *)
- (* special programming of the CRT registers is required. *)
- (* The PCjr has a similar 160x200 standard graph mode. *)
- (* *)
- (* This new version incorporates the ability to write *)
- (* alphanumeric text using both the low and high ascii *)
- (* character maps that are standard in the rom of an IBM *)
- (* PCjr. The PC does not have the high set in rom and it *)
- (* must either be hard-coded or read from disk. I created *)
- (* both disk files ( LO_ASCII.FNT and HI_ASCII.FNT ) by *)
- (* copying them from the rom of an IBM PCjr. Procedures to *)
- (* blank the screen and disable blink were also included. *)
- (* *)
- (* The plot and draw routines are originally by Philip Burns *)
- (* ( see PC SIG Turbo Disk No. 7 (#427) for PIBLORES.PAS ) *)
- (* and the CRT controller re-programming comes from an article *)
- (* (using Basic) by Bernie Lawrence in PC WORLD (Apr 1985). *)
- (* Philip asked for a routine to do text - here it is. *)
- (* I took some liberties in rewriting and shortening the *)
- (* previous programs. This new program will run on a PCjr. *)
- (* It will run on a CGA, but not an EGA which does not use a *)
- (* 6845 CRT controller chip. This is not a very portable routine. *)
- (* *)
- (* With the Color Graphics Adapter Donald L. Pavia *)
- (* a satisfactory solution to the Dept. of Chemistry - WWU *)
- (* the problem of snow remains to be Bellingham, WA. 98225 *)
- (* solved. I used a 2nd graphics January 1986 *)
- (* page here to avoid the problem. *)
- (* Snow is no problem on the PCjr. *)
- (*--------------------------------------------------------------------------*)
-
- const ColorSeg = $B800; ColorOfs = $0000;
-
- ModeReg = $3D8; ColorReg = $3D9; { control registers }
-
- ModeSave = $465; ColorSave = $466; { BIOS saves registers here }
-
- CRTReg = $3D4; CRTData = $3D5; { 6845 CRT controller registers }
-
- RetraceReg = $3DA; PCjrVGA = $3DA; { vertical retrace register }
- { video gate array for PCjr }
- HiResMode = 1; VideoMode = 8; { lores is form of 80x25 text }
-
- OffSet = 0;
-
- RegData : array[0..11] of integer { 6845 register data }
-
- = ( 113, (* Horizontal total *)
- 80, (* Horizontal displayed *)
- 90, (* Horizontal sync position *)
- 10, (* Horizontal sync width *)
- 127, (* Vertical total *)
- 6, (* Vertical adjust *)
- 100, (* Vertical displayed *)
- 112, (* Vertical sync position *)
- 2, (* Non-interlace mode *)
- 1, (* Maximum scan line address *)
- 32, (* Disable cursor display *)
- 0 ); (* Cursor end *)
-
- type str20 = string[20];
- ScreenType = array[0..16383] of byte;
- ScreenPointer = ^ScreenType;
- ScreenFile = file of ScreenType;
-
- var Register,Mode,Current : integer;
- i,PixCol,Color,X,Y,T : integer;
- ColorScreen : ScreenType absolute $B800:$0000;
- ScreenBuffer : ScreenType;
- LoFonts,HiFonts : array[1..1024] of byte; { in an IBM you could have }
- CRTStatus : byte; Wait : char; { an absolute address for }
- Screen : ScreenPointer; { LoFonts, rather than }
- { loading it from disk }
- {----------------------------------------------------------------------------}
- procedure SaveScreen (FileName : str20);
-
- var FileToSave : ScreenFile;
-
- begin
- Screen := ptr (ColorSeg,ColorOfs);
- assign (FileToSave,FileName);
- rewrite (FileToSave);
- write (FileToSave,Screen^);
- close (FileToSave);
- end;
- {----------------------------------------------------------------------------}
- procedure LoadScreen (FileName : str20);
-
- var DisplayFile : ScreenFile;
-
- begin
- Screen := ptr (ColorSeg,Offset);
- assign (DisplayFile,FileName);
- reset (DisplayFile);
- read (DisplayFile,Screen^);
- close (DisplayFile);
- end;
- {----------------------------------------------------------------------------}
- procedure AwaitVRetrace; { to eliminate snow on CGA }
-
- begin
- repeat CRTStatus := Port[RetraceReg]; until ((CRTStatus and 8) = 0);
-
- while ((CRTStatus and 8) = 0) do CRTStatus := Port[RetraceReg];
- end;
- {----------------------------------------------------------------------------}
- procedure BlankScreen; { turn off CRT }
-
- begin MemW[CSeg : ModeSave] := Mode; Port[ModeReg] := Mode and $F7; end;
-
- {----------------------------------------------------------------------------}
- procedure RestoreScreen; { turn on CRT }
-
- begin MemW[CSeg : ModeSave] := Mode; Port[ModeReg] := Mode or $08; end;
-
- {----------------------------------------------------------------------------}
- procedure ClrLoResScreen; (* byte = { **B* ***F } *)
- (* sum of *'s = 222 *)
- begin FillChar (ColorScreen ,16383,0);
- for i := 0 to 7999 do ColorScreen[2*i] := 222;
- end;
- {----------------------------------------------------------------------------}
- procedure ClrLoResBuff; { clear the screen buffer }
-
- begin FillChar (ScreenBuffer,16383,0);
- for i := 0 to 7999 do ScreenBuffer[2*i] := 222;
- end;
- {----------------------------------------------------------------------------}
- procedure Show; { transfer to screen in bursts to prevent snow }
- { 50 x 320 + 384 = 16384 might be safer than }
- var i,k : integer; { the currently used 40 x 400 + 384 combo }
-
- begin
- if mem[$F000:$FFFE] = $FD then move (ScreenBuffer,ColorScreen,16383)
-
- else
- begin k := 0;
- for i := 1 to 40 do begin
- AwaitVRetrace;
- move (ScreenBuffer[k],ColorScreen[k],400);
- k := k + 400;
- end;
- AwaitVRetrace;
- move (ScreenBuffer[k],ColorScreen[k],384);
- end;
- end;
- {----------------------------------------------------------------------------}
- procedure DisableBlink; { the earlier version did NOT have 16 colors }
- { the blink bit must be disabled for that. }
- { Enable it again to see the difference. }
- begin
- if mem[$F000:$FFFE] = $FD then { PCjr }
- begin Port[PCjrVGA] := 3; Port[PCjrVGA] := 0; end
- else begin { PC }
- Current := mem[$0000:$465]; Port[$03D8] := Current and $DF;
- end;
- end;
- {----------------------------------------------------------------------------}
- procedure LoResGraphMode; { set lores graphics mode }
-
- begin
- Mode := HiResMode + VideoMode;
- MemW[CSeg : ModeSave] := Mode; Port[ModeReg] := Mode;
-
- for Register := 0 TO 11 do { reprogram 6845 for lores }
- begin
- Port[CrtReg] := Register; Port[CrtData] := RegData[Register];
- end;
-
- DisableBlink;
-
- BlankScreen; { to prevent display of garbage }
- ClrLoResScreen;
- RestoreScreen;
-
- end; { LoResGraphMode }
- {----------------------------------------------------------------------------}
- procedure LoResPlot (X,Y,PixCol : integer); { plots to hidden screen }
- { to avoid snow }
-
- { Plots point in low-resolution graphics mode }
- { X -- Horizontal postion (0 through 159) }
- { Y -- Vertical position (0 through 119) }
- { PixCol -- Color (0 through 15) of point }
- { calls outside range are ignored }
-
- var Pixel,PixelAddr,Nibble : integer;
- Legal: boolean;
-
- begin
- Legal := (x >= 0) and (x <= 159) and (y >= 0) and (y <= 119) and
- (PixCol >= 0) and (PixCol <= 15);
- if Legal then
- begin
- Pixel := X + ( Y * 160 );
- PixelAddr := ( Pixel and $FFFE ) + 1;
- Nibble := Pixel mod 2;
-
- { AwaitVRetrace; } { works great, but really slows output ! }
- { to see, remove SHOW's in main program }
- { and change ScreenBuffer to ColorScreen }
- { in this procedure }
- if Nibble = 0 then
- ScreenBuffer[PixelAddr] :=
- ( ScreenBuffer[PixelAddr] and $0F ) + PixCol * 16
- else
- ScreenBuffer[PixelAddr] :=
- ( ScreenBuffer[PixelAddr] and $F0 ) + PixCol;
- end;
-
- end; { LoResPlot }
- {----------------------------------------------------------------------------}
- procedure LoResDraw (X1,Y1,X2,Y2,LineCol : integer);
-
- var X,Y,Xinc,Yinc,CorrecInc : integer; Dx,Cdx,Dy,Cdy : integer;
- Plotit: boolean;
-
- begin
- X := X1; Y := Y1; { starting point }
-
- Dx := X2 - X1; Dy := Y2 - Y1; { changes in (x,y) directions }
-
- { set increments }
-
- if Dx > 0 then Xinc := 1 else begin Xinc := -1; Dx := -Dx; end;
- if Dy > 0 then Yinc := 1 else begin Yinc := -1; Dy := -Dy; end;
-
- { CorrecInc is correction value }
-
- if Dy > Dx then CorrecInc := Dy else CorrecInc := Dx;
-
- Cdx := CorrecInc; Cdy := CorrecInc;
-
- LoResPlot( X, Y, LineCol ); { plot first point }
-
- while ( (X <> X2) and (Y <> Y2)) do { plot remaining points }
- begin
- PlotIt := false; Cdx := Cdx - Dx;
-
- if Cdx < 0 then
- begin
- PlotIt := true; X := X + Xinc; Cdx := Cdx + CorrecInc;
- end;
-
- Cdy := Cdy - Dy;
-
- if Cdy < 0 then
- begin
- PlotIt := true; Y := Y + Yinc; Cdy := Cdy + CorrecInc;
- end;
-
- if PlotIt then LoResPlot( X, Y, LineCol );
- end;
-
- end; { LoResDraw }
- {----------------------------------------------------------------------------}
- function BitSet (InByte : byte; WhichBit : integer) : boolean;
-
- begin if ((InByte div WhichBit) mod 2) = 1 then BitSet := true
- else BitSet := false;
- end;
- {----------------------------------------------------------------------------}
- procedure LoResChar (CharNum,x,y,color : integer);
-
- var Index,i,xx,yy : integer; InByte : byte;
-
- begin
- if CharNum < 128 then Index := (CharNum * 8)
- else Index := ((CharNum - 128) * 8);
- xx := x - 8; yy := y - 8;
-
- for i := 1 to 8 do begin
-
- if CharNum < 128 then InByte := LoFonts[Index+i]
- else InByte := HiFonts[Index+i];
-
- if BitSet (InByte,128) then LoResPlot (xx+1,yy+i,Color);
- if BitSet (InByte, 64) then LoResPlot (xx+2,yy+i,Color);
- if BitSet (InByte, 32) then LoResPlot (xx+3,yy+i,Color);
- if BitSet (InByte, 16) then LoResPlot (xx+4,yy+i,Color);
- if BitSet (InByte, 8) then LoResPlot (xx+5,yy+i,Color);
- if BitSet (InByte, 4) then LoResPlot (xx+6,yy+i,Color);
- if BitSet (InByte, 2) then LoResPlot (xx+7,yy+i,Color);
- if BitSet (InByte, 1) then LoResPlot (xx+8,yy+i,Color);
- end;
-
- end;
- {----------------------------------------------------------------------------}
- procedure LoResString (DisplayString : str20; col,row,color : integer);
-
- var i,x,y,AsciiNum : integer;
- Valid : boolean;
-
- begin
- Valid := (col >= 1) and (col <= 20) and (row >= 1) and (row <= 12);
-
- if Valid then begin
- x := (8 * col) ; y := (8 * row) ;
- for i := 1 to length(DisplayString) do
- begin
- AsciiNum := ord(DisplayString[i]);
- LoResChar (AsciiNum,x,y,color);
- x := x + 8;
- end;
- end;
-
- end;
- {----------------------------------------------------------------------------}
- procedure LoadFonts; { these files have to be on the disk ! }
- { or you can read then from rom if you }
- var FontFile : file; { have a PCjr. Only the first one is }
- { in rom in a PC. }
- begin
- assign (FontFile,'LO_ASCII.FNT');
- reset (FontFile); { you could have an absolute }
- BlockRead (FontFile,LoFonts,8); { address for LoFonts if you }
- close (FontFile); { if you have an IBM }
-
- assign (FontFile,'HI_ASCII.FNT');
- reset (FontFile);
- BlockRead (FontFile,HiFonts,8);
- close (FontFile);
- end;
- (*--------------------------------------------------------------------------*)
- (* NewLoRes --- Main Program *)
- (*--------------------------------------------------------------------------*)
-
- BEGIN (* program NewLoRes *)
-
- ClrScr; LoadFonts;
- gotoxy (5,5);
- write ('Press the <ENTER> key now to see 160x100 LoRes Graphics ');
- gotoxy (5,7);
- write ('Then press it again after each display.');
- gotoxy (5,9);
- write ('After pressing <ENTER> there will be about a 10 sec wait ');
- gotoxy (5,10); write ('while I set up. ');
- read (Kbd,Wait);
-
- LoResGraphMode; ClrLoResBuff;
-
- LoResDraw (0,0,100,100,5);
- for i := 0 to 159 do LoResPlot (i,0,6);
- for i := 0 to 99 do LoResPlot (159,i,2);
- for i := 0 to 99 do LoResPlot (0,i,3);
- for i := 0 to 159 do LoResPlot (i,99,4);
- SHOW;
-
- for i := 0 to 7 do
- LoResString ('16 Colors',i+3,i+1,i);
- SHOW;
-
- LoResString ('NEW',1,5,12);
- LoResString ('VIDEO',1,6,11);
- LoResString ('MODE',1,7,14);
- LoResString ('LOW RES',1,8,9);
- LoResString ('16 COLOR',1,9,10);
- LoResString ('GRAPHICS',1,10,15);
- LoResString ('160x100',1,11,13);
- Delay (1500);
- SHOW;
-
- LoResString ('D.Pavia',3,12,8);
- LoResString ('Jan 86',14,1,8);
- LoResString (#240+#241+#242+#243+#244+#245+#246+#247,12,10,3);
- LoResString (#224+#225+#226+#227+#228+#229,14,12,1);
- Delay (2500);
- SHOW;
-
- read (Kbd,Wait);
- BlankScreen; SaveScreen ('LORES.PIC'); RestoreScreen;
- GraphMode; TextMode (c80); clrscr;
-
- gotoxy (5,5);
- write ('This is TextMode (80x25). But I Saved Your Screen in Memory.');
- gotoxy (5,8); write ('Press <ENTER> to See It.. ');
-
- read (Kbd,Wait); LoResGraphMode;
- SHOW;
-
- read (Kbd,Wait); GraphMode; TextMode (c80); clrscr;
-
- gotoxy (5,5);
- write ('While You are Reading This I am Preparing a New Screen. ');
- write ('Wait Please. ');
-
- ClrLoResBuff;
- for i := 1 to 7 do LoResString ('This is New !',i,i+1,i);
- gotoxy (5,8); write ('READY ...... ');
-
- read (Kbd,Wait); LoResGraphMode;
- SHOW;
-
- read (Kbd,Wait); GraphMode; TextMode (c80); clrscr;
-
- gotoxy (5,5); write ('I also Saved Your Screen on Disk !!!');
- gotoxy (5,8); write ('Press <ENTER> to See ... ');
-
- read (Kbd,Wait); LoResGraphMode;
-
- BlankScreen; LoadScreen ('LORES.PIC'); RestoreScreen;
-
- read (Kbd,Wait); GraphMode; TextMode( C80 ); clrscr;
- gotoxy (15,10); write ('Thank You for Watching the Show !!!');
- gotoxy (40,14); write ('Donald L. Pavia');
- gotoxy (40,15); write ('January 20, 1986');
- gotoxy (30,24); write ('Press <ENTER> to Quit ');
-
- read (Kbd,Wait);
- GraphMode; TextMode (c80); clrscr; { exit gracefully, restore 6845 }
-
- END. (* program CGALoRes *)
-