Move everything into one directory, update links
This commit is contained in:
parent
b946ff9e70
commit
4eef8b2919
680 changed files with 1638 additions and 1638 deletions
356
44-02.html
Normal file
356
44-02.html
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
<HTML>
|
||||
<HEAD>
|
||||
<META name=vsisbn content="1576101746">
|
||||
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
||||
<META name=vsauthor content="Michael Abrash">
|
||||
<META name=vspublisher content="The Coriolis Group">
|
||||
<META name=vspubdate content="07/01/97">
|
||||
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Split Screens Save the Page Flipped Day</TITLE>
|
||||
|
||||
<!-- HEADER -->
|
||||
<!-- Empty Reference Subhead -->
|
||||
|
||||
<!--ISBN=1576101746//-->
|
||||
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
||||
<!--AUTHOR=Michael Abrash//-->
|
||||
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
||||
<!--CHAPTER=44//-->
|
||||
<!--PAGES=820-825//-->
|
||||
<!--UNASSIGNED1//-->
|
||||
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
||||
|
||||
<CENTER>
|
||||
<TABLE BORDER>
|
||||
<TR>
|
||||
<TD><A HREF="44-01.html">Previous</A></TD>
|
||||
<TD><A HREF="index.html">Table of Contents</A></TD>
|
||||
<TD><A HREF="44-03.html">Next</A></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
<P><BR></P>
|
||||
<P><B>LISTING 44.1 L44-1.C</B></P>
|
||||
<!-- CODE //-->
|
||||
<PRE>
|
||||
/* 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++ 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, &regset, &regset);
|
||||
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, &regset, &regset);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
</PRE>
|
||||
<!-- END CODE //-->
|
||||
<P><BR></P>
|
||||
<CENTER>
|
||||
<TABLE BORDER>
|
||||
<TR>
|
||||
<TD><A HREF="44-01.html">Previous</A></TD>
|
||||
<TD><A HREF="index.html">Table of Contents</A></TD>
|
||||
<TD><A HREF="44-03.html">Next</A></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</CENTER>
|
||||
|
||||
<hr width="90%" size="1" noshade>
|
||||
<div align="center">
|
||||
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
||||
</div>
|
||||
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
||||
<!-- reference_subfoot = footer -->
|
||||
<!-- reference_footer = subfoot -->
|
||||
|
||||
<!-- BEGIN SUB FOOTER -->
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
||||
<!-- END FOOTER -->
|
||||
|
||||
|
||||
Loading…
Reference in a new issue