📄 dsp4emu.cpp
字号:
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 + -