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

📄 dsp4emu.cpp

📁 SFC游戏模拟器 snes9x 1.43 的原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:

		DSP4_WRITE_WORD(0,project_x2);
		DSP4_WRITE_WORD(2,project_y2);
		DSP4_WRITE_WORD(4,segments);

#if 0
		DSP4_WRITE_WORD(0,-1);
		DSP4_WRITE_WORD(2,-1);
		DSP4_WRITE_WORD(4,-1);
#endif

		index=6;

		project_x = project_centerx + project_x1;

		for( lcv=0; lcv<segments; lcv++ )
		{
			// pre-compute
			y_out = project_y+((py_dy*lcv)>>8);
			x_out = project_x+((px_dx*lcv)>>8);

			// factor in dynamic track changes
			y_out += envelope;

#if 0
			project_ptr = -1;
			//y_out = -1;
			x_out = -1;
#endif

			// data
			DSP4_WRITE_WORD(index+0,project_ptr);
			DSP4_WRITE_WORD(index+2,y_out);
			DSP4_WRITE_WORD(index+4,x_out);
			index += 6;

			// post-update
			project_ptr -= 4;
		}

		// update internal variables
		project_y += ((py_dy*lcv)>>8);

		// new positions
		if(segments>0)
		{
			project_x1 = project_x2;
			project_y1 = project_y2;

			// multi-op storage
			multi_index2++;
		}
	} while(1);

	DSP4.waiting4command = TRUE;
	DSP4.out_count = 0;
}

#undef PRINT

#if OP==0x0008
#define PRINT
#endif

