⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 images.cpp

📁 DOS游戏编程中处理Int 13的工具包
💻 CPP
📖 第 1 页 / 共 5 页
字号:

// *************************************************************************
// set the pixel at coordinate x,y to color
// This could be translated into assembler, but is probably fast enough
// *************************************************************************

void writepixel(int x, int y, int color)
	{
	*(char far *)MK_FP(GRAPH_SEG,(y*320)+x)=color;
	}

// *************************************************************************
// read the color of the pixel at coordinate x,y
// Could also be done in assembler, but may be fast enough as is
// *************************************************************************

char readpixel(int x, int y)
	{
	return(*(char far *)MK_FP(GRAPH_SEG,(y*320)+x));
	}

// *************************************************************************
// returns a void type pointer to video memory at pixel coordinate x,y
// *************************************************************************

void far *xy_to_ptr(int x, int y)
	{
	return((char *)MK_FP(GRAPH_SEG,(y*320)+x));
	}

// *************************************************************************
// The following three functions make up the line drawing routine
//
// Draws a line in vga mode 13h only from (x0,y0) to (x1,y1) in color color.
// Drawing code adapted from Power Graphics Programming, Michael Abrash
// *************************************************************************

// *************************************************************************
// Octant0() and Octant1() are support functions for line()
// Adapted from "Power Graphics Programming", Michael Abrash.
// *************************************************************************

void static near Octant0(unsigned int x0,unsigned int y0,unsigned int deltaX,
			 unsigned int deltaY, int Xdirection, int color)
	{
	int deltaYx2;
	int deltaYx2minusdeltaXx2;
	int errorterm;

	deltaYx2 = deltaY*2;
	deltaYx2minusdeltaXx2=deltaYx2-(int)(deltaX*2);
	errorterm=deltaYx2-(int)deltaX;

	writepixel(x0,y0,color);
	while (deltaX--)
		{
		if (errorterm>=0)
			{
			y0++;
			errorterm+=deltaYx2minusdeltaXx2;
			}
		else
			errorterm+=deltaYx2;
		x0+=Xdirection;
		writepixel(x0,y0,color);
		}
	}

void static near Octant1(unsigned int x0,unsigned int y0,unsigned int deltaX,
			 unsigned int deltaY, int Xdirection, int color)
	{

	int deltaXx2;
	int deltaXx2minusdeltaYx2;
	int errorterm;

	deltaXx2=deltaX*2;
	deltaXx2minusdeltaYx2=deltaXx2-(int)(deltaY*2);
	errorterm=deltaXx2-(int)deltaY;

	writepixel(x0,y0,color);
	while (deltaY--)
		{
		if (errorterm>=0)
			{
			x0+=Xdirection;
			errorterm+=deltaXx2minusdeltaYx2;
			}
		else
			errorterm+=deltaXx2;
		y0++;
		writepixel(x0,y0,color);
		}
	}

// **************************************************************************
// takes the initial call and manages the line drawing
// Adapted from "Power Graphics Programming", Michael Abrash
// **************************************************************************

void line(int x0, int y0, int x1, int y1, int color)
	{
	int deltaX, deltaY;
	int temp;

	if (y0>y1)
		{
		temp=y0;
		y0=y1;
		y1=temp;
		temp=x0;
		x0=x1;
		x1=temp;
		}

	deltaX=x1-x0;
	deltaY=y1-y0;

	if (deltaX > 0)
		{
		if (deltaX>deltaY)
			Octant0(x0,y0,deltaX,deltaY,1,color);
		else
			Octant1(x0,y0,deltaX,deltaY,1,color);
		}
	else
		{
		deltaX= -deltaX;
		if (deltaX > deltaY)
			Octant0(x0,y0,deltaX,deltaY,-1,color);
		else
			Octant1(x0,y0,deltaX,deltaY,-1,color);
		}
	}

// **************************************************************************
// getimage() grabs the pixel values in the rectangle marked by (x0,y0) on
// the top left, and (x1,y1) on the bottom right. The data is placed in buff.
//
// NOTE: This function needs translating into assembler
// **************************************************************************

void getimage(int x0, int y0, int x1, int y1, char far *buff)
	{
	int i;
	int deltaY=(y1-y0);
	int xdim=(x1-x0);

	for (i=0;i<=deltaY;i++)
		{
		_fmemcpy((void *)&buff[i*xdim],xy_to_ptr(x0,(y0+i)),xdim);
		}
	}

