home *** CD-ROM | disk | FTP | other *** search
- /* Split screen VGA animation program. Performs page flipping in the
- top portion of the screen while displaying non-page flipped
- information in the split screen at the bottom of the screen.
- Compiled with Borland C++ 2.0 in C compilation mode. */
-
- #include <stdio.h>
- #include <conio.h>
- #include <dos.h>
- #include <math.h>
-
- #define SCREEN_SEG 0xA000
- #define SCREEN_PIXWIDTH 640 /* in pixels */
- #define SCREEN_WIDTH 80 /* in bytes */
- #define SPLIT_START_LINE 339
- #define SPLIT_LINES 141
- #define NONSPLIT_LINES 339
- #define SPLIT_START_OFFSET 0
- #define PAGE0_START_OFFSET (SPLIT_LINES*SCREEN_WIDTH)
- #define PAGE1_START_OFFSET ((SPLIT_LINES+NONSPLIT_LINES)*SCREEN_WIDTH)
- #define CRTC_INDEX 0x3D4 /* CRT Controller Index register */
- #define CRTC_DATA 0x3D5 /* CRT Controller Data register */
- #define OVERFLOW 0x07 /* index of CRTC reg holding bit 8 of the
- line the split screen starts after */
- #define MAX_SCAN 0x09 /* index of CRTC reg holding bit 9 of the
- line the split screen starts after */
- #define LINE_COMPARE 0x18 /* index of CRTC reg holding lower 8 bits
- of line split screen starts after */
- #define NUM_BUMPERS (sizeof(Bumpers)/sizeof(bumper))
- #define BOUNCER_COLOR 15
- #define BACK_COLOR 1 /* playfield background color */
-
- typedef struct { /* one solid bumper to be bounced off of */
- int LeftX,TopY,RightX,BottomY;
- int Color;
- } bumper;
-
- typedef struct { /* one bit pattern to be used for drawing */
- int WidthInBytes;
- int Height;
- unsigned char *BitPattern;
- } image;
-
- typedef struct { /* one bouncing object to move around the screen */
- int LeftX,TopY; /* location */
- int Width,Height; /* size in pixels */
- int DirX,DirY; /* motion vectors */
- int CurrentX[2],CurrentY[2]; /* current location in each page */
- int Color; /* color in which to be drawn */
- image *Rotation0; /* rotations for handling the 8 possible */
- image *Rotation1; /* intrabyte start address at which the */
- image *Rotation2; /* left edge can be */
- image *Rotation3;
- image *Rotation4;
- image *Rotation5;
- image *Rotation6;
- image *Rotation7;
- } bouncer;
-
- void main(void);
- void DrawBumperList(bumper *, int, unsigned int);
- void DrawSplitScreen(void);
- void EnableSplitScreen(void);
- void MoveBouncer(bouncer *, bumper *, int);
- extern void DrawRect(int,int,int,int,int,unsigned int,unsigned int);
- extern void ShowPage(unsigned int);
- extern void DrawImage(int,int,image **,int,unsigned int,unsigned int);
- extern void ShowBounceCount(void);
- extern void TextUp(char *,int,int,unsigned int,unsigned int);
- extern void SetBIOS8x8Font(void);
-
- /* All bumpers in the playfield */
- bumper Bumpers[] = {
- {0,0,19,339,2}, {0,0,639,19,2}, {620,0,639,339,2},
- {0,320,639,339,2}, {60,48,79,67,12}, {60,108,79,127,12},
- {60,168,79,187,12}, {60,228,79,247,12}, {120,68,131,131,13},
- {120,188,131,271,13}, {240,128,259,147,14}, {240,192,259,211,14},
- {208,160,227,179,14}, {272,160,291,179,14}, {228,272,231,319,11},
- {192,52,211,55,11}, {302,80,351,99,12}, {320,260,379,267,13},
- {380,120,387,267,13}, {420,60,579,63,11}, {428,110,571,113,11},
- {420,160,579,163,11}, {428,210,571,213,11}, {420,260,579,263,11} };
-
- /* Image for bouncing object when left edge is aligned with bit 7 */
- unsigned char _BouncerRotation0[] = {
- 0xFF,0x0F,0xF0, 0xFE,0x07,0xF0, 0xFC,0x03,0xF0, 0xFC,0x03,0xF0,
- 0xFE,0x07,0xF0, 0xFF,0xFF,0xF0, 0xCF,0xFF,0x30, 0x87,0xFE,0x10,
- 0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x07,0x0E,0x00, 0x07,0x0E,0x00,
- 0x87,0xFE,0x10, 0xCF,0xFF,0x30, 0xFF,0xFF,0xF0, 0xFE,0x07,0xF0,
- 0xFC,0x03,0xF0, 0xFC,0x03,0xF0, 0xFE,0x07,0xF0, 0xFF,0x0F,0xF0};
- image BouncerRotation0 = {3, 20, _BouncerRotation0};
-
- /* Image for bouncing object when left edge is aligned with bit 3 */
- unsigned char _BouncerRotation4[] = {
- 0x0F,0xF0,0xFF, 0x0F,0xE0,0x7F, 0x0F,0xC0,0x3F, 0x0F,0xC0,0x3F,
- 0x0F,0xE0,0x7F, 0x0F,0xFF,0xFF, 0x0C,0xFF,0xF3, 0x08,0x7F,0xE1,
- 0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x00,0x70,0xE0, 0x00,0x70,0xE0,
- 0x08,0x7F,0xE1, 0x0C,0xFF,0xF3, 0x0F,0xFF,0xFF, 0x0F,0xE0,0x7F,
- 0x0F,0xC0,0x3F, 0x0F,0xC0,0x3F, 0x0F,0xE0,0x7F, 0x0F,0xF0,0xFF};
- image BouncerRotation4 = {3, 20, _BouncerRotation4};
-
- /* Initial settings for bouncing object. Only 2 rotations are needed
- because the object moves 4 pixels horizontally at a time */
- bouncer Bouncer = {156,60,20,20,4,4,156,156,60,60,BOUNCER_COLOR,
- &BouncerRotation0,NULL,NULL,NULL,&BouncerRotation4,NULL,NULL,NULL};
- unsigned int PageStartOffsets[2] =
- {PAGE0_START_OFFSET,PAGE1_START_OFFSET};
- unsigned int BounceCount;
-
- void main() {
- int DisplayedPage, NonDisplayedPage, Done, i;
- union REGS regset;
-
- regset.x.ax = 0x0012; /* set display to 640x480 16-color mode */
- int86(0x10, ®set, ®set);
- SetBIOS8x8Font(); /* set the pointer to the BIOS 8x8 font */
- EnableSplitScreen(); /* turn on the split screen */
-
- /* Display page 0 above the split screen */
- ShowPage(PageStartOffsets[DisplayedPage = 0]);
-
- /* Clear both pages to background and draw bumpers in each page */
- for (i=0; i<2; i++) {
- DrawRect(0,0,SCREEN_PIXWIDTH-1,NONSPLIT_LINES-1,BACK_COLOR,
- PageStartOffsets[i],SCREEN_SEG);
- DrawBumperList(Bumpers,NUM_BUMPERS,PageStartOffsets[i]);
- }
-
- DrawSplitScreen(); /* draw the static split screen info */
- BounceCount = 0;
- ShowBounceCount(); /* put up the initial zero count */
-
- /* Draw the bouncing object at its initial location */
- DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
- Bouncer.Color,PageStartOffsets[DisplayedPage],SCREEN_SEG);
-
- /* Move the object, draw it in the nondisplayed page, and flip the
- page until Esc is pressed */
- Done = 0;
- do {
- NonDisplayedPage = DisplayedPage ^ 1;
- /* Erase at current location in the nondisplayed page */
- DrawRect(Bouncer.CurrentX[NonDisplayedPage],
- Bouncer.CurrentY[NonDisplayedPage],
- Bouncer.CurrentX[NonDisplayedPage]+Bouncer.Width-1,
- Bouncer.CurrentY[NonDisplayedPage]+Bouncer.Height-1,
- BACK_COLOR,PageStartOffsets[NonDisplayedPage],SCREEN_SEG);
- /* Move the bouncer */
- MoveBouncer(&Bouncer, Bumpers, NUM_BUMPERS);
- /* Draw at the new location in the nondisplayed page */
- DrawImage(Bouncer.LeftX,Bouncer.TopY,&Bouncer.Rotation0,
- Bouncer.Color,PageStartOffsets[NonDisplayedPage],
- SCREEN_SEG);
- /* Remember where the bouncer is in the nondisplayed page */
- Bouncer.CurrentX[NonDisplayedPage] = Bouncer.LeftX;
- Bouncer.CurrentY[NonDisplayedPage] = Bouncer.TopY;
- /* Flip to the page we just drew into */
- ShowPage(PageStartOffsets[DisplayedPage = NonDisplayedPage]);
- /* Respond to any keystroke */
- if (kbhit()) {
- switch (getch()) {
- case 0x1B: /* Esc to end */
- Done = 1; break;
- case 0: /* branch on the extended code */
- switch (getch()) {
- case 0x48: /* nudge up */
- Bouncer.DirY = -abs(Bouncer.DirY); break;
- case 0x4B: /* nudge left */
- Bouncer.DirX = -abs(Bouncer.DirX); break;
- case 0x4D: /* nudge right */
- Bouncer.DirX = abs(Bouncer.DirX); break;
- case 0x50: /* nudge down */
- Bouncer.DirY = abs(Bouncer.DirY); break;
- }
- break;
- default:
- break;
- }
- }
- } while (!Done);
-
- /* Restore text mode and done */
- regset.x.ax = 0x0003;
- int86(0x10, ®set, ®set);
- }
-
- /* Draws the specified list of bumpers into the specified page */
- void DrawBumperList(bumper * Bumpers, int NumBumpers,
- unsigned int PageStartOffset)
- {
- int i;
-
- for (i=0; i<NumBumpers; i++,Bumpers++) {
- DrawRect(Bumpers->LeftX,Bumpers->TopY,Bumpers->RightX,
- Bumpers->BottomY,Bumpers->Color,PageStartOffset,
- SCREEN_SEG);
- }
- }
-
- /* Displays the current bounce count */
- void ShowBounceCount() {
- char CountASCII[7];
-
- itoa(BounceCount,CountASCII,10); /* convert the count to ASCII */
- TextUp(CountASCII,344,64,SPLIT_START_OFFSET,SCREEN_SEG);
- }
-
- /* Frames the split screen and fills it with various text */
- void DrawSplitScreen() {
- DrawRect(0,0,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,0,SPLIT_START_OFFSET,
- SCREEN_SEG);
- DrawRect(0,1,SCREEN_PIXWIDTH-1,4,15,SPLIT_START_OFFSET,
- SCREEN_SEG);
- DrawRect(0,SPLIT_LINES-4,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,15,
- SPLIT_START_OFFSET,SCREEN_SEG);
- DrawRect(0,1,3,SPLIT_LINES-1,15,SPLIT_START_OFFSET,SCREEN_SEG);
- DrawRect(SCREEN_PIXWIDTH-4,1,SCREEN_PIXWIDTH-1,SPLIT_LINES-1,15,
- SPLIT_START_OFFSET,SCREEN_SEG);
- TextUp("This is the split screen area...",8,8,SPLIT_START_OFFSET,
- SCREEN_SEG);
- TextUp("Bounces: ",272,64,SPLIT_START_OFFSET,SCREEN_SEG);
- TextUp("\033: nudge left",520,78,SPLIT_START_OFFSET,SCREEN_SEG);
- TextUp("\032: nudge right",520,90,SPLIT_START_OFFSET,SCREEN_SEG);
- TextUp("\031: nudge down",520,102,SPLIT_START_OFFSET,SCREEN_SEG);
- TextUp("\030: nudge up",520,114,SPLIT_START_OFFSET,SCREEN_SEG);
- TextUp("Esc to end",520,126,SPLIT_START_OFFSET,SCREEN_SEG);
- }
-
- /* Turn on the split screen at the desired line (minus 1 because the
- split screen starts *after* the line specified by the LINE_COMPARE
- register) (bit 8 of the split screen start line is stored in the
- Overflow register, and bit 9 is in the Maximum Scan Line reg) */
- void EnableSplitScreen() {
- outp(CRTC_INDEX, LINE_COMPARE);
- outp(CRTC_DATA, (SPLIT_START_LINE - 1) & 0xFF);
- outp(CRTC_INDEX, OVERFLOW);
- outp(CRTC_DATA, (((((SPLIT_START_LINE - 1) & 0x100) >> 8) << 4) |
- (inp(CRTC_DATA) & ~0x10)));
- outp(CRTC_INDEX, MAX_SCAN);
- outp(CRTC_DATA, (((((SPLIT_START_LINE - 1) & 0x200) >> 9) << 6) |
- (inp(CRTC_DATA) & ~0x40)));
- }
-
- /* Moves the bouncer, bouncing if bumpers are hit */
- void MoveBouncer(bouncer *Bouncer, bumper *BumperPtr, int NumBumpers) {
- int NewLeftX, NewTopY, NewRightX, NewBottomY, i;
-
- /* Move to new location, bouncing if necessary */
- NewLeftX = Bouncer->LeftX + Bouncer->DirX; /* new coords */
- NewTopY = Bouncer->TopY + Bouncer->DirY;
- NewRightX = NewLeftX + Bouncer->Width - 1;
- NewBottomY = NewTopY + Bouncer->Height - 1;
- /* Compare the new location to all bumpers, checking for bounce */
- for (i=0; i<NumBumpers; i++,BumperPtr++) {
- /* If moving puts the bouncer inside this bumper, bounce */
- if ( (NewLeftX <= BumperPtr->RightX) &&
- (NewRightX >= BumperPtr->LeftX) &&
- (NewTopY <= BumperPtr->BottomY) &&
- (NewBottomY >= BumperPtr->TopY) ) {
- /* The bouncer has tried to move into this bumper; figure
- out which edge(s) it crossed, and bounce accordingly */
- if (((Bouncer->LeftX > BumperPtr->RightX) &&
- (NewLeftX <= BumperPtr->RightX)) ||
- (((Bouncer->LeftX + Bouncer->Width - 1) <
- BumperPtr->LeftX) &&
- (NewRightX >= BumperPtr->LeftX))) {
- Bouncer->DirX = -Bouncer->DirX; /* bounce horizontally */
- NewLeftX = Bouncer->LeftX + Bouncer->DirX;
- }
- if (((Bouncer->TopY > BumperPtr->BottomY) &&
- (NewTopY <= BumperPtr->BottomY)) ||
- (((Bouncer->TopY + Bouncer->Height - 1) <
- BumperPtr->TopY) &&
- (NewBottomY >= BumperPtr->TopY))) {
- Bouncer->DirY = -Bouncer->DirY; /* bounce vertically */
- NewTopY = Bouncer->TopY + Bouncer->DirY;
- }
- /* Update the bounce count display; turn over at 10000 */
- if (++BounceCount >= 10000) {
- TextUp("0 ",344,64,SPLIT_START_OFFSET,SCREEN_SEG);
- BounceCount = 0;
- } else {
- ShowBounceCount();
- }
- }
- }
- Bouncer->LeftX = NewLeftX; /* set the final new coordinates */
- Bouncer->TopY = NewTopY;
- }