dsp4emu.c

来自「linux下的任天堂模拟器代码。供大家参考。」· C语言 代码 · 共 2,173 行 · 第 1/5 页

C
2,173
字号
  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();  DSP4_vars.viewport_bottom = DSP4_READ_WORD();  DSP4_vars.world_x = DSP4_READ_DWORD();  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();  DSP4_vars.world_yofs = DSP4_READ_WORD();  DSP4_vars.distance = DSP4_READ_WORD();  DSP4_vars.view_y2 = DSP4_READ_WORD();  DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15;  DSP4_vars.view_x2 = DSP4_READ_WORD();  DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15;  DSP4_vars.view_yofsenv = DSP4_READ_WORD();  // initial (x,y,offset) at starting DSP4_vars.raster line  DSP4_vars.view_x1 = (int16)(DSP4_vars.world_x >> 16);  DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16);  DSP4_vars.view_xofs1 = DSP4_vars.view_x1;  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;  // first DSP4_vars.raster line  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];  do  {    ////////////////////////////////////////////////////    // process one iteration of projection    // add shaping    DSP4_vars.view_x2 += DSP4_vars.view_dx;    DSP4_vars.view_y2 += DSP4_vars.view_dy;    // vertical scroll calculation    DSP4_vars.view_xofs2 = DSP4_vars.view_x2;    DSP4_vars.view_yofs2 = (DSP4_vars.world_yofs * DSP4_vars.distance >> 15) + DSP4_vars.poly_bottom[0][0] - DSP4_vars.view_y2;    // 1. Viewer x-position at the next    // 2. Viewer y-position below the horizon    // 3. Number of DSP4_vars.raster lines drawn in this iteration    DSP4_CLEAR_OUT();    DSP4_WRITE_WORD(DSP4_vars.view_x2);    DSP4_WRITE_WORD(DSP4_vars.view_y2);    //////////////////////////////////////////////////////    // SR = 0x00    // determine # of DSP4_vars.raster lines used    DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.view_y2;    // prevent overdraw    if (DSP4_vars.view_y2 >= DSP4_vars.poly_raster[0][0])      DSP4_vars.segments = 0;    else      DSP4_vars.poly_raster[0][0] = DSP4_vars.view_y2;    // don't draw outside the window    if (DSP4_vars.view_y2 < DSP4_vars.poly_top[0][0])    {      DSP4_vars.segments = 0;      // flush remaining DSP4_vars.raster lines      if (DSP4_vars.view_y1 >= DSP4_vars.poly_top[0][0])        DSP4_vars.segments = DSP4_vars.view_y1 - DSP4_vars.poly_top[0][0];    }    // SR = 0x80    DSP4_WRITE_WORD(DSP4_vars.segments);    //////////////////////////////////////////////////////    // scan next command if no SR check needed    if (DSP4_vars.segments)    {      int32 px_dx, py_dy;      int32 x_scroll, y_scroll;      // SR = 0x00      // linear interpolation (lerp) between projected points      px_dx = (DSP4_vars.view_xofs2 - DSP4_vars.view_xofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;      py_dy = (DSP4_vars.view_yofs2 - DSP4_vars.view_yofs1) * DSP4_Inverse(DSP4_vars.segments) << 1;      // starting step values      x_scroll = SEX16(DSP4_vars.poly_cx[0][0] + DSP4_vars.view_xofs1);      y_scroll = SEX16(-DSP4_vars.viewport_bottom + DSP4_vars.view_yofs1 + DSP4_vars.view_yofsenv + DSP4_vars.poly_cx[1][0] - DSP4_vars.world_yofs);      // SR = 0x80      // rasterize line      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)      {        // 1. HDMA memory pointer (bg2)        // 2. vertical scroll offset ($2110)        // 3. horizontal scroll offset ($210F)        DSP4_WRITE_WORD(DSP4_vars.poly_ptr[0][0]);        DSP4_WRITE_WORD((uint16)((y_scroll + 0x8000) >> 16));        DSP4_WRITE_WORD((uint16)((x_scroll + 0x8000) >> 16));        // update memory address        DSP4_vars.poly_ptr[0][0] -= 4;        // update screen values        x_scroll += px_dx;        y_scroll += py_dy;      }    }    /////////////////////////////////////////////////////    // Post-update    // update new viewer (x,y,scroll) to last DSP4_vars.raster line drawn    DSP4_vars.view_x1 = DSP4_vars.view_x2;    DSP4_vars.view_y1 = DSP4_vars.view_y2;    DSP4_vars.view_xofs1 = DSP4_vars.view_xofs2;    DSP4_vars.view_yofs1 = DSP4_vars.view_yofs2;    ////////////////////////////////////////////////////    // command check    // scan next command    DSP4.in_count = 2;    DSP4_WAIT(1) resume1 :    // check for opcode termination    DSP4_vars.distance = DSP4_READ_WORD();    if (DSP4_vars.distance == -0x8000)      break;    // already have 2 bytes in queue    DSP4.in_count = 10;    DSP4_WAIT(2) resume2 :    // inspect inputs    DSP4_vars.view_y2 = DSP4_READ_WORD();    DSP4_vars.view_dy = DSP4_READ_WORD() * DSP4_vars.distance >> 15;    DSP4_vars.view_x2 = DSP4_READ_WORD();    DSP4_vars.view_dx = DSP4_READ_WORD() * DSP4_vars.distance >> 15;    DSP4_vars.view_yofsenv = DSP4_READ_WORD();  }  while (1);  DSP4.waiting4command = TRUE;}//////////////////////////////////////////////////////////////void DSP4_OP08(){  int16 win_left, win_right;  int16 view_x[2], view_y[2];  int16 envelope[2][2];  DSP4.waiting4command = FALSE;  // op flow control  switch (DSP4_vars.DSP4_Logic)  {    case 1:      goto resume1; break;    case 2:      goto resume2; break;  }  ////////////////////////////////////////////////////  // process initial inputs for two polygons  // clip values  DSP4_vars.poly_clipRt[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_clipRt[0][1] = DSP4_READ_WORD();  DSP4_vars.poly_clipRt[1][0] = DSP4_READ_WORD();  DSP4_vars.poly_clipRt[1][1] = DSP4_READ_WORD();  DSP4_vars.poly_clipLf[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_clipLf[0][1] = DSP4_READ_WORD();  DSP4_vars.poly_clipLf[1][0] = DSP4_READ_WORD();  DSP4_vars.poly_clipLf[1][1] = DSP4_READ_WORD();  // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6)  DSP4_READ_WORD();  DSP4_READ_WORD();  DSP4_READ_WORD();  DSP4_READ_WORD();  // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7)  DSP4_READ_WORD();  DSP4_READ_WORD();  DSP4_READ_WORD();  DSP4_READ_WORD();  // polygon centering (left,right)  DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_cx[0][1] = DSP4_READ_WORD();  DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD();  DSP4_vars.poly_cx[1][1] = DSP4_READ_WORD();  // HDMA pointer locations  DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_ptr[0][1] = DSP4_READ_WORD();  DSP4_vars.poly_ptr[1][0] = DSP4_READ_WORD();  DSP4_vars.poly_ptr[1][1] = DSP4_READ_WORD();  // starting DSP4_vars.raster line below the horizon  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_bottom[0][1] = DSP4_READ_WORD();  DSP4_vars.poly_bottom[1][0] = DSP4_READ_WORD();  DSP4_vars.poly_bottom[1][1] = DSP4_READ_WORD();  // top boundary line to clip  DSP4_vars.poly_top[0][0] = DSP4_READ_WORD();  DSP4_vars.poly_top[0][1] = DSP4_READ_WORD();  DSP4_vars.poly_top[1][0] = DSP4_READ_WORD();  DSP4_vars.poly_top[1][1] = DSP4_READ_WORD();  // unknown  // (ex. 1P = $2FC8, $0034, $FF5C, $0035)  //  // (ex. 2P = $3178, $0034, $FFCC, $0035)  // (ex. 2P = $2FC8, $0034, $FFCC, $0035)  DSP4_READ_WORD();  DSP4_READ_WORD();  DSP4_READ_WORD();  DSP4_READ_WORD();  // look at guidelines for both polygon shapes  DSP4_vars.distance = DSP4_READ_WORD();  view_x[0] = DSP4_READ_WORD();  view_y[0] = DSP4_READ_WORD();  view_x[1] = DSP4_READ_WORD();  view_y[1] = DSP4_READ_WORD();  // envelope shaping guidelines (one frame only)  envelope[0][0] = DSP4_READ_WORD();  envelope[0][1] = DSP4_READ_WORD();  envelope[1][0] = DSP4_READ_WORD();  envelope[1][1] = DSP4_READ_WORD();  // starting base values to project from  DSP4_vars.poly_start[0] = view_x[0];  DSP4_vars.poly_start[1] = view_x[1];  // starting DSP4_vars.raster lines to begin drawing  DSP4_vars.poly_raster[0][0] = view_y[0];  DSP4_vars.poly_raster[0][1] = view_y[0];  DSP4_vars.poly_raster[1][0] = view_y[1];  DSP4_vars.poly_raster[1][1] = view_y[1];  // starting distances  DSP4_vars.poly_plane[0] = DSP4_vars.distance;  DSP4_vars.poly_plane[1] = DSP4_vars.distance;  // SR = 0x00  // re-center coordinates  win_left = DSP4_vars.poly_cx[0][0] - view_x[0] + envelope[0][0];  win_right = DSP4_vars.poly_cx[0][1] - view_x[0] + envelope[0][1];  // saturate offscreen data for polygon #1  if (win_left < DSP4_vars.poly_clipLf[0][0])  {    win_left = DSP4_vars.poly_clipLf[0][0];  }  if (win_left > DSP4_vars.poly_clipRt[0][0])  {    win_left = DSP4_vars.poly_clipRt[0][0];  }  if (win_right < DSP4_vars.poly_clipLf[0][1])  {    win_right = DSP4_vars.poly_clipLf[0][1];  }  if (win_right > DSP4_vars.poly_clipRt[0][1])  {    win_right = DSP4_vars.poly_clipRt[0][1];  }  // SR = 0x80  // initial output for polygon #1  DSP4_CLEAR_OUT();  DSP4_WRITE_BYTE(win_left & 0xff);  DSP4_WRITE_BYTE(win_right & 0xff);  do  {    int16 polygon;    ////////////////////////////////////////////////////    // command check    // scan next command    DSP4.in_count = 2;    DSP4_WAIT(1) resume1 :    // terminate op    DSP4_vars.distance = DSP4_READ_WORD();    if (DSP4_vars.distance == -0x8000)      break;    // already have 2 bytes in queue    DSP4.in_count = 16;    DSP4_WAIT(2) resume2 :    // look at guidelines for both polygon shapes    view_x[0] = DSP4_READ_WORD();    view_y[0] = DSP4_READ_WORD();    view_x[1] = DSP4_READ_WORD();    view_y[1] = DSP4_READ_WORD();    // envelope shaping guidelines (one frame only)    envelope[0][0] = DSP4_READ_WORD();    envelope[0][1] = DSP4_READ_WORD();    envelope[1][0] = DSP4_READ_WORD();    envelope[1][1] = DSP4_READ_WORD();    ////////////////////////////////////////////////////    // projection begins    // init    DSP4_CLEAR_OUT();    //////////////////////////////////////////////    // solid polygon renderer - 2 shapes    for (polygon = 0; polygon < 2; polygon++)    {      int32 left_inc, right_inc;      int16 x1_final, x2_final;      int16 env[2][2];      int16 poly;      // SR = 0x00      // # DSP4_vars.raster lines to draw      DSP4_vars.segments = DSP4_vars.poly_raster[polygon][0] - view_y[polygon];      // prevent overdraw      if (DSP4_vars.segments > 0)      {        // bump drawing cursor        DSP4_vars.poly_raster[polygon][0] = view_y[polygon];        DSP4_vars.poly_raster[polygon][1] = view_y[polygon];      }      else        DSP4_vars.segments = 0;      // don't draw outside the window      if (view_y[polygon] < DSP4_vars.poly_top[polygon][0])      {        DSP4_vars.segments = 0;        // flush remaining DSP4_vars.raster lines        if (view_y[polygon] >= DSP4_vars.poly_top[polygon][0])          DSP4_vars.segments = view_y[polygon] - DSP4_vars.poly_top[polygon][0];      }      // SR = 0x80      // tell user how many DSP4_vars.raster structures to read in      DSP4_WRITE_WORD(DSP4_vars.segments);      // normal parameters      poly = polygon;      /////////////////////////////////////////////////////      // scan next command if no SR check needed      if (DSP4_vars.segments)      {        int32 win_left, win_right;        // road turnoff selection        if( (uint16) envelope[ polygon ][ 0 ] == (uint16) 0xc001 )          poly = 1;        else if( envelope[ polygon ][ 1 ] == 0x3fff )          poly = 1;        ///////////////////////////////////////////////        // left side of polygon        // perspective correction on additional shaping parameters        env[0][0] = envelope[polygon][0] * DSP4_vars.poly_plane[poly] >> 15;        env[0][1] = envelope[polygon][0] * DSP4_vars.distance >> 15;        // project new shapes (left side)        x1_final = view_x[poly] + env[0][0];        x2_final = DSP4_vars.poly_start[poly] + env[0][1];        // interpolate between projected points with shaping        left_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4_vars.segments) << 1;        if (DSP4_vars.segments == 1)          left_inc = -left_inc;        ///////////////////////////////////////////////        // right side of polygon        // perspective correction on additional shaping parameters        env[1][0] = envelope[polygon][1] * DSP4_vars.poly_plane[poly] >> 15;;        env[1][1] = envelope[polygon][1] * DSP4_vars.distance >> 15;        // project new shapes (right side)        x1_final = view_x[poly] + env[1][0];        x2_final = DSP4_vars.poly_start[poly] + env[1][1];        // interpolate between projected points with shaping        right_inc = (x2_final - x1_final) * DSP4_Inverse(DSP4_vars.segments) << 1;        if (DSP4_vars.segments == 1)          right_inc = -right_inc;        ///////////////////////////////////////////////        // update each point on the line        win_left = SEX16(DSP4_vars.poly_cx[polygon][0] - DSP4_vars.poly_start[poly] + env[0][0]);        win_right = SEX16(DSP4_vars.poly_cx[polygon][1] - DSP4_vars.poly_start[poly] + env[1][0]);        // update DSP4_vars.distance drawn into world        DSP4_vars.poly_plane[polygon] = DSP4_vars.distance;        // rasterize line        for (DSP4_vars.lcv = 0; DSP4_vars.lcv < DSP4_vars.segments; DSP4_vars.lcv++)        {          int16 x_left, x_right;          // project new coordinates          win_left += left_inc;          win_right += right_inc;          // grab integer portion, drop fraction (no rounding)

⌨️ 快捷键说明

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