home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
progjour
/
1991
/
04
/
cegdraw.c
< prev
next >
Wrap
Text File
|
1991-04-15
|
14KB
|
324 lines
/* Performs 256-color animation on the Edsun DAC, taking advantage of
both pixel weighting (selecting pixel colors as weighted averages
of the colors of nearby pixels) and EDP (the ability to embed
information in the bitmap that reprograms the DAC's palette during
the course of each frame). Requires a VGA equipped with an Edsun
CEG/DAC. All C code compiled with Borland C++ 2.0, operating in C
mode, and using the small model */
#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include <math.h>
#define PI 3.141592
#define ADVANCED_8_EDP 15 /* CEG/DAC mode # for Advanced-8 mode with
EDP enabled */
#define FRAME_WIDTH 10 /* width of frame around bouncing area */
/* Bounds within which balls bounce */
#define TOP_EDGE FRAME_WIDTH
#define BOTTOM_EDGE (200-FRAME_WIDTH-1)
#define LEFT_EDGE FRAME_WIDTH
#define RIGHT_EDGE (320-FRAME_WIDTH-1)
typedef struct _RGB { /* defines RGB triplet for a color */
unsigned char Red;
unsigned char Green;
unsigned char Blue;
} RGB;
typedef struct _Image { /* defines a drawable image */
int Width, Height; /* dimensions */
unsigned char *PixMap; /* image bytes */
} Image;
typedef struct _Ball { /* defines a bouncing ball */
int X, Y; /* location */
int XDir, YDir; /* direction of movement */
Image *BallImage; /* image to draw for ball */
} Ball;
int main(void);
int EnableCEGMode(int);
void DrawFrame(int,int);
void SetEDPAtRight(int,RGB*,int,int);
void FillRect(int,int,int,int,int);
void DisableCEGMode(void);
void WaitVerticalSync(void);
void DrawImage(int,int,Image *);
void SetEDPAtLeft(int,int,int,int,int);
void AdvanceAndDrawBalls(Ball**,int);
void Delay(void);
void SetCyclingAttributes(RGB*);
void InitializePalette(void);
/* Byte pattern for balls that bounce horizontally */
unsigned char HBallPixMap[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1, 1, 1, 2, 2, 3,212,208,204,200,218, 1, 1, 1,
1, 1, 2, 2, 3,214,210,205,200,198,200,220, 1, 1,
1, 1, 2, 2, 3,216,212,207,202,200,204,218, 1, 1,
1, 2, 2, 2, 3,218,214,208,206,205,210,216, 2, 1,
1, 2, 2, 2, 3,220,216,214,212,210,216,220, 2, 1,
1, 2, 2, 2, 3,222,220,218,216,216,218,222, 2, 1,
1, 2, 2, 2, 2, 2, 3,221,220,221, 2, 2, 2, 1,
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1,
1, 1, 1, 1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
/* Byte pattern for ball that bounces diagonally */
unsigned char DBallPixMap[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1, 1,
1, 1, 1, 4, 4, 5,212,208,204,200,218, 1, 1, 1,
1, 1, 4, 4, 5,214,210,205,200,198,200,220, 1, 1,
1, 1, 4, 4, 5,216,212,207,202,200,204,218, 1, 1,
1, 4, 4, 4, 5,218,214,208,206,205,210,216, 4, 1,
1, 4, 4, 4, 5,220,216,214,212,210,216,220, 4, 1,
1, 4, 4, 4, 5,222,220,218,216,216,218,222, 4, 1,
1, 4, 4, 4, 4, 4, 5,221,220,221, 4, 4, 4, 1,
1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1,
1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1,
1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1,
1, 1, 1, 1, 1, 4, 4, 4, 4, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
};
Image HBall = {14,14,HBallPixMap}; /* image for horz bouncing balls */
Image DBall = {14,14,DBallPixMap}; /* image for diag bouncing ball */
Ball Ball1 = {60, 30, -1, 0, &HBall}; /* the four balls to bounce */
Ball Ball2 = {150, 90, 1, 0, &HBall};
Ball Ball3 = {220, 150, -1, 0, &HBall};
Ball Ball4 = {100, 120, -1, -1, &DBall};
Ball* BallArray[] = {&Ball1, &Ball2, &Ball3, &Ball4};
#define NUM_BALLS (sizeof(BallArray)/sizeof(Ball*))
int main() {
int i, GreenTemp, BlueTemp, AttributeStart, FrameCount;
int FrameDelay, Temp;
union REGS regset;
RGB Attribute1Settings[384]; /* used to store the EDP settings for
attribute 1 */
/* Set to the standard 256-color VGA mode, mode 0x13, 320x200 */
regset.x.ax = 0x0013; int86(0x10, ®set, ®set);
/* Now enable Advanced-8 CEG mode, so that pixel value 191 becomes
the EDP opcode, and pixel values 192-223 become pixel weighting
opcodes */
if (!EnableCEGMode(ADVANCED_8_EDP)) {
/* This isn't a CEG/DAC; back to text mode and we're done */
regset.x.ax = 0x0003; int86(0x10, ®set, ®set);
fprintf(stderr, "No CEG/DAC installed\n");
return(1);
}
InitializePalette(); /* set up the palette */
/* Draw a frame, using the colors 6-190 & 224-255 that we just set
up to produce a smooth color gradient from top to bottom */
DrawFrame(6,FRAME_WIDTH);
/* Fill inside the frame with attribute 1, which we'll use EDP to
change from line to line */
FillRect(LEFT_EDGE, TOP_EDGE, RIGHT_EDGE+1, BOTTOM_EDGE+1, 1);
/* Set the array of values for EDP loads of attribute 1 and put the
EDP sequences for the first 200 of those colors at the right
edge of display memory, in the frame */
SetCyclingAttributes(Attribute1Settings);
SetEDPAtRight(1, Attribute1Settings, AttributeStart = 0,
sizeof(Attribute1Settings)/sizeof(RGB));
/* Set the EDP sequences for the colors of the three horz balls */
SetEDPAtLeft(2, 0, 0, 0x20, 29); /* top ball is blue */
SetEDPAtLeft(3, 0, 0, 0xAF, 30); /* top ball highlight color */
SetEDPAtLeft(2, 0, 0x20, 0, 89); /* middle ball is green */
SetEDPAtLeft(3, 0, 0x9F, 0, 90); /* middle ball highlight color */
SetEDPAtLeft(2, 0x20, 0, 0, 149); /* bottom ball is red */
SetEDPAtLeft(3, 0xCF, 0, 0, 150); /* bottom ball highlight color */
/* Now cycle through a frame at a time, moving the balls and
advancing the EDP settings for the background (attribute 1) so
the background appears to move. Stop when a key is pressed */
for (FrameCount = FrameDelay = 1; ; ) { /* draw on first frame */
WaitVerticalSync(); /* wait until the end of current frame */
if (--FrameCount == 0) {
FrameCount = FrameDelay;
AdvanceAndDrawBalls(BallArray, NUM_BALLS);
/* Change the attribute 1 (background) EDP loads by one
position in Attribute1Settings, wrapping from start back
to end. This has the effect of shifting the EDP load of
attribute 1 with any given color by one scan line, so the
whole background appears to move one scan line */
if (AttributeStart == 0)
AttributeStart = sizeof(Attribute1Settings)/sizeof(RGB)-1;
else
AttributeStart--;
SetEDPAtRight(1, Attribute1Settings, AttributeStart,
sizeof(Attribute1Settings)/sizeof(RGB));
/* set the new attribute 1 EDP sequences */
}
if (kbhit()) {
Temp = getch();
if ((Temp == 'f') || (Temp == 'F')) {
if ((FrameDelay -= 5) <= 0) FrameDelay = 1; /* faster */
} else if ((Temp == 's') || (Temp == 'S')) {
FrameDelay += 5; /* slower */
} else {
break; /* done */
}
}
}
DisableCEGMode();
regset.x.ax = 0x0003; int86(0x10,®set,®set); /* text mode */
return(0);
}
/* Enables the desired CEG/DAC mode. Returns 1 for success, 0 if no
CEG/DAC is installed. */
int EnableCEGMode(int mode) {
WaitVerticalSync();
/* Write the CEG enable sequence, which is "CEGEDSUN" followed by
the mode byte, to palette location 222 */
outp(0x3C7,222); Delay(); outp(0x3C9,'C'); Delay();
outp(0x3C9,'E'); Delay(); outp(0x3C9,'G'); Delay();
outp(0x3C7,222); Delay(); outp(0x3C9,'E'); Delay();
outp(0x3C9,'D'); Delay(); outp(0x3C9,'S'); Delay();
outp(0x3C7, 222); Delay(); outp(0x3C9,'U'); Delay();
outp(0x3C9,'N'); Delay();
outp(0x3C9, mode); Delay(); /* write the CEG mode */
/* At this point, CEG mode should be enabled. Make sure this really
is a CEG/DAC */
outp(0x3C6, 0xFF); Delay(); /* enable all DAC mask bits */
if ((inp(0x3C6) & 0x70) == 0x70)
return(0); /* no version # bit is 0; this is not a CEG/DAC */
else
return(1); /* this is a CEG/DAC, and CEG mode is now enabled */
}
/* Disable CEG mode by writing to palette location 223 */
void DisableCEGMode() {
WaitVerticalSync();
outp(0x3C8, 223); outp(0x3C9, 0); outp(0x3C9, 0); outp(0x3C9, 0);
}
/* Wait for the leading edge of vertical sync */
void WaitVerticalSync() {
while (inp(0x3DA) & 0x08) ; /* wait for not vertical sync */
while (!(inp(0x3DA) & 0x08)) ; /* wait for vertical sync */
}
/* Advance each ball and draw it (the blank fringe around each ball
erases it at the old location) */
void AdvanceAndDrawBalls(Ball** BallPtrPtr, int NumBalls) {
int i, Temp;
Ball *BallPtr;
for (i=0; i<NumBalls; i++) {
BallPtr = *BallPtrPtr++; /* point to current ball */
/* Advance the X coordinate, bouncing if frame reached */
Temp = BallPtr->X + BallPtr->XDir;
if ((Temp < LEFT_EDGE) ||
((Temp + BallPtr->BallImage->Width) > RIGHT_EDGE)) {
BallPtr->XDir = -BallPtr->XDir; /* bounce in X dir */
Temp += BallPtr->XDir;
}
BallPtr->X = Temp;
/* Advance the Y coordinate, bouncing if frame reached */
Temp = BallPtr->Y + BallPtr->YDir;
if ((Temp < TOP_EDGE) ||
((Temp + BallPtr->BallImage->Height) > BOTTOM_EDGE)) {
BallPtr->YDir = -BallPtr->YDir; /* bounce in Y dir */
Temp += BallPtr->YDir;
}
BallPtr->Y = Temp;
/* Draw the ball at the new location */
DrawImage(BallPtr->X, BallPtr->Y, BallPtr->BallImage);
}
}
/* Used to provide a brief delay between OUTs */
void Delay() {
}
/* Set AttributeArray to contain a color sequence gradually
cycling through each primary color */
void SetCyclingAttributes(RGB* AttributeArray) {
int i;
for (i=0; i<64; i++) {
AttributeArray[i].Red = i; /* ascending red */
AttributeArray[i].Green = 0;
AttributeArray[i].Blue = 0;
AttributeArray[i+64].Red = 63-i; /* descending red */
AttributeArray[i+64].Green = 0;
AttributeArray[i+64].Blue = 0;
AttributeArray[i+128].Red = 0; /* ascending green */
AttributeArray[i+128].Green = i;
AttributeArray[i+128].Blue = 0;
AttributeArray[i+192].Red = 0; /* descending green */
AttributeArray[i+192].Green = 63-i;
AttributeArray[i+192].Blue = 0;
AttributeArray[i+256].Red = 0; /* ascending blue */
AttributeArray[i+256].Green = 0;
AttributeArray[i+256].Blue = i;
AttributeArray[i+320].Red = 0; /* descending blue */
AttributeArray[i+320].Green = 0;
AttributeArray[i+320].Blue = 63-i;
}
}
/* Set up the palette with the colors for the outer frame (colors 6
through 190 and 224 through 255) cycling through combinations of
the three primary colors as determined by out-of-phase sine waves.
(There's nothing profound about these colors; it just makes an
attractive, multicolored border.) Also set attributes 4 and 5 to
the colors for the ball that bounces diagonally, and sets attrs
0-3 to black (attributes 1-3 will be altered via EDP later) */
void InitializePalette() {
int i, ColorEntry;
RGB PaletteTemp[256]; /* used to pass palette settings to BIOS */
union REGS regset;
struct SREGS sregset;
for (i=0; i<4; i++) {
PaletteTemp[i].Red = 0; /* black */
PaletteTemp[i].Green = 0;
PaletteTemp[i].Blue = 0;
}
PaletteTemp[4].Red = 0; /* the diagonal ball is cyan */
PaletteTemp[4].Green = 0x20;
PaletteTemp[4].Blue = 0x20;
PaletteTemp[5].Red = 0; /* highlight color for diagonal ball */
PaletteTemp[5].Green = 0xAF;
PaletteTemp[5].Blue = 0xAF;
ColorEntry = 0;
for (i=6; i<=255; ColorEntry++, i = ((i==190) ? 224 : i+1)) {
/* skip i from 190->224 */
PaletteTemp[i].Red = abs((int)(255.0 *
sin((double)(ColorEntry+67)/217.0*PI))); /* Red */
PaletteTemp[i].Green = abs((int)(255.0 *
sin((double)ColorEntry/217.0*PI))); /* Green */
PaletteTemp[i].Blue = abs((int)(255.0 *
sin((double)(ColorEntry+133)/217.0*PI))); /* Blue */
}
regset.x.ax = 0x1012; /* set block of DAC registers function */
regset.x.bx = 0; /* set register 0 first */
regset.x.cx = 190-0+1; /* # of registers to set */
regset.x.dx = (unsigned int)&PaletteTemp[0];
/* offset of array from which to set */
sregset.es = _DS; /* segment of array from which to set */
int86x(0x10, ®set, ®set, &sregset); /* attributes 0->190 */
regset.x.ax = 0x1012; regset.x.bx = 224;
regset.x.cx = 255-224+1; sregset.es = _DS;
regset.x.dx = (unsigned int)&PaletteTemp[224];
int86x(0x10, ®set, ®set, &sregset); /* attributes 224->225 */
}