Use backtick code blocks for syntax highlighting

This commit is contained in:
James Gregory 2013-12-31 11:38:48 +11:00
commit f658bfbb40
203 changed files with 26546 additions and 25801 deletions

470
45-03.md
View file

@ -45,261 +45,263 @@ on my 486/33, 10 11x11 images animate at a very respectable clip.
**LISTING 45.1 L45-1.C**
/* 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++ in the small model. */
```c
/* 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++ in the small model. */
#include <stdlib.h>
#include <conio.h>
#include <alloc.h>
#include <memory.h>
#include <dos.h>
#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
#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 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;
/* 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];
/* 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;
/* 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];
/* 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 system buffer into which we'll draw */
char far *SystemBufferPtr;
/* pointer to screen */
char far *ScreenPtr;
/* pointer to screen */
char far *ScreenPtr;
void EraseEntities(void);
void CopyDirtyRectanglesToScreen(void);
void DrawEntities(void);
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);
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, &regs, &regs);
/* 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, &regs, &regs);
/* 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();
/* 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();
/* Draw the dirty rectangles, or the whole system buffer if
appropriate */
CopyDirtyRectanglesToScreen();
/* Reset the dirty rectangle list to empty */
NumDirtyRectangles = 0;
/* 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();
/* 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;
}
/* 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, &regs, &regs);
}
/* 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;
} while (!kbhit());
getch(); /* clear the keypress */
/* Back to text mode */
regs.x.ax = 0x0003;
int86(0x10, &regs, &regs);
}
/* 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++) {
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 on screen */
TempPtrScreen = ScreenPtr + Offset;
/* Point to the start of row in system buffer */
TempPtrBuffer = SystemBufferPtr + 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;
/* 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;
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;
}
}
}
/* 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;
}
}
}
```