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

📄 dsp4emu.cpp

📁 SFC游戏模拟器 snes9x 1.43 的原代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		project_y2 = project_focaly * plane / view_plane;

		// quadratic regression (rough)
		if(project_focaly>=-0x0f) 
			py_dy = project_focaly * project_focaly * -0.20533553
							- 1.08330005 * project_focaly - 69.61094639;
		else
			py_dy = project_focaly * project_focaly * -0.000657035759
							- 1.07629051 * project_focaly - 65.69315963;

		// approximate # of raster lines
		segments = abs(project_y2-project_y1);

		// prevent overdraw
		if(project_y2>=raster) segments=0;
		else raster=project_y2;

		// don't draw outside the window
		if(project_y2<viewport_top) segments=0;

		// project new positions
		if(segments>0)
		{
			// interpolate between projected points
			px_dx = ((project_x2-project_x1)<<8)/segments;
		}

		// debug
		++block;

#ifdef PRINT
		printf("(line %d) Op0D check %02X, plane %04X\n",c,(uint16)segments,(uint16)(plane));
#endif

		// prepare output
		DSP4.out_count=8+2+6*segments;

		DSP4_WRITE_WORD(0,project_focalx);
		DSP4_WRITE_WORD(2,project_x2);
		DSP4_WRITE_WORD(4,project_focaly);
		DSP4_WRITE_WORD(6,project_y2);
		DSP4_WRITE_WORD(8,segments);
#if 0
		DSP4_WRITE_WORD(0,-1);
		DSP4_WRITE_WORD(2,-1);
		DSP4_WRITE_WORD(4,-1);
		//DSP4_WRITE_WORD(6,-1);
		DSP4_WRITE_WORD(8,-1);
#endif

		index=10;

		project_x = project_centerx + project_x1;

		// iterate through each point
		for( lcv=0; lcv<segments; lcv++ )
		{
			// step through the projected line
			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;
		}

		// post-update
		project_y += ((py_dy*lcv)>>8);

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

			// track occlusion: can't see anything below it
			multi_farplane[multi_index2] = plane;
			multi_raster[multi_index2] -= segments;
		}

		// update focal projection points
		project_pitchy += (int8)DSP4.parameters[3];
		project_pitchx += (int8)DSP4.parameters[5];

		project_focaly += project_pitchy;
		project_focalx += project_pitchx;
	} while(1);
	
	DSP4.waiting4command = TRUE;
	DSP4.out_count = 0;
}

#undef PRINT

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

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

