diff options
Diffstat (limited to 'source/dsp4emu.cpp')
-rw-r--r-- | source/dsp4emu.cpp | 1483 |
1 files changed, 0 insertions, 1483 deletions
diff --git a/source/dsp4emu.cpp b/source/dsp4emu.cpp deleted file mode 100644 index b36cadb..0000000 --- a/source/dsp4emu.cpp +++ /dev/null @@ -1,1483 +0,0 @@ -/******************************************************************************* - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - - (c) Copyright 1996 - 2002 Gary Henderson (gary.henderson@ntlworld.com) and - Jerremy Koot (jkoot@snes9x.com) - - (c) Copyright 2001 - 2004 John Weidman (jweidman@slip.net) - - (c) Copyright 2002 - 2004 Brad Jorsch (anomie@users.sourceforge.net), - funkyass (funkyass@spam.shaw.ca), - Joel Yliluoma (http://iki.fi/bisqwit/) - Kris Bleakley (codeviolation@hotmail.com), - Matthew Kendora, - Nach (n-a-c-h@users.sourceforge.net), - Peter Bortas (peter@bortas.org) and - zones (kasumitokoduck@yahoo.com) - - C4 x86 assembler and some C emulation code - (c) Copyright 2000 - 2003 zsKnight (zsknight@zsnes.com), - _Demo_ (_demo_@zsnes.com), and Nach - - C4 C++ code - (c) Copyright 2003 Brad Jorsch - - DSP-1 emulator code - (c) Copyright 1998 - 2004 Ivar (ivar@snes9x.com), _Demo_, Gary Henderson, - John Weidman, neviksti (neviksti@hotmail.com), - Kris Bleakley, Andreas Naive - - DSP-2 emulator code - (c) Copyright 2003 Kris Bleakley, John Weidman, neviksti, Matthew Kendora, and - Lord Nightmare (lord_nightmare@users.sourceforge.net - - OBC1 emulator code - (c) Copyright 2001 - 2004 zsKnight, pagefault (pagefault@zsnes.com) and - Kris Bleakley - Ported from x86 assembler to C by sanmaiwashi - - SPC7110 and RTC C++ emulator code - (c) Copyright 2002 Matthew Kendora with research by - zsKnight, John Weidman, and Dark Force - - S-DD1 C emulator code - (c) Copyright 2003 Brad Jorsch with research by - Andreas Naive and John Weidman - - S-RTC C emulator code - (c) Copyright 2001 John Weidman - - ST010 C++ emulator code - (c) Copyright 2003 Feather, Kris Bleakley, John Weidman and Matthew Kendora - - Super FX x86 assembler emulator code - (c) Copyright 1998 - 2003 zsKnight, _Demo_, and pagefault - - Super FX C emulator code - (c) Copyright 1997 - 1999 Ivar, Gary Henderson and John Weidman - - - SH assembler code partly based on x86 assembler code - (c) Copyright 2002 - 2004 Marcus Comstedt (marcus@mc.pp.se) - - - Specific ports contains the works of other authors. See headers in - individual files. - - Snes9x homepage: http://www.snes9x.com - - Permission to use, copy, modify and distribute Snes9x in both binary and - source form, for non-commercial purposes, is hereby granted without fee, - providing that this license information and copyright notice appear with - all copies and any derived work. - - This software is provided 'as-is', without any express or implied - warranty. In no event shall the authors be held liable for any damages - arising from the use of this software. - - Snes9x is freeware for PERSONAL USE only. Commercial users should - seek permission of the copyright holders first. Commercial use includes - charging money for Snes9x or software derived from Snes9x. - - The copyright holders request that bug fixes and improvements to the code - should be forwarded to them so everyone can benefit from the modifications - in future versions. - - Super NES and Super Nintendo Entertainment System are trademarks of - Nintendo Co., Limited and its subsidiary companies. -*******************************************************************************/ - -#include "dsp4.h" - -#define DSP4_READ_WORD(x) \ - READ_WORD(DSP4.parameters+x) - -#define DSP4_WRITE_WORD(x,d) \ - WRITE_WORD(DSP4.output+x,d); - -// used to wait for dsp i/o -#define DSP4_WAIT(x) \ - DSP4_Logic = x; return; - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - -void DSP4_Multiply(short Multiplicand, short Multiplier, int &Product) -{ - Product = Multiplicand * Multiplier; -} - -void DSP4_UnknownOP11(short A, short B, short C, short D, short &M) -{ - M = ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | - ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); -} - -////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////// - -void DSP4_Op06(bool8 size, bool8 msb) -{ - // save post-oam table data for future retrieval - op06_OAM[op06_index] |= (msb<<(op06_offset+0)); - op06_OAM[op06_index] |= (size<<(op06_offset+1)); - op06_offset += 2; - - if(op06_offset==8) - { - // move to next byte in buffer - op06_offset=0; - op06_index++; - } -} - -#if OP==0x0001 -#define PRINT -#endif - -void DSP4_Op01() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - // 0x00 = DSP4_READ_WORD(0x00); - project_focaly = DSP4_READ_WORD(0x02); - raster = DSP4_READ_WORD(0x04); - viewport_top = DSP4_READ_WORD(0x06); - project_y = DSP4_READ_WORD(0x08); - viewport_bottom = DSP4_READ_WORD(0x0a); - project_x1low = DSP4_READ_WORD(0x0c); - project_focalx = DSP4_READ_WORD(0x0e); - project_centerx = DSP4_READ_WORD(0x10); - project_ptr = DSP4_READ_WORD(0x12); - // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); - project_pitchylow = DSP4_READ_WORD(0x16); - project_pitchy = DSP4_READ_WORD(0x18); - project_pitchxlow = DSP4_READ_WORD(0x1a); - project_pitchx = DSP4_READ_WORD(0x1c); - far_plane = DSP4_READ_WORD(0x1e); - // ? = DSP4_READ_WORD(0x20); - project_y1low = DSP4_READ_WORD(0x22); - - // pre-compute - view_plane = PLANE_START; - - // find starting projection points - project_x1 = project_focalx; - project_y -= viewport_bottom; - project_x = project_centerx + project_x1; - - // multi-op storage - multi_index1 = 0; - multi_index2 = 0; - - // debug - block=0; - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // check for termination - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 8; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // process one iteration of projection - - // inspect inputs - int16 plane = DSP4_READ_WORD(0); - int16 index, lcv; - int16 py_dy=0, px_dx=0; - int16 y_out, x_out; - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // one-time init - if(far_plane) - { - // setup final parameters - project_focalx += plane; - project_x1 = project_focalx; - project_y1 = project_focaly; - plane = far_plane; - far_plane = 0; - } - - // use proportional triangles to project new coords - project_x2 = project_focalx * plane / view_plane; - project_y2 = project_focaly * plane / view_plane; - - // quadratic regression (rough) - if(project_focaly>=-0x0f) - py_dy = (short) (project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (short) (project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); - - // approximate # of raster lines - segments = abs(project_y2-project_y1); - - // prevent overdraw - if(project_y2>=raster) segments=0; - else raster=project_y2; - - // don't draw outside the window - if(project_y2<viewport_top) segments=0; - - // project new positions - if(segments>0) - { - // interpolate between projected points - px_dx = ((project_x2-project_x1)<<8)/segments; - } - - // debug - ++block; -#ifdef PRINT - printf("(line %d) Op01 check %02X, plane %04X, focal_y %04X, y2 %04X\n",c,(uint16)segments,(uint16)(plane),(uint16)project_focaly,(uint16)project_y2); -#endif - - // prepare output - DSP4.out_count=8+2+6*segments; - - // pre-block data - DSP4_WRITE_WORD(0,project_focalx); - DSP4_WRITE_WORD(2,project_x2); - DSP4_WRITE_WORD(4,project_focaly); - DSP4_WRITE_WORD(6,project_y2); - DSP4_WRITE_WORD(8,segments); - -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); - DSP4_WRITE_WORD(6,-1); - DSP4_WRITE_WORD(8,-1); -#endif - - index=10; - - // iterate through each point - for( lcv=0; lcv<segments; lcv++ ) - { - // step through the projected line - y_out = project_y+((py_dy*lcv)>>8); - x_out = project_x+((px_dx*lcv)>>8); - -#if 0 - project_ptr=-1; - y_out=-1; - x_out=-1; -#endif - - // data - DSP4_WRITE_WORD(index+0,project_ptr); - DSP4_WRITE_WORD(index+2,y_out); - DSP4_WRITE_WORD(index+4,x_out); - index += 6; - - // post-update - project_ptr -= 4; - } - - // post-update - project_y += ((py_dy*lcv)>>8); - project_x += ((px_dx*lcv)>>8); - - // new positions - if(segments>0) - { - project_x1 = project_x2; - project_y1 = project_y2; - - // multi-op storage - multi_focaly[multi_index2++] = project_focaly; - multi_farplane[1] = plane; - multi_raster[1] = project_y1-1; - } - - // update projection points - project_pitchy += (int8)DSP4.parameters[3]; - project_pitchx += (int8)DSP4.parameters[5]; - - project_focaly += project_pitchy; - project_focalx += project_pitchx; - } while (1); - - // terminate op - DSP4.waiting4command = TRUE; - DSP4.out_count = 0; -} - -#undef PRINT - -#if OP==0x0007 -#define PRINT -#endif - -void DSP4_Op07() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - // 0x00 = DSP4_READ_WORD(0x00); - project_focaly = DSP4_READ_WORD(0x02); - raster = DSP4_READ_WORD(0x04); - viewport_top = DSP4_READ_WORD(0x06); - project_y = DSP4_READ_WORD(0x08); - viewport_bottom = DSP4_READ_WORD(0x0a); - project_x1low = DSP4_READ_WORD(0x0c); - project_x1 = DSP4_READ_WORD(0x0e); - project_centerx = DSP4_READ_WORD(0x10); - project_ptr = DSP4_READ_WORD(0x12); - // (envelope?) 0xc0 = DSP4_READ_WORD(0x14); - - // pre-compute - view_plane = PLANE_START; - - // find projection targets - project_y1 = project_focaly; - project_y -= viewport_bottom; - project_x = project_centerx + project_x1; - - // multi-op storage - multi_index2 = 0; - - // debug - block=0; - -#ifdef PRINT - printf("(line %d) Op07 data %04X\n",c,(uint16)project_y1); -#endif - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // check for opcode termination - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 12; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // process one loop of projection - - int16 plane; - int16 index,lcv; - int16 y_out,x_out; - int16 py_dy=0,px_dx=0; - - // debug - ++block; - - // inspect inputs - plane = DSP4_READ_WORD(0); - project_y2 = DSP4_READ_WORD(2); - // ? = DSP4_READ_WORD(4); - project_x2 = DSP4_READ_WORD(6); - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // multi-op storage - project_focaly = multi_focaly[multi_index2]; - - // quadratic regression (rough) - if(project_focaly>=-0x0f) - py_dy = (short) (project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (short) (project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); - - // approximate # of raster lines - segments = abs(project_y2-project_y1); - - // prevent overdraw - if(project_y2>=raster) segments=0; - else raster=project_y2; - - // don't draw outside the window - if(project_y2<viewport_top) segments=0; - - // project new positions - if(segments>0) - { - // interpolate between projected points - px_dx = ((project_x2-project_x1)<<8)/segments; - } - -#ifdef PRINT - printf("(line %d) Op07 block %d, loc %04X, out %02X, project_x2 %04X\n",c,block,plane,segments,(uint16)project_x2); -#endif - - // prepare pre-output - DSP4.out_count=4+2+6*segments; - - DSP4_WRITE_WORD(0,project_x2); - DSP4_WRITE_WORD(2,project_y2); - DSP4_WRITE_WORD(4,segments); - -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); -#endif - - index=6; - for( lcv=0; lcv<segments; lcv++ ) - { - // pre-compute - y_out = project_y+((py_dy*lcv)>>8); - x_out = project_x+((px_dx*lcv)>>8); - -#if 0 - project_ptr = -1; - //y_out = -1; - x_out = -1; -#endif - - // data - DSP4_WRITE_WORD(index+0,project_ptr); - DSP4_WRITE_WORD(index+2,y_out); - DSP4_WRITE_WORD(index+4,x_out); - index += 6; - - // post-update - project_ptr -= 4; - } - - // update internal variables - project_y += ((py_dy*lcv)>>8); - project_x += ((px_dx*lcv)>>8); - - // new positions - if(segments>0) - { - project_x1 = project_x2; - project_y1 = project_y2; - - // multi-op storage - multi_index2++; - } - } while(1); - - DSP4.waiting4command = TRUE; - DSP4.out_count = 0; -} - -#undef PRINT - -#if OP==0x0008 -#define PRINT -#endif - -void DSP4_Op08() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // clip values - path_clipRight[0] = DSP4_READ_WORD(0x00); - path_clipRight[1] = DSP4_READ_WORD(0x02); - path_clipRight[2] = DSP4_READ_WORD(0x04); - path_clipRight[3] = DSP4_READ_WORD(0x06); - - path_clipLeft[0] = DSP4_READ_WORD(0x08); - path_clipLeft[1] = DSP4_READ_WORD(0x0a); - path_clipLeft[2] = DSP4_READ_WORD(0x0c); - path_clipLeft[3] = DSP4_READ_WORD(0x0e); - - // unknown (constant) - // unknown (constant) - - // path positions - path_pos[0] = DSP4_READ_WORD(0x20); - path_pos[1] = DSP4_READ_WORD(0x22); - path_pos[2] = DSP4_READ_WORD(0x24); - path_pos[3] = DSP4_READ_WORD(0x26); - - // data locations - path_ptr[0] = DSP4_READ_WORD(0x28); - path_ptr[1] = DSP4_READ_WORD(0x2a); - path_ptr[2] = DSP4_READ_WORD(0x2c); - path_ptr[3] = DSP4_READ_WORD(0x2e); - - // project_y1 lines - path_raster[0] = DSP4_READ_WORD(0x30); - path_raster[1] = DSP4_READ_WORD(0x32); - path_raster[2] = DSP4_READ_WORD(0x34); - path_raster[3] = DSP4_READ_WORD(0x36); - - // viewport_top - path_top[0] = DSP4_READ_WORD(0x38); - path_top[1] = DSP4_READ_WORD(0x3a); - path_top[2] = DSP4_READ_WORD(0x3c); - path_top[3] = DSP4_READ_WORD(0x3e); - - // unknown (constants) - - view_plane = PLANE_START; - - // debug - block=0; - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // terminate op - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 18; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // projection begins - - // debug - ++block; - - // used in envelope shaping - int16 x1_final; - int16 x2_final; - - // look at guidelines - int16 plane = DSP4_READ_WORD(0x00); - int16 x_left = DSP4_READ_WORD(0x02); - int16 y_left = DSP4_READ_WORD(0x04); - int16 x_right = DSP4_READ_WORD(0x06); - int16 y_right = DSP4_READ_WORD(0x08); - - // envelope guidelines (one frame only) - int16 envelope1 = DSP4_READ_WORD(0x0a); - int16 envelope2 = DSP4_READ_WORD(0x0c); - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // first init - if(plane == 0x7fff) - { - int pos1,pos2; - - // initialize projection - path_x[0] = x_left; - path_x[1] = x_right; - - path_y[0] = y_left; - path_y[1] = y_right; - - // update coordinates - path_pos[0]-=x_left; - path_pos[1]-=x_left; - path_pos[2]-=x_right; - path_pos[3]-=x_right; - - pos1 = path_pos[0]+envelope1; - pos2 = path_pos[1]+envelope2; - - // clip offscreen data - if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0]; - if(pos1>path_clipRight[0]) pos1 = path_clipRight[0]; - if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1]; - if(pos2>path_clipRight[1]) pos2 = path_clipRight[1]; - -#if 0 - pos1=-1; - //pos2=-1; -#endif - - path_plane[0] = plane; - path_plane[1] = plane; - - // initial output - DSP4.out_count = 2; - DSP4.output[0]=pos1&0xFF; - DSP4.output[1]=pos2&0xFF; - -#ifdef PRINT - printf("(line %d) Op08 x_left %04X\n",c,(uint16)x_left); -#endif - } - // proceed with projection - else - { - int16 index=0, lcv; - int16 left_inc=0,right_inc=0; - int16 dx1=0,dx2=0,dx3,dx4; - - // # segments to traverse - segments = abs(y_left - path_y[0]); - - // prevent overdraw - if(y_left>=path_raster[0]) segments=0; - else path_raster[0]=y_left; - - // don't draw outside the window - if(path_raster[0]<path_top[0]) segments=0; - - // proceed if visibility rules apply - if(segments>0) - { - // use previous data - dx1 = (envelope1 * path_plane[0] / view_plane); - dx2 = (envelope2 * path_plane[0] / view_plane); - - // use temporary envelope pitch (this frame only) - dx3 = (envelope1 * plane / view_plane); - dx4 = (envelope2 * plane / view_plane); - - // project new shapes (left side) - x1_final = x_left+dx1; - x2_final = path_x[0]+dx3; - - // interpolate between projected points with shaping - left_inc = ((x2_final-x1_final)<<8)/segments; - - // project new shapes (right side) - x1_final = x_left+dx2; - x2_final = path_x[0]+dx4; - - // interpolate between projected points with shaping - right_inc = ((x2_final-x1_final)<<8)/segments; - - path_plane[0] = plane; - } - -#ifdef PRINT - printf("(line %d) Op08 block %d, out %02X, raster %02X\n",c,block,segments,(uint16)y_left); -#endif - - // zone 1 - DSP4.out_count = (2+4*segments); - DSP4_WRITE_WORD(index,segments); index+=2; - - for( lcv=1; lcv<=segments; lcv++ ) - { - int16 pos1,pos2; - - // pre-compute - pos1 = path_pos[0]+((left_inc*lcv)>>8)+dx1; - pos2 = path_pos[1]+((right_inc*lcv)>>8)+dx2; - - // clip offscreen data - if(pos1<path_clipLeft[0]) pos1 = path_clipLeft[0]; - if(pos1>path_clipRight[0]) pos1 = path_clipRight[0]; - if(pos2<path_clipLeft[1]) pos2 = path_clipLeft[1]; - if(pos2>path_clipRight[1]) pos2 = path_clipRight[1]; - -#if 0 - if(pos1==0x00ff) pos1=0; - if(pos2==0x00ff) pos2=0; - path_ptr[0] = -1; - pos1 = -1; - pos2 = -1; -#endif - - // data - DSP4_WRITE_WORD(index,path_ptr[0]); index+=2; - DSP4.output[index++]=pos1&0xFF; - DSP4.output[index++]=pos2&0xFF; - - // post-update - path_ptr[0] -= 4; - path_ptr[1] -= 4; - } - lcv--; - - if(segments>0) - { - // project points w/out the envelopes - int16 inc = ((path_x[0]-x_left)<<8)/segments; - - // post-store - path_pos[0] += ((inc*lcv)>>8); - path_pos[1] += ((inc*lcv)>>8); - - path_x[0] = x_left; - path_y[0] = y_left; - } - - ////////////////////////////////////////////// - // zone 2 - segments = abs(y_right - path_y[1]); - - // prevent overdraw - if(y_right>=path_raster[2]) segments=0; - else path_raster[2]=y_right; - - // don't draw outside the window - if(path_raster[2]<path_top[2]) segments=0; - - // proceed if visibility rules apply - if(segments>0) - { - // use previous data - dx1 = (envelope1 * path_plane[1] / view_plane); - dx2 = (envelope2 * path_plane[1] / view_plane); - - // use temporary envelope pitch (this frame only) - dx3 = (envelope1 * plane / view_plane); - dx4 = (envelope2 * plane / view_plane); - - // project new shapes (left side) - x1_final = x_left+dx1; - x2_final = path_x[1]+dx3; - - // interpolate between projected points with shaping - left_inc = ((x2_final-x1_final)<<8)/segments; - - // project new shapes (right side) - x1_final = x_left+dx2; - x2_final = path_x[1]+dx4; - - // interpolate between projected points with shaping - right_inc = ((x2_final-x1_final)<<8)/segments; - - path_plane[1] = plane; - } - - // write out results - DSP4.out_count += (2+4*segments); - DSP4_WRITE_WORD(index,segments); index+=2; - - for( lcv=1; lcv<=segments; lcv++ ) - { - int16 pos1,pos2; - - // pre-compute - pos1 = path_pos[2]+((left_inc*lcv)>>8)+dx1; - pos2 = path_pos[3]+((right_inc*lcv)>>8)+dx2; - - // clip offscreen data - if(pos1<path_clipLeft[2]) pos1 = path_clipLeft[2]; - if(pos1>path_clipRight[2]) pos1 = path_clipRight[2]; - if(pos2<path_clipLeft[3]) pos2 = path_clipLeft[3]; - if(pos2>path_clipRight[3]) pos2 = path_clipRight[3]; - -#if 0 - if(pos1==0x00ff) pos1=0; - if(pos2==0x00ff) pos2=0; - path_ptr[2] = -1; - //pos1 = -1; - pos2 = -1; -#endif - - // data - DSP4_WRITE_WORD(index,path_ptr[2]); index+=2; - DSP4.output[index++]=pos1&0xFF; - DSP4.output[index++]=pos2&0xFF; - - // post-update - path_ptr[2] -= 4; - path_ptr[3] -= 4; - } - lcv--; - - if(segments>0) - { - // project points w/out the envelopes - int16 inc = ((path_x[1]-x_right)<<8)/segments; - - // post-store - path_pos[2] += ((inc*lcv)>>8); - path_pos[3] += ((inc*lcv)>>8); - - path_x[1] = x_right; - path_y[1] = y_right; - } - } - } while(1); - - DSP4.waiting4command = TRUE; - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,0); -} - -#undef PRINT - -#if OP==0x000D -#define PRINT -#endif - -void DSP4_Op0D() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(DSP4_Logic) { - case 1: goto resume1; break; - case 2: goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - // 0x00 = DSP4_READ_WORD(0x00); - project_focaly = DSP4_READ_WORD(0x02); - raster = DSP4_READ_WORD(0x04); - viewport_top = DSP4_READ_WORD(0x06); - project_y = DSP4_READ_WORD(0x08); - viewport_bottom = DSP4_READ_WORD(0x0a); - project_x1low = DSP4_READ_WORD(0x0c); - project_x1 = DSP4_READ_WORD(0x0e); - project_focalx = DSP4_READ_WORD(0x0e); - project_centerx = DSP4_READ_WORD(0x10); - project_ptr = DSP4_READ_WORD(0x12); - // 0xc0 = DSP4_READ_WORD(0x14); - project_pitchylow = DSP4_READ_WORD(0x16); - project_pitchy = DSP4_READ_WORD(0x18); - project_pitchxlow = DSP4_READ_WORD(0x1a); - project_pitchx = DSP4_READ_WORD(0x1c); - far_plane = DSP4_READ_WORD(0x1e); - // ? = DSP4_READ_WORD(0x20); - - // multi-op storage - multi_index1++; - multi_index1%=4; - - // remap 0D->09 window data ahead of time - // index starts at 1-3,0 - // - // Op0D: BL,TL,BR,TR - // Op09: TL,TR,BL,BR (1,2,3,0) - switch(multi_index1) - { - case 1: multi_index2=3; break; - case 2: multi_index2=1; break; - case 3: multi_index2=0; break; - case 0: multi_index2=2; break; - } - - // pre-compute - view_plane = PLANE_START; - - // figure out projection data - project_y -= viewport_bottom; - project_x = project_centerx + project_x1; - - // debug - block=0; - - //////////////////////////////////////////////////// - // command check - - do { - // scan next command - DSP4.in_count = 2; - - DSP4_WAIT(1) resume1: - - // inspect input - command = DSP4_READ_WORD(0); - - // terminate op - if(command == 0x8000) break; - - // already have 2 bytes in queue - DSP4.in_index = 2; - DSP4.in_count = 8; - - DSP4_WAIT(2) resume2: - - //////////////////////////////////////////////////// - // project section of the track - - // inspect inputs - int16 plane = DSP4_READ_WORD(0); - int16 index, lcv; - int16 py_dy=0, px_dx=0; - int16 y_out, x_out; - - // ignore invalid data - if((uint16) plane == 0x8001) continue; - - // one-time init - if(far_plane) - { - // setup final data - // low16=plane - project_x1 = project_focalx; - project_y1 = project_focaly; - plane = far_plane; - far_plane = 0; - } - - // use proportional triangles to project new coords - project_x2 = project_focalx * plane / view_plane; - project_y2 = project_focaly * plane / view_plane; - - // quadratic regression (rough) - if(project_focaly>=-0x0f) - py_dy = (short) (project_focaly * project_focaly * -0.20533553 - - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (short) (project_focaly * project_focaly * -0.000657035759 - - 1.07629051 * project_focaly - 65.69315963); - - // approximate # of raster lines - segments = abs(project_y2-project_y1); - - // prevent overdraw - if(project_y2>=raster) segments=0; - else raster=project_y2; - - // don't draw outside the window - if(project_y2<viewport_top) segments=0; - - // project new positions - if(segments>0) - { - // interpolate between projected points - px_dx = ((project_x2-project_x1)<<8)/segments; - } - - // debug - ++block; - -#ifdef PRINT - printf("(line %d) Op0D check %02X, plane %04X\n",c,(uint16)segments,(uint16)(plane)); -#endif - - // prepare output - DSP4.out_count=8+2+6*segments; - - DSP4_WRITE_WORD(0,project_focalx); - DSP4_WRITE_WORD(2,project_x2); - DSP4_WRITE_WORD(4,project_focaly); - DSP4_WRITE_WORD(6,project_y2); - DSP4_WRITE_WORD(8,segments); -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); - DSP4_WRITE_WORD(6,-1); - DSP4_WRITE_WORD(8,-1); -#endif - - index=10; - - // iterate through each point - for( lcv=0; lcv<segments; lcv++ ) - { - // step through the projected line - y_out = project_y+((py_dy*lcv)>>8); - x_out = project_x+((px_dx*lcv)>>8); - -#if 0 - project_ptr=-1; - //y_out=-1; - x_out=-1; -#endif - - // data - DSP4_WRITE_WORD(index+0,project_ptr); - DSP4_WRITE_WORD(index+2,y_out); - DSP4_WRITE_WORD(index+4,x_out); - index += 6; - - // post-update - project_ptr -= 4; - } - - // post-update - project_y += ((py_dy*lcv)>>8); - project_x += ((px_dx*lcv)>>8); - - if(segments > 0) - { - project_x1 = project_x2; - project_y1 = project_y2; - - // multi-op storage - multi_farplane[multi_index2] = plane; - multi_raster[multi_index2] = project_y1; - } - - // update focal projection points - project_pitchy += (int8)DSP4.parameters[3]; - project_pitchx += (int8)DSP4.parameters[5]; - - project_focaly += project_pitchy; - project_focalx += project_pitchx; - } while(1); - - DSP4.waiting4command = TRUE; - DSP4.out_count = 0; -} - -#undef PRINT - -#if OP==0x0009 -#define PRINT -#endif - -#if OP==0x0006 -#define PRINT -#endif - -void DSP4_Op09() -{ - uint16 command; - - DSP4.waiting4command = FALSE; - - // op flow control - switch(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; - case 7: goto resume7; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // debug - block=0; - - // grab screen information - view_plane = PLANE_START; - center_x = DSP4_READ_WORD(0x00); - center_y = DSP4_READ_WORD(0x02); - // 0x00 = DSP4_READ_WORD(0x04); - viewport_left = DSP4_READ_WORD(0x06); - viewport_right = DSP4_READ_WORD(0x08); - viewport_top = DSP4_READ_WORD(0x0a); - viewport_bottom = DSP4_READ_WORD(0x0c); - -#ifdef PRINT2 - printf("Window: (%04X,%04X) (%04X,%04X)\n", - viewport_left,viewport_right,viewport_top,viewport_bottom); -#endif - - // expand viewport dimensions - viewport_left -= 8; - - // cycle through viewport window data - multi_index1++; - multi_index1%=4; - -#if 1 - // convert track line to the window region - project_y2 = center_y + multi_raster[multi_index1] * - (viewport_bottom-center_y)/(0x33-0); - if(op09_mode==0) project_y2 -= 2; -#endif - - goto no_sprite; - - do { - //////////////////////////////////////////////////// - // check for new sprites - - do { - uint16 second; - - DSP4.in_count = 4; - DSP4.in_index = 2; - - DSP4_WAIT(1) resume1: - - // try to classify sprite - second = DSP4_READ_WORD(2); - - // op termination - if(second == 0x8000) goto terminate; - - second >>= 8; - sprite_type = 0; - - // vehicle sprite - if(second == 0x90) - { - sprite_type = 1; - break; - } - // terrain sprite - else if(second != 0) - { - sprite_type = 2; - break; - } - -no_sprite: - // no sprite. try again - - DSP4.in_count = 2; - - DSP4_WAIT(2) resume2: - ; - } while (1); - - //////////////////////////////////////////////////// - // process projection information - -sprite_found: - // vehicle sprite - if(sprite_type == 1) - { - int16 plane; - int16 car_left, car_right, car_left_a; - int16 focal_back, focal_front; - uint8 distance, id; - - // we already have 4 bytes we want - DSP4.in_count = 6+12; - DSP4.in_index = 4; - - DSP4_WAIT(3) resume3: - - // filter inputs - project_y1 = DSP4_READ_WORD(0x00); - // 0x9000 = DSP4_READ_WORD(0x02); - id = DSP4.parameters[0x04]; - distance = DSP4.parameters[0x05]; - focal_back = DSP4_READ_WORD(0x06); - focal_front = DSP4_READ_WORD(0x08); - car_left_a = DSP4_READ_WORD(0x0a); - car_left = DSP4_READ_WORD(0x0c); - plane = DSP4_READ_WORD(0x0e); - car_right = DSP4_READ_WORD(0x10); - - // calculate car's x-center - project_focalx = car_right-car_left; - - // determine how far into the screen to project - project_focaly = focal_back; - project_x = project_focalx * plane / view_plane; - segments = 0x33 - project_focaly * plane / view_plane; - far_plane = plane; - - // prepare memory - sprite_x = center_x+project_x; - sprite_y = viewport_bottom-segments; - far_plane = plane; - - // debug - ++block; -#ifdef PRINT - printf("(line %d) Op09 vehicle block %d, Loop %04X\n",c,block,(uint16)project_y1); - //printf("%04X %04X %04X %04X / ",focal_back,focal_front,car_left_a,car_left); - //printf("%02X %02X ", distance, id); -#endif - - // make the car's x-center available - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,project_focalx); - -#if 0 - DSP4_WRITE_WORD(0,-1); -#endif - - // grab a few remaining vehicle values - DSP4.in_count = 4; - - DSP4_WAIT(4) resume4: - - // store final values - int height = DSP4_READ_WORD(0); - sprite_offset = DSP4_READ_WORD(2); - - // vertical lift factor - sprite_y += height; - -#ifdef PRINT_09 - printf("%04X\n",sprite_offset); -#endif - } - // terrain sprite - else if(sprite_type == 2) - { - int16 plane; - - // we already have 4 bytes we want - DSP4.in_count = 6+6+2; - DSP4.in_index = 4; - - DSP4_WAIT(5) resume5: - - // sort loop inputs - project_y1 = DSP4_READ_WORD(0x00); - plane = DSP4_READ_WORD(0x02); - project_centerx = DSP4_READ_WORD(0x04); - //project_y1 = DSP4_READ_WORD(0x06); - project_focalx = DSP4_READ_WORD(0x08); - project_focaly = DSP4_READ_WORD(0x0a); - sprite_offset = DSP4_READ_WORD(0x0c); - - // determine distances into virtual world - segments = 0x33 - project_y1; - project_x = project_focalx * plane / view_plane; - project_y = project_focaly * plane / view_plane; - - // prepare memory - sprite_x = center_x+project_x-project_centerx; - sprite_y = viewport_bottom-segments+project_y; - far_plane = plane; - - // debug - ++block; -#ifdef PRINT - printf("(line %d) Op09 terrain block %d, Loop %04X\n",c,block,(uint16)project_y1); -#endif - } - - // default sprite size: 16x16 - sprite_size = 1; - - //////////////////////////////////////////////////// - // convert tile data to OAM - - do { - DSP4.in_count = 2; - - DSP4_WAIT(6) resume6: - - command = DSP4_READ_WORD(0); - - // opcode termination - if(command == 0x8000) goto terminate; - - // toggle sprite size - if(command == 0x0000) - { - sprite_size = !sprite_size; -#ifdef PRINT - printf("TOGGLE=%02X\n",(uint8)sprite_size); -#endif - continue; - } - - // new sprite information - command >>= 8; - if(command != 0x20 && command != 0x40 && - command != 0x60 && command != 0xa0 && - command != 0xc0 && command != 0xe0) - break; - - DSP4.in_count = 6; - DSP4.in_index = 2; - - DSP4_WAIT(7) resume7: - - ///////////////////////////////////// - // process tile data - - bool8 clip; - int16 sp_x, sp_y, sp_oam, sp_msb; - int16 sp_dx, sp_dy; - - // sprite deltas - sp_dy = DSP4_READ_WORD(2); - sp_dx = DSP4_READ_WORD(4); - - // update coordinates - sp_y = sprite_y + sp_dy; - sp_x = sprite_x + sp_dx; - - // reject points outside the clipping window - clip = FALSE; - if(sp_x < viewport_left || sp_x > viewport_right) clip=TRUE; - if(sp_y < viewport_top || sp_y > viewport_bottom) clip=TRUE; - - // track depth sorting - if(far_plane <= multi_farplane[multi_index1] && - sp_y >= project_y2) clip=TRUE; - -#ifdef PRINT2 - printf("(line %d) %04X, %04X, %04X / %04X %04X\n",line, - (uint16)sp_x,(uint16)sp_y,(uint16)far_plane,(uint16)multi_farplane[multi_index1],(uint16)project_y2); -#endif - - // don't draw offscreen coordinates - DSP4.out_count = 0; - if(!clip) - { - int16 out_index = 0; - int16 offset = DSP4_READ_WORD(0); - - // update sprite nametable/attribute information - sp_oam = sprite_offset + offset; - sp_msb = (sp_x<0 || sp_x>255); - -#ifdef PRINT - printf("(line %d) %04X, %04X, %04X, %04X, %04X\n",line, - (uint16)sp_oam,(uint16)sprite_offset,(uint16)offset, - (uint16)sp_x,(uint16)sp_y); -#endif - - // emit transparency information - if( - (sprite_offset&0x08) && - ((sprite_type==1 && sp_y>=0xcc) || - (sprite_type==2 && sp_y>=0xbb)) - ) - { - DSP4.out_count = 6; - - // one block of OAM data - DSP4_WRITE_WORD(0,1); - - // OAM: x,y,tile,no attr - DSP4.output[2] = sp_x&0xFF; - DSP4.output[3] = (sp_y+6)&0xFF; - DSP4_WRITE_WORD(4,0xEE); - - out_index = 6; - - // OAM: size,msb data - DSP4_Op06(sprite_size,(char) sp_msb); - } - - // normal data - DSP4.out_count += 8; - - // one block of OAM data - DSP4_WRITE_WORD(out_index+0,1); - - // OAM: x,y,tile,attr - DSP4.output[out_index+2] = sp_x&0xFF; - DSP4.output[out_index+3] = sp_y&0xFF; - DSP4_WRITE_WORD(out_index+4,sp_oam); - - // no following OAM data - DSP4_WRITE_WORD(out_index+6,0); - - // OAM: size,msb data - DSP4_Op06(sprite_size, (char) sp_msb); - -#if 0 - DSP4_WRITE_WORD(0,-1); - DSP4_WRITE_WORD(2,-1); - DSP4_WRITE_WORD(4,-1); - DSP4_WRITE_WORD(6,-1); - DSP4_WRITE_WORD(8,-1); - DSP4_WRITE_WORD(10,-1); - DSP4_WRITE_WORD(12,-1); -#endif - } - - // no sprite information - if(DSP4.out_count == 0) - { - DSP4.out_count = 2; - DSP4_WRITE_WORD(0,0); - } - } while (1); - - ///////////////////////////////////// - // special cases: plane == 0x0000 - - // special vehicle case - if(command == 0x90) - { - sprite_type = 1; - - // shift bytes - DSP4.parameters[2] = DSP4.parameters[0]; - DSP4.parameters[3] = DSP4.parameters[1]; - DSP4.parameters[0] = 0; - DSP4.parameters[1] = 0; - - goto sprite_found; - } - // special terrain case - else if(command != 0x00 && command != 0xff) - { - sprite_type = 2; - - // shift bytes - DSP4.parameters[2] = DSP4.parameters[0]; - DSP4.parameters[3] = DSP4.parameters[1]; - DSP4.parameters[0] = 0; - DSP4.parameters[1] = 0; - - goto sprite_found; - } - } while (1); - -terminate: - DSP4.waiting4command = TRUE; - DSP4.out_count=0; -} - -#undef PRINT - |