// **************************************************************************
// putimage() copies the data in *buff to a rectangular area of the screen
// marked by (x0,y0) on the top left, and (x1,y1) on the bottom right.
//
// NOTE: This function needs translating into assembler
// **************************************************************************

void putimage(int x0, int y0, int x1, int y1, char far *buff)
	{
	int i;
	int deltaY=(y1-y0);
	int xdim=(x1-x0);

	for (i=0;i<=deltaY;i++)
		{
		_fmemcpy(xy_to_ptr(x0,(y0+i)),(void *)&buff[i*xdim],xdim);
		}
	}

// *************************************************************************
// copyimage copies a rectangular image bounded by (x0, y0) at top left, and
// (x1, y1) at bottom right, to the video buffer at (putx, puty). The func-
// tion is very fast, suitable for copying blocks of a virtual screen into
// the physical screen for animation. It does no clipping, or checking for
// the vertical blanking interval. If using it to copy from system ram to
// the video buffer, make sure to pass a pointer to the buffer in src_buff,
// and set GRAPH_SEG = to the video buffer before the call.
// *************************************************************************

void copyimage(int x0, int y0, int x1, int y1, int putx, int puty,
			   void far *src_buf)
	{
	int deltaY=(y1-y0);
	int xdim=(x1-x0);
	asm	{
		mov es, GRAPH_SEG           // establish GRAPH_SEG as destination seg
		mov bx, 320                 // increment value to move down one line
		mov ax, puty                // calculate the start of the first line
		mul bx                      // for the destination
		add ax, putx
		mov di, ax
		mov ax, y0                  // caluclate the start of the first line
		mul bx                      // for the source
		add ax, x0
		push ds
		lds si, src_buf
		add si, ax
		mov dx, deltaY              // set dx up as loop counter
		cld                         // clear the direction flag
		}
	mainloop:                       // frame drawing loop
	asm	{
		mov cx, xdim                // cx == frame width in pixels
		push si                     // save the line pointers
		push di
		shr cx, 1                   // optimized copy
		rep movsw
		rcl cx, 1
		rep movsb
		pop di                      // restore the line pointers
		pop si
		add di, 320                 // point to next line in source, dest
		add si, 320
		dec dx                      // adjust the loop counter
		jnz mainloop
		pop ds
		}
	}

// *************************************************************************
// doSplitVerticalWipe causes the picture in pic_buf to be displayed by
// wiping from left and right to the center. If called with a null pointer
// it will clear the screen using palette register 0. Waits for the vertical
// blanking interval, producing a smooth motion. This function really doesn't
// need to be done in assembler, as the vbi test is the limiting factor (see
// below)
// *************************************************************************

void  doSplitVerticalWipe(void far *pic_buf)
	{
	unsigned leftx = 0;
	unsigned rightx = 319;
	unsigned run_y;                    // counts rows
	char far *lsrc_ptr;                // pointer to left column in source
	char far *ldst_ptr;                // pointer to left column in dest
	char far *rsrc_ptr;                // pointer to right column in source
	char far *rdst_ptr;                // pointer to right column in dest

	if (pic_buf != NULL)
		{
		while (rightx > leftx)
			{
			ldst_ptr = (char far *)xy_to_ptr(leftx, 0);
			lsrc_ptr = (char far *)pic_buf+leftx;
			rdst_ptr = (char far *)xy_to_ptr(rightx, 0);
			rsrc_ptr = (char far *)pic_buf+rightx;
			wait_vbi();
			for (run_y = 0; run_y < 200; run_y++)
				{
				*ldst_ptr = *lsrc_ptr;
				*rdst_ptr = *rsrc_ptr;
				ldst_ptr += 320;
				lsrc_ptr += 320;
				rdst_ptr += 320;
				rsrc_ptr += 320;
				}
			leftx++;
			rightx--;
			}
		}
	else
		{
		while (rightx > leftx)
			{
			ldst_ptr = (char far *)xy_to_ptr(leftx, 0);
			rdst_ptr = (char far *)xy_to_ptr(rightx, 0);
			wait_vbi();
			for (run_y = 0; run_y < 200; run_y++)
				{
				*ldst_ptr = 0;
				*rdst_ptr = 0;
				ldst_ptr += 320;
				rdst_ptr += 320;
				}
			leftx++;
			rightx--;
			}
		}
	}

