home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / BASIC / GRAFWZ15.ZIP / GRAFWIZ.DOC < prev    next >
Encoding:
Text File  |  1991-02-11  |  49.3 KB  |  1,119 lines

  1.                    The Graphics Wizard's Library for BASIC              page 1
  2.                    =-------------------------------------=
  3.                                  Version 1.5
  4.  
  5.            GRAFWIZ  Copyright (c) 1990-1991  Thomas G. Hanlin III
  6.  
  7.  
  8.  
  9. This is GRAFWIZ, a library of assembly language and BASIC routines for use
  10. with QuickBASIC version 4.5.  Support for other recent versions of the BASIC
  11. compiler is provided with registration.  The GRAFWIZ collection is
  12. copyrighted and may be distributed only under the following conditions:
  13.  
  14.    1) No fee of over $10.00 may be charged for distribution.  This
  15.       restriction applies only to physical copies and is not meant to
  16.       prevent distribution by telecommunication services.
  17.  
  18.    2) All GRAFWIZ files must be distributed together in original, unaltered
  19.       form.  This includes GRAFWIZ.BI, GRAFWIZ.DOC, GRAFWIZ.LIB, GRAFWIZ.NEW,
  20.       GRAFWIZ.REF, BIBLIO.TXT, CATALOG.TXT, CREATE.BAT, DEMO.BAS, DEMO.PCX,
  21.       FILES.LST, LIBRARY.TXT, MIRRORS.BAS, PRODUCT.TXT, QUESTION.TXT,
  22.       REGISTER.TXT, ROSES.BAS, S&B4EGA.BAS, S&B4EGA.EXE, VGABOX.BAS, and
  23.       VGABOX.EXE.
  24.  
  25. You use this library at your own risk.  It has been tested by me on my own
  26. computer, but I will not assume any responsibility for any problems which
  27. GRAFWIZ may cause you.  If you do encounter a problem, please let me know
  28. about it, and I will do my best to verify and repair the error.
  29.  
  30. It is expected that if you find GRAFWIZ useful, you will register your copy.
  31. You may not use GRAFWIZ routines in programs intended for sale unless you
  32. have registered.  Registration entitles you to receive the latest version of
  33. GRAFWIZ, complete with full source code in assembly language and BASIC.  The
  34. assembly code is designed for the OPTASM assembler by SLR Systems and will
  35. require modifications if you wish to use it with MASM or TASM.  You will be
  36. able to compile the BASIC code with whatever version of the compiler you
  37. have, allowing you to use GRAFWIZ with QuickBASIC versions 4.0 - 4.5 and
  38. BASCOM versions 6.0 - 7.1 (QBX and BASCOM 7.x far strings aren't supported).
  39.  
  40. Warning: Use of GRAFWIZ for more than 30 days without registering may cause
  41. the author to play the drums outside your window at two in the morning!
  42.  
  43. The GRAFWIZ.QLB file is no longer included in order to save space.  You can
  44. create it by doing the following:
  45.  
  46.    LINK GRAFWIZ.LIB/Q/SE:512,,NUL,BQLB45;
  47.  
  48. For an example of how to set up your program to access the GRAFWIZ library,
  49. how to LINK the routines, and so forth, take a look at the CREATE.BAT and
  50. DEMO.BAS files.  The LIBRARY.TXT file explains libraries.
  51.  
  52. So who's the Graphics Wizard?  With this library, you will be!  Read this
  53. tome well, for invoking these routines without proper preparation may bring
  54. unexpected results.  Cape and hat (optional) not included.  No assembly
  55. required.
  56.  
  57.                               Table of Contents                         page 2
  58.  
  59.  
  60.  
  61.  Overview and Legal Info ................................................ 1
  62.  
  63.  Non-Specific Routines .................................................. 3
  64.  
  65.  Mode-Specific Routines ................................................. 4
  66.  
  67.  Printer Routines ...................................................... 16
  68.  
  69.  A Little Geometry ..................................................... 17
  70.  
  71.  Equations, Etc ........................................................ 20
  72.  
  73.  Miscellaneous Notes ................................................... 23
  74.  
  75.  Memory Considerations ................................................. 25
  76.  
  77.  Troubleshooting ....................................................... 26
  78.  
  79.  Using GRAFWIZ with PDQ ................................................ 27
  80.  
  81.  Credits ............................................................... 28
  82.  
  83.                             Non-specific Routines                      page 3
  84.  
  85.  
  86.  
  87. These are routines that will work with more than one graphics mode, more than
  88. one text mode, or with many combinations of graphics and text modes.
  89.  
  90. The PrintScreen routine will work in all text modes and in most graphics
  91. modes.  It sends the contents of the screen to LPT1/PRN, the standard
  92. printer.  It expects an Epson-compatible printer for graphics modes.
  93. Graphics printing is not particularly sophisticated in that there is no
  94. attempt to provide gray levels-- a point is either on or off, so complex
  95. screens with images in many colors may not print out very well.
  96.  
  97. You must specify the screen mode when the PrintScreen routine is used.  You
  98. may choose SCREEN 0, 1, 2, 7, 8, 9, 11, 12, or 13.  This covers virtually all
  99. CGA, EGA, and VGA text and graphics modes.  Text mode support includes
  100. automatic handling of 25x40, 25x80, 43x80, 50x80 and 60x80 text modes from
  101. MDA to VGA.  Here's how to print the screen:
  102.  
  103.    PrintScreen ScreenMode%
  104.  
  105. In order to determine what size a text mode screen is, PrintScreen relies on
  106. another routine which may be used independently.  That's called ScreenSize,
  107. simply enough.  It returns the number of rows and columns available for a
  108. display in any of the text modes, like so:
  109.  
  110.    ScreenSize Rows%, Columns%
  111.  
  112. The GetDisplay routine tells what kind of display adapter is active and
  113. whether it's hooked up to a color monitor.  The only time it can't detect the
  114. monitor type is on CGA setups (it assumes "color").  It's a good idea to
  115. allow a "/B" switch for your program so the user can specify if a monochrome
  116. monitor is attached to a CGA.
  117.  
  118.    GetDisplay Adapter, Mono
  119.    IF Mono THEN
  120.       PRINT "Monochrome monitor"
  121.    ELSE
  122.       PRINT "Color monitor"
  123.    END IF
  124.    SELECT CASE Adapter
  125.       CASE 1: PRINT "MDA"
  126.       CASE 2: PRINT "Hercules"
  127.       CASE 3: PRINT "CGA"
  128.       CASE 4: PRINT "EGA"
  129.       CASE 5: PRINT "MCGA"
  130.       CASE 6: PRINT "VGA"
  131.    END SELECT
  132.  
  133. The GetDisplay routine is also included in my BASWIZ library.  If you intend
  134. to use both libraries together, you should remove this routine from GRAFWIZ:
  135.  
  136.    LIB GRAFWIZ,-GETDISP,NUL;
  137.    LINK GRAFWIZ.LIB/Q,,NUL,BQLB45;              (or whatever BQLBxx you have)
  138.  
  139.                            Mode-Specific Routines                      page 4
  140.  
  141.  
  142.  
  143. These routines are designed to work with specific graphics modes, so your
  144. program will only include those routines which apply to the modes you use.
  145. The following modes are currently supported:
  146.  
  147.    SCREEN #    Adapter     Graphics Res   Colors   Text Res   Notes
  148.       1          CGA         320x200          4      40x25
  149.       2          CGA         640x200          2      80x25
  150.       3          Herc        720x348          2      90x43      *1
  151.       7          EGA         320x200         16      40x25
  152.       8          EGA         640x200         16      80x25
  153.       9          EGA         640x350         16      80x25      *2
  154.      11          VGA         640x480          2      80x30      *2
  155.      12          VGA         640x480         16      80x30      *2
  156.      13          VGA         320x200        256      40x25
  157.      N0          VGA         360x480        256      45x60      *3
  158.      N1          VGA         320x400        256      40x50      *4
  159.      N2        <Epson>       480x640          2      60x80      *5
  160.      N4          any          80x50           2      10x6       *6
  161.  
  162. *1  Note that the GRAFWIZ Hercules routines, unlike those provided with
  163.     QuickBASIC, do not require the QBHERC TSR to be loaded.  They are
  164.     entirely self-contained.  However, they may need to be compiled by BC
  165.     instead of QB, which may refuse to deal with the video mode change.
  166.  
  167. *2  These text resolutions are capable of more rows than indicated, but
  168.     GRAFWIZ doesn't yet support such extra-row modes.
  169.  
  170. *3  This is a non-standard VGA mode.  It should work on many VGAs, however.
  171.  
  172. *4  This is a non-standard VGA mode.  It should work on nearly all VGAs.
  173.  
  174. *5  This works with an Epson-compatible printer rather than the display.  The
  175.     results may be previewed on a VGA, however.  See "Printer Routines" for
  176.     additional information.
  177.  
  178. *6  This actually provides graphics in text mode.  It will work on any
  179.     display adapter.  80x25 text remains available through PRINT.
  180.  
  181.  
  182.  
  183. See "Miscellaneous Notes" for additional comments on the new modes.
  184.  
  185. The routine for a specific mode is indicated by a prefix of "G", followed by
  186. the mode number, and then the routine name.  For example, if you wished to
  187. plot a point in SCREEN 2 mode, you would use:
  188.  
  189.    G2Plot X%, Y%
  190.  
  191.                            Mode-Specific Routines                      page 5
  192.  
  193.  
  194.  
  195. Many of these routines correspond with existing BASIC instructions.  However,
  196. they are smaller and usually faster by 22% - 64%.  See "Miscellaneous Notes"
  197. for notes on the differences between BASIC and the GRAFWIZ routines.
  198.  
  199. The smaller size may not be noticeable if you use the SCREEN statement, since
  200. that causes BASIC to link in some of its own graphics routines.  If you
  201. intend to use only GRAFWIZ routines for graphics, you can avoid that by using
  202. the G#Mode command instead of SCREEN:
  203.  
  204.    G#Mode Graphics%         ' use 0 for SCREEN 0, any other for SCREEN #
  205.  
  206. One difference between BASIC and GRAFWIZ is that, instead of each "draw"
  207. command requiring a color parameter as in BASIC, the GRAFWIZ library provides
  208. a separate color command:
  209.  
  210.    G#Color Foreground%, Background%
  211.  
  212. The "foreground" color is used by all graphics routines.  The background
  213. color is used by the G#Cls routine.  Both foreground and background colors
  214. are used in the G#Write and G#WriteLn routines.
  215.  
  216.                            Mode-Specific Routines                      page 6
  217.  
  218.  
  219.  
  220. Here is a list of the corresponding routines, first BASIC, then GRAFWIZ
  221. (replace the "#" with the appropriate mode number):
  222.  
  223.    ' get the color of a specified point
  224.    colour% = POINT(x%, y%)
  225.    colour% = G#GetPel(x%, y%)
  226.  
  227.    ' set the color of a specified point
  228.    PSET (x%, y%), colour%
  229.    G#Color colour%, backgnd% : G#Plot x%, y%
  230.  
  231.    ' draw a line of a specified color
  232.    LINE (x1%, y1%) - (x2%, y2%), colour%
  233.    G#Color colour%, backgnd% : G#Line x1%, y1%, x2%, y2%
  234.  
  235.    ' draw a box frame of a specified color
  236.    LINE (x1%, y1%) - (x2%, y2%), colour%, B
  237.    G#Color colour%, backgnd% : G#Box x1%, y1%, x2%, y2%, 0
  238.  
  239.                            Mode-Specific Routines                      page 7
  240.  
  241.  
  242.  
  243. Here are some more BASIC and GRAFWIZ routines:
  244.  
  245.    ' draw a box of a specified color and fill it in
  246.    LINE (x1%, y1%) - (x2%, y2%), colour%, BF
  247.    G#Color colour%, backgnd% : G#Box x1%, y1%, x2%, y2%, 1
  248.  
  249.    ' clear the screen and home the cursor
  250.    CLS
  251.    G#Cls
  252.  
  253.    ' get the current cursor position
  254.    Row% = CSRLIN: Column% = POS(0)
  255.    G#GetLocate Row%, Column%
  256.  
  257.    ' set the current cursor position
  258.    LOCATE Row%, Column%
  259.    G#Locate Row%, Column%
  260.  
  261.    ' display a string without a carriage return and linefeed
  262.    PRINT St$;
  263.    G#Write St$
  264.  
  265.    ' display a string with a carriage return and linefeed
  266.    PRINT St$
  267.    G#WriteLn St$
  268.  
  269. Note that GRAFWIZ, unlike BASIC, allows both foreground and background colors
  270. for text in graphics mode.  It also displays text substantially faster than
  271. BASIC.  See the "Miscellaneous Notes" section for information on other
  272. differences in text printing.
  273.  
  274. If you need to print a number rather than a string, just use the BASIC
  275. function STR$ to convert it.  If you don't want a leading space (assuming the
  276. number is not negative), use this formula:
  277.  
  278.    St$ = MID$(STR$(Number), 2)
  279.  
  280. The GRAFWIZ library has other routines which have no BASIC equivalent.  One
  281. allows you to get the current colors:
  282.  
  283.    G#GetColor Foreground%, Background%
  284.  
  285.                            Mode-Specific Routines                      page 8
  286.  
  287.  
  288.  
  289. Sometimes the normal text services seem unduly limited.  Text is displayed
  290. only at specific character positions, so it may not align properly with a
  291. graph, for instance.  Text is also of only one specific size.  These are
  292. limitations which make the normal text routines very fast, but for times when
  293. you need something a little bit more fancy, try:
  294.  
  295.    G#Banner St$, X%, Y%, Xmul%, Ymul%
  296.  
  297. You may display the string starting at any graphics position.  The Xmul% and
  298. Ymul% values are multipliers, specifying how many times larger than normal
  299. each character should be.  Using Xmul% = 1 and Ymul% = 1 will give you
  300. normal-sized characters.  What "normal" means depends on the font in use.
  301.  
  302. Since G#Banner "draws" the text onto the screen, it is a bit slower than the
  303. normal text services.  It also uses only the foreground color, so the letters
  304. go right on top of anything that was previously there.  Use G#Box to clear
  305. the area beforehand if this is a problem for you.
  306.  
  307. The G#Banner routine supports several fonts.  The larger fonts provide a more
  308. precise character set but leave you with less room on the screen.  You may
  309. choose from these fonts:
  310.  
  311.    Font Number     Font Size (width x height)
  312.         0            8 x 8    --- default
  313.         1            8 x 14
  314.         2            8 x 16
  315.  
  316. Select a font like so:
  317.  
  318.    BFont FontNr%
  319.  
  320. If you want to find out what the current font is, that's possible too:
  321.  
  322.    FontNr% = GetBFont
  323.  
  324. Besides looking more elegant, the larger fonts are easier to read.  They will
  325. also suffer less from being increased in size, although some deterioration is
  326. inevitable when magnifying these kinds of fonts.
  327.  
  328. The G#Banner routines accept CHR$(0) - CHR$(127).  No handling of control
  329. codes is done.  All codes are displayed directly to the screen.
  330.  
  331.                            Mode-Specific Routines                      page 9
  332.  
  333.  
  334.  
  335. Circles and ellipses can be drawn with the Ellipse routine.  This is similar
  336. to the BASIC CIRCLE statement.  You specify the center of the ellipse (X,Y),
  337. plus the X and Y radius values:
  338.  
  339.    G#Ellipse CenterX%, CenterY%, XRadius%, YRadius%
  340.  
  341. A circle is an ellipse with a constant radius.  So, to draw a circle, just
  342. set both radius values to the single desired radius.
  343.  
  344. As well as the usual points, lines, and ellipses, GRAFWIZ also allows you to
  345. draw polygons: triangles, squares, pentagons, hexagons, all the way up to
  346. full circles!
  347.  
  348.    G#Polygon X%, Y%, Radius%, Vertices%, Angle!
  349.  
  350. The X% and Y% values represent the coordinates of the center of the polygon.
  351. The Radius% is the radius of the polygon (as if you were fitting it into a
  352. circle).  Vertices% is the number of angles (also the number of sides) for
  353. the polygon to have.  Angle! specifies the rotation of the polygon, and is
  354. specified in radians.  See "A Little Geometry" for more information.
  355.  
  356.                            Mode-Specific Routines                      page 10
  357.  
  358.  
  359.  
  360. Another new routine is designed to manipulate a GET/PUT image.  Given an
  361. image in array Original%() and a blank array of the same dimensions called
  362. Flipped%(), this routine copies the original image to the new array as a
  363. mirror image about the horizontal axis.  This is the same as the image you'd
  364. see if you turned your monitor upside-down: the resulting image is
  365. upside-down and backwards.
  366.  
  367.    G#MirrorH Original%(), Flipped%()
  368.  
  369. Don't forget to make the Flipped%() array the same DIM size as the original,
  370. or the picture will overflow into main memory, probably causing disaster!
  371.  
  372. Note that G#MirrorH will only work properly on images with byte alignment.
  373. This means that the width of the image must be evenly divisible by four if
  374. SCREEN 1 is used, or evenly divisible by eight if SCREEN 2 is used.  EGA
  375. modes are not yet supported for this routine.
  376.  
  377.                            Mode-Specific Routines                      page 11
  378.  
  379.  
  380.  
  381. There are more routines that work only with SCREEN 2.  One allows you to load
  382. a MacPaint-type image ("ReadMac" or .MAC files) into an array which can then
  383. be PUT onto the screen:
  384.  
  385.    G2LoadMAC FileName$, Image%(), StartRow%
  386.  
  387. Note that a full .MAC picture is 576x720, which won't fit on the screen, so
  388. the image will be truncated to 576x200.  You may specify a starting row
  389. within the .MAC image, StartRow%, which may be 0-521, allowing the entire
  390. picture to be loaded in several parts.
  391.  
  392. The Image%() must be dimensioned with 7202 elements:
  393.  
  394.    DIM Array(1 TO 7202) AS INTEGER
  395.  
  396. If you don't give an extension in the FileName$, an extension of ".MAC" will
  397. be used.  There is no checking to see if the file actually exists, so you may
  398. wish to do this beforehand.
  399.  
  400. There is no way of knowing whether a .MAC picture is supposed to be black on
  401. white or white on black.  If the image doesn't look right when you PUT using
  402. PSET, you can switch it around by using PUT with PRESET instead.
  403.  
  404. PC PaintBrush (.PCX) pictures can also be loaded.  These images can be of
  405. various sizes, so you need to dimension a dynamic array for them:
  406.  
  407.    REM $DYNAMIC
  408.    DIM Image(1 TO 2) AS INTEGER
  409.  
  410. The array will be set to the correct size by the loader.  It goes like this:
  411.  
  412.    G2LoadPCX FileName$, Image%(), ErrCode%
  413.  
  414. If you don't give an extension in the FileName$, an extension of ".PCX" will
  415. be used.  You may wish to check to see if the file exists beforehand.
  416. Possible errors are as follows:
  417.  
  418.    -1   File is not in PCX format
  419.     1   Image is too large for desired screen mode
  420.     2   Image won't work in desired screen mode (too many planes/colors)
  421.  
  422.                            Mode-Specific Routines                      page 12
  423.  
  424.  
  425.  
  426. Two new routines are replacements for the GET and PUT image statements in
  427. BASIC.  They are on the slow side, but if you don't intend to use them for
  428. animation, they will serve to save some memory:
  429.  
  430.    REM $DYNAMIC
  431.    DIM Image(1 TO 2) AS INTEGER
  432.    G2Get X1%, Y1%, X2%, Y2%, Image()
  433.  
  434. Note the DIMensioning of a dynamic array.  The G2Get routine will set the
  435. array to the appropriate size to hold the image.
  436.  
  437. The PUT replacement assumes that you intend to PSET the image.  It doesn't
  438. allow for other display modes yet:
  439.  
  440.    G2Put X%, Y%, Image()
  441.  
  442. See "Miscellaneous Notes" for more information on using GET/PUT images and
  443. the directions I'll be taking with them in the future.  Note that SCREEN 13
  444. is also supported, via G13Get and G13Put.
  445.  
  446. The COLOR statement in SCREEN 1 is anomalous.  It doesn't really control
  447. color at all, which is why QuickBASIC proper doesn't support colored text in
  448. this (or any graphics) mode.  Instead, it is used for controlling the
  449. background/border color and palette.  Since GRAFWIZ -does- support a true
  450. G1COLOR routine, there are different routines which allow you to change the
  451. palette and border colors. To change the background (and border) color, use:
  452.  
  453.    G1Border Colour%
  454.  
  455.                            Mode-Specific Routines                      page 13
  456.  
  457.  
  458.  
  459. There are two palette routines.  Why two?  Well, QuickBASIC supports two CGA
  460. palettes.  One of the routines works like QuickBASIC and can be used on any
  461. CGA, EGA or VGA display (as long as it's in CGA mode).  The other routine
  462. gives you a wider choice of palettes, but will only work on true CGAs (and
  463. some EGA or VGA systems that have been "locked" into CGA mode).
  464.  
  465. Here's the QuickBASIC-style two-palette routine for any CGA/EGA/VGA:
  466.  
  467.    G1PaletteA PaletteNr%
  468.  
  469. The PaletteNr% may be as follows:
  470.  
  471.    0     (bright) Green, Red, Yellow
  472.    1     Cyan, Violet, White
  473.  
  474.  
  475. The more flexible six-palette routine (for CGA only) works like this:
  476.  
  477.    G1PaletteB PaletteNr%
  478.  
  479. Palettes are as follows:
  480.  
  481.    0     Green, Red, Brown            4     (bright) Green, Red, Yellow
  482.    1     Cyan, Violet, White          5     (bright) Cyan, Violet, White
  483.    2     Cyan, Red, White             6     (bright) Cyan, Red, White
  484.  
  485.                            Mode-Specific Routines                      page 14
  486.  
  487.  
  488.  
  489. The EGA has a number of features which work in all its modes, so rather than
  490. giving them screen mode prefixes, they are simply named with an "E".  These
  491. routines allow you to get or set the palette, get or set the border color,
  492. and determine whether the higher background colors should be displayed as
  493. bright colors or as blinking.
  494.  
  495. To get a palette color value, use:
  496.  
  497.    Colour% = EGetPalette(ColorNumber%)
  498.  
  499. To set the color value, use:
  500.  
  501.    EPalette ColorNumber%, Colour%
  502.  
  503. To get the border color:
  504.  
  505.    Colour% = EGetBorder%
  506.  
  507. You can probably guess how to set the border color:
  508.  
  509.    EBorder Colour%
  510.  
  511. Finally, the blink vs. intensity.  Actually, this is designed for text mode;
  512. I'm not sure whether it has any function in graphics modes.  The text-mode
  513. default is for blinking to be turned on.  With BASIC, you add 16 to the
  514. foreground color to make it blink.  That's a little weird, since the "blink"
  515. attribute is actually a part of the background color, but that's how BASIC
  516. views it.  You can tell the EGA to turn off blinking, in which case adding 16
  517. to the foreground color makes the background color intense.  This doubles the
  518. number of available background colors.
  519.  
  520.    EBlink Blink%
  521.  
  522. Use -1 for blinking (default), or 0 to turn off blinking.
  523.  
  524.                            Mode-Specific Routines                      page 15
  525.  
  526.  
  527.  
  528. Like the EGA, the VGA has a number of features which work in all its modes.
  529. Again, rather than giving them screen mode prefixes, we simply name them with
  530. a "V".  The current routines allow you to get or set the palette colors.
  531.  
  532. To get a palette color value, use:
  533.  
  534.    VGetPalette(ColorNumber%, Red%, Green%, Blue%)
  535.  
  536. To set the color value, use:
  537.  
  538.    VPalette ColorNumber%, Red%, Green%, Blue%
  539.  
  540. As you've probably noticed, this doesn't work the same way as the QuickBASIC
  541. PALETTE statement.  Rather than using a formula to calculate a single LONG
  542. color value, like QuickBASIC, the GRAFWIZ library allows you to specify the
  543. color in a more meaningful way.  The Red%, Green%, and Blue% parameters each
  544. hold an intensity value (0-63).  By mixing these three, you can get an
  545. immense variety of shades-- well over 200,000 combinations in all.
  546.  
  547. If you need to keep track of the intensities in your program, I'd suggest the
  548. following TYPE definition:
  549.  
  550.    TYPE VGAcolor
  551.       Red AS INTEGER
  552.       Green AS INTEGER
  553.       Blue AS INTEGER
  554.    END TYPE
  555.  
  556. If speed is not of the essence, you can compress that to half the size by
  557. using STRING * 1 instead of INTEGER.  In that case, you will need to use the
  558. CHR$ and ASC functions to convert the intensities between string and integer.
  559.  
  560.                               Printer Routines                         page 16
  561.  
  562.  
  563.  
  564. The GRAFWIZ printer routines allow you to work with a printer using the same
  565. convenient methods you'd use on a screen.  The image is created with the
  566. usual G# routines (use mode N2), but the results are kept in a buffer in
  567. memory (about 37K bytes) rather than being displayed directly.  The image can
  568. be previewed on a VGA or printed out at your convenience, to any printer or
  569. even a file.  The results will take up a single printer page, assuming normal
  570. 8.5" x 11" paper.
  571.  
  572. Printing a finished page works like this:
  573.  
  574.    GN2Print Device$
  575.  
  576. The Device$ variable should be set to the name of the device:
  577.  
  578.    LPT1    parallel printer on port 1
  579.    LPT2    parallel printer on port 2
  580.    LPT3    parallel printer on port 3
  581.    COM1    serial printer on port 1
  582.    COM2    serial printer on port 2
  583.  
  584. Instead of using a device name, you can also use a file name, to store the
  585. results for later printing.  Output is done using BASIC file handling, so it
  586. would be a good idea to provide an ON ERROR GOTO trap in case of problems.
  587. The FREEFILE function is used, so you don't have to worry about conflicts
  588. with any files in use by your program.
  589.  
  590. Getting a page layout just right can consume a lot of paper.  Fortunately,
  591. there's a "preview" routine that allows you to display the results on a VGA.
  592. The display will be sideways, allowing the whole page to be seen at once.
  593. This will exactly match the printed output in N2 mode.  Here's how it works:
  594.  
  595.    G11Mode 1               ' set SCREEN 11 (VGA graphics mode, 640x480 x2)
  596.    GN2Display              ' display the page
  597.    DO                      ' wait for a key to be pressed
  598.    LOOP UNTIL LEN(INKEY$)  '
  599.    G11Mode 0               ' set SCREEN 0 (text mode)
  600.  
  601. The G#Write and G#WriteLn printer routines are unlike the display versions of
  602. the same routines in that they don't scroll.  These routines only allow you
  603. to design one page at a time.
  604.  
  605.                                A Little Geometry                       page 17
  606.  
  607.  
  608.  
  609. The increasing capabilities of computer graphics systems has left many of us
  610. in the dust.  It's great to be able to run dazzling applications or to doodle
  611. with a "paint" program, but many of us find it difficult to design appealing
  612. images of our own.  Becoming an artist is perhaps a bit more than most of us
  613. are willing to take on!  It is important to remember, however, that computers
  614. are wonderful number-crunchers.  With a little application of plane geometry,
  615. you can have the computer take on much of the work for you-- and after all,
  616. isn't that why we have computers in the first place?
  617.  
  618. A complete review of plane geometry is a bit beyond the scope of this text.
  619. However, I'm going to run through some of the things I think you'll find most
  620. useful.  I'd also like to suggest that you might dig out your old textbooks
  621. or rummage through your local used book store.  It may have seemed like a dry
  622. subject at the time, but when you can watch the results growing on your
  623. computer screen, you will have a much better idea of how geometry can be
  624. useful to you-- and it can be surprisingly fun, too!
  625.  
  626. In geometry talk, a "point" doesn't have any actual size.  In our case, we
  627. want to apply geometry to physical reality, namely the computer screen.  As
  628. far as we're concerned, a "point" will be an individual graphics dot, also
  629. called a "pel" or "pixel" (for "picture element").  We can safely dispense
  630. with such formalities for our applications, for the most part.
  631.  
  632. The most important thing about a point is that it has a location!  Ok, that
  633. may not seem staggering, but it happens that there are a number of ways of
  634. specifying that location.  The most common method is called the Cartesian
  635. coordinate system.  It is based on a pair of numbers: X, which represents the
  636. distance along a horizontal line, and Y, which represents the distance along
  637. a vertical line.  Consider the CGA in SCREEN 2, for instance.  It has a
  638. coordinate system where X can be 0 - 639 and Y can be 0 - 199.  The points
  639. are mapped on kind of an invisible grid.
  640.  
  641. The Cartesian coordinate system makes it easy to visualize how a given point
  642. relates to other points on the same plane (or screen).  It is particularly
  643. useful for drawing lines.  Horizontal and vertical lines become a cinch: just
  644. change the X value to draw horizontally, or the Y value to draw vertically.
  645. Squares and rectangles (or boxes) can be formed by a combination of such
  646. lines.  You can define an area of the screen in terms of an imaginary box
  647. (as GET and PUT do) with nice, clean boundaries.  When we get to diagonal
  648. lines, it's a bit more of a nuisance, but still easy enough with the proper
  649. formula.  That means we can do triangles too.  Curves are worse... when it
  650. comes to even a simple circle or ellipse, the calculations start to get on
  651. the messy side.  For things like that, though, there is an alternative.
  652.  
  653. Another way of describing the location of a point is by Polar coordinates.
  654. In Cartesian coordinates, the location is specified by its horizontal and
  655. vertical distances from the "origin" or reference point, (0,0).  In Polar
  656. coordinates, the location is specified by its distance and angle from the
  657. origin.  Think of it as following a map: Cartesian coordinates tell you how
  658. many blocks down and how many blocks over the point is, whereas Polar
  659. coordinates tell you in which direction the point is and how far away it is
  660. "as the crow flies".
  661.  
  662.                                A Little Geometry                       page 18
  663.  
  664.  
  665.  
  666. The Polar coordinate system is great for describing many kinds of curves,
  667. much better than Cartesian.  For example, a circle is defined as all of the
  668. points at a given (fixed) distance from a center point.  Polar coordinates
  669. include both a distance and an angle, and we've already got the distance, so
  670. all we need to do is plot points at all of the angles on a circle.
  671. Technically, there is an infinite number of angles, but since our points
  672. don't follow the mathematical definition (they have a size), we don't have to
  673. worry about that.
  674.  
  675. Let me digress for a moment to talk about angles.  In BASIC, angles are
  676. specified in "radians".  People more often use "degrees".  Fortunately, it
  677. isn't hard to convert from one to the other.  Both may be visualized on a
  678. circle.  In radians, the sum of the angles in a circle is twice pi.  In
  679. degrees, the sum of the angles is 360.  That's something like this:
  680.  
  681.  
  682.                           90 deg, 1/2 * pi rad
  683.                                 /---|---\
  684.                                /    |    \
  685.                               /     |     \
  686.                 180 degrees   |___  .  ___|    0 deg, 0 rad; or...
  687.                 pi radians    |           |  360 deg, 2 * pi rad
  688.                               \     |     /
  689.                                \    |    /
  690.                                 \---|---/
  691.                           270 deg, 3/2 * pi rad
  692.  
  693.  
  694. Ok, so that's a grotesquely ugly circle!  Hopefully it shows the important
  695. thing, though.  Angles start at zero on the extreme right and get larger as
  696. they work around counter-clockwise.  The places marked on the "circle" are
  697. places where lines drawn horizontally and vertically through the center
  698. intersect the outside of the circle.  These serve as a useful reference
  699. point, especially in that they help show how the angles can be construed from
  700. a Cartesian viewpoint.
  701.  
  702. So much for angles.  I'll go into conversion formulae, the value of pi, and
  703. other good junk a bit later on.  Right now, let's get back to our discussion
  704. of Polar coordinates.
  705.  
  706. I've explained how the Polar system makes it easy to draw a circle.  Since
  707. you can vary the range of angles, it's equally simple to draw an arc.  If you
  708. wanted to make a pie chart, you might want to join the ends of the arcs to
  709. the center of the circle, in which case you'd keep the angle constant (at the
  710. ends of the arc) and plot by changing the distance from zero to the radius.
  711. Circles are also handy for drawing equilateral polygons... you know, shapes
  712. with sides of equal length: triangle, square, pentagon, hexagon, etc.  In
  713. this case, the best features of the Cartesian and Polar systems can be joined
  714. to accomplish something that would be difficult in either alone.
  715.  
  716.                                A Little Geometry                       page 19
  717.  
  718.  
  719.  
  720. The starting point for these polygons is the circle.  Imagine that the
  721. polygon is inside a circle, with the vertices (pointy ends, that is, wherever
  722. the sides meet) touching the edge of the circle.  These are equilateral
  723. polygons, so all of the sides and angles are the same size.  Each of the
  724. vertices touches the circle, and each does it at exactly the same distance
  725. from each other along the arc of the circle.  All of this detail isn't
  726. precisely necessary, but I hope it makes the reasoning a bit more clear!
  727.  
  728. The circle can be considered as being divided by the polygon into a number of
  729. arcs that corresponds to the number of vertices (and sides) the polygon has.
  730. Think of a triangle inside a circle, with the tips all touching the circle.
  731. If you ignore the area inside the triangle, you will see that the circle is
  732. divided into three equal arcs.  The same property is true of any equilateral
  733. polygon.  As a matter of fact, as the number of vertices goes up, the circle
  734. is partitioned into more, but smaller, arcs... so that a polygon with a large
  735. enough number of vertices is effectively a circle itself!
  736.  
  737. Anyway, the important thing is the equal partitioning.  We know how many
  738. angles, be they degrees or radians, are in a circle.  To get the points of a
  739. polygon, then... well, we already know the "distance" part, that's the same
  740. as the radius.  The angles can be calculated by dividing the angles in the
  741. whole circle by the number of vertices in the desired polygon.  Trying that
  742. case with the triangle, assuming a radius of 20 (why not), and measuring in
  743. degrees, that would give us the Polar points (20, 0), (20, 120), (20, 240).
  744. To make this a triangle, we need to connect the points using lines, which is
  745. easy in Cartesian coordinates.  Since the computer likes Cartesian anyway, we
  746. just convert the Polar coordinates to Cartesian, draw the lines, and viola!
  747.  
  748. That's essentially the method used by the G#Polygon routines.  It's very
  749. simple in practice, but I haven't seen it elsewhere... probably because
  750. people forget about the Polar coordinate system, which is what makes it all
  751. come together.  Polar coordinates also have simple equations for figures that
  752. look like daisies, hearts, and other unusual things.  See "Equations, Etc"
  753. and ROSES.BAS for more information.
  754.  
  755. On a side note, the Cartesian system isn't used by all computers, although
  756. it's the most common.  Cartesian coordinates are the standard for what is
  757. called "raster" displays.  The Polar coordinate system is used on "vector"
  758. displays.  One example of a vector display that you may have seen is the old
  759. Asteroids video arcade game.  They tend to be used for drawing monochrome
  760. "framework" pictures where the image must be very sharp (unlike in raster
  761. images, the diagonal lines aren't jagged, since there's no raster "grid").
  762.  
  763.                                 Equations, Etc                         page 20
  764.  
  765.  
  766.  
  767. In this section, I'm going to list a number of equations and so forth.  Some
  768. of them will be useful to you in experimenting with Polar coordinates.  Some
  769. of them provide formulae for things that are already in GRAFWIZ, but which
  770. you might like to understand better.  Some of them are just for the heck of
  771. it... note that not all of this information may be complete enough for you to
  772. just use without understanding it.
  773.  
  774. One problem is... if you try to draw a circle, for instance, it will come out
  775. looking squashed in most SCREEN modes.  Remember we said our points, unlike
  776. mathematical points, have a size?  In most graphics modes, the points are
  777. effectively wider than they are high, so a real circle looks like an ellipse.
  778.  
  779. Another problem is that these equations are based on an origin of (0,0) which
  780. is assumed to be at the center of the plane.  In our case, (0,0) is at the
  781. upper right edge, which also makes the Y axis (vertical values) effectively
  782. upside-down.  This isn't necessarily a problem, but sometimes it is!  Adding
  783. appropriate offsets to the plotted X and Y coordinates often fixes it.  In
  784. the case of Y, you may need to subtract the value from the maximum Y value to
  785. make it appear rightside-up.
  786.  
  787. The displayed form of these equations may contain "holes", usually again
  788. because the points have a size, and/or since we try to use integer math to
  789. speed things up.  If the screen had infinite resolution, this would not be a
  790. problem... meanwhile (!), getting around such problems takes fiddlin'.
  791.  
  792. There are other problems, mostly due to forcing these simplified-universe
  793. theoretical equations into practical use.  It's a lot easier to shoehorn in
  794. these simple equations than to use more accurate mathematical descriptions,
  795. though... a -lot- easier.  So a few minor quirks can be ignored!
  796.  
  797. With those disclaimers, here's the scoop on some handy equations.
  798.  
  799.    Polar coordinates may be expressed as (R, A), where R is radius or
  800.    distance from the origin, and A is the angle.
  801.  
  802.    Cartesian coordinates may be expressed as (X, Y), where X is the distance
  803.    along the horizontal axis and Y is the distance along the vertical axis.
  804.  
  805.    Polar coordinates can be converted to Cartesian coordinates like so:
  806.       X = R * COS(A)
  807.       Y = R * SIN(A)
  808.  
  809.    Angles may be expressed in radians or degrees.  BASIC prefers radians.
  810.    Radians are based on PI, with 2 * PI radians in a circle.  There are 360
  811.    degrees in a circle.  Angles increase counter-clockwise from a 3:00 clock
  812.    position, which is the starting (zero) angle.  Angles can wrap around: 720
  813.    degrees is the same as 360 degrees or 0 degrees, just as 3:00 am is at the
  814.    same clock position as 3:00 pm.
  815.  
  816.    Angles may be converted between degrees and radians as follows:
  817.       radians = degrees * PI / 180
  818.       degrees = radians * 180 / PI
  819.  
  820.                                 Equations, Etc                         page 21
  821.  
  822.  
  823.  
  824.  
  825.    The value PI is approximately 3.14159265358979.  For most graphics
  826.    purposes, a simple 3.141593 should do quite nicely.  The true value of PI
  827.    is an irrational number (the decimal part repeats forever, as near as
  828.    anyone can tell).  It has been calculated out to millions of decimal
  829.    points by people with a scientific bent (and/or nothing better to do)!
  830.  
  831. Line Drawing:
  832.  
  833.    One of the convenient ways of expressing the formula of a line (Cartesian
  834.    coordinates) is:
  835.       Y = M * X + B
  836.  
  837.    Given the starting and ending points for the line, M (the slope,
  838.    essentially meaning the angle of the line) can be determined by:
  839.       M = (Y2 - Y1) / (X2 - X1)
  840.  
  841.    The B value is called the Y-intercept, and indicates where the line
  842.    intersects with the Y-axis.  Given the ingredients above, you can
  843.    calculate that as:
  844.       B = Y1 - M * X1
  845.  
  846.    With this much figured out, you can use the original formula to calculate
  847.    the appropriate Y values, given a FOR X = X1 TO X2 sort of arrangement.
  848.    If the slope is steep, however, this will result in holes in the line.  In
  849.    that case, it will be smoother to recalculate the formula in terms of the
  850.    X value and run along FOR Y = Y1 TO Y2... in that case, restate it as:
  851.       X = (Y - B) / M
  852.  
  853.    Keep an eye on conditions where X1 = X2 or Y1 = Y2!  In those cases,
  854.    you've got a vertical or horizontal line.  Implement those cases by simple
  855.    loops to improve speed and to avoid dividing by zero.
  856.  
  857.  
  858.  
  859. Circle Drawing:
  860.  
  861.    The Cartesian formula gets messy, especially due to certain aspects of the
  862.    display that are not accounted for (mainly that pixels, unlike theoretical
  863.    points, have a size and shape which is usually rectangular).  The Polar
  864.    formula is trivial, though.  The radius should be specified to the circle
  865.    routine, along with the center point.  Do a FOR ANGLE! = 0 TO 2 * PI! STEP
  866.    0.5, converting the resulting (Radius, Angle) coordinates to Cartesian,
  867.    then adding the center (X,Y) as an offset to the result.  The appropriate
  868.    STEP value for the loop may be determined by trial and error.  Smaller
  869.    values make better circles but take more time.  Larger values may leave
  870.    "holes" in the circle.
  871.  
  872.                                 Equations, Etc                         page 22
  873.  
  874.  
  875.  
  876. Polygon Drawing:
  877.  
  878.    I've already discussed that, so I'll leave it as an exercise... or of
  879.    course you can examine my source code if you register GRAFWIZ!  The
  880.    polygon routines are in BASIC, except for the line-drawing parts.
  881.  
  882.  
  883.  
  884. Flower Drawing:
  885.  
  886.    This sort of thing would be rather difficult to do using strictly
  887.    Cartesian methods, but with Polar coordinates, no problem.  Here we
  888.    calculate the radius based on the angle, using something like:
  889.  
  890.       FOR Angle! = 0 TO PI! * 2 STEP .01
  891.  
  892.    (a low STEP value is a good idea).  The radius is calculated like so:
  893.  
  894.       Radius! = TotalRadius! * COS(Petals! * Angle!)
  895.  
  896.    The Petals! value specifies how many petals the flower should have.  If it
  897.    is odd, the exact number of petals will be generated; if even, twice that
  898.    number will be generated.
  899.  
  900.    These figures are technically called "roses", although they more resemble
  901.    daisies.  Try the ROSES.BAS program to see how they look.
  902.  
  903.  
  904.  
  905. Other Drawing:
  906.  
  907.    Experiment!  There are all sorts of interesting things you can do with the
  908.    Polar coordinate system in particular.  Dig up those old Geometry texts or
  909.    see if your Calculus books review it.  If you've kept well away from math,
  910.    try your local library or used book store.
  911.  
  912.                              Miscellaneous Notes                       page 23
  913.  
  914.  
  915.  
  916. Limitations:
  917.  
  918.    The EGA graphics routines are designed for use with EGAs having at least
  919.    256K RAM on board.  They will not operate properly on old 64K EGA systems.
  920.  
  921.    Image loading (.MAC and .PCX) is quite slow.  The bulk of the code is in
  922.    BASIC at this point, to make it easier for me to extend the routines to
  923.    cover other graphics modes.  They will be translated to assembly later.
  924.  
  925.    The G#Write and G#WriteLn services do not allow for extended ASCII
  926.    characters at this time.  This includes CHR$(128) - CHR$(255).  Later
  927.    versions of these services will include support for extended ASCII,
  928.    allowing for a redefinable extended character set as well as providing the
  929.    standard characters as defined in text modes.
  930.  
  931.    The G#Write and G#WriteLn services interpret ASCII control characters,
  932.    i.e. CHR$(0) - CHR$(31), according to the more standard handling used by
  933.    DOS rather than the esoteric interpretation offered by QuickBASIC.  This
  934.    is not entirely a limitation, but it could conceivably cause confusion if
  935.    your program happens to use these characters.  The ASCII interpretion runs
  936.    as follows:
  937.  
  938.        Code       Meaning
  939.        ====       =======
  940.          7        Bell      (sound a beep through the speaker)
  941.          8        Backspace (destructive: eliminates the previous character)
  942.          9        Tab       (based on 8-character tab fields)
  943.         10        LineFeed  (move down one line, keep current column)
  944.         12        FormFeed  (clear the screen)
  945.         13        Return    (move to the start of the current line)
  946.  
  947.    G#MirrorH will only work properly on images with byte alignment!  This
  948.    means that the width of the image must be evenly divisible by four if
  949.    SCREEN 1 is used, or evenly divisible by eight if SCREEN 2 is used.
  950.  
  951.    The graphics routines provide little error checking and will not do
  952.    clipping (which ignores points outside the range of the graphics mode).
  953.    If you specify coordinates which don't exist, the results will be unusual
  954.    at best.  Try to keep those values within the proper range!
  955.  
  956.    A very few of the graphics routines are slower than their counterparts in
  957.    QuickBASIC.  These are mostly drawing diagonal lines and filling boxes.  I
  958.    hope to get these better optimized in a future release.  The GET/PUT image
  959.    replacements are quite slow, but that's strictly temporary!  I rushed 'em
  960.    in by special request from a registered GRAFWIZ owner.
  961.  
  962.                              Miscellaneous Notes                       page 24
  963.  
  964.  
  965.  
  966.    If you use PRINT in conjunction with GN4Write/WriteLn, be sure to save the
  967.    cursor position before the PRINT and restore it afterwards... or use
  968.    GN4Locate to position the GN4Write.  BASIC and GRAFWIZ share the cursor
  969.    position, but each interprets it to mean a different thing.
  970.  
  971.    The GN0 (360x480x256) and GN1 (320x400x256) routines use nonstandard VGA
  972.    modes.  The GN1 routines should work on just about any VGA, however.  The
  973.    GN0 routines will work on many VGAs, but are somewhat less likely to work
  974.    than the GN1 routines due to the techniques involved.
  975.  
  976.    The GN0Write, GN0WriteLn, GN1Write and GN1WriteLn routines are somewhat
  977.    slow in general and quite slow when it comes to scrolling the screen.
  978.    These problems are related to peculiarities of these modes that I'm still
  979.    grappling with.  They will hopefully be improved in a future release.
  980.  
  981.    The EGA and VGA versions of G#Write and G#WriteLn routines expect to see a
  982.    particular number of text rows per screen, although their expectations may
  983.    be incorrect.  This will be fixed in a later release.
  984.  
  985.    The G1Border routine is normally used to select the background (and
  986.    border) color for SCREEN 1 mode.  It can also be used in SCREEN 2 mode,
  987.    where it will change the foreground color instead.  Note that this may
  988.    produce peculiar results if an EGA or VGA is used and it isn't locked into
  989.    "CGA" mode, so be careful if your program may run on systems with displays
  990.    other than true CGAs.
  991.  
  992. GET/PUT Images:
  993.  
  994.    These guys have a lot of possibilities that Microsoft has never touched
  995.    on.  I'll be exploring this extensively in future versions.  Among other
  996.    things, expect the ability to change the colors, rotate the image, and
  997.    translate the image from one graphics mode format to another.  Enlarging
  998.    and shrinking the image will also be a good bet.
  999.  
  1000. Odd ends:
  1001.  
  1002.    You can GET an image in SCREEN 1 and PUT it in SCREEN 2!  It'll be shaded
  1003.    instead of in colors.  This is a side-effect of the CGA display format.
  1004.  
  1005.    The first two elements of a GET/PUT array (assuming it's an integer array)
  1006.    tells you the size of the image.  The first element is the width and the
  1007.    second is the height, in pixels.  Actually, that's not quite true.  Divide
  1008.    the first element by 2 for the width if the image is for SCREEN 1, or by 8
  1009.    if for SCREEN 13.
  1010.  
  1011.                             Memory Considerations                      page 25
  1012.  
  1013.  
  1014.  
  1015. GrafWiz uses almost none of BASIC's data space.  Since the code is split into
  1016. many modules, none of which are large, it is unlikely to affect your
  1017. available programming memory either (unless you are using the QB environment
  1018. with GRAFWIZ.QLB loaded).  In other words, you will rarely have to worry
  1019. about the RAM used by GrafWiz.  The possible exception to this is if you use
  1020. the Epson graphics routines, as they must allocate about 37K as a graphics
  1021. buffer.  The memory requirements listed here are included in case you are
  1022. interested, not because I expect them to matter.
  1023.  
  1024. Keep in mind that the memory used is offset to some extent by the memory you
  1025. save by not using the graphics routines provided by BASIC.  You save the most
  1026. amount of memory by not using -any- BASIC graphics command, as this will
  1027. avoid loading BASIC graphics support into your program.
  1028.  
  1029. The GrafWiz routines are largely in modules based on specific graphics mode,
  1030. i.e. each graphics mode has its own separate module(s).  This means that only
  1031. the mode(s) that you use are brought into your BASIC program.
  1032.  
  1033. The overhead to support for each graphics mode ranges from around 1K-2K,
  1034. depending on the routines you use.
  1035.  
  1036. There is an additional module which supports the fonts for the G#Banner
  1037. routine.  If you use G#Banner, regardless of the graphics mode(s), the font
  1038. module will be added to your program (just once).  This adds about 4K.
  1039.  
  1040. The G#Polygon routine is written in BASIC and uses single-precision math.  It
  1041. is not particularly large in itself, but will cause BASIC's floating point
  1042. support to be linked in to your program.  Depending on the program, this may
  1043. cause the executable to grow by as much as 14K or so.
  1044.  
  1045.                                Troubleshooting                         page 26
  1046.  
  1047.  
  1048.  
  1049. Problem:
  1050.    QB says "subprogram not defined".
  1051.  
  1052. Solution:
  1053.    The definition file was not included.  Your program must contain the line
  1054.       REM $INCLUDE: 'GRAFWIZ.BI'
  1055.    before any executable code in your program.  You should also start
  1056.    QuickBASIC with
  1057.       QB /L GRAFWIZ
  1058.    so it knows to use the GRAFWIZ library.
  1059.  
  1060.  
  1061. Problem:
  1062.    LINK says "unresolved external reference".
  1063.  
  1064. Solution:
  1065.    Did you specify GRAFWIZ as the library when you used LINK?  You should!
  1066.    The GRAFWIZ.LIB file must be in the current directory or along a path
  1067.    specified by the LIB environment variable (like PATH, but for LIB files).
  1068.  
  1069.  
  1070. Problem:
  1071.    The G#MirrorH routine is -almost- working right, but the results are
  1072.    truncated or wrapped to one side.
  1073.  
  1074. Solution:
  1075.    Make your GET image a tad wider!  The number of pixels wide must be evenly
  1076.    divisible by four in SCREEN 1, or by eight in SCREEN 2.
  1077.  
  1078.                            Using GRAFWIZ with PDQ                      page 27
  1079.  
  1080.  
  1081.  
  1082. Crescent Software's PDQ library does not currently support floating point
  1083. math, which is required by the G#Polygon routines.  Other than that, all of
  1084. the routines should work fine with PDQ.
  1085.  
  1086. Crescent thoughtfully provided me with a free copy of PDQ in order that I
  1087. might resolve any incompatibilities between it and my BASIC libraries.  If
  1088. you are not familiar with PDQ, it is a replacement library for BASIC's own
  1089. runtime libraries.  While not providing every capability of plain QuickBASIC,
  1090. it allows you to create substantially smaller EXE files for those programs
  1091. that qualify.  Support is currently lacking for floating point (single/double
  1092. precision) numbers, music, and graphics, among other things.  I understand
  1093. that these will be added to a future version of the library.  Communications
  1094. support is available as an add-on package.  PDQ also adds new capabilities
  1095. which are quite impressive, such as being able to write small TSRs in BASIC.
  1096. Check with Crescent for more recent details.
  1097.  
  1098.                                   Credits                              page 28
  1099.  
  1100.  
  1101.  
  1102. For some of the reference works I have used in writing GRAFWIZ, see the
  1103. BIBLIO.TXT file.
  1104.  
  1105. I am also indebted to the following people, among others:
  1106.  
  1107. Bill Cliver, president of F & I Controls, which markets software and hardware
  1108. solutions for every aspect of car dealerships.  He has provided me with the
  1109. VGA system which has allowed me to support VGA graphics modes in GRAFWIZ.
  1110.  
  1111. Mike Welch, co-sysop of The Shipyard BBS, the best BASIC support BBS that
  1112. I've ever encountered.  Among other fine deeds, he is responsible for the
  1113. S&B4EGA and VGABOX demonstration programs which accompany GRAFWIZ.
  1114.  
  1115. The 360x480 256-color VGA mode was made possible by John Bridges' VGAKIT 3.4
  1116. library for C.  Two of the most vital low-level routines are based directly
  1117. on code from VGAKIT.  If you use C, check your local BBS for this library.
  1118.  
  1119.