void DSP4_Op08()
{
	uint16 command;

	DSP4.waiting4command = FALSE;

	// op flow control
	switch(DSP4_Logic) {
		case 1: goto resume1; break;
		case 2: goto resume2; break;
	}

	////////////////////////////////////////////////////
	// process initial inputs

	// clip values
	path_clipRight[0] = DSP4_READ_WORD(0x00);
	path_clipRight[1] = DSP4_READ_WORD(0x02);
	path_clipRight[2] = DSP4_READ_WORD(0x04);
	path_clipRight[3] = DSP4_READ_WORD(0x06);

	path_clipLeft[0] = DSP4_READ_WORD(0x08);
	path_clipLeft[1] = DSP4_READ_WORD(0x0a);
	path_clipLeft[2] = DSP4_READ_WORD(0x0c);
	path_clipLeft[3] = DSP4_READ_WORD(0x0e);

	// unknown (constant)
	// unknown (constant)

	// path positions
	path_pos[0] = DSP4_READ_WORD(0x20);
	path_pos[1] = DSP4_READ_WORD(0x22);
	path_pos[2] = DSP4_READ_WORD(0x24);
	path_pos[3] = DSP4_READ_WORD(0x26);

	// data locations
	path_ptr[0] = DSP4_READ_WORD(0x28);
	path_ptr[1] = DSP4_READ_WORD(0x2a);
	path_ptr[2] = DSP4_READ_WORD(0x2c);
	path_ptr[3] = DSP4_READ_WORD(0x2e);

	// project_y1 lines
	path_raster[0] = DSP4_READ_WORD(0x30);
	path_raster[1] = DSP4_READ_WORD(0x32);
	path_raster[2] = DSP4_READ_WORD(0x34);
	path_raster[3] = DSP4_READ_WORD(0x36);

	// viewport_top
	path_top[0] = DSP4_READ_WORD(0x38);
	path_top[1] = DSP4_READ_WORD(0x3a);
	path_top[2] = DSP4_READ_WORD(0x3c);
	path_top[3] = DSP4_READ_WORD(0x3e);

	// unknown (constants)

	view_plane = PLANE_START;

	// debug
	block=0;

	////////////////////////////////////////////////////
	// command check

	do {
		// scan next command
		DSP4.in_count = 2;

		DSP4_WAIT(1) resume1:
	
		// inspect input
		command = DSP4_READ_WORD(0);

		// terminate op
		if(command == 0x8000) break;

		// already have 2 bytes in queue
		DSP4.in_index = 2;
		DSP4.in_count = 18;

		DSP4_WAIT(2) resume2:

		////////////////////////////////////////////////////
		// projection begins

		// debug
		++block;

		// used in envelope shaping
		int16 x1_final;
		int16 x2_final;

		// look at guidelines
		int16 plane = DSP4_READ_WORD(0x00);
		int16 x_left = DSP4_READ_WORD(0x02);
		int16 y_left = DSP4_READ_WORD(0x04);
		int16 x_right = DSP4_READ_WORD(0x06);
		int16 y_right = DSP4_READ_WORD(0x08);

		// envelope guidelines (one frame only)
		int16 envelope1 = DSP4_READ_WORD(0x0a);
		int16 envelope2 = DSP4_READ_WORD(0x0c);
		int16 envelope3 = DSP4_READ_WORD(0x0e);
		int16 envelope4 = DSP4_READ_WORD(0x10);

		// ignore invalid data
		if((uint16) plane == 0x8001) continue;

		// first init
		if(plane == 0x7fff)
		{
			int pos1,pos2;

			// initialize projection
			path_x[0] = x_left;
			path_x[1] = x_right;

			path_y[0] = y_left;
			path_y[1] = y_right;

			// update coordinates
			path_pos[0]-=x_left;
			path_pos[1]-=x_left;
			path_pos[2]-=x_right;
			path_pos[3]-=x_right;

			pos1 = path_pos[0]+envelope1;
			pos2 = path_pos[1]+envelope2;

			// clip offscreen data
			if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0];
			if(pos1>path_clipRight[0]) pos1 = path_clipRight[0];
			if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1];
			if(pos2>path_clipRight[1]) pos2 = path_clipRight[1];

#if 0
			pos1=-1;
			//pos2=-1;
#endif

			path_plane[0] = plane;
			path_plane[1] = plane;

			// initial output
			DSP4.out_count = 2;
			DSP4.output[0]=pos1&0xFF;
			DSP4.output[1]=pos2&0xFF;

#ifdef PRINT
			printf("(line %d) Op08 x_left %04X\n",c,(uint16)x_left);
#endif
		}
		// proceed with projection
		else
		{
			int16 index=0, lcv;
			int16 left_inc=0,right_inc=0;
			int16 dx1,dx2,dx3,dx4;

			// # segments to traverse
			segments = abs(y_left - path_y[0]);

			// prevent overdraw
			if(y_left>=path_raster[0]) segments=0;
			else path_raster[0]=y_left;

			// don't draw outside the window
			if(path_raster[0]<path_top[0]) segments=0;

			// proceed if visibility rules apply
			if(segments>0)
			{
				// use previous data
				dx1 = (envelope1 * path_plane[0] / view_plane);
				dx2 = (envelope2 * path_plane[0] / view_plane);

				// use temporary envelope pitch (this frame only)
				dx3 = (envelope1 * plane / view_plane);
				dx4 = (envelope2 * plane / view_plane);

				// project new shapes (left side)
				x1_final = x_left+dx1;
				x2_final = path_x[0]+dx3;

				// interpolate between projected points with shaping
				left_inc = ((x2_final-x1_final)<<8)/segments;

				// project new shapes (right side)
				x1_final = x_left+dx2;
				x2_final = path_x[0]+dx4;

				// interpolate between projected points with shaping
				right_inc = ((x2_final-x1_final)<<8)/segments;

				path_plane[0] = plane;
			}

#ifdef PRINT
			printf("(line %d) Op08 block %d, out %02X, raster %02X\n",c,block,segments,(uint16)y_left);
#endif

			// zone 1
			DSP4.out_count = (2+4*segments);
			DSP4_WRITE_WORD(index,segments); index+=2;

			for( lcv=1; lcv<=segments; lcv++ )
			{
				int16 pos1,pos2;

				// pre-compute
				pos1 = path_pos[0]+((left_inc*lcv)>>8)+dx1;
				pos2 = path_pos[1]+((right_inc*lcv)>>8)+dx2;

				// clip offscreen data
				if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0];
				if(pos1>path_clipRight[0]) pos1 = path_clipRight[0];
				if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1];
				if(pos2>path_clipRight[1]) pos2 = path_clipRight[1];