// **************************************************************************
// doSplitHorizWipe displays the picture in pic_buf by wiping it down from
// top and bottom. If it's called with a null pointer it clears the screen
// with palette register 0. Waits for vertical blanking interval, producing
// a smooth wipe. This function really didn't need to be done in assembler.
// I realized after I did it that the test for the vertical blanking interval
// was the limiting factor, not the execution time. Lessons learned! <g>.
//
// This function moves the image data by copying lines to the top and bottom
// of the screen alternately. The key to this process is the value in the
// unsigned integer adjust. In the setup es:di and ds:si are set up to point
// to the first line of the dest and source memory areas respectively. The
// adjust variable is intialized to 64000, which, when added to the offset of
// the first line, yields the offset of the last. Then adjust is decremented,
// and subtracted from the offset of the last line to get the offset of the
// second, and so on. The value of adjust is not used directly, but is loaded
// into the bx register. Keep an eye on si and di, as they are saved and
// restored quite often in all of these dissolve functions.
// **************************************************************************

void  doSplitHorizWipe(void far *pic_buf)
	{
	unsigned adjust = 64000U;    // used to adjust di and si
	asm {
		mov dx, input_status_1   // used to test for vbi later
		mov cx, 200              // line counter
		mov bx, adjust           // bx stores adjust value
		mov es, GRAPH_SEG        // else get video segment into es
		xor di, di               // zero out the offset
		push ds
		lds si, pic_buf          // get pic_buf into es:di
		mov ax, ds               // check for a null pointer
		cmp ax,0
		je clearscr              // if it's null clear the screen
		cld                      // clear the direction flag
		}
	mainloop1:                   // outer line loop
	asm {
		push cx                  // save loop counter
		mov cx, 160              // move 160 words
		push si                  // save offsets
		push di
		}
	test_11:                     // these lines wait for vbi
	asm	{
		in al, dx                // first test, out of vbi
		test al,0x8
		jnz test_11
		}
	test_12:
	asm	{
		in al, dx                // second test, in vbi
		test al,0x8
		jz test_12

		rep movsw                // copy words to video segment
		pop di                   // restore the original offsets
		pop si
		sub bx, 320              // take one line off of bx
		add si, bx               // add it to the offsets
		add di, bx
		mov cx, 160              // move 160 more words
		push si                  // save the offsets
		push di
		rep movsw                // copy the data to video seg
		pop di                   // restore the offsets
		pop si
		sub bx, 320              // take 1 line off of bx
		sub si, bx               // subtract it from the offsets
		sub di, bx
		pop cx                   // restore the outer loop counter
		loop mainloop1           // do next two lines
		jmp done                 // skip the next part
		}
	clearscr:
	asm cld;                     // clear the direction flag

	mainloop2:
	asm {
		push cx                  // save the loop counter
		mov cx, 160              // move 160 words
		push di                  // save the offset
		}
	test_21:                     // these lines test for vbi
	asm	{
		in al, dx                // first test, out of vbi
		test al,0x8
		jnz test_21
		}
	test_22:
	asm	{
		in al, dx                // second test, in vbi
		test al,0x8
		jz test_22
		xor ax, ax               // clear ax, value to be stored==0
		rep stosw                // clear the line
		pop di                   // restore the offset
		sub bx, 320              // take one line from bx
		add di, bx               // add it to the offset
		mov cx, 160              // mov 160 more words
		push di                  // save the offset
		rep stosw                // copy the data to video buff
		pop di                   // restore the offset
		sub bx, 320              // take one line from bx
		sub di, bx               // subtract it from the offset
		pop cx                   // restore the loop counter
		loop mainloop2
		}
	done:
	asm pop ds;
	}

// **************************************************************************
// doSlideVerticalWipe causes the image in pic_buf to be displayed by sliding
// it in from both sides toward the center. Does not check pic_buff for a non
// null address. Waits for vertical blanking interval between writes, produc-
// ing a smooth image motion.
//
// This function basically captures frames from the left and right sides of
// the source image and displays them in the video buffer so that the image

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -