QBSVGA, version 3.1 "QBSVGA" is a set of subroutines/functions (and an "include file") that can be used within QB programs to achieve SVGA graphic capability. Much, but not all, of the standard QB graphic routines are emulated. To be specific, the QBSVGA routines work best when the video system is not just SVGA-capable, but VESA-aware as well. (I have yet to encounter an SVGA-equipped system that is not VESA-aware, but I understand they exist.) There are included stand-alone routines, VS.EXE and VS1.EXE, that you can use to determine whether or not your system is VESA-aware and what video modes you have support for. See VS.TXT for more information concerning these routines. Whether or not a VESA bios is present on your SVGA card, you must not only have hardware support for the video mode you want to use, it must be supported by your VESA bios as well. (It's entirely possible to have support in hardware for a video mode that your bios cannot itself access. The routines supplied here do not use direct hardware access, as opposed to the intrinsic QB graphic routines.) Further, for the software to auto-detect a VESA video mode, your VESA bios must provide the so-called extended information about that mode. (VS1 will tell you whether or not this information is available. If VS1 informs you that such information is unavailable for any given mode, there is not necessarily any reason to worry. If QBSVGA fails to find such information for any one particular mode, it will simply look for another one.) Most of the documentation regarding the QBSVGA routines can be found by reading the comments associated with each subroutine/function in QBSVGA.BAS. This file simply makes some general comments and lists the functionallity provided by QBSVGA. QBSVGA gives you access to up to 12 different SVGA modes/resolutions: MODE = 14: 640 x 480 x 256 MODE = 15: 800 x 600 x 16 MODE = 16: 800 x 600 x 256 MODE = 17: 1024 x 768 x 16 MODE = 18: 1024 x 768 x 256 MODE = 19: 1200 x 1024 x 16 MODE = 20: 1200 x 1024 x 256 MODE = 21: 1600 x 1200 x 16 MODE = 22: 1600 x 1200 x 256 MODE = 23: 132 x 25 x 16 (text) MODE = 24: 132 x 43 x 16 (text) MODE = 25: 132 x 50 x 16 (text) The mode integers listed above are the "QB-type" integers that you would input to QBSVGA's analog of QB's screen statement. They are not necessarily the actual hex numbers that your bios references (i.e., the video mode specifiers that QBSVGA, via its subroutine FINDVESA, attempts to auto- detect). Except for 0, and assuming that auto-detection works, if you try to use a QB-type mode not specified above, you'll get an 800 x 600 x 16 mode (if support for it can be found). (Using a mode of 0 produces the same effect as QB's SCREEN 0 statement.) The general method of using QBSVGA is to put the contents of REGTYPE.INC at the top of your program, write your program, calling any and whichever of the QBSVGA routines you need, and then put the contents of QBSVGA.BAS at the bottom of your program. When you go to link your compiled program, be sure and use the auxiliary library QB.LIB in addition to whatever libraries you normally link with. The usage syntax of the routines is similar to that with the corresponding internal QB routines. The QBSVGA routine names are prefixed with a "B" (for "bios") to distinguish them from their intrinsic QB analogs. (For the few routines provided that do not emulate specific QB functions, this convention isn't necessarily followed. Another exception is MPUT/MGET, previously named BGET/BPUT. There are now *new* BPUT/BGET subroutines.) One difference between the intrinsic and QBSVGA routines is that you must not leave out parameters unimportant to you in the calls to the QBSVGA routines. Another difference is that, except for functions BPOINT and BPOS, these routines must be accessed via QB's CALL statement. You can put DECLARE statements at the top of your program if you wish to avoid this detail, but there is still the matter of enclosing the arguments/parameters in parentheses. Except for various character string inputs (which should be obvious), all data passed to the routines should be of type single precision (real). (BPOINT and QRYMOUSE *return* 2-byte integers.) Example MAIN routines, SIM.BAS, MOUSDEMO.BAS, and PRTEST.BAS are included to show the basic usage of the routines. (You may of course wish to read the commentary and inspect the SUB/FUNCTION statements themselves in QBSVGA.BAS.) The rest of this file gives a basic description of the different routines supplied in QBSVGA.BAS. SUB BSCREEN: analog of QB's SCREEN statement (QB's SCREEN function is not emulated here. BSCREEN will not change the video mode if the screen is already in the mode you're requesting. In this situation, BSCREEN serves merely to change active and displayed video pages. Exceptions to this are when your inputting a video mode of 0 to BSCREEN, to achieve the same effect as QB's SCREEN 0 statement, or when auto-mode detection failed and you get prompted for the bios video mode to use--see below. BSCREEN should be called before any of the other routines--and then again with a QB-type mode of 0 when you're all done.) SUB BPSET: analog of QB's PSET statement SUB BLINE: analog of QB's LINE statement (QB's style option is not supported.) SUB BCIRCLE: analog of QB's CIRCLE statement SUB BCLS: analog of QB's CLS 0 and CLS 1 statements (CLS 2 is not supported.) SUB BCOLOR: analog of QB's COLOR statement SUB BLOCATE: analog of QB's LOCATE statement (LOCATE's cursor control options are not included.) SUB BPRINT: analog of QB's PRINT statement (See QBSVGA.BAS for discussion of differences in how this routine formats output.) FUNCTION BPOINT%: analog of QB's POINT function (Note that BPOINT is a 2-byte INTEGER.) SUB BVIEW: analog of QB's graphics VIEW statement (The SCREEN option of VIEW is not supported and its performance is somewhat limited when its border encroaches on a screen edge.) SUB BPAINT: a not necessarily exact analog of QB's PAINT statement (You should be able to use this subroutine to achieve the same results that PAINT would give if it applied to SVGA video modes. However, especially when painting the exterior of objects, you may need to make multiple calls to BPAINT with different (x,y) inputs. Also, painting only occurs in regions in which the pixel color is the same as the background. The background color is either 0 or it is the color of whatever the viewport (if active) was filled with. (PAINT's tiling option is not supported.) Also, BPAINT may at times perform better if the coordinate you specify isn't directly adjacent to a pixel bordering the area you're painting. These slight idiosyncracies are perhaps offset by a difference between BPAINT and PAINT that may make BPAINT somewhat better. PAINT will not let you, for example, paint the inside of a circle with a different color than used to draw the circle. If you try, the painting will progress outside of the circle until pixels of the painting color or the screen/viewport edge are encountered. BPAINT doesn't perform that way. BPAINT has no problems with your drawing a circle (or any closed object) with one color and painting its interior with an another.) FUNCTION BPOS: an emulation of QB's POS *and* CRSLIN functions (The current line, or row, is returned via the argument list and the current column is returned as BPOS.) SUB BPCOPY: an emulation of QB's PCOPY statement SUB MGET: a monochromatic emulation of QB's graphics GET statement (Unlike GET, you don't send the name of the array to BGET. Rather, you send it the memory location segment and offset of the first element in the array. (These can be obtained via QB's VARSEG and VARPTR functions.) As with GET, it is best to use an INTEGER or LONG array. Also, unless your picture occupies less than 64K, you should use a DYNAMIC array (which will make the offset 0). (These comments apply to MPUT, BGET, and BPUT, below, as well.) MGET only saves graphic data in a monochrome format. If W and H are the width and height of the screen area to be saved, the size of the array in bytes can be calculated the same way as with GET: BYTES = 4 + H * INT( (W + 7) / 8). The number of elements is then INT( (BYTES + N - 1) / N), where N = 2 or 4, depending on whether it is an INTEGER or LONG array, respectively. If you have a lot of colors and filled/painted areas, this subroutine (and BPUT, below) may not be of much use. Also, BGET does not generally save the border of a graphics viewport. (If the border is at a screen edge, that border will be saved--not a generally desirable result. This is one of the reasons why the border option of BVIEW isn't particularly useful when the viewport is encroaching on a screen border.) Except for perhaps the case in which the viewport encroaches on a screen edge and the possible change in color, you can circumvent this problem by regenerating the viewport before using BPUT. The format of the call is CALL BGET (XL, YL, XR, YR, SM, OS) where the first four variables are analogous to the quantities in GET, and SM and OS are the above mentioned segment and offset.) SUB MPUT: a monochrome emulation of QB's graphics PUT statement (This routine also inputs the memory segment and offset of the array instead of the name of the array itself. Although BPUT only works with a monochrome-formatted picture, you can specify the color attribute to use for that one color via the parameter CL. PUT's action verb is also supported, in a monochrome sense-- it is input via the character string ACT$. The format of the call is CALL BPUT (X, Y, CL, SM, OS, ACT$) where (X,Y) is the viewport/screen coordinate of where the upper lefthand corner of the picture is to be, just like PUT.) SUB BGET: a more exact emulation of QB's graphics GET statement (BGET supports color in single and 4 bit plane modes. (I'm not aware of other numbers of bit planes per pixel in an SVGA mode.) The call to BGET is the same as the call to MGET. The number of bytes in the array that BGET stores data to is calculated just as with normal QB color modes. If PLANES is the number of bit planes per pixel and BITS is the number of bits per pixel, BYTES = 4 + H * PLANES * INT( (W * BITS / PLANES + 7) / 8).) SUB BPUT: a more exact emulation of QB's graphics PUT statement (BPUT supports color. The call to it is the same as the call to MPUT except that you leave out the color parameter: CALL BPUT (X, Y, SM, OS, ACT$) The colors in your stored picture now determine the colors that appear on the screen. If you're using the SET MODE##= option discussed in the file FEATURE.ADV, or if QBSVGA cannot autodetect a suitable SVGA video mode and asks you to input a valid bios mode integer, BGET and BPUT will assume single bit plane graphics. Even if you only need 16 colors, if you're going to be using BGET and BPUT, I strongly suggest you use a 256-color video mode. Such modes generally only have one bit plane per pixel, and these subroutines are significantly faster in single bit plane modes than 4 bit plane modes.) The following routines are not emulations of intrinsic QB statements/ commands. They are simply provided as (hopefully) a convenience to give at least minimal mouse and printer support to your programs in a *GRAPHIC* video mode. FUNCTION QRYMOUSE%: mouse driver detecting function (QRYMOUSE, a 2-byte integer, is returned as -1 if a rodent driver is installed via interrupt 33h and 0, otherwise. If driver is detected, QRYMOUSE returns the number of buttons present via the global variable BUTTONS and a default color attribute for the mouse cursor of 15 in the global 2-byte integer variable MCOLOR. (You can change this to any other valid attribute that you'd like after QRYMOUSE sets it but don't do so until *after* you call BSCREEN because BSCREEN uses QRYMOUSE.) QRYMOUSE's has no explicit arguments.) SUB MOUSINIT: initializes mouse (You don't need to call MOUSINIT; subroutine BSCREEN does that.) SUB GETLIM: determines physical constraints on mouse cursor motion (Outputs maximum screen coordinates cursor can move to and cursor movement discretization data to global variables listed below. This description is only here in case you're interested. You don't need to explicitly worry about it-- BSCREEN calls GETLIM via subroutine MOUSINIT.) SUB SETLIM: sets new limits for mouse cursor motion (The input parameters are the upper lefthand and lower right- hand coordinates of the rectangle the cursor is to move in-- much like the inputs to BVIEW, for example. If you are going to use this subroutine, do so before using GETPOS, below. BSCREEN, via subroutine MOUSINIT, calls it inititally to set things up.) SUB GETPOS: turns on and controls a cross-hair style graphics mouse cursor. (This is the tricky part here. SVGA monitors do not generally display mouse cursors correctly, if at all, in a graphics mode using standard mouse driver functions. (The cursor's there. You can track its position, etc., you just can't see it.) GETPOS doesn't use the mouse driver to turn the cursor on. Rather, it just uses bios functions to draw a cross-hair style cursor. GETPOS lets you move the cursor around the screen and returns its (X,Y) screen position when you press a button. It also returns 0 for the variable BUTTON if you pressed the left button, 1 if you pressed the right button, and BUTTON will be returned as 2 if you pressed the middle button (Mouse Systems). Do not call this function if you're in a text screen mode. The general use of GETPOS is to put it in a loop. Although the cursor is turned off between calls to GETPOS, its position is maintained.) SUB BOXDRAG: a "click and drag with bounding box" routine (Once this routine is called it waits for you to press and hold a mouse button. You may then move the cursor around the screen and an ever-expanding or contracting rectangle will be drawn to track the motion. (The cursor itself is not drawn once the button is pressed; just use the moving corner of the rectangle as the position indicator.) When you release the button, BOXDRAG returns the positions (XP,YP) and (XR,YR), the screen coordinates where the button was pressed and released, respectively. It also returns the parameter BUTTON to indicate which button was involved. (BUTTON has the same interpretation as in GETPOS, which BOXDRAG uses to get the button-press data. Like GETPOS, BOXDRAG requires a graphics screen mode.) The box is drawn with the same attribute MCOLOR used by GETPOS to draw the cursor. (You may want to avoid using this color yourself for other purposes. You may also want to avoid dragging a box of zero width vertically over graphics/"text" that's already on the screen--there's a minor bug which I'll fix as soon as I figure out how. (Generally, this doesn't appear to be a problem with the normal uses that drawing a bounding box has.)) Also, the box disappears when BOXDRAG returns.) SUB HPRINT: a routine to print QBSVGA pictures on an HP Laserjet/Deskjet (This routine is similar to BGET in operation and function. It merely transfers the graphic data to an HP Laserjet/Deskjet (B & W) instead of an array. The format of the call is CALL HPRINT (XL, YL, XR, YR, DPI, FF) where the first four quantities work just like in BGET, DPI gives the number of dots per inch to print with, and FF should be input as 1 (1! or 1., actually, like most of the other inputs to the QBSVGA routines) if you want the printer to form feed when the picture is done printing or anything but 1 if you don't want a form feed. (It's up to you to determine what DPI values your printer supports.) You might want to avoid situations for which 8 * DPI < your horizontal screen width. Also, HPRINT outputs to LPT1.) SUB EPRINT: a routine to print QBSVGA pictures on a 24-pin Epson LQ (This is just like HPRINT except that you don't include the DPI parameter. Since EPRINT outputs at 180 dots/inch you may wish to avoid printing regions of your screen wider than about 1,440 pixels. (You won't have a problem unless you're using mode 21 or 22.)) SUB PRINT8: a routine to print QBSVGA pictures to "standard" 8-pin graphics printers (This routine should work with 9-pin printers such as Epsons, the Star SG-10 or 15, the Panasonic KX-P1092, etc. The call is similar to the others, but there is a new parameter: CALL PRINT8 (XL, YL, XR, YR, FF, PTYPE$) The character string PTYPE$ should be input as "S" if your printer is set up in its standard or native mode and "I" if your printer is set up to emulate IBM graphics. (Obviously, this is more than an emulation if your printer *is* an IBM graphics printer.) Since PRINT8 outputs at 120 dots/inch, you should avoid trying to print regions of your screen wider than about 960 pixels. (Modes above 16 present the constraint here.)) It may have been noticed that the STEP option of the various intrinsic QB graphics statements is not supported in QBSVGA. (It's relatively simple to program around this.) Other than BSCREEN to set the video mode and various defaults, you should not call any of these routines except BCOLOR, BCLS, BLOCATE, BPOS, and BPRINT *unless* you are in a graphics mode (QB-type modes 14 - 22). (And to reiterate, don't call ANY of these routines without calling BSCREEN first! (However, you can use QRYMOUSE before setting the video mode if you wish.)) You should be aware that the mouse routines output screen coordinates, not viewport coordinates. If a graphics viewport is defined, you must convert the mouse coordinates to viewport coordinates before using them with the other routines. This is simple to do. Just subtract VXL from the "x" coordinates and VYL from the "y" coordinates. Most of the routines work with the active video page, which is not necessarily the displayed video page. The mouse routines, function BPOINT, and the printer routines, however, work with the displayed page. (This point is probably rather nitpicking since the lack of more than one video page on most SVGAs precludes the active page from being different than the displayed page.) There are two other routines that you do not necessarily need to be concerned with, but at least one of which is worth discussing--especially if your SVGA isn't a VESA SVGA. Subroutine FINDVESA inputs a QB-type mode integer (see above) and first attempts to determine the presence of a VESA bios. If it succeeds, it then tries to find a VESA video mode supported in bios by your video card that gives the resolution and colors associated with the QB-type mode. (If it finds one with the right resolution but can only find such a mode with *more* than the number of desired colors, the mode is accepted.) Note that this automatic mode detection only applies to your video card. FINDVESA cannot determine whether or not your monitor has the desired capability. If FINDVESA determines that you don't have a VESA system or if, for whatever reason, it cannot determine what bios mode gives you the resolution you want, it will cause BSCREEN to prompt you for the bios mode integer (hexadecimal) that gives you your resolution. If you know that your system supports the mode you're requesting, input the hex number that your bios recognizes for that mode. If you don't know what to input here, just press ENTER and the program will STOP. (This prompt for input somewhat interferes with using multiple calls to BSCREEN (which calls FINDVESA) to change video modes or active/displayed pages repeatedly.) If by chance your graphics calls don't really need as high resolution as the one for which FINDVESA couldn't find, you can input the bios mode integer for a lesser mode if you know it. The functionallity of BSCREEN and FINDVESA is incorporated in another included stand-alone routine, FINDMODE. This program may be of more direct use in regard to QBSVGA than VS or VS1. Run FINDMODE from the DOS command-line with your desired QB-type mode integer specified as an argument and FINDMODE will either tell you what VESA mode it found that corresponds to your QB-type mode or it will tell you that it couldn't find such a mode. This is the same behavior you can expect when you use QBSVGA with your QB-type mode. FINDVESA and a few of the other routines use the function BIN$ to input a LONG integer (4 bytes) and convert it to a binary number (represented by the text string BIN$). You don't need to worry about this function unless you have some wish to use it yourself. There are a few caveats. First, there are a few Basic variables that QBSVGA uses that your program must not use (unless of course you're intentionally doing so as a "backdoor" method of by-passing some of QBSVGA's simpler routines). These variables are: ACPAGE (active video page) DEFLTC (default color) VESSUP (0 if VESA is supported/detected, 1 otherwise) HMAX (zero-based horizontal screen resolution) VMAX (zero-based vertical screen resolution) VXL (x-coordinate of upper left viewport corner) VYL (y-coordinate of upper left viewport corner) VXR (x-coordinate of lower right viewport corner) VYR (y-coordinate of lower right viewport corner) VCOL (color with which viewport was last filled / -1 if no viewport) VBORD (color with which viewport border was last drawn) BVCBL (an internal switch used by BVIEW to control BLINE) MXMAX (the physical maximum horizontal extent of mouse motion) \ MYMAX (the physical maximum vertical extent of mouse motion) \ from MDX (number of mouse motion pixels per horizontal screen pixel) / GETLIM MDY (number of " " " " vertical " " ) / MXMINC (minimum horizontal screen coordinate that mouse can move to) \ MXMAXC (maximum horizontal screen coordinate that mouse can move to) \ from MYMINC (minimum vertical screen coordinate that mouse can move to) / SETLIM MYMAXC (maximum vertical screen coordinate that mouse can move to) / BUTTONS (number of buttons on mouse--from QRYMOUSE) XMOUSE (previous horizontal screen coordinate of mouse cursor) YMOUSE (previous vertical screen coordinate of mouse cursor) BITPLANES (the number of bit planes per pixel in the graphics mode in use) BITSPIXEL (the number of bits per pixel in the graphics mode in use) Two global variables not mentioned above are INREGS and OUTREGS. These are so-called user-defined REGISTER variable types. If you wish to use them in your own programming in their context as registers, that's fine. Just don't try to use them in any other context. (If the compiler doesn't catch you, the .EXE likely will!) Similarly, you should avoid using the variables in the TYPE REGISTERS...END TYPE construct in any manner other than their use as suffixes to the INREGS and OUTREGS variables. (You can also of course use the global variables in the above list as long as you do so in their appropriate contexts. You just must not arbitrarily define them for your own uses. In particular, you may need the 0-based screen resolutions HMAX and VMAX.) There are also some labels you should avoid using: FIXFRC: NEWMODE: RETMODE: NOSUP: QUIT: SKIPCON: NOVESA: SETMODE: LEAVE: GETBUTTON: EXITROD: GETRELEASE: Third, although I certainly don't mean to scare you away from using QBSVGA, I must insist that you use it and the included utilities AT YOUR OWN RISK. You may want to be careful about using video modes you don't have support for. If you are not manually inputting bios video mode data to BSCREEN's prompt for it, QBSVGA will not make any attempt to put your video adapter into any mode for which it cannot confirm support. One problem is that it is your video card that video support is confirmed for. If your video card has more capabilities than your monitor, QBSVGA cannot detect that. In particular, you may want to be careful using these routines if you have a color-capable video card (I've not actually heard of a monochrome SVGA card) but a monochrome monitor. (You may especially want to avoid using color attributes other than 7 (or maybe 15) in that situation. However, I've never heard of a monochrome SVGA monitor either--but that doesn't necessarily mean they don't exist.) Other than possibly avoiding very old bioses or other hardware, QBSVGA has no particular hardware requirements. The most substantial requirements are that your operating system be at least compatible with standard PC/MS- DOS and your computer be IBM compatible--the mouse routines require at least version 2 of DOS. (And I can't guarantee results on computers with "nonstandard" bioses or SVGA cards/monitors--not that I can guarantee them anywhere else either.) And, although I'm not necessarily relinquishing copyright or the desire for credit of authorship, I don't have any particular rules concerning what you do with this software, except for perhaps selling it. (I didn't charge YOU for it, did I?) (But if not sending me money is keeping you awake nights, by all means, send me some and get some sleep!) (Distributing it with software that you've developed and are selling would be okay--it would be flattering. I just don't think the presence of my software in and of itself should influence your sales price.) Glenn Stumpff 4960 Egret Ct. Dayton, Ohio 45424 CIS: 73137,3537