void DSP4_Op09()
{
	uint16 command;

	DSP4.waiting4command = FALSE;

	// op flow control
	switch(DSP4_Logic) {
		case 1: goto resume1; break;
		case 2: goto resume2; break;
		case 3: goto resume3; break;
		case 4: goto resume4; break;
		case 5: goto resume5; break;
		case 6: goto resume6; break;
		case 7: goto resume7; break;
	}

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

	// debug
	block=0;

	// grab screen information
	view_plane = PLANE_START;
	center_x = DSP4_READ_WORD(0x00);
	center_y = DSP4_READ_WORD(0x02);
	// 0x00 = DSP4_READ_WORD(0x04);
	viewport_left = DSP4_READ_WORD(0x06);
	viewport_right = DSP4_READ_WORD(0x08);
	viewport_top = DSP4_READ_WORD(0x0a);
	viewport_bottom = DSP4_READ_WORD(0x0c);

#ifdef PRINT2
	printf("Window: (%04X,%04X) (%04X,%04X)\n",
		viewport_left,viewport_right,viewport_top,viewport_bottom);
#endif

	// cycle through viewport window data
	multi_index1++;
	multi_index1%=4;

	goto no_sprite;

	do {
		////////////////////////////////////////////////////
		// check for new sprites

		do {
			uint16 second;

			DSP4.in_count = 4;
			DSP4.in_index = 2;

			DSP4_WAIT(1) resume1:

			// try to classify sprite
			second = DSP4_READ_WORD(2);

			// op termination
			if(second == 0x8000) goto terminate;

			second >>= 8;
			sprite_type = 0;

			// vehicle sprite
			if(second == 0x90)
			{
				sprite_type = 1;
				break;
			}
			// terrain sprite
			else if(second != 0)
			{
				sprite_type = 2;
				break;
			}

no_sprite:
			// no sprite. try again

			DSP4.in_count = 2;

			DSP4_WAIT(2) resume2:
			;
		} while (1);

		////////////////////////////////////////////////////
		// process projection information

sprite_found:
		// vehicle sprite
		if(sprite_type == 1)
		{
			int16 plane;
			int16 car_left, car_right, car_left_a;
			int16 focal_back, focal_front;
			uint8 distance, id;

			// we already have 4 bytes we want
			DSP4.in_count = 6+12;
			DSP4.in_index = 4;

			DSP4_WAIT(3) resume3:

			// filter inputs
			project_y1 = DSP4_READ_WORD(0x00);
			// 0x9000 = DSP4_READ_WORD(0x02);
			id = DSP4.parameters[0x04];
			distance = DSP4.parameters[0x05];
			focal_back = DSP4_READ_WORD(0x06);
			focal_front = DSP4_READ_WORD(0x08);
			car_left_a = DSP4_READ_WORD(0x0a);
			car_left = DSP4_READ_WORD(0x0c);
			plane = DSP4_READ_WORD(0x0e);
			car_right = DSP4_READ_WORD(0x10);

			// calculate car's x-center
			project_focalx = car_right-car_left;

			// determine how far into the screen to project
			project_focaly = focal_back;
			project_x = project_focalx * plane / view_plane;
			segments = 0x33 - project_focaly * plane / view_plane;
			far_plane = plane;

			// prepare memory
			sprite_x = center_x+project_x;
			sprite_y = viewport_bottom-segments;
			far_plane = plane;

			// debug
			++block;
#ifdef PRINT
			printf("(line %d) Op09 vehicle block %d, Loop %04X\n",c,block,(uint16)project_y1);
			//printf("%04X %04X %04X %04X / ",focal_back,focal_front,car_left_a,car_left);
			//printf("%02X %02X ", distance, id);
#endif

			// make the car's x-center available
			DSP4.out_count = 2;
			DSP4_WRITE_WORD(0,project_focalx);

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

			// grab a few remaining vehicle values
			DSP4.in_count = 4;

			DSP4_WAIT(4) resume4:

			// store final values
			int height = DSP4_READ_WORD(0);
			sprite_offset = DSP4_READ_WORD(2);

			// vertical lift factor
			sprite_y += height;

#ifdef PRINT_09
			printf("%04X\n",sprite_offset);
#endif
		}
		// terrain sprite
		else if(sprite_type == 2)
		{
			int16 plane;

			// we already have 4 bytes we want
			DSP4.in_count = 6+6+2;
			DSP4.in_index = 4;

			DSP4_WAIT(5) resume5:

			// sort loop inputs
			project_y1 = DSP4_READ_WORD(0x00);
			plane = DSP4_READ_WORD(0x02);
			project_centerx = DSP4_READ_WORD(0x04);
			//project_y1 = DSP4_READ_WORD(0x06);
			project_focalx = DSP4_READ_WORD(0x08);
			project_focaly = DSP4_READ_WORD(0x0a);
			sprite_offset = DSP4_READ_WORD(0x0c);

			// determine distances into virtual world
			segments = 0x33 - project_y1;
			project_x = project_focalx * plane / view_plane;
			project_y = project_focaly * plane / view_plane;

			// prepare memory
			sprite_x = center_x+project_x-project_centerx;
			sprite_y = viewport_bottom-segments+project_y;
			far_plane = plane;

			// debug
			++block;
#ifdef PRINT
			printf("(line %d) Op09 terrain block %d, Loop %04X\n",c,block,(uint16)project_y1);
#endif
		}

		// default sprite size: 16x16
		sprite_size = 1;

		////////////////////////////////////////////////////
		// convert tile data to OAM

		do {
			DSP4.in_count = 2;

			DSP4_WAIT(6) resume6:

			command = DSP4_READ_WORD(0);

			// opcode termination
			if(command == 0x8000) goto terminate;

			// toggle sprite size
			if(command == 0x0000)
			{
				sprite_size = !sprite_size;
#ifdef PRINT
				//printf("TOGGLE=%02X\n",(uint8)sprite_size);
#endif
				continue;
			}

			// new sprite information
			command >>= 8;
			if(command != 0x20 && command != 0x40 &&
				 command != 0x60 && command != 0xa0 &&
				 command != 0xc0 && command != 0xe0)
				break;

			DSP4.in_count = 6;
			DSP4.in_index = 2;

			DSP4_WAIT(7) resume7:

			/////////////////////////////////////
			// process tile data

			bool8 clip;
			int16 sp_x, sp_y, sp_oam, sp_msb;
			int16 sp_dx, sp_dy;
			int16 expand = sprite_size ? 15:7;

			// sprite deltas
			sp_dy = DSP4_READ_WORD(2);
			sp_dx = DSP4_READ_WORD(4);

			// update coordinates
			sp_y = sprite_y + sp_dy;
			sp_x = sprite_x + sp_dx;

			// reject points outside the clipping window
			clip = FALSE;

			// window clipping
			if(sp_x < viewport_left-expand || sp_x > viewport_right) clip=TRUE;
			if(sp_y < viewport_top || sp_y > viewport_bottom) clip=TRUE;

			// track occlusion:
			// clip any tiles that are below the road
			if(far_plane <= multi_farplane[multi_index1] &&
				 (sp_y>>3) >= (multi_raster[multi_index1]>>3)) clip=TRUE;

			// tile limitations
			if ((sp_y >= -expand) && ((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)) && !clip)
			{
				short Row = (sp_y >> 3) & 0x1f;

				if(!sprite_size)
				{
					// 1x1 tile
					if (RowCount[Row] < MaxTilesPerRow)
						RowCount[Row]++;
					else
						clip=TRUE;
				}
				else
				{
					// 2x2 tile
					if ((RowCount[Row+0]+1 < MaxTilesPerRow) &&
						  (RowCount[Row+1]+1 < MaxTilesPerRow))
					{
						RowCount[Row+0]+=2;
						RowCount[Row+1]+=2;
					}
					else
						clip=TRUE;
				}
			}
	
#ifdef PRINT
			printf("(line %d) %04X, %04X, %04X / %04X %04X\n",line,
				(uint16)sp_x,(uint16)sp_y,(uint16)far_plane,(uint16)multi_farplane[multi_index1],(uint16)multi_raster[multi_index1]);
#endif

			// don't draw offscreen coordinates
			DSP4.out_count = 0;
			if(!clip)
			{
				int16 out_index = 0;
				int16 offset = DSP4_READ_WORD(0);

				// update sprite nametable/attribute information
				sp_oam = sprite_offset + offset;
				sp_msb = (sp_x<0 || sp_x>255);

#ifdef PRINT2
			printf("(line %d) %04X, %04X, %04X, %04X, %04X\n",line,
				(uint16)sp_oam,(uint16)sprite_offset,(uint16)offset,
				(uint16)sp_x,(uint16)sp_y);
#endif

				// emit transparency information
				if(
						(sprite_offset&0x08) &&
						((sprite_type==1 && sp_y>=0xcc) ||
						 (sprite_type==2 && sp_y>=0xbb))
					)
				{
					DSP4.out_count = 6;

					// one block of OAM data
					DSP4_WRITE_WORD(0,1);

					// OAM: x,y,tile,no attr
					DSP4.output[2] = sp_x&0xFF;
					DSP4.output[3] = (sp_y+6)&0xFF;
					DSP4_WRITE_WORD(4,0xEE);

					out_index = 6;

					// OAM: size,msb data
					DSP4_Op06(sprite_size,sp_msb);

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

				// normal data
				DSP4.out_count += 8;

				// one block of OAM data
				DSP4_WRITE_WORD(out_index+0,1);

				// OAM: x,y,tile,attr
				DSP4.output[out_index+2] = sp_x&0xFF;
				DSP4.output[out_index+3] = sp_y&0xFF;
				DSP4_WRITE_WORD(out_index+4,sp_oam);

				// no following OAM data
				DSP4_WRITE_WORD(out_index+6,0);

				// OAM: size,msb data
				DSP4_Op06(sprite_size,sp_msb);

#if 0
				//DSP4_WRITE_WORD(out_index+0,-1);
				DSP4_WRITE_WORD(out_index+2,-1);
				DSP4_WRITE_WORD(out_index+4,-1);
#endif
			}
			
			// no sprite information
			if(DSP4.out_count == 0)
			{
				DSP4.out_count = 2;
				DSP4_WRITE_WORD(0,0);
			}
		} while (1);

		/////////////////////////////////////
		// special cases: plane == 0x0000

		// special vehicle case
		if(command == 0x90)
		{
			sprite_type = 1;

			// shift bytes
			DSP4.parameters[2] = DSP4.parameters[0];
			DSP4.parameters[3] = DSP4.parameters[1];
			DSP4.parameters[0] = 0;
			DSP4.parameters[1] = 0;

			goto sprite_found;
		}
		// special terrain case
		else if(command != 0x00 && command != 0xff)
		{
			sprite_type = 2;

			// shift bytes
			DSP4.parameters[2] = DSP4.parameters[0];
			DSP4.parameters[3] = DSP4.parameters[1];
			DSP4.parameters[0] = 0;
			DSP4.parameters[1] = 0;

			goto sprite_found;
		}
	} while (1);

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

#undef PRINT

⌨️ 快捷键说明

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