#if 0
				if(pos1==0x00ff) pos1=0;
				if(pos2==0x00ff) pos2=0;
				path_ptr[0] = -1;
				pos1 = -1;
				pos2 = -1;
#endif

				// data
				DSP4_WRITE_WORD(index,path_ptr[0]); index+=2;
				DSP4.output[index++]=pos1&0xFF;
				DSP4.output[index++]=pos2&0xFF;

				// post-update
				path_ptr[0] -= 4;
				path_ptr[1] -= 4;
			}
			lcv--;

			if(segments>0)
			{
				// project points w/out the envelopes
				int16 inc = ((path_x[0]-x_left)<<8)/segments;

				// post-store
				path_pos[0] += ((inc*lcv)>>8);
				path_pos[1] += ((inc*lcv)>>8);

				path_x[0] = x_left;
				path_y[0] = y_left;
			}

			//////////////////////////////////////////////
			// zone 2
			segments = abs(y_right - path_y[1]);

			// prevent overdraw
			if(y_right>=path_raster[2]) segments=0;
			else path_raster[2]=y_right;

			// don't draw outside the window
			if(path_raster[2]<path_top[2]) segments=0;

			// proceed if visibility rules apply
			if(segments>0)
			{
				// use previous data
				dx1 = (envelope1 * path_plane[1] / view_plane);
				dx2 = (envelope2 * path_plane[1] / view_plane);

				// use temporary envelope pitch (this frame only)
				dx3 = (envelope1 * plane / view_plane);
				dx4 = (envelope2 * plane / view_plane);

				// project new shapes (left side)
				x1_final = x_left+dx1;
				x2_final = path_x[1]+dx3;

				// interpolate between projected points with shaping
				left_inc = ((x2_final-x1_final)<<8)/segments;

				// project new shapes (right side)
				x1_final = x_left+dx2;
				x2_final = path_x[1]+dx4;

				// interpolate between projected points with shaping
				right_inc = ((x2_final-x1_final)<<8)/segments;

				path_plane[1] = plane;
			}

			// write out results
			DSP4.out_count += (2+4*segments);
			DSP4_WRITE_WORD(index,segments); index+=2;

			for( lcv=1; lcv<=segments; lcv++ )
			{
				int16 pos1,pos2;

				// pre-compute
				pos1 = path_pos[2]+((left_inc*lcv)>>8)+dx1;
				pos2 = path_pos[3]+((right_inc*lcv)>>8)+dx2;

				// clip offscreen data
				if(pos1<path_clipLeft[2]) pos1 = path_clipLeft[2];
				if(pos1>path_clipRight[2]) pos1 = path_clipRight[2];
				if(pos2<path_clipLeft[3]) pos2 = path_clipLeft[3];
				if(pos2>path_clipRight[3]) pos2 = path_clipRight[3];

#if 0
				if(pos1==0x00ff) pos1=0;
				if(pos2==0x00ff) pos2=0;
				path_ptr[2] = -1;
				//pos1 = -1;
				pos2 = -1;
#endif

				// data
				DSP4_WRITE_WORD(index,path_ptr[2]); index+=2;
				DSP4.output[index++]=pos1&0xFF;
				DSP4.output[index++]=pos2&0xFF;

				// post-update
				path_ptr[2] -= 4;
				path_ptr[3] -= 4;
			}
			lcv--;

			if(segments>0)
			{
				// project points w/out the envelopes
				int16 inc = ((path_x[1]-x_right)<<8)/segments;

				// post-store
				path_pos[2] += ((inc*lcv)>>8);
				path_pos[3] += ((inc*lcv)>>8);

				path_x[1] = x_right;
				path_y[1] = y_right;
			}
		}
	} while(1);

	DSP4.waiting4command = TRUE;
	DSP4.out_count = 2;
	DSP4_WRITE_WORD(0,0);
}

