home *** CD-ROM | disk | FTP | other *** search
- /* Sample simple dirty-rectangle animation program. Doesn't attempt to coalesce
- rectangles to minimize display memory accesses. Not even vaguely optimized!
- Tested with Borland C++ 4.02 in small model. by Jim Mischel 12/16/94.
- */
- #include <stdlib.h>
- #include <conio.h>
- #include <alloc.h>
- #include <memory.h>
- #include <dos.h>
-
- #define SCREEN_WIDTH 320
- #define SCREEN_HEIGHT 200
- #define SCREEN_SEGMENT 0xA000
-
- /* Describes a rectangle */
- typedef struct {
- int Top;
- int Left;
- int Right;
- int Bottom;
- } Rectangle;
-
- /* Describes an animated object */
- typedef struct {
- int X; /* upper left corner in virtual bitmap */
- int Y;
- int XDirection; /* direction and distance of movement */
- int YDirection;
- } Entity;
-
- /* Storage used for dirty rectangles */
- #define MAX_DIRTY_RECTANGLES 100
- int NumDirtyRectangles;
- Rectangle DirtyRectangles[MAX_DIRTY_RECTANGLES];
-
- /* If set to 1, ignore dirty rectangle list and copy the whole screen. */
- int DrawWholeScreen = 0;
-
- /* Pixels for image we'll animate */
- #define IMAGE_WIDTH 11
- #define IMAGE_HEIGHT 11
- char ImagePixels[] = {
- 15,15,15, 9, 9, 9, 9, 9,15,15,15,
- 15,15, 9, 9, 9, 9, 9, 9, 9,15,15,
- 15, 9, 9,14,14,14,14,14, 9, 9,15,
- 9, 9,14,14,14,14,14,14,14, 9, 9,
- 9, 9,14,14,14,14,14,14,14, 9, 9,
- 9, 9,14,14,14,14,14,14,14, 9, 9,
- 9, 9,14,14,14,14,14,14,14, 9, 9,
- 9, 9,14,14,14,14,14,14,14, 9, 9,
- 15, 9, 9,14,14,14,14,14, 9, 9,15,
- 15,15, 9, 9, 9, 9, 9, 9, 9,15,15,
- 15,15,15, 9, 9, 9, 9, 9,15,15,15,
- };
- /* Animated entities */
- #define NUM_ENTITIES 10
- Entity Entities[NUM_ENTITIES];
-
- /* Pointer to system buffer into which we'll draw */
- char far *SystemBufferPtr;
-
- /* Pointer to screen */
- char far *ScreenPtr;
-
- void EraseEntities(void);
- void CopyDirtyRectanglesToScreen(void);
- void DrawEntities(void);
-
- void main()
- {
- int i, XTemp, YTemp;
- unsigned int TempCount;
- char far *TempPtr;
- union REGS regs;
- /* Allocate memory for the system buffer into which we'll draw */
- if (!(SystemBufferPtr = farmalloc((unsigned int)SCREEN_WIDTH*
- SCREEN_HEIGHT))) {
- printf("Couldn't get memory\n");
- exit(1);
- }
- /* Clear the system buffer */
- TempPtr = SystemBufferPtr;
- for (TempCount = ((unsigned)SCREEN_WIDTH*SCREEN_HEIGHT); TempCount--; ) {
- *TempPtr++ = 0;
- }
- /* Point to the screen */
- ScreenPtr = MK_FP(SCREEN_SEGMENT, 0);
-
- /* Set up the entities we'll animate, at random locations */
- randomize();
- for (i = 0; i < NUM_ENTITIES; i++) {
- Entities[i].X = random(SCREEN_WIDTH - IMAGE_WIDTH);
- Entities[i].Y = random(SCREEN_HEIGHT - IMAGE_HEIGHT);
- Entities[i].XDirection = 1;
- Entities[i].YDirection = -1;
- }
- /* Set 320x200 256-color graphics mode */
- regs.x.ax = 0x0013;
- int86(0x10, ®s, ®s);
-
- /* Loop and draw until a key is pressed */
- do {
- /* Draw the entities to the system buffer at their current locations,
- updating the dirty rectangle list */
- DrawEntities();
-
- /* Draw the dirty rectangles, or the whole system buffer if
- appropriate */
- CopyDirtyRectanglesToScreen();
-
- /* Reset the dirty rectangle list to empty */
- NumDirtyRectangles = 0;
-
- /* Erase the entities in the system buffer at their old locations,
- updating the dirty rectangle list */
- EraseEntities();
-
- /* Move the entities, bouncing off the edges of the screen */
- for (i = 0; i < NUM_ENTITIES; i++) {
- XTemp = Entities[i].X + Entities[i].XDirection;
- YTemp = Entities[i].Y + Entities[i].YDirection;
- if ((XTemp < 0) || ((XTemp + IMAGE_WIDTH) > SCREEN_WIDTH)) {
- Entities[i].XDirection = -Entities[i].XDirection;
- XTemp = Entities[i].X + Entities[i].XDirection;
- }
- if ((YTemp < 0) || ((YTemp + IMAGE_HEIGHT) > SCREEN_HEIGHT)) {
- Entities[i].YDirection = -Entities[i].YDirection;
- YTemp = Entities[i].Y + Entities[i].YDirection;
- }
- Entities[i].X = XTemp;
- Entities[i].Y = YTemp;
- }
-
- } while (!kbhit());
- getch(); /* clear the keypress */
- /* Back to text mode */
- regs.x.ax = 0x0003;
- int86(0x10, ®s, ®s);
- }
- /* Draw entities at current locations, updating dirty rectangle list. */
- void DrawEntities()
- {
- int i, j, k;
- char far *RowPtrBuffer;
- char far *TempPtrBuffer;
- char far *TempPtrImage;
- for (i = 0; i < NUM_ENTITIES; i++) {
- /* Remember the dirty rectangle info for this entity */
- if (NumDirtyRectangles >= MAX_DIRTY_RECTANGLES) {
- /* Too many dirty rectangles; just redraw the whole screen */
- DrawWholeScreen = 1;
- } else {
- /* Remember this dirty rectangle */
- DirtyRectangles[NumDirtyRectangles].Left = Entities[i].X;
- DirtyRectangles[NumDirtyRectangles].Top = Entities[i].Y;
- DirtyRectangles[NumDirtyRectangles].Right =
- Entities[i].X + IMAGE_WIDTH;
- DirtyRectangles[NumDirtyRectangles++].Bottom =
- Entities[i].Y + IMAGE_HEIGHT;
- }
- /* Point to the destination in the system buffer */
- RowPtrBuffer = SystemBufferPtr + (Entities[i].Y * SCREEN_WIDTH) +
- Entities[i].X;
- /* Point to the image to draw */
- TempPtrImage = ImagePixels;
- /* Copy the image to the system buffer */
- for (j = 0; j < IMAGE_HEIGHT; j++) {
- /* Copy a row */
- for (k = 0, TempPtrBuffer = RowPtrBuffer; k < IMAGE_WIDTH; k++) {
- *TempPtrBuffer++ = *TempPtrImage++;
- }
- /* Point to the next system buffer row */
- RowPtrBuffer += SCREEN_WIDTH;
- }
- }
- }
- /* Copy the dirty rectangles, or the whole system buffer if appropriate,
- to the screen. */
- void CopyDirtyRectanglesToScreen()
- {
- int i, j, k, RectWidth, RectHeight;
- unsigned int TempCount;
- unsigned int Offset;
- char far *TempPtrScreen;
- char far *TempPtrBuffer;
-
- if (DrawWholeScreen) {
- /* Just copy the whole buffer to the screen */
- DrawWholeScreen = 0;
- TempPtrScreen = ScreenPtr;
- TempPtrBuffer = SystemBufferPtr;
- for (TempCount = ((unsigned)SCREEN_WIDTH*SCREEN_HEIGHT); TempCount--; ) {
- *TempPtrScreen++ = *TempPtrBuffer++;
- }
- } else {
- /* Copy only the dirty rectangles */
- for (i = 0; i < NumDirtyRectangles; i++) {
- /* Offset in both system buffer and screen of image */
- Offset = (unsigned int) (DirtyRectangles[i].Top * SCREEN_WIDTH) +
- DirtyRectangles[i].Left;
- /* Dimensions of dirty rectangle */
- RectWidth = DirtyRectangles[i].Right - DirtyRectangles[i].Left;
- RectHeight = DirtyRectangles[i].Bottom - DirtyRectangles[i].Top;
- /* Copy a dirty rectangle */
- for (j = 0; j < RectHeight; j++) {
-
- /* Point to the start of row on screen */
- TempPtrScreen = ScreenPtr + Offset;
-
- /* Point to the start of row in system buffer */
- TempPtrBuffer = SystemBufferPtr + Offset;
-
- /* Copy a row */
- for (k = 0; k < RectWidth; k++) {
- *TempPtrScreen++ = *TempPtrBuffer++;
- }
- /* Point to the next row */
- Offset += SCREEN_WIDTH;
- }
- }
- }
- }
- /* Erase the entities in the system buffer at their current locations,
- updating the dirty rectangle list. */
- void EraseEntities()
- {
- int i, j, k;
- char far *RowPtr;
- char far *TempPtr;
-
- for (i = 0; i < NUM_ENTITIES; i++) {
- /* Remember the dirty rectangle info for this entity */
- if (NumDirtyRectangles >= MAX_DIRTY_RECTANGLES) {
- /* Too many dirty rectangles; just redraw the whole screen */
- DrawWholeScreen = 1;
- } else {
- /* Remember this dirty rectangle */
- DirtyRectangles[NumDirtyRectangles].Left = Entities[i].X;
- DirtyRectangles[NumDirtyRectangles].Top = Entities[i].Y;
- DirtyRectangles[NumDirtyRectangles].Right =
- Entities[i].X + IMAGE_WIDTH;
- DirtyRectangles[NumDirtyRectangles++].Bottom =
- Entities[i].Y + IMAGE_HEIGHT;
- }
- /* Point to the destination in the system buffer */
- RowPtr = SystemBufferPtr + (Entities[i].Y*SCREEN_WIDTH) + Entities[i].X;
-
- /* Clear the entity's rectangle */
- for (j = 0; j < IMAGE_HEIGHT; j++) {
- /* Clear a row */
- for (k = 0, TempPtr = RowPtr; k < IMAGE_WIDTH; k++) {
- *TempPtr++ = 0;
- }
- /* Point to the next row */
- RowPtr += SCREEN_WIDTH;
- }
- }
- }
-
-