dsp4emu.c

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

C
2,173
字号
          x_left = (int16)(win_left >> 16);          x_right = (int16)(win_right >> 16);          // saturate offscreen data          if (x_left < DSP4_vars.poly_clipLf[polygon][0])            x_left = DSP4_vars.poly_clipLf[polygon][0];          if (x_left > DSP4_vars.poly_clipRt[polygon][0])            x_left = DSP4_vars.poly_clipRt[polygon][0];          if (x_right < DSP4_vars.poly_clipLf[polygon][1])            x_right = DSP4_vars.poly_clipLf[polygon][1];          if (x_right > DSP4_vars.poly_clipRt[polygon][1])            x_right = DSP4_vars.poly_clipRt[polygon][1];          // 1. HDMA memory pointer          // 2. Left window position ($2126/$2128)          // 3. Right window position ($2127/$2129)          DSP4_WRITE_WORD(DSP4_vars.poly_ptr[polygon][0]);          DSP4_WRITE_BYTE(x_left & 0xff);          DSP4_WRITE_BYTE(x_right & 0xff);          // update memory pointers          DSP4_vars.poly_ptr[polygon][0] -= 4;          DSP4_vars.poly_ptr[polygon][1] -= 4;        } // end rasterize line      }      ////////////////////////////////////////////////      // Post-update      // new projection spot to continue rasterizing from      DSP4_vars.poly_start[polygon] = view_x[poly];    } // end polygon rasterizer  }  while (1);  // unknown output  DSP4_CLEAR_OUT();  DSP4_WRITE_WORD(0);  DSP4.waiting4command = TRUE;}//////////////////////////////////////////////////////////////void DSP4_OP09(){  DSP4.waiting4command = FALSE;  // op flow control  switch (DSP4_vars.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;  }  ////////////////////////////////////////////////////  // process initial inputs  // grab screen information  DSP4_vars.viewport_cx = DSP4_READ_WORD();  DSP4_vars.viewport_cy = DSP4_READ_WORD();  DSP4_READ_WORD(); // 0x0000  DSP4_vars.viewport_left = DSP4_READ_WORD();  DSP4_vars.viewport_right = DSP4_READ_WORD();  DSP4_vars.viewport_top = DSP4_READ_WORD();  DSP4_vars.viewport_bottom = DSP4_READ_WORD();  // starting DSP4_vars.raster line below the horizon  DSP4_vars.poly_bottom[0][0] = DSP4_vars.viewport_bottom - DSP4_vars.viewport_cy;  DSP4_vars.poly_raster[0][0] = 0x100;  do  {    ////////////////////////////////////////////////////    // check for new sprites    DSP4.in_count = 4;    DSP4_WAIT(1) resume1 :    ////////////////////////////////////////////////    // DSP4_vars.raster overdraw check    DSP4_vars.raster = DSP4_READ_WORD();    // continue updating the DSP4_vars.raster line where overdraw begins    if (DSP4_vars.raster < DSP4_vars.poly_raster[0][0])    {      DSP4_vars.sprite_clipy = DSP4_vars.viewport_bottom - (DSP4_vars.poly_bottom[0][0] - DSP4_vars.raster);      DSP4_vars.poly_raster[0][0] = DSP4_vars.raster;    }    /////////////////////////////////////////////////    // identify sprite    // op termination    DSP4_vars.distance = DSP4_READ_WORD();    if (DSP4_vars.distance == -0x8000)      goto terminate;    // no sprite    if (DSP4_vars.distance == 0x0000)    {      continue;    }    ////////////////////////////////////////////////////    // process projection information    // vehicle sprite    if ((uint16) DSP4_vars.distance == 0x9000)    {      int16 car_left, car_right, car_back;      int16 impact_left, impact_back;      int16 world_spx, world_spy;      int16 view_spx, view_spy;      uint16 energy;      // we already have 4 bytes we want      DSP4.in_count = 14;      DSP4_WAIT(2) resume2 :      // filter inputs      energy = DSP4_READ_WORD();      impact_back = DSP4_READ_WORD();      car_back = DSP4_READ_WORD();      impact_left = DSP4_READ_WORD();      car_left = DSP4_READ_WORD();      DSP4_vars.distance = DSP4_READ_WORD();      car_right = DSP4_READ_WORD();      // calculate car's world (x,y) values      world_spx = car_right - car_left;      world_spy = car_back;      // add in collision vector [needs bit-twiddling]      world_spx -= energy * (impact_left - car_left) >> 16;      world_spy -= energy * (car_back - impact_back) >> 16;      // perspective correction for world (x,y)      view_spx = world_spx * DSP4_vars.distance >> 15;      view_spy = world_spy * DSP4_vars.distance >> 15;      // convert to screen values      DSP4_vars.sprite_x = DSP4_vars.viewport_cx + view_spx;      DSP4_vars.sprite_y = DSP4_vars.viewport_bottom - (DSP4_vars.poly_bottom[0][0] - view_spy);      // make the car's (x)-coordinate available      DSP4_CLEAR_OUT();      DSP4_WRITE_WORD(world_spx);      // grab a few remaining vehicle values      DSP4.in_count = 4;      DSP4_WAIT(3) resume3 :      // add vertical lift factor      DSP4_vars.sprite_y += DSP4_READ_WORD();    }    // terrain sprite    else    {      int16 world_spx, world_spy;      int16 view_spx, view_spy;      // we already have 4 bytes we want      DSP4.in_count = 10;      DSP4_WAIT(4) resume4 :      // sort loop inputs      DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD();      DSP4_vars.poly_raster[0][1] = DSP4_READ_WORD();      world_spx = DSP4_READ_WORD();      world_spy = DSP4_READ_WORD();      // compute base DSP4_vars.raster line from the bottom      DSP4_vars.segments = DSP4_vars.poly_bottom[0][0] - DSP4_vars.raster;      // perspective correction for world (x,y)      view_spx = world_spx * DSP4_vars.distance >> 15;      view_spy = world_spy * DSP4_vars.distance >> 15;      // convert to screen values      DSP4_vars.sprite_x = DSP4_vars.viewport_cx + view_spx - DSP4_vars.poly_cx[0][0];      DSP4_vars.sprite_y = DSP4_vars.viewport_bottom - DSP4_vars.segments + view_spy;    }    // default sprite size: 16x16    DSP4_vars.sprite_size = 1;    DSP4_vars.sprite_attr = DSP4_READ_WORD();    ////////////////////////////////////////////////////    // convert tile data to SNES OAM format    do    {      uint16 header;      int16 sp_x, sp_y, sp_attr, sp_dattr;      int16 sp_dx, sp_dy;      int16 pixels;      bool8 draw;      DSP4.in_count = 2;      DSP4_WAIT(5) resume5 :      draw = TRUE;      // opcode termination      DSP4_vars.raster = DSP4_READ_WORD();      if (DSP4_vars.raster == -0x8000)        goto terminate;      // stop code      if (DSP4_vars.raster == 0x0000 && !DSP4_vars.sprite_size)        break;      // toggle sprite size      if (DSP4_vars.raster == 0x0000)      {        DSP4_vars.sprite_size = !DSP4_vars.sprite_size;        continue;      }      // check for valid sprite header      header = DSP4_vars.raster;      header >>= 8;      if (header != 0x20 &&          header != 0x2e && //This is for attractor sprite          header != 0x40 &&          header != 0x60 &&          header != 0xa0 &&          header != 0xc0 &&          header != 0xe0)        break;      // read in rest of sprite data      DSP4.in_count = 4;      DSP4_WAIT(6) resume6 :      draw = TRUE;      /////////////////////////////////////      // process tile data      // sprite deltas      sp_dattr = DSP4_vars.raster;      sp_dy = DSP4_READ_WORD();      sp_dx = DSP4_READ_WORD();      // update coordinates to screen space      sp_x = DSP4_vars.sprite_x + sp_dx;      sp_y = DSP4_vars.sprite_y + sp_dy;      // update sprite nametable/attribute information      sp_attr = DSP4_vars.sprite_attr + sp_dattr;      // allow partially visibile tiles      pixels = DSP4_vars.sprite_size ? 15 : 7;      DSP4_CLEAR_OUT();      // transparent tile to clip off parts of a sprite (overdraw)      if (DSP4_vars.sprite_clipy - pixels <= sp_y &&          sp_y <= DSP4_vars.sprite_clipy &&          sp_x >= DSP4_vars.viewport_left - pixels &&          sp_x <= DSP4_vars.viewport_right &&          DSP4_vars.sprite_clipy >= DSP4_vars.viewport_top - pixels &&          DSP4_vars.sprite_clipy <= DSP4_vars.viewport_bottom)      {        DSP4_OP0B(&draw, sp_x, DSP4_vars.sprite_clipy, 0x00EE, DSP4_vars.sprite_size, 0);      }      // normal sprite tile      if (sp_x >= DSP4_vars.viewport_left - pixels &&          sp_x <= DSP4_vars.viewport_right &&          sp_y >= DSP4_vars.viewport_top - pixels &&          sp_y <= DSP4_vars.viewport_bottom &&          sp_y <= DSP4_vars.sprite_clipy)      {        DSP4_OP0B(&draw, sp_x, sp_y, sp_attr, DSP4_vars.sprite_size, 0);      }      // no following OAM data      DSP4_OP0B(&draw, 0, 0x0100, 0, 0, 1);    }    while (1);  }  while (1);  terminate : DSP4.waiting4command = TRUE;}//////////////////////////////////////////////////////////////const uint16 OP0A_Values[16] = { 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, 0xfe80,                                 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 };void DSP4_OP0A(int16 n2, int16 *o1, int16 *o2, int16 *o3, int16 *o4){  *o4 = OP0A_Values[(n2 & 0x000f)];  *o3 = OP0A_Values[(n2 & 0x00f0) >> 4];  *o2 = OP0A_Values[(n2 & 0x0f00) >> 8];  *o1 = OP0A_Values[(n2 & 0xf000) >> 12];}//////////////////////////////////////////////////////////////void DSP4_OP0B(bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop){  int16 Row1, Row2;  // SR = 0x00  // align to nearest 8-pixel row  Row1 = (sp_y >> 3) & 0x1f;  Row2 = (Row1 + 1) & 0x1f;  // check boundaries  if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb)))  {    *draw = 0;  }  if (size)  {    if (DSP4_vars.OAM_Row[Row1] + 1 >= DSP4_vars.OAM_RowMax)      *draw = 0;    if (DSP4_vars.OAM_Row[Row2] + 1 >= DSP4_vars.OAM_RowMax)      *draw = 0;  }  else  {    if (DSP4_vars.OAM_Row[Row1] >= DSP4_vars.OAM_RowMax)    {      *draw = 0;    }  }  // emulator fail-safe (unknown if this really exists)  if (DSP4_vars.sprite_count >= 128)  {    *draw = 0;  }  // SR = 0x80  if (*draw)  {    // Row tiles    if (size)    {      DSP4_vars.OAM_Row[Row1] += 2;      DSP4_vars.OAM_Row[Row2] += 2;    }    else    {      DSP4_vars.OAM_Row[Row1]++;    }    // yield OAM output    DSP4_WRITE_WORD(1);    // pack OAM data: x,y,name,attr    DSP4_WRITE_BYTE(sp_x & 0xff);    DSP4_WRITE_BYTE(sp_y & 0xff);    DSP4_WRITE_WORD(sp_attr);    DSP4_vars.sprite_count++;    // OAM: size,msb data    // save post-oam table data for future retrieval    DSP4_vars.OAM_attr[DSP4_vars.OAM_index] |= ((sp_x <0 || sp_x> 255) << DSP4_vars.OAM_bits);    DSP4_vars.OAM_bits++;    DSP4_vars.OAM_attr[DSP4_vars.OAM_index] |= (size << DSP4_vars.OAM_bits);    DSP4_vars.OAM_bits++;    // move to next byte in buffer    if (DSP4_vars.OAM_bits == 16)    {      DSP4_vars.OAM_bits = 0;      DSP4_vars.OAM_index++;    }  }  else if (stop)  {    // yield no OAM output    DSP4_WRITE_WORD(0);  }}//////////////////////////////////////////////////////////////void DSP4_OP0D(){  DSP4.waiting4command = FALSE;  // op flow control  switch (DSP4_vars.DSP4_Logic)  {    case 1:      goto resume1; break;    case 2:      goto resume2; break;  }  ////////////////////////////////////////////////////  // process initial inputs  // sort inputs  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.world_dy = DSP4_READ_DWORD();

⌨️ 快捷键说明

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