#undef PRINT

#if OP==0x000D
#define PRINT
#endif

void DSP4_Op0D()
{
	uint16 command;

	DSP4.waiting4command = FALSE;

	// op flow control
	switch(DSP4_Logic) {
		case 1: goto resume1; break;
		case 2: goto resume2; break;
	}

	////////////////////////////////////////////////////
	// process initial inputs

	// sort inputs
	// 0x00 = DSP4_READ_WORD(0x00);
	project_focaly = DSP4_READ_WORD(0x02);
	raster = DSP4_READ_WORD(0x04);
	viewport_top = DSP4_READ_WORD(0x06);
	project_y = DSP4_READ_WORD(0x08);
	viewport_bottom = DSP4_READ_WORD(0x0a);
	project_x1low = DSP4_READ_WORD(0x0c);
	project_x1 = DSP4_READ_WORD(0x0e);
	project_focalx = DSP4_READ_WORD(0x0e);
	project_centerx = DSP4_READ_WORD(0x10);
	project_ptr = DSP4_READ_WORD(0x12);
	// 0xc0 = DSP4_READ_WORD(0x14);
	project_pitchylow = DSP4_READ_WORD(0x16);
	project_pitchy = DSP4_READ_WORD(0x18);
	project_pitchxlow = DSP4_READ_WORD(0x1a);
	project_pitchx = DSP4_READ_WORD(0x1c);
	far_plane = DSP4_READ_WORD(0x1e);
	// ? = DSP4_READ_WORD(0x20);

	// multi-op storage
	multi_index1++;
	multi_index1%=4;

	// remap 0D->09 window data ahead of time
	// index starts at 1-3,0
	//
	// Op0D: BL,TL,BR,TR
	// Op09: TL,TR,BL,BR (1,2,3,0)
	switch(multi_index1)
	{
		case 1: multi_index2=3; break;
		case 2: multi_index2=1; break;
		case 3: multi_index2=0; break;
		case 0: multi_index2=2; break;
	}

	// pre-compute
	view_plane = PLANE_START;

	// figure out projection data
	project_y -= viewport_bottom;

	// debug
	block=0;

	////////////////////////////////////////////////////
	// command check

	do {
		// scan next command
		DSP4.in_count = 2;
		
		DSP4_WAIT(1) resume1:

		// inspect input
		command = DSP4_READ_WORD(0);

		// terminate op
		if(command == 0x8000) break;

		// already have 2 bytes in queue
		DSP4.in_index = 2;
		DSP4.in_count = 8;

		DSP4_WAIT(2) resume2:

		////////////////////////////////////////////////////
		// project section of the track

		// inspect inputs
		int16 plane = DSP4_READ_WORD(0);
		int16 index, lcv;
		int16 py_dy=0, px_dx=0;
		int16 y_out, x_out;
		int16 envelope = DSP4_READ_WORD(6);
		int16 project_x;

		// ignore invalid data
		if((uint16) plane == 0x8001) continue;

		// one-time init
		if(far_plane)
		{
			// setup final data
			// low16=plane
			project_x1 = project_focalx;
			project_y1 = project_focaly;
			plane = far_plane;
			far_plane = 0;

			// track occlusion
			multi_farplane[multi_index2] = plane;
			multi_raster[multi_index2] = viewport_bottom;
		}

		// use proportional triangles to project new coords
		project_x2 = project_focalx * plane / view_plane;

⌨️ 快捷键说明

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