diff options
Diffstat (limited to 'source/dsp4emu.c')
-rw-r--r-- | source/dsp4emu.c | 1227 |
1 files changed, 0 insertions, 1227 deletions
diff --git a/source/dsp4emu.c b/source/dsp4emu.c deleted file mode 100644 index da6e80f..0000000 --- a/source/dsp4emu.c +++ /dev/null @@ -1,1227 +0,0 @@ -#include "../copyright" - -#include "dsp4.h" -#include "memmap.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 - -int32_t DSP4_Multiply(int16_t Multiplicand, int16_t Multiplier) -{ - return Multiplicand * Multiplier; -} - -int16_t DSP4_UnknownOP11(int16_t A, int16_t B, int16_t C, int16_t D) -{ - return ((A * 0x0155 >> 2) & 0xf000) | ((B * 0x0155 >> 6) & 0x0f00) | ((C * 0x0155 >> 10) & 0x00f0) | ((D * 0x0155 >> 14) & 0x000f); -} - -void DSP4_Op06(bool size, bool 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++; - } -} - -void DSP4_Op01(void) -{ - int16_t plane; - int16_t index, lcv; - int16_t py_dy, px_dx; - int16_t y_out, x_out; - uint16_t command; - DSP4.waiting4command = false; - - switch (DSP4_Logic) /* op flow control */ - { - case 1: - goto resume1; - break; - case 2: - goto resume2; - break; - } - - /* - * process initial inputs - */ - - /* sort inputs */ - 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); - 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); - 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; - - /* - * 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); - - /* process one iteration of projection */ - - /* inspect inputs */ - -resume2: - plane = DSP4_READ_WORD(0); - px_dx = 0; - - /* ignore invalid data */ - if((uint16_t) 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 = (int16_t)(project_focaly * project_focaly * -0.20533553 - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (int16_t)(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) - px_dx = ((project_x2 - project_x1) << 8) / segments; /* interpolate between projected points */ - - /* 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); - - index = 10; - - for (lcv = 0; lcv < segments; lcv++) /* iterate through each point */ - { - /* step through the projected line */ - y_out = project_y + ((py_dy * lcv) >> 8); - x_out = project_x + ((px_dx * lcv) >> 8); - - /* 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) /* new positions */ - { - 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_t)DSP4.parameters[3]; - project_pitchx += (int8_t)DSP4.parameters[5]; - - project_focaly += project_pitchy; - project_focalx += project_pitchx; - } while (1); - - /* terminate op */ - DSP4.waiting4command = true; - DSP4.out_count = 0; -} - -void DSP4_Op07(void) -{ - uint16_t command; - int16_t plane; - int16_t index, lcv; - int16_t y_out, x_out; - int16_t py_dy, px_dx; - - DSP4.waiting4command = false; - - /* op flow control */ - switch (DSP4_Logic) - { - case 1: - goto resume1; - break; - case 2: - goto resume2; - break; - } - - /* sort inputs */ - - 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); - - /* 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; - - /* 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); - - /* process one loop of projection */ - -resume2: - px_dx = 0; - - /* inspect inputs */ - plane = DSP4_READ_WORD(0); - project_y2 = DSP4_READ_WORD(2); - project_x2 = DSP4_READ_WORD(6); - - /* ignore invalid data */ - if((uint16_t) plane == 0x8001) - continue; - - /* multi-op storage */ - project_focaly = multi_focaly[multi_index2]; - - /* quadratic regression (rough) */ - if (project_focaly >= -0x0f) - py_dy = (int16_t)(project_focaly * project_focaly * -0.20533553 - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (int16_t)(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; - } - - /* 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); - - 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); - - /* 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; -} - -void DSP4_Op08(void) -{ - uint16_t command; - /* used in envelope shaping */ - int16_t x1_final; - int16_t x2_final; - int16_t plane, x_left, y_left, x_right, y_right; - int16_t envelope1, envelope2; - 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); - - /* 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; - - /* 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 */ - - /* look at guidelines */ - plane = DSP4_READ_WORD(0x00); - x_left = DSP4_READ_WORD(0x02); - y_left = DSP4_READ_WORD(0x04); - x_right = DSP4_READ_WORD(0x06); - y_right = DSP4_READ_WORD(0x08); - - /* envelope guidelines (one frame only) */ - envelope1 = DSP4_READ_WORD(0x0a); - envelope2 = DSP4_READ_WORD(0x0c); - - /* ignore invalid data */ - if((uint16_t) plane == 0x8001) - continue; - - /* first init */ - if (plane == 0x7fff) - { - int32_t 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]; - - path_plane[0] = plane; - path_plane[1] = plane; - - /* initial output */ - DSP4.out_count = 2; - DSP4.output[0] = pos1 & 0xFF; - DSP4.output[1] = pos2 & 0xFF; - } - /* proceed with projection */ - else - { - int16_t index = 0, lcv; - int16_t left_inc = 0, right_inc = 0; - int16_t 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; - } - - /* zone 1 */ - DSP4.out_count = (2 + 4 * segments); - DSP4_WRITE_WORD(index, segments); - index += 2; - - for (lcv = 1; lcv <= segments; lcv++) - { - int16_t 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]; - - /* 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_t 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_t 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]; - - /* 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_t 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); -} - -void DSP4_Op0D(void) -{ - uint16_t command; - /* inspect inputs */ - int16_t plane; - int16_t index, lcv; - int16_t py_dy, px_dx; - int16_t y_out, x_out; - - DSP4.waiting4command = false; - - /* op flow control */ - switch (DSP4_Logic) - { - case 1: - goto resume1; - break; - case 2: - goto resume2; - break; - } - - /* process initial inputs */ - - /* sort inputs */ - 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); - 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); - - /* 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; - - /* 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); - - /* project section of the track */ - -resume2: - plane = DSP4_READ_WORD(0); - px_dx = 0; - - - /* ignore invalid data */ - if((uint16_t) plane == 0x8001) - continue; - - /* one-time init */ - if (far_plane) - { - /* setup final data */ - 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 = (int16_t)(project_focaly * project_focaly * -0.20533553 - 1.08330005 * project_focaly - 69.61094639); - else - py_dy = (int16_t)(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; - } - - /* 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); - index = 10; - - for (lcv = 0; lcv < segments; lcv++) /* iterate through each point */ - { - /* step through the projected line */ - y_out = project_y + ((py_dy * lcv) >> 8); - x_out = project_x + ((px_dx * lcv) >> 8); - - /* 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_t)DSP4.parameters[3]; - project_pitchx += (int8_t)DSP4.parameters[5]; - - project_focaly += project_pitchy; - project_focalx += project_pitchx; - } while (1); - - DSP4.waiting4command = true; - DSP4.out_count = 0; -} - -void DSP4_Op09(void) -{ - uint16_t command; - bool clip; - int16_t sp_x, sp_y, sp_oam, sp_msb; - int16_t sp_dx, sp_dy; - - 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 */ - - /* grab screen information */ - view_plane = PLANE_START; - center_x = DSP4_READ_WORD(0x00); - center_y = DSP4_READ_WORD(0x02); - viewport_left = DSP4_READ_WORD(0x06); - viewport_right = DSP4_READ_WORD(0x08); - viewport_top = DSP4_READ_WORD(0x0a); - viewport_bottom = DSP4_READ_WORD(0x0c); - - /* expand viewport dimensions */ - viewport_left -= 8; - - /* cycle through viewport window data */ - multi_index1++; - multi_index1 %= 4; - - /* convert track line to the window region */ - project_y2 = center_y + multi_raster[multi_index1] * (viewport_bottom - center_y) / (0x33 - 0); - if (!op09_mode) - project_y2 -= 2; - - goto no_sprite; - - do - { - /* check for new sprites */ - do - { - uint16_t 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_t plane; - int16_t car_left, car_right; - int16_t focal_back; - int32_t height; - - /* 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); - focal_back = DSP4_READ_WORD(0x06); - 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; - - /* make the car's x-center available */ - DSP4.out_count = 2; - DSP4_WRITE_WORD(0, project_focalx); - - /* grab a few remaining vehicle values */ - DSP4.in_count = 4; - - DSP4_WAIT(4); - -resume4: /* store final values */ - height = DSP4_READ_WORD(0); - sprite_offset = DSP4_READ_WORD(2); - - /* vertical lift factor */ - sprite_y += height; - } - else if (sprite_type == 2) /* terrain sprite */ - { - int16_t 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_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; - } - - /* default sprite size: 16x16 */ - sprite_size = true; - - /* 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; - 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); - - /* process tile data */ - -resume7: - /* 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; - - /* don't draw offscreen coordinates */ - DSP4.out_count = 0; - if (!clip) - { - int16_t out_index = 0; - int16_t offset = DSP4_READ_WORD(0); - - /* update sprite nametable/attribute information */ - sp_oam = sprite_offset + offset; - sp_msb = (sp_x < 0 || sp_x > 255); - - /* 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, (int8_t) 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, (int8_t) sp_msb); - } - - /* 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; - } - else if (command != 0x00 && command != 0xff) /* special terrain case */ - { - 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; -} |