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

📄 dsp4emu.c

📁 linux下的任天堂模拟器代码。供大家参考。
💻 C
📖 第 1 页 / 共 5 页
字号:
/*Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )http://www.zsnes.comhttp://sourceforge.net/projects/zsneshttps://zsnes.bountysource.comThis program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseversion 2 as published by the Free Software Foundation.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <string.h>#include "dsp4emu.h"/*Due recognition and credit are given on Overload's DSP website.Thank those contributors for their hard work on this chip.Fixed-point math reminder:[sign, integer, fraction]1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0')1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0')*/#define READ_WORD(s) (*(uint16 *) (s))#define READ_DWORD(s) (*(uint32 *) (s))#define WRITE_WORD(s, d) (*(uint16 *) (s)) = (d)#define WRITE_DWORD(s, d) (*(uint32 *) (s)) = (d)struct DSP4_t DSP4;struct DSP4_vars_t DSP4_vars;//////////////////////////////////////////////////////////////// input protocolstatic int16 DSP4_READ_WORD(){  int16 out;  out = READ_WORD(DSP4.parameters + DSP4.in_index);  DSP4.in_index += 2;  return out;}static int32 DSP4_READ_DWORD(){  int32 out;  out = READ_DWORD(DSP4.parameters + DSP4.in_index);  DSP4.in_index += 4;  return out;}//////////////////////////////////////////////////////////////// output protocol#define DSP4_CLEAR_OUT() \{ DSP4.out_count = 0; DSP4.out_index = 0; }#define DSP4_WRITE_BYTE( d ) \{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count++; }#define DSP4_WRITE_WORD( d ) \{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count += 2; }#ifndef MSB_FIRST#define DSP4_WRITE_16_WORD( d ) \{ memcpy(DSP4.output + DSP4.out_count, ( d ), 32); DSP4.out_count += 32; }#else#define DSP4_WRITE_16_WORD( d )                         \{ int16 *p = ( d ), *end = ( d )+16;                    \  for (; p != end; p++)                                 \  {                                                     \    WRITE_WORD( DSP4.output + DSP4.out_count, *p );     \  }                                                     \  DSP4.out_count += 32;                                 \}#endif#ifdef PRINT_OP#define DSP4_WRITE_DEBUG( x, d ) \  WRITE_WORD( nop + x, d );#endif#ifdef DEBUG_DSP#define DSP4_WRITE_DEBUG( x, d ) \  WRITE_WORD( nop + x, d );#endif//////////////////////////////////////////////////////////////// used to wait for dsp i/o#define DSP4_WAIT( x ) \  DSP4.in_index = 0; DSP4_vars.DSP4_Logic = x; return;//////////////////////////////////////////////////////////////// 1.7.8 -> 1.15.16#define SEX78( a ) ( ( (int32) ( (int16) (a) ) ) << 8 )// 1.15.0 -> 1.15.16#define SEX16( a ) ( ( (int32) ( (int16) (a) ) ) << 16 )#ifdef PRINT_OP#define U16( a ) ( (uint16) ( a ) )#endif#ifdef DEBUG_DSP#define U16( a ) ( (uint16) ( a ) )#endif//////////////////////////////////////////////////////////////// Attention: This lookup table is not verifiedstatic const uint16 div_lut[64] = { 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, 0x1000, 0x0e38,                                    0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, 0x0800, 0x0787, 0x071c, 0x06bc,                                    0x0666, 0x0618, 0x05d1, 0x0590, 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469,                                    0x0444, 0x0421, 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348,                                    0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, 0x02aa, 0x029c,                                    0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, 0x0249, 0x023e, 0x0234, 0x022b,                                    0x0222, 0x0219, 0x0210, 0x0208,  };int16 DSP4_Inverse(int16 value){  // saturate bounds  if (value < 0)  {    value = 0;  }  if (value > 63)  {    value = 63;  }  return div_lut[value];}//////////////////////////////////////////////////////////////// Prototypevoid DSP4_OP0B(bool8 *draw, int16 sp_x, int16 sp_y, int16 sp_attr, bool8 size, bool8 stop);//////////////////////////////////////////////////////////////// OP00void DSP4_Multiply(int16 Multiplicand, int16 Multiplier, int32 *Product){  *Product = (Multiplicand * Multiplier << 1) >> 1;}//////////////////////////////////////////////////////////////void DSP4_OP01(){  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;  }  ////////////////////////////////////////////////////  // 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();  DSP4_vars.world_dx = DSP4_READ_DWORD();  DSP4_vars.distance = DSP4_READ_WORD();  DSP4_READ_WORD(); // 0x0000  DSP4_vars.world_xenv = DSP4_READ_DWORD();  DSP4_vars.world_ddy = DSP4_READ_WORD();  DSP4_vars.world_ddx = DSP4_READ_WORD();  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 + DSP4_vars.world_xenv) >> 16);  DSP4_vars.view_y1 = (int16)(DSP4_vars.world_y >> 16);  DSP4_vars.view_xofs1 = (int16)(DSP4_vars.world_x >> 16);  DSP4_vars.view_yofs1 = DSP4_vars.world_yofs;  DSP4_vars.view_turnoff_x = 0;  DSP4_vars.view_turnoff_dx = 0;  // first DSP4_vars.raster line  DSP4_vars.poly_raster[0][0] = DSP4_vars.poly_bottom[0][0];  do  {    ////////////////////////////////////////////////////    // process one iteration of projection    // perspective projection of world (x,y,scroll) points    // based on the current projection lines    DSP4_vars.view_x2 = (int16)(( ( ( DSP4_vars.world_x + DSP4_vars.world_xenv ) >> 16 ) * DSP4_vars.distance >> 15 ) + ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 ));    DSP4_vars.view_y2 = (int16)((DSP4_vars.world_y >> 16) * DSP4_vars.distance >> 15);    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. World x-location before transformation    // 2. Viewer x-position at the next    // 3. World y-location before perspective projection    // 4. Viewer y-position below the horizon    // 5. Number of DSP4_vars.raster lines drawn in this iteration    DSP4_CLEAR_OUT();    DSP4_WRITE_WORD((uint16)((DSP4_vars.world_x + DSP4_vars.world_xenv) >> 16));    DSP4_WRITE_WORD(DSP4_vars.view_x2);    DSP4_WRITE_WORD((uint16)(DSP4_vars.world_y >> 16));    DSP4_WRITE_WORD(DSP4_vars.view_y2);    //////////////////////////////////////////////////////    // SR = 0x00    // determine # of DSP4_vars.raster lines used    DSP4_vars.segments = DSP4_vars.poly_raster[0][0] - 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 (bg1)        // 2. vertical scroll offset ($210E)        // 3. horizontal scroll offset ($210D)        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;    // add deltas for projection lines    DSP4_vars.world_dx += SEX78(DSP4_vars.world_ddx);    DSP4_vars.world_dy += SEX78(DSP4_vars.world_ddy);    // update projection lines    DSP4_vars.world_x += (DSP4_vars.world_dx + DSP4_vars.world_xenv);    DSP4_vars.world_y += DSP4_vars.world_dy;    // update road turnoff position    DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx;    ////////////////////////////////////////////////////    // command check    // scan next command    DSP4.in_count = 2;    DSP4_WAIT(1) resume1 :    // check for termination    DSP4_vars.distance = DSP4_READ_WORD();    if (DSP4_vars.distance == -0x8000)      break;    // road turnoff    if( (uint16) DSP4_vars.distance == 0x8001 )    {      DSP4.in_count = 6;      DSP4_WAIT(2) resume2:      DSP4_vars.distance = DSP4_READ_WORD();      DSP4_vars.view_turnoff_x = DSP4_READ_WORD();      DSP4_vars.view_turnoff_dx = DSP4_READ_WORD();      // factor in new changes      DSP4_vars.view_x1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 );      DSP4_vars.view_xofs1 += ( DSP4_vars.view_turnoff_x * DSP4_vars.distance >> 15 );      // update stepping values      DSP4_vars.view_turnoff_x += DSP4_vars.view_turnoff_dx;      DSP4.in_count = 2;      DSP4_WAIT(1)    }    // already have 2 bytes read    DSP4.in_count = 6;    DSP4_WAIT(3) resume3 :    // inspect inputs    DSP4_vars.world_ddy = DSP4_READ_WORD();    DSP4_vars.world_ddx = DSP4_READ_WORD();    DSP4_vars.view_yofsenv = DSP4_READ_WORD();    // no envelope here    DSP4_vars.world_xenv = 0;  }  while (1);  // terminate op  DSP4.waiting4command = TRUE;}//////////////////////////////////////////////////////////////void DSP4_OP03(){  DSP4_vars.OAM_RowMax = 33;  memset(DSP4_vars.OAM_Row, 0, 64);}//////////////////////////////////////////////////////////////void DSP4_OP05(){  DSP4_vars.OAM_index = 0;  DSP4_vars.OAM_bits = 0;  memset(DSP4_vars.OAM_attr, 0, 32);  DSP4_vars.sprite_count = 0;}//////////////////////////////////////////////////////////////void DSP4_OP06(){  DSP4_CLEAR_OUT();  DSP4_WRITE_16_WORD(DSP4_vars.OAM_attr);}//////////////////////////////////////////////////////////////void DSP4_OP07(){  DSP4.waiting4command = FALSE;  // op flow control  switch (DSP4_vars.DSP4_Logic)  {    case 1:      goto resume1; break;    case 2:      goto resume2; break;  }  ////////////////////////////////////////////////////  // sort inputs  DSP4_vars.world_y = DSP4_READ_DWORD();  DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD();

⌨️ 快捷键说明

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