dsp4emu.c

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

C
2,173
字号
  ////////////////////////////////////////////////////  // sort inputs  DSP4_READ_WORD(); // 0x0000  DSP4_vars.world_y = DSP4_READ_DWORD();  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();  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)    {      for (DSP4_vars.lcv = 0; DSP4_vars.lcv < 4; DSP4_vars.lcv++)      {        // grab inputs        DSP4.in_count = 4;        DSP4_WAIT(1);        resume1 :        for (;;)        {          int16 distance;          int16 color, red, green, blue;          distance = DSP4_READ_WORD();          color = DSP4_READ_WORD();          // U1+B5+G5+R5          red = color & 0x1f;          green = (color >> 5) & 0x1f;          blue = (color >> 10) & 0x1f;          // dynamic lighting          red = (red * distance >> 15) & 0x1f;          green = (green * distance >> 15) & 0x1f;          blue = (blue * distance >> 15) & 0x1f;          color = red | (green << 5) | (blue << 10);          DSP4_CLEAR_OUT();          DSP4_WRITE_WORD(color);          break;        }      }    }    //////////////////////////////////////////////////////    // 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(2) resume2 :    // 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(3) resume3 :    // 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;  }  while (1);  DSP4.waiting4command = TRUE;}//////////////////////////////////////////////////////////////void DSP4_OP11(int16 A, int16 B, int16 C, int16 D, int16 *M){  // 0x155 = 341 = Horizontal Width of the Screen  *M = ((A * 0x0155 >> 2) & 0xf000) |       ((B * 0x0155 >> 6) & 0x0f00) |       ((C * 0x0155 >> 10) & 0x00f0) |       ((D * 0x0155 >> 14) & 0x000f);}///////////////////////////////////////////////////////////////Processing Code/////////////////////////////////////////////////////////////uint8 dsp4_byte;uint16 dsp4_address;void InitDSP4(){  memset(&DSP4, 0, sizeof(DSP4));  DSP4.waiting4command = TRUE;}void DSP4SetByte(){  // clear pending read  if (DSP4.out_index < DSP4.out_count)  {    DSP4.out_index++;    return;  }  if (DSP4.waiting4command)  {    if (DSP4.half_command)    {      DSP4.command |= (dsp4_byte << 8);      DSP4.in_index = 0;      DSP4.waiting4command = FALSE;      DSP4.half_command = FALSE;      DSP4.out_count = 0;      DSP4.out_index = 0;      DSP4_vars.DSP4_Logic = 0;      switch (DSP4.command)      {        case 0x0000:          DSP4.in_count = 4; break;        case 0x0001:          DSP4.in_count = 44; break;        case 0x0003:          DSP4.in_count = 0; break;        case 0x0005:          DSP4.in_count = 0; break;        case 0x0006:          DSP4.in_count = 0; break;        case 0x0007:          DSP4.in_count = 34; break;        case 0x0008:          DSP4.in_count = 90; break;        case 0x0009:          DSP4.in_count = 14; break;        case 0x000a:          DSP4.in_count = 6; break;        case 0x000b:          DSP4.in_count = 6; break;        case 0x000d:          DSP4.in_count = 42; break;        case 0x000e:          DSP4.in_count = 0; break;        case 0x000f:          DSP4.in_count = 46; break;        case 0x0010:          DSP4.in_count = 36; break;        case 0x0011:          DSP4.in_count = 8; break;        default:          DSP4.waiting4command = TRUE;          break;      }    }    else    {      DSP4.command = dsp4_byte;      DSP4.half_command = TRUE;    }  }  else  {    DSP4.parameters[DSP4.in_index] = dsp4_byte;    DSP4.in_index++;  }  if (!DSP4.waiting4command && DSP4.in_count == DSP4.in_index)  {    // Actually execute the command    DSP4.waiting4command = TRUE;    DSP4.out_index = 0;    DSP4.in_index = 0;    switch (DSP4.command)    {        // 16-bit multiplication      case 0x0000:      {        int16 multiplier, multiplicand;        int32 product;        multiplier = DSP4_READ_WORD();        multiplicand = DSP4_READ_WORD();        DSP4_Multiply(multiplicand, multiplier, &product);        DSP4_CLEAR_OUT();        DSP4_WRITE_WORD((uint16)(product));        DSP4_WRITE_WORD((uint16)(product >> 16));      }      break;      // single-player track projection      case 0x0001:        DSP4_OP01(); break;      // single-player selection      case 0x0003:        DSP4_OP03(); break;      // clear OAM      case 0x0005:        DSP4_OP05(); break;      // transfer OAM      case 0x0006:        DSP4_OP06(); break;      // single-player track turnoff projection      case 0x0007:        DSP4_OP07(); break;      // solid polygon projection      case 0x0008:        DSP4_OP08(); break;      // sprite projection      case 0x0009:        DSP4_OP09(); break;      // unknown      case 0x000A:      {        //int16 in1a = DSP4_READ_WORD();        int16 in2a = DSP4_READ_WORD();        //int16 in3a = DSP4_READ_WORD();        int16 out1a, out2a, out3a, out4a;        DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a);        DSP4_CLEAR_OUT();        DSP4_WRITE_WORD(out1a);        DSP4_WRITE_WORD(out2a);        DSP4_WRITE_WORD(out3a);        DSP4_WRITE_WORD(out4a);      }      break;      // set OAM      case 0x000B:      {        int16 sp_x = DSP4_READ_WORD();        int16 sp_y = DSP4_READ_WORD();        int16 sp_attr = DSP4_READ_WORD();        bool8 draw = 1;        DSP4_CLEAR_OUT();        DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, 0, 1);      }      break;      // multi-player track projection      case 0x000D:        DSP4_OP0D(); break;      // multi-player selection      case 0x000E:        DSP4_OP0E(); break;      // single-player track projection with lighting      case 0x000F:        DSP4_OP0F(); break;      // single-player track turnoff projection with lighting      case 0x0010:        DSP4_OP10(); break;      // unknown: horizontal mapping command      case 0x0011:      {        int16 a, b, c, d, m;        d = DSP4_READ_WORD();        c = DSP4_READ_WORD();        b = DSP4_READ_WORD();        a = DSP4_READ_WORD();        DSP4_OP11(a, b, c, d, &m);        DSP4_CLEAR_OUT();        DSP4_WRITE_WORD(m);        break;      }      default:        break;    }  }}void DSP4GetByte(){  if (DSP4.out_count)  {    dsp4_byte = (uint8) DSP4.output[DSP4.out_index&0x1FF];    DSP4.out_index++;    if (DSP4.out_count == DSP4.out_index)      DSP4.out_count = 0;  }  else  {    dsp4_byte = 0xff;  }}

⌨️ 快捷键说明

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