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