Okay, let's take a break and write our first program using the functions covered so far. This program, called PIXELS.C, will simply put the video card into mode 13h and display random pixels at random colors, press a key, and the program puts the video card back into text display mode before exiting.
/* PIXELS.C -- by Gary N Wilkerson Jr. * * Demonstrates the usage of the SetVideoMode * and the SetPixel functions. */ #include <stdlib.h> /* Required for rand() functions */ #include <dos.h> /* Required for int86() functions */ #include <conio.h> /* Required for keyboard functions */ /* Video display definitions */ #define TEXT_MODE 0x03 #define VGA256 0x13 /* Function prototypes */ void SetVideoMode(int mode); void SetPixel(int X, int Y, unsigned char C); /* Create a pointer to video memory */ unsigned char far *videoMem = (unsigned char far *)0xA0000000L; /* Our main program */ int main(void) { while (kbhit()) getch(); /* Clear keyboard */ SetVideoMode(VGA256); /* Set VGA mode 13h */ while (!kbhit()) /* Set random dots to random colors */ SetPixel(rand() % 320, rand() % 200, rand() % 256); SetVideoMode(TEXT_MODE); /* Return to text mode */ while (kbhit()) getch(); /* Clear keyboard */ return 0; /* Return without errors */ } /* SetVideoMode function */ void SetVideoMode(int mode) { union REGS regs; /* Create register variables */ regs.x.ax = mode; /* Set video mode */ /* Call interrupt to complete the task */ int86(0x10, ®s, ®s); } /* SetPixel function */ void SetPixel(int X, int Y, unsigned char C) { videoMem[Y * 320 + X] = C; }
I haven't forgotten all of you, even though eventually you will find it difficult to keep up with C users. You will be happy to know that QBasic also has a function for setting pixels, PSET. Using that and the SCREEN statement, let's duplicate the PIXELS.C program. We'll call it, PIXELS.BAS.
' PIXELS.BAS -- by Gary N. Wilkerson Jr. ' ' Uses BASIC's SCREEN and PSET statements to fill ' your screen with random pixels of random colors. ' WHILE INKEY$ <> "": WEND ' Clear keyboard SCREEN 13 ' Set VGA mode 13h WHILE INKEY$ = "" ' Set random dots with random colors PSET(RND * 320, RND * 200), RND * 256 WEND WHILE INKEY$ <> "": WEND ' Clear keyboard END
You'll find that, in BASIC, many of the functions we need are defined for us. Most C compilers also come with the necessary library functions to perform many of these graphics functions without our having to reinvent the wheel. So why do we do it? Why can't we just use the library functions that are packaged in our C compilers to set the video mode or to plot pixels? The main reason here is because there is no standard in the libraries packaged with all C compilers for dealing with graphics. For example, Turbo C++ 3.0 (the compiler I use) has a wealth of graphics functions that you can use by including the GRAPHICS.H header file in your source and linking the object code with the GRAPHICS.LIB library file, included with the compiler. However, if you use them and then you tried to compile the code with a Microsoft compiler, much of the code will break.
While there are no true standards to BASIC for much of its code either, there are "de-facto" standards. Even though Microsoft has discontinued support for all of its BASIC programming software for DOS years ago, they are still the reigning king of the hill as far as "de-facto standards" go. Even though other BASIC programming software may be far superior in functionality, Power Basic is such a product. QuickBASIC, and its stripped down cousin QBasic, has the largest support in the BASIC programming community as far as DOS programming goes.
While, I think, the SCREEN and PSET statements are your best bet for QBasic programs, you can write your own functions that mimic them. Here are some examples:
' This code will run in both QuickBASIC and QBasic SUB SetPixel(X%, Y%, C%) ' Set default segment to video segment. DEF SEG = &HA000 ' Write pixel to video memory. POKE Y% * 320 + X%, C% ' Restore BASIC's segment. DEF SEG END SUB ' This example works only in QuickBASIC ' In order to run it, start QuickBASIC with ' the /L switch. '$INCLUDE: 'qb.bi' SUB SetVideoMode(mode AS INTEGER) ' Declare our register variables. DIM regs AS RegType regs.AX = mode ' Set video mode. ' Call interrupt to complete process. CALL INTERRUPT(&H10, regs, regs) END SUB
Some BASIC programmers find these functions faster than the statements they replace. I personally don't agree because of the nature of BASIC programs being slow. I find it hard to beleive that a function call to SetPixel that contains 3 BASIC statements could be faster than a single PSET statement, however I really haven't tested it. If you want, try it and see which is faster. Of course if you drop down to assembly, you can write even faster code but I doubt the difference would be very noticable on the super fast Pentiums of today.