319 lines
15 KiB
Plaintext
319 lines
15 KiB
Plaintext
---------------------------------
|
|
ZipGraph: The Low-Level Routines!
|
|
---------------------------------
|
|
|
|
version 1.20
|
|
1 November, 1989
|
|
|
|
|
|
written by:
|
|
-----------
|
|
Scott Robert Ladd
|
|
705 West Virginia
|
|
Gunnison CO 81230
|
|
|
|
BBS (303)641-5125
|
|
FidoNet 1:104/708
|
|
|
|
Legal Disclaimer (Yuck)
|
|
=======================
|
|
|
|
The software presented in this package is public domain. You
|
|
may do anything you please with this software. As such,
|
|
there are no warranties or guarantees whatsoever as to the
|
|
quality, suitability, or general functionality of this
|
|
software. If you use this software, you accept full
|
|
responsibility for what it does or doesn't do.
|
|
|
|
Personally, I hate these disclaimers; however, in the
|
|
litigious world we live in, you can't even give something
|
|
away for free without covering yourself. Frankly, I suspect
|
|
most people are generally appreciative that I've made this
|
|
stuff available to them.
|
|
|
|
This software was developed using Zortech's C 2.01 on a
|
|
20Mhz 80386-based PC running MS-DOS 3.30. It's also been
|
|
tested with Mcirosft C 5.10 and QuickC 2.01, Borland Turbo
|
|
C 2.0, and Lattice C 6.01. I suspect other compilers will
|
|
work, too, but I haven't had time to try them.
|
|
|
|
One last request: if you do use this module, I'd like to hear
|
|
from you. I'm interested in any changes you might make. If
|
|
you find any bugs (!), drop me a line, and I'll see what I
|
|
can do. Again, since this is free, I can't make any
|
|
guarantees about how quickly any bug will get fixed. But I
|
|
will do my best!
|
|
|
|
Introduction
|
|
============
|
|
|
|
This document should be part of an archived package, which
|
|
contains a complete C-language module for the low-level portion
|
|
of the ZipGraph graphics library for PCs using MS-DOS. Included
|
|
in the archive should be:
|
|
|
|
ZG_LWLVL.H -- the required header file
|
|
ZG_LWLVL.C -- C language cource code
|
|
ZGTEST.C -- a program to test the above
|
|
ZG_LWLVL.DOC -- This document!
|
|
|
|
|
|
If you do redistribute this code, please do so with all of
|
|
the files together in an archive. While I use LHARC to
|
|
distribute this package, you can use any archiver you want.
|
|
Just keep these three files together, since that's how they
|
|
belong.
|
|
|
|
General Documentation
|
|
=====================
|
|
|
|
The following is an excerpt reprint from my Januray-February 1990
|
|
Cing Clearly column in Micro Cornucopia Magazine, where this module
|
|
first appeared.
|
|
|
|
|
|
|
|
The files in this archive are a part of a library called ZipGraph,
|
|
which provides several levels of functionality. These are
|
|
the low-level routines, which handle basic tasks such as the
|
|
determination of the installed adapter type and the plotting
|
|
of pixels. Future segments will cover drawing primitives,
|
|
clipping, region filling, and other basic tasks. In the
|
|
highest level of this library, I will present a series of
|
|
C++ classes, built on the lower-level C code, which will
|
|
handle advanced routines to handle ray tracing, 3D
|
|
modelling, and animation.
|
|
|
|
An obvious question might be: why write a graphics module?
|
|
Not only are there dozens of commercial graphics libraries
|
|
for C, but almost every compiler vendor now includes their
|
|
own graphics routines. What does ZipGraph offer that others
|
|
don't?
|
|
|
|
I had several goal in mind when building ZipGraph. To begin
|
|
with, I wanted it to be fast. The current version is more
|
|
than twice as fast as any other graphics library I have
|
|
tried. I was surprised to find that my C-language version of
|
|
the low-level graphics routines was nearly as fast as the
|
|
one I had built in assembler language. The advantages of
|
|
having easily maintainable C source far outweighed the few
|
|
percentage points loss in speed when compared to my
|
|
assembler language implementation.
|
|
|
|
My second goal was to make ZipGraph portable. As time
|
|
passes, more and more of my article involve programs which
|
|
do graphics. Alas, C compiler vendors do not have any
|
|
interest in making their proprietary graphics libraries
|
|
compatible. If I write a program using the Borland Graphic
|
|
Interface (BGI) included with Turbo C, that program won't
|
|
compile with any other C compiler. Rather than shut people
|
|
out, I decided to build a library which compiled with all of
|
|
the popular compilers. The version of ZipGraph presented
|
|
here compiles with Borland Turbo C 2.0, Lattice C 6.01,
|
|
Microsoft C 5.10 and QuickC 2.01, and Zortech C/C++ 2.01. In
|
|
addition, the resulting object modules can be linked to
|
|
Microsoft Fortran 5.0 and Stony Brook Modula-2 2.01.
|
|
|
|
My final reason for writing ZipGraph is that I find
|
|
commercial libraries limited. For example, most do not
|
|
include printer routines, and some do not support certain
|
|
graphics adapters. On top of that they lack fundamental
|
|
capabilities, such as a function to generate non-orthagonal
|
|
ellipses. No graphics library I know of completely supports
|
|
ray tracing, animation, object rotation, and 3D plotting.
|
|
Additionally, commercial libraries are written using C and
|
|
assembler language only, without utilizing the object-
|
|
oriented features of C++. As you'll see in future columns,
|
|
C++ provides the ability to do some fantastic things.
|
|
|
|
The ZG_LWLVL module, presented here, is the basis of all the
|
|
other modules in the ZipGraph system. It uses some of the
|
|
more powerful features of C, and provides the basic
|
|
functions for detecting the type of graphics adapter
|
|
installed in your machine, and supports the plotting and
|
|
reading pixels on all common IBM adapters. As mentioned
|
|
earlier, this module is almost 850 lines long, making it the
|
|
longest piece of code ever published in this column.
|
|
Subsequently, I'll have to forego a long detailed discussion
|
|
of ZG_LWLVL. Instead, I'll be focusing on the techniques
|
|
used to make it work.
|
|
|
|
IBM PCs and their compatibles were originally designed to be
|
|
modular; in spite of IBM's recent move toward building video
|
|
hardware into the computer's motherboard, most vendors have
|
|
maintained the ability to install whatever kind of video
|
|
adapter you want. Currently, there are six standard video
|
|
adapters in common use in PCs: the Monochrome Display
|
|
Adapter (MDA), the Color Graphics Adapter (CGA), the
|
|
Hercules Graphics Card (HGC), the Enhanced Graphics Adapter
|
|
(EGA), the Multi-Colored Graphics Array (MCGA), and the
|
|
Video Graphics Array (VGA).
|
|
|
|
One problem PC software has always faced is that any one of
|
|
these video adapters can be installed in a PC. While most of
|
|
the adapters are supported by the PC's BIOS, the Hercules
|
|
card is not. I'm sure most of you have had the experience of
|
|
finding a pieces of graphics software which will not run on
|
|
your computer.
|
|
|
|
Some graphics libraries allow you to "detect" which kind of
|
|
video adapter is installed. Borland's Graphic Interface
|
|
(BGI) has this capability. However, the BGI uses external
|
|
drivers, which are loaded at run time. While you can convert
|
|
the BGI drivers to object modules, you then have to go
|
|
through a clumsy procedure to link them in and make the
|
|
program aware of their resident status. Other "auto-sensing
|
|
packages" fail to support certain adapters, or are just
|
|
simply clumsy.
|
|
|
|
I've always been a believer that computers should do work
|
|
for you. ZipGraph not only detects the presence of all of
|
|
the above adapters, it also automatically sets up its
|
|
routines so that you can write one program with which works
|
|
with all of those adapters. The type of adapter you're
|
|
working with is as transparent as possible.
|
|
|
|
Listing 1 shows ZG_LWLVL.H, the header file which must be
|
|
included in any source program which uses the LG_LWLVL
|
|
module. Listing 2 is ZG_LWLVL.C, the implementation of the
|
|
module. Finally, Listing 3 shows one of my test programs,
|
|
ZGTEST.C, which will give you an example of how to use the
|
|
ZG_LWLVL module.
|
|
|
|
We'll start with a quick synopsis of how to use the ZG_LWLVL
|
|
functions. First, you need to call ZG_Init to initialize
|
|
the module. ZG_Init detects the adapter installed in the
|
|
PC, and saves its initial status. Information on the adapter
|
|
will be returned in the public ZG_VideoInfo structure.
|
|
Then you need to set a graphics mode using the
|
|
ZG_SetMode function. It sets the video mode you request,
|
|
assigns the proper pixel plotting and reading function to
|
|
the function pointers ZG_PlotPixel and ZG_ReadPixel,
|
|
and returns information on the new graphics mode in
|
|
ZG_VideoInfo. You can then plot pixels by calling the
|
|
function pointed to by ZG_PlotPixel, a read pixels via
|
|
the function pointer ZG_ReadPixel. When your program is
|
|
done, it should call ZG_Done to restored the video
|
|
adapter to its pre-program state. Examining ZGTEST.C will
|
|
show you the details of how this all fits together. No let's
|
|
examine the above process in detail.
|
|
|
|
When ZG_Init is called, it attempts to identify the
|
|
video adapter installed in your computer. There isn't an
|
|
built-in way to determine the adapter type, but we can use
|
|
the process of elimination. ZG_Init() begins be calling
|
|
an MCGA and VGA BIOS function which returns the adapter
|
|
type. If an MCGA or VGA BIOS is installed, this call will
|
|
tell us which one of those it is. If the adapter installed
|
|
is not a VGA, the call to this BIOS function will fail. Once
|
|
we've eliminated the VGA, we call an EGA BIOS function.
|
|
Again, if the EGA BIOS is not present, the function will not
|
|
return expected values, and we know that an EGA is not
|
|
present. If no EGA is found, we ask the BIOS for the
|
|
hardware information word. We check the appropriate bits to
|
|
see if a color or monochrome adapter is installed. A color
|
|
adapter will be a CGA at this point (since we have
|
|
eliminated the other color adapters). If a monochrome
|
|
adapter is installed, our final task is to differentiate
|
|
between an MDA and a HGC. This is done by monitoring the
|
|
vertical synch bit of the monochrome card's status register;
|
|
if the bit changes, we have a Hercules card.
|
|
|
|
Information on the adapter's type and its installed monitor
|
|
are placed into the ZG_VideoInfo structure. Constants
|
|
for these values are defined in the ZG_LWLVL.H files can be
|
|
used to make you code a bit clearer. At this point, all
|
|
ZipGraph has done is determine what kind of video adapter
|
|
you have. I've tested the detection routine on several
|
|
computers with a variety of adapters installed. So far, it
|
|
has worked flawlessly with VGA, EGA, MDA, and Hercules
|
|
adapters. I do not have a CGA or MCGA adapter available to
|
|
me, but I was able to test those routines on my Paradise 16-
|
|
bit VGA card, which emulates the CGA and MCGA. I'd
|
|
appreciate hearing from you if you have problems.
|
|
|
|
In order to display graphics, you now need to set a graphics
|
|
mode. You do this by calling the ZG_SetMode function,
|
|
passing it as its first parameter one of the ZG_MOD
|
|
constants defined in ZG_LWLVL.H. ZG_SetMode will return
|
|
1 if the requested mode is not valid for the adapter
|
|
detected. Information on the mode will again be returned in
|
|
the public global variable ZG_VideoInfo. That
|
|
information includes the x and y dimensions of the new
|
|
graphics mode, and the number of colors available. If all
|
|
goes well, ZG_SetMode will return 0 to indicate that
|
|
success.
|
|
|
|
ZG_SetMode also does some automagical work for you. Two
|
|
special graphics modes are ZG_MOD_BESTRES and
|
|
ZG_MOD_MOSTCOLOR. Respectively, they represent -- for
|
|
the detected adapter -- the best possible resolution, and
|
|
the resolution providing the greatest selection of colors.
|
|
The global static array VideoTable contains the actual
|
|
modes for both of these modes, for each adapter. In
|
|
addition, VideoTable also contains a bit mask which
|
|
indicates the valid modes for a given adapter. The requested
|
|
graphics mode is compared against the ModeList value for
|
|
a given adapter type, to be sure it is valid. If it isn't,
|
|
ZG_SetMode returns an error.
|
|
|
|
Once it has determined the validity of the requested
|
|
graphics mode, ZG_SetMode uses the information stored in
|
|
the global static array ModeData to do the actual mode
|
|
set-up. ModeData contains the equivalent BIOS mode for
|
|
the mode requested, the addresses of the appropriate pixel
|
|
plotting and reading functions, and the dimensions and color
|
|
counts for each mode. When the mode is set, ZG_SetMode
|
|
assigns the appropriate values in the ModeData table to
|
|
the function pointers ZG_PlotPixel and ZG_ReadPixel.
|
|
We are ensured that for each graphics mode, the correct
|
|
pixel plotting and reading routines are set -- all
|
|
automatically. Once that is done, ZG_SetMode assigns
|
|
values from the ModeData table to the width, height, and
|
|
color count values of the ZG_VideoInfo structure.
|
|
|
|
It should be noted here that the Hercules card is handled in
|
|
a special manner by ZG_LWLVL.C. Since the HGC is not
|
|
supported by the PC BIOS in any way, it's graphics and text
|
|
modes must be set via special functions. All the ZipGraph
|
|
functions do is make exceptions to their normal set-up by
|
|
calling the special Hercules functions rather than the BIOS
|
|
(as used for the other graphics cards).
|
|
|
|
And we're ready to plot pixels! Different video modes
|
|
require different pixel plotting and reading routines, which
|
|
is why I use pointers to the functions for these tasks.
|
|
ZG_PlotPixel and ZG_ReadPixel can be used exactly as
|
|
if they were regular functions. However, they do different
|
|
things based on the specific type of graphics adapter
|
|
installed. Their value is set based on the graphics mode you
|
|
requested via ZG_SetMode. In a way, you can look upon
|
|
this as a form of polymorphism (an object-oriented
|
|
programming concept) for C.
|
|
|
|
This document has already run far longer than it should, so
|
|
I won't go into the specifics of how the individual pixel
|
|
plotting and reading functions work. If you're dying to
|
|
know, pick up a copy of Richard Wilton's Programmer's
|
|
Guide to PC & PS/2 Video Systems (ISBN 1-55615-103-9), by
|
|
far the best reference ever published about the nuts and
|
|
bolts of PC graphics programming.
|
|
|
|
I doubt ZG_LWLVL will remain static. The most obvious
|
|
enhancement is to include support for the "Super VGA modes,
|
|
such as 800 x 600 graphics. Additionally, it would be nice
|
|
to add the capability to use some of the non-documented VGA
|
|
modes, such as 320 by 400 pixels with 256 colors. But all in
|
|
good time. I suspect this issue's source code is more than
|
|
enough for most of you to "chew" on for a while.
|
|
|
|
VERSION HISTORY!
|
|
----------------
|
|
|
|
Version 1.00 was built and released quickly because of a magazine
|
|
article deadline. Later, as I looked at it, I saw that the performance
|
|
could be increased dramatically. So, that's what I did, generating
|
|
version 1.10. 1.20 corrected some minor bugs in the handling of
|
|
modes which are only rarely used, such as 320 by 200 by 16 color
|
|
and EGA monochrome mode.
|