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 + -
显示快捷键?