DEFINITION MODULE Graphics; (****************************************************************) (* *) (* Screen graphics output *) (* *) (* Programmer: P. Moylan *) (* Last edited: 10 February 1995 *) (* Status: OK *) (* *) (* The procedures in this module assume that the caller *) (* has control of the entire screen. *) (* For multi-window graphics, see module GWindows. *) (* *) (* The support status for the various graphics modes is listed *) (* below. Text modes are listed for information only; this *) (* module allows you to select a text mode, but does not supply *) (* any support beyond that point. *) (* *) (* - 720x348x1 (Hercules only) working *) (* 0 40x25 BW text text *) (* 1 40x25 colour text text *) (* 2 80x25 BW text text *) (* 3 80x25 colour text text *) (* 4 320x200x4 (CGA) working *) (* 5 320x200 BW (CGA) working *) (* 6 640x200 BW (CGA) working *) (* 7 80x25 mono text (MDA/Hercules) text *) (* 8-12 unsure, but not graphics not supported *) (* 13 320x200x16 (EGA) working *) (* 14 640x200x16 (EGA) working *) (* 15 640x350x1 (EGA) working *) (* 16 640x350x16 (EGA) working *) (* 17 640x480x1 (VGA) working *) (* 18 640x480x16 (VGA) working *) (* 19 320x200x256 (VGA) working *) (* *) (* ATI SVGA modes: *) (* 83 800x600x16 working *) (* 84 800x600x16 working *) (* 85 1024x768x16 working *) (* 97 640x400x256 working *) (* 98 640x480x256 working *) (* 99 800x600x256 working* *) (* 100 1024x768x256 untested *) (* 101 1024x768x16 packed BIOS problem? *) (* *) (* S3 modes: *) (* The S3 supports only VESA SVGA modes. Of these, *) (* mode 257 works (after a correction in SCREEN.MOD for a *) (* bug in the BIOS), but for some reason I can't succeed *) (* in setting any other VESA mode. *) (* *) (* Trident SVGA modes: *) (* 17 extra modes defined, all untested so far. *) (* *) (* VESA modes: *) (* 106 800x600x16 working *) (* 256 640x400x256 working *) (* 257 640x480x256 working *) (* 258 800x600x16 working* *) (* 259 800x600x256 working* *) (* 260 1024x768x16 working* *) (* 261 1024x768x256 untested *) (* 262 1280x1024x16 untested *) (* 263 1280x1024x256 untested *) (* 264 80x60 text text *) (* 265 132x25 text text *) (* 266 132x43 text text *) (* 267 132x50 text text *) (* 268 132x60 text text *) (* 269 300x200x32K untested *) (* 270 320x200x64K untested *) (* 271 320x200x16.8M not supported *) (* 272 640x480x32K working *) (* 273 640x480x64K working *) (* 274 640x480x16.8M not supported *) (* 275 800x600x32K working *) (* 276 800x600x64K working *) (* 277 800x600x16.8M not supported *) (* 278 1024x768x32K untested *) (* 279 1024x768x64K untested *) (* 280 1024x768x16.8M not supported *) (* 281 1280x1024x32K untested *) (* 282 1280x1024x64K untested *) (* 283 1280x1024x16.8M not supported *) (* Modes 271,274,277,280, and 283, which use 24-bit colours, *) (* are not supported by the current version of module Graphics. *) (* *) (* The notation "working*" means that the modes are working on *) (* some hardware but failing on others. Since this is due to *) (* BIOS errors the only remedy is to disable or avoid the modes *) (* that don't work on your hardware (or upgrade your BIOS). *) (* *) (* I now have partial support on the Trident for the *) (* following "VESA" modes: *) (* 368 512x480x32K working? *) (* 369 512x480x64K working? *) (* These have poor horizontal position on my monitor, but this *) (* is possibly just a monitor limitation; otherwise they *) (* work well. *) (* *) (* Comments on modes which are "almost" working: *) (* 106,258,260 *) (* Sync problem on Trident *) (* 99,259 Fails on some but not all ATI adaptors. *) (* 261..263,269..283 *) (* The hardware I'm using so far doesn't support *) (* these modes, so I can't yet test them. *) (* 348..351, 354, 362, 372..375 (plus some text modes) *) (* these are in some sense "supported" on the *) (* Trident; most of them turn out to be duplicates,*) (* so I've eliminated them from the list of *) (* supported modes. The only genuine extras are *) (* 272,273,275,276 (which are not listed as *) (* supported, but are available anyway); and *) (* 368,369 (which are listed as supported, *) (* although I'm not sure that the Vesa standard *) (* includes them). *) (* *) (* Note that on the Trident: *) (* - all the 16-colour modes using bank switching show the *) (* same symptom: a triple image apparently caused by a *) (* clock synch problem; *) (* - the 32K and 64K colour modes are working to some *) (* extent, but the colours are not what one would expect. *) (* *) (****************************************************************) FROM ScreenGeometry IMPORT (* type *) Rectangle; FROM Screen IMPORT (* const*) HercGraphics; (* 720x348 monochrome Hercules graphics *) (************************************************************************) (* *) (* The constant BLorigin defined below is to support two different *) (* origin conventions. When a reference is made to (x,y) coordinates *) (* in this module, the x value is the horizontal coordinate, with 0 *) (* at the left of the the screen, and the y value is the vertical *) (* coordinate. If BLorigin is TRUE then y=0 is at the bottom of the *) (* screen and y values increase upwards. If BLorigin is FALSE then *) (* y=0 is at the top of the screen and y values increase downwards. *) (* You can choose whichever convention suits you best; the effect on *) (* execution speed is negligible. Some other PMOS modules assume *) (* that you have selected the TRUE option. *) (* *) (* NOTE: The case BLorigin=FALSE has not yet been fully tested. *) (* *) (* You might think that the inclusion of this choice will increase *) (* software overheads, but in fact any reasonable compiler will do *) (* the constant testing at compile time rather than at execution time, *) (* eliminating the unreachable code. *) (* *) (************************************************************************) CONST BLorigin = TRUE; (************************************************************************) TYPE ColourType = CARDINAL; PROCEDURE SetMode (newmode: CARDINAL; ClearScreen: BOOLEAN); (* Sets the video mode. *) (* Warning: the option ClearScreen=FALSE sometimes produces some *) (* strange effects, apparently because of some aspect of the BIOS *) (* that I don't yet understand. *) PROCEDURE SetDefaultMode; (* Sets the video mode to (our opinion of) the "best" graphics mode *) (* supported by the hardware. *) PROCEDURE GraphicsOff (ClearScreen: BOOLEAN); (* Sets the video mode to a default text mode. *) PROCEDURE GetScreenShape (VAR (*OUT*) xmax, ymax: CARDINAL; VAR (*OUT*) maxcolour: ColourType; VAR (*OUT*) CharHeight: CARDINAL); (* Returns the maximum values permitted by the current mode for *) (* x, y, and colour; and the number of rows in a character. *) PROCEDURE SetPaletteColour (Palette_Index, Red, Green, Blue: SHORTCARD); (* Sets the colour for one palette register. Applicable only to *) (* VGA or better. The three colour codes are 6-bit numbers. *) PROCEDURE PlotDot (x, y: CARDINAL; colour: ColourType); (* Writes a dot at screen position (x, y). *) PROCEDURE PlotMark (x, y: CARDINAL; colour: ColourType; pointtype: SHORTCARD); (* Writes a mark at screen position (x, y). Currently, the options *) (* for pointtype are: *) (* 0 dot *) (* 1 X *) (* 2 box *) PROCEDURE PlotLine (x0, y0, x1, y1: CARDINAL; colour: ColourType); (* Plots a straight line from (x0,y0) to (x1,y1). It is the *) (* caller's responsibility to ensure that the coordinates are in *) (* range for the current video mode. *) PROCEDURE PlotRectangle (R: Rectangle; colour: ColourType); (* Plots a rectangle, with clipping if necessary to keep the *) (* points within the screen boundary. *) PROCEDURE ClippedLine (x0, y0, x1, y1: CARDINAL; colour: ColourType; left, right, ymin, ymax: CARDINAL); (* Like PlotLine, but plots only that part of the line which lies *) (* in the rectangle (left <= x <= right), (ymin <= y <= ymax). *) (* The caller is expected to ensure, by appropriate definition of *) (* the rectangle, that all plotted points are in range for the *) (* current video mode. *) PROCEDURE Fill (x0, y0, x1, y1: CARDINAL; colour: ColourType); (* Fills a rectangle with the indicated colour. The rectangle is *) (* specified by giving two opposite corners (x0,y0) and (x1,y1). *) PROCEDURE ACopy (xs, ys, width, height: CARDINAL; dx, dy: INTEGER); (* Copies a rectangular region by an offset (dx, dy). The pair *) (* (xs,ys) gives the coordinates of the top left of the source *) (* rectangle. Restrictions: this procedure is restricted to the *) (* case where distance to move the data is an integral number of *) (* bytes (i.e. if you want it to work for all modes then dx should *) (* be a multiple of 8); and in the case where the source and *) (* destination rectangles overlap then the move has to be upwards *) (* on the screen. Thus we do not have a completely general "block *) (* copy" operation, but we do have something sufficient to support *) (* "scroll up" and similar operations. *) (* Further restriction: for multibank modes, will work only on *) (* hardware that permits separate "read" and "write" banks. A fix *) (* for this would be sufficiently troublesome that I don't plan *) (* to fix the problem unless/until I discover that someone needs *) (* the software for that kind of hardware. *) PROCEDURE DrawChar (ch: CHAR; x, y: CARDINAL; colour: ColourType); (* Draws the single character ch. The coordinates (x,y) are the *) (* location of the bottom left of the character. *) PROCEDURE PlotString (VAR (*IN*) text: ARRAY OF CHAR; x, y, length: CARDINAL; colour: ColourType); (* Draws a string of "length" characters starting at location (x,y) *) (* It is the caller's responsibility to ensure that the string will *) (* not run off the screen edges. *) PROCEDURE ClippedString (VAR (*IN*) text: ARRAY OF CHAR; x, y, length: CARDINAL; colour: ColourType; left, right, ymin, ymax: CARDINAL); (* Like PlotString, but excludes any points which fall outside the *) (* clip rectangle defined by (left,right,ymin,ymax). *) PROCEDURE PlotStringUp (VAR (*IN*) text: ARRAY OF CHAR; x, y, length: CARDINAL; colour: ColourType); (* Like PlotString, but with text written in the +Y direction *) PROCEDURE ClippedUpString (VAR (*IN*) text: ARRAY OF CHAR; x, y, length: CARDINAL; colour: ColourType; left, right, ymin, ymax: CARDINAL); (* Like ClippedString, but with text written in the +Y direction. *) END Graphics.