dsp4emu.c
来自「linux下的任天堂模拟器代码。供大家参考。」· C语言 代码 · 共 2,173 行 · 第 1/5 页
C
2,173 行
DSP4_vars.world_dx = DSP4_READ_DWORD(); DSP4_vars.distance = DSP4_READ_WORD(); DSP4_READ_WORD(); // 0x0000 DSP4_vars.world_xenv = SEX78(DSP4_READ_WORD()); 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; // 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 current // 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.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 (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; //////////////////////////////////////////////////// // command check // scan next command DSP4.in_count = 2; DSP4_WAIT(1) resume1 : // inspect input DSP4_vars.distance = DSP4_READ_WORD(); // terminate op if (DSP4_vars.distance == -0x8000) break; // already have 2 bytes in queue DSP4.in_count = 6; DSP4_WAIT(2) resume2: // 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); DSP4.waiting4command = TRUE;}//////////////////////////////////////////////////////////////void DSP4_OP0E(){ DSP4_vars.OAM_RowMax = 16; memset(DSP4_vars.OAM_Row, 0, 64);}//////////////////////////////////////////////////////////////void DSP4_OP0F(){ 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; } //////////////////////////////////////////////////// // process initial inputs // 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.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_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; 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; } } ////////////////////////////////////////////////////// // 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 // 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(2) resume2: // check for termination DSP4_vars.distance = DSP4_READ_WORD(); if (DSP4_vars.distance == -0x8000) break; // road splice if( (uint16) DSP4_vars.distance == 0x8001 ) { DSP4.in_count = 6; DSP4_WAIT(3) resume3: 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(2) } // already have 2 bytes in queue DSP4.in_count = 6; DSP4_WAIT(4) resume4 : // 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_OP10(){ 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; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?