From ed6bd9cd5fe12da683f475e4955260ea45c10ee0 Mon Sep 17 00:00:00 2001 From: "R. Belmont" Date: Sun, 2 Jan 2011 21:59:28 +0000 Subject: [PATCH] Removing no longer needed SNES HLE code [R. Belmont] --- .gitattributes | 5 - src/mame/machine/snesdsp1.c | 1722 -------------------------- src/mame/machine/snesdsp2.c | 412 ------- src/mame/machine/snesdsp3.c | 1113 ----------------- src/mame/machine/snesdsp4.c | 2264 ----------------------------------- src/mame/machine/snesdsp4.h | 100 -- 6 files changed, 5616 deletions(-) delete mode 100644 src/mame/machine/snesdsp1.c delete mode 100644 src/mame/machine/snesdsp2.c delete mode 100644 src/mame/machine/snesdsp3.c delete mode 100644 src/mame/machine/snesdsp4.c delete mode 100644 src/mame/machine/snesdsp4.h diff --git a/.gitattributes b/.gitattributes index e940e581d0d..88c59ed9e24 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3538,11 +3538,6 @@ src/mame/machine/snes7110.c svneol=native#text/plain src/mame/machine/snesbsx.c svneol=native#text/plain src/mame/machine/snescx4.c svneol=native#text/plain src/mame/machine/snescx4.h svneol=native#text/plain -src/mame/machine/snesdsp1.c svneol=native#text/plain -src/mame/machine/snesdsp2.c svneol=native#text/plain -src/mame/machine/snesdsp3.c svneol=native#text/plain -src/mame/machine/snesdsp4.c svneol=native#text/plain -src/mame/machine/snesdsp4.h svneol=native#text/plain src/mame/machine/snesobc1.c svneol=native#text/plain src/mame/machine/snesrtc.c svneol=native#text/plain src/mame/machine/snessdd1.c svneol=native#text/plain diff --git a/src/mame/machine/snesdsp1.c b/src/mame/machine/snesdsp1.c deleted file mode 100644 index c1729f64d61..00000000000 --- a/src/mame/machine/snesdsp1.c +++ /dev/null @@ -1,1722 +0,0 @@ -/*************************************************************************** - - snesdsp1.c - - File to handle emulation of the SNES "DSP-1" add-on chip. - - Original C++ "dsp1emul.cpp" by Andreas Naive - Based on research by Overload, The Dumper, Neviksti and Andreas Naive - MAME/MESS C conversion by R. Belmont - - This is up to date with the source version dated June 2006. - -***************************************************************************/ - -#define dsp1_VERSION 0x0102 - -// The DSP-1 status register has 16 bits, but only -// the upper 8 bits can be accessed from an external device, so all these -// positions are referred to the upper byte (bits D8 to D15) - -enum SrFlags { DRC = 0x04, DRS = 0x10, RQM = 0x80 }; - -// According to Overload's docs, these are the meanings of the flags: -// DRC: The Data Register Control (DRC) bit specifies the data transfer length to and from the host CPU. -// 0: Data transfer to and from the DSP-1 is 16 bits. -// 1: Data transfer to and from the DSP-1 is 8 bits. -// DRS: The Data Register Status (DRS) bit indicates the data transfer status in the case of transfering 16-bit data. -// 0: Data transfer has terminated. -// 1: Data transfer in progress. -// RQM: The Request for Master (RQM) indicates that the DSP1 is requesting host CPU for data read/write. -// 0: Internal Data Register Transfer. -// 1: External Data Register Transfer. - -enum Fsm_Major_State { WAIT_COMMAND, READ_DATA, WRITE_DATA }; -enum Max_Data_Accesses { MAX_READS = 7, MAX_WRITES = 1024 }; - -struct dsp1_Command -{ - void (*callback)(INT16 *, INT16 *); - unsigned int reads; - unsigned int writes; -}; - -struct SharedData -{ - // some RAM variables shared between commands - INT16 MatrixA[3][3]; // attitude matrix A - INT16 MatrixB[3][3]; - INT16 MatrixC[3][3]; - INT16 CentreX, CentreY, CentreZ; // center of projection - INT16 CentreZ_C, CentreZ_E; - INT16 VOffset; // vertical offset of the screen with regard to the centre of projection - INT16 Les, C_Les, E_Les; - INT16 SinAas, CosAas; - INT16 SinAzs, CosAzs; - INT16 SinAZS, CosAZS; - INT16 SecAZS_C1, SecAZS_E1; - INT16 SecAZS_C2, SecAZS_E2; - INT16 Nx, Ny, Nz; // normal vector to the screen (norm 1, points toward the center of projection) - INT16 Gx, Gy, Gz; // center of the screen (global coordinates) - INT16 Hx, Hy; // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) - INT16 Vx, Vy, Vz; // vertical vector of the screen (norm 1, points toward the top of the screen) -}; - -struct _snes_dsp1_state -{ - SharedData shared; - UINT8 Sr; // status register - int SrLowByteAccess; - UINT16 Dr; // "internal" representation of the data register - Fsm_Major_State FsmMajorState; // current major state of the FSM - UINT8 Command; // current command processed by the FSM - UINT8 DataCounter; // #UINT16 read/writes counter used by the FSM - INT16 ReadBuffer[MAX_READS]; - INT16 WriteBuffer[MAX_WRITES]; - UINT8 Freeze; // need explanation? ;) - - - -////////////////////////////////////////////////////////////////// - -// Data ROM, as logged from a DSP-1B with the 0x1f command; -// it contains the tables and constants used by the commands. -// The tables used are: two shift tables (0x022-0x031 and 0x031-0x040 -this last one -// with an error in 0x03c which has survived to all the DSP-1 revisions-); a inverse -// table (used as initial guess) at 0x065-0x0e4; a square root table (used also -// as initial guess) at 0x0e5-0x115; two sin and cos tables (used as nodes to construct -// a interpolation curve) at, respectively, 0x116-0x197 and 0x196-0x215. -// As a curiosity, in the positions 0x21c-0x31c it's contained a -// 257-points arccos table that, apparently, have been not used anywhere -// (maybe for the MaxAZS_Exp table?). - - UINT16 DataRom[1024]; -}; - -static struct _snes_dsp1_state dsp1_state; - - -/* Prototypes */ - -static void dsp1_fsm_step(UINT8 read, UINT8 *data); // FSM logic - -// commands -static void dsp1_memory_test(INT16 *input, INT16 *output); -static void dsp1_memory_dump(INT16 *input, INT16 *output); -static void dsp1_memory_size(INT16 *input, INT16 *output); -static void dsp1_multiply(INT16* input, INT16* output); -static void dsp1_multiply2(INT16* input, INT16* output); -static void dsp1_inverse(INT16 *input, INT16 *output); -static void dsp1_triangle(INT16 *input, INT16 *output); -static void dsp1_radius(INT16 *input, INT16 *output); -static void dsp1_range(INT16 *input, INT16 *output); -static void dsp1_range2(INT16 *input, INT16 *output); -static void dsp1_distance(INT16 *input, INT16 *output); -static void dsp1_rotate(INT16 *input, INT16 *output); -static void dsp1_polar(INT16 *input, INT16 *output); -static void dsp1_attitudeA(INT16 *input, INT16 *output); -static void dsp1_attitudeB(INT16 *input, INT16 *output); -static void dsp1_attitudeC(INT16 *input, INT16 *output); -static void dsp1_objectiveA(INT16 *input, INT16 *output); -static void dsp1_objectiveB(INT16 *input, INT16 *output); -static void dsp1_objectiveC(INT16 *input, INT16 *output); -static void dsp1_subjectiveA(INT16 *input, INT16 *output); -static void dsp1_subjectiveB(INT16 *input, INT16 *output); -static void dsp1_subjectiveC(INT16 *input, INT16 *output); -static void dsp1_scalarA(INT16 *input, INT16 *output); -static void dsp1_scalarB(INT16 *input, INT16 *output); -static void dsp1_scalarC(INT16 *input, INT16 *output); -static void dsp1_gyrate(INT16 *input, INT16 *output); -static void dsp1_parameter(INT16 *input, INT16 *output); -static void dsp1_raster(INT16 *input, INT16 *output); -static void dsp1_target(INT16 *input, INT16 *output); -static void dsp1_project(INT16 *input, INT16 *output); - -// auxiliar functions -static INT16 dsp1_sin(INT16 Angle); -static INT16 dsp1_cos(INT16 Angle); -static void inverse(INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent); -static INT16 denormalize_and_clip(INT16 C, INT16 E); -static void normalize(INT16 m, INT16 *Coefficient, INT16 *Exponent); -static void normalize_double(INT32 Product, INT16 *Coefficient, INT16 *Exponent); -static INT16 shiftR(INT16 C, INT16 E); - -// register saves -static void dsp1_register_save(running_machine *machine); - -////////////////////////////////////////////////////////////////// - -// The info on this table follows Overload's docs. - -static const struct dsp1_Command mCommandTable[0x40] = -{ - {&dsp1_multiply, 2, 1}, //0x00 - {&dsp1_attitudeA, 4, 0}, //0x01 - {&dsp1_parameter, 7, 4}, //0x02 - {&dsp1_subjectiveA, 3, 3}, //0x03 - {&dsp1_triangle, 2, 2}, //0x04 - {&dsp1_attitudeA, 4, 0}, //0x01 - {&dsp1_project, 3, 3}, //0x06 - {&dsp1_memory_test, 1, 1}, //0x0f - {&dsp1_radius, 3, 2}, //0x08 - {&dsp1_objectiveA, 3, 3}, //0x0d - {&dsp1_raster, 1, 4}, // 0x0a. This will normally work in continuous mode - {&dsp1_scalarA, 3, 1}, //0x0b - {&dsp1_rotate, 3, 2}, //0x0c - {&dsp1_objectiveA, 3, 3}, //0x0d - {&dsp1_target, 2, 2}, //0x0e - {&dsp1_memory_test, 1, 1}, //0x0f - - {&dsp1_inverse, 2, 2}, //0x10 - {&dsp1_attitudeB, 4, 0}, //0x11 - {&dsp1_parameter, 7, 4}, //0x02 - {&dsp1_subjectiveB, 3, 3}, //0x13 - {&dsp1_gyrate, 6, 3}, //0x14 - {&dsp1_attitudeB, 4, 0}, //0x11 - {&dsp1_project, 3, 3}, //0x06 - {&dsp1_memory_dump, 1, 1024}, //0x1f - {&dsp1_range, 4, 1}, //0x18 - {&dsp1_objectiveB, 3, 3}, //0x1d - {0, 0, 0}, // 0x1a; the chip freezes - {&dsp1_scalarB, 3, 1}, //0x1b - {&dsp1_polar, 6, 3}, //0x1c - {&dsp1_objectiveB, 3, 3}, //0x1d - {&dsp1_target, 2, 2}, //0x0e - {&dsp1_memory_dump, 1, 1024}, //0x1f - - {&dsp1_multiply2, 2, 1}, //0x20 - {&dsp1_attitudeC, 4, 0}, //0x21 - {&dsp1_parameter, 7, 4}, //0x02 - {&dsp1_subjectiveC, 3, 3}, //0x23 - {&dsp1_triangle, 2, 2}, //0x04 - {&dsp1_attitudeC, 4, 0}, //0x21 - {&dsp1_project, 3, 3}, //0x06 - {&dsp1_memory_size, 1, 1}, //0x2f - {&dsp1_distance, 3, 1}, //0x28 - {&dsp1_objectiveC, 3, 3}, //0x2d - {0, 0, 0}, // 0x1a; the chip freezes - {&dsp1_scalarC, 3, 1}, //0x2b - {&dsp1_rotate, 3, 2}, //0x0c - {&dsp1_objectiveC, 3, 3}, //0x2d - {&dsp1_target, 2, 2}, //0x0e - {&dsp1_memory_size, 1, 1}, //0x2f - - {&dsp1_inverse, 2, 2}, //0x10 - {&dsp1_attitudeA, 4, 0}, //0x01 - {&dsp1_parameter, 7, 4}, //0x02 - {&dsp1_subjectiveA, 3, 3}, //0x03 - {&dsp1_gyrate, 6, 3}, //0x14 - {&dsp1_attitudeA, 4, 0}, //0x01 - {&dsp1_project, 3, 3}, //0x06 - {&dsp1_memory_dump, 1, 1024}, //0x1f - {&dsp1_range2, 4, 1}, //0x38 - {&dsp1_objectiveA, 3, 3}, //0x0d - {0, 0, 0}, // 0x1a; the chip freezes - {&dsp1_scalarA, 3, 1}, //0x0b - {&dsp1_polar, 6, 3}, //0x1c - {&dsp1_objectiveA, 3, 3}, //0x0d - {&dsp1_target, 2, 2}, //0x0e - {&dsp1_memory_dump, 1, 1024}, //0x1f -}; - -////////////////////////////////////////////////////////////////// - -static const INT16 dsp1_MaxAZS_Exp[16] = { - 0x38b4, 0x38b7, 0x38ba, 0x38be, 0x38c0, 0x38c4, 0x38c7, 0x38ca, - 0x38ce, 0x38d0, 0x38d4, 0x38d7, 0x38da, 0x38dd, 0x38e0, 0x38e4 -}; - -////////////////////////////////////////////////////////////////// - -static const INT16 dsp1_sin_table[256] = { - 0x0000, 0x0324, 0x0647, 0x096a, 0x0c8b, 0x0fab, 0x12c8, 0x15e2, - 0x18f8, 0x1c0b, 0x1f19, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11, - 0x30fb, 0x33de, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a, - 0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842, - 0x5a82, 0x5cb4, 0x5ed7, 0x60ec, 0x62f2, 0x64e8, 0x66cf, 0x68a6, - 0x6a6d, 0x6c24, 0x6dca, 0x6f5f, 0x70e2, 0x7255, 0x73b5, 0x7504, - 0x7641, 0x776c, 0x7884, 0x798a, 0x7a7d, 0x7b5d, 0x7c29, 0x7ce3, - 0x7d8a, 0x7e1d, 0x7e9d, 0x7f09, 0x7f62, 0x7fa7, 0x7fd8, 0x7ff6, - 0x7fff, 0x7ff6, 0x7fd8, 0x7fa7, 0x7f62, 0x7f09, 0x7e9d, 0x7e1d, - 0x7d8a, 0x7ce3, 0x7c29, 0x7b5d, 0x7a7d, 0x798a, 0x7884, 0x776c, - 0x7641, 0x7504, 0x73b5, 0x7255, 0x70e2, 0x6f5f, 0x6dca, 0x6c24, - 0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f2, 0x60ec, 0x5ed7, 0x5cb4, - 0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4, - 0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33de, - 0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f19, 0x1c0b, - 0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8b, 0x096a, 0x0647, 0x0324, - -0x0000, -0x0324, -0x0647, -0x096a, -0x0c8b, -0x0fab, -0x12c8, -0x15e2, - -0x18f8, -0x1c0b, -0x1f19, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11, - -0x30fb, -0x33de, -0x36ba, -0x398c, -0x3c56, -0x3f17, -0x41ce, -0x447a, - -0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842, - -0x5a82, -0x5cb4, -0x5ed7, -0x60ec, -0x62f2, -0x64e8, -0x66cf, -0x68a6, - -0x6a6d, -0x6c24, -0x6dca, -0x6f5f, -0x70e2, -0x7255, -0x73b5, -0x7504, - -0x7641, -0x776c, -0x7884, -0x798a, -0x7a7d, -0x7b5d, -0x7c29, -0x7ce3, - -0x7d8a, -0x7e1d, -0x7e9d, -0x7f09, -0x7f62, -0x7fa7, -0x7fd8, -0x7ff6, - -0x7fff, -0x7ff6, -0x7fd8, -0x7fa7, -0x7f62, -0x7f09, -0x7e9d, -0x7e1d, - -0x7d8a, -0x7ce3, -0x7c29, -0x7b5d, -0x7a7d, -0x798a, -0x7884, -0x776c, - -0x7641, -0x7504, -0x73b5, -0x7255, -0x70e2, -0x6f5f, -0x6dca, -0x6c24, - -0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f2, -0x60ec, -0x5ed7, -0x5cb4, - -0x5a82, -0x5842, -0x55f5, -0x539b, -0x5133, -0x4ebf, -0x4c3f, -0x49b4, - -0x471c, -0x447a, -0x41ce, -0x3f17, -0x3c56, -0x398c, -0x36ba, -0x33de, - -0x30fb, -0x2e11, -0x2b1f, -0x2826, -0x2528, -0x2223, -0x1f19, -0x1c0b, - -0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324}; - - ////////////////////////////////////////////////////////////////// - -// Optimised for Performance -static const INT16 dsp1_mul_table[256] = { - 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, - 0x0019, 0x001c, 0x001f, 0x0022, 0x0025, 0x0028, 0x002b, 0x002f, - 0x0032, 0x0035, 0x0038, 0x003b, 0x003e, 0x0041, 0x0045, 0x0048, - 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005b, 0x005e, 0x0061, - 0x0064, 0x0067, 0x006a, 0x006d, 0x0071, 0x0074, 0x0077, 0x007a, - 0x007d, 0x0080, 0x0083, 0x0087, 0x008a, 0x008d, 0x0090, 0x0093, - 0x0096, 0x0099, 0x009d, 0x00a0, 0x00a3, 0x00a6, 0x00a9, 0x00ac, - 0x00af, 0x00b3, 0x00b6, 0x00b9, 0x00bc, 0x00bf, 0x00c2, 0x00c5, - 0x00c9, 0x00cc, 0x00cf, 0x00d2, 0x00d5, 0x00d8, 0x00db, 0x00df, - 0x00e2, 0x00e5, 0x00e8, 0x00eb, 0x00ee, 0x00f1, 0x00f5, 0x00f8, - 0x00fb, 0x00fe, 0x0101, 0x0104, 0x0107, 0x010b, 0x010e, 0x0111, - 0x0114, 0x0117, 0x011a, 0x011d, 0x0121, 0x0124, 0x0127, 0x012a, - 0x012d, 0x0130, 0x0133, 0x0137, 0x013a, 0x013d, 0x0140, 0x0143, - 0x0146, 0x0149, 0x014d, 0x0150, 0x0153, 0x0156, 0x0159, 0x015c, - 0x015f, 0x0163, 0x0166, 0x0169, 0x016c, 0x016f, 0x0172, 0x0175, - 0x0178, 0x017c, 0x017f, 0x0182, 0x0185, 0x0188, 0x018b, 0x018e, - 0x0192, 0x0195, 0x0198, 0x019b, 0x019e, 0x01a1, 0x01a4, 0x01a8, - 0x01ab, 0x01ae, 0x01b1, 0x01b4, 0x01b7, 0x01ba, 0x01be, 0x01c1, - 0x01c4, 0x01c7, 0x01ca, 0x01cd, 0x01d0, 0x01d4, 0x01d7, 0x01da, - 0x01dd, 0x01e0, 0x01e3, 0x01e6, 0x01ea, 0x01ed, 0x01f0, 0x01f3, - 0x01f6, 0x01f9, 0x01fc, 0x0200, 0x0203, 0x0206, 0x0209, 0x020c, - 0x020f, 0x0212, 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, - 0x0228, 0x022c, 0x022f, 0x0232, 0x0235, 0x0238, 0x023b, 0x023e, - 0x0242, 0x0245, 0x0248, 0x024b, 0x024e, 0x0251, 0x0254, 0x0258, - 0x025b, 0x025e, 0x0261, 0x0264, 0x0267, 0x026a, 0x026e, 0x0271, - 0x0274, 0x0277, 0x027a, 0x027d, 0x0280, 0x0284, 0x0287, 0x028a, - 0x028d, 0x0290, 0x0293, 0x0296, 0x029a, 0x029d, 0x02a0, 0x02a3, - 0x02a6, 0x02a9, 0x02ac, 0x02b0, 0x02b3, 0x02b6, 0x02b9, 0x02bc, - 0x02bf, 0x02c2, 0x02c6, 0x02c9, 0x02cc, 0x02cf, 0x02d2, 0x02d5, - 0x02d8, 0x02db, 0x02df, 0x02e2, 0x02e5, 0x02e8, 0x02eb, 0x02ee, - 0x02f1, 0x02f5, 0x02f8, 0x02fb, 0x02fe, 0x0301, 0x0304, 0x0307, - 0x030b, 0x030e, 0x0311, 0x0314, 0x0317, 0x031a, 0x031d, 0x0321}; - -////////////////////////////////////////////////////////////////// - -static UINT8 dsp1_get_sr( void ) -{ - dsp1_state.SrLowByteAccess = ~dsp1_state.SrLowByteAccess; - - if (dsp1_state.SrLowByteAccess) - return 0; - else - return dsp1_state.Sr; -} - -////////////////////////////////////////////////////////////////// - -static UINT8 dsp1_get_dr( void ) -{ - UINT8 oDr; - - dsp1_fsm_step(1, &oDr); - return oDr; -} - -////////////////////////////////////////////////////////////////// - -static void dsp1_set_dr( UINT8 iDr ) -{ - dsp1_fsm_step(0, &iDr); -} - -////////////////////////////////////////////////////////////////// - -static void dsp1_init( running_machine *machine ) -{ - UINT32 i; - UINT8 *dspin = machine->region("addons")->base(); - - dsp1_state.Sr = DRC|RQM; - dsp1_state.SrLowByteAccess = FALSE; - dsp1_state.Dr = 0x0080; // Only a supposition. Is this correct? - dsp1_state.Freeze = FALSE; - dsp1_state.FsmMajorState = WAIT_COMMAND; - memset(&dsp1_state.shared, 0, sizeof(struct SharedData)); // another supposition - - // expand the DSP-1 data ROM - for (i = 0; i < 2048; i += 2) - { - dsp1_state.DataRom[i / 2] = (dspin[i] << 8) | dspin[i + 1]; - } - - dsp1_register_save(machine); -} - -////////////////////////////////////////////////////////////////// - -// Though the DSP-1 is unaware of the type of operation (read or write) -// we need to know what is being done by the program, as the class -// is responsible for maintaining the binding between the -// "external" and "internal" representations of the DR (data register). - -static void dsp1_fsm_step( UINT8 read, UINT8 *data ) -{ - if (0 == (dsp1_state.Sr & RQM)) - return; - - // Now RQM would be cleared; however, as this code is not to be used in - // a multithread environment, we will simply fake RQM operation. - // (The only exception would be Op1A's freeze.) - - // binding - if (read) - { - if (dsp1_state.Sr & DRS) - *data = (UINT8)(dsp1_state.Dr >> 8); - else - *data = (UINT8)(dsp1_state.Dr); - } - else - { - if (dsp1_state.Sr & DRS) - { - dsp1_state.Dr &= 0x00ff; - dsp1_state.Dr |= *data << 8; - } - else - { - dsp1_state.Dr &= 0xff00; - dsp1_state.Dr |= *data; - } - } - - - switch (dsp1_state.FsmMajorState) - { - case WAIT_COMMAND: - dsp1_state.Command = (UINT8)(dsp1_state.Dr); - if (!(dsp1_state.Command & 0xc0)) // valid command? - { - switch(dsp1_state.Command) - { - // freeze cases - case 0x1a: - case 0x2a: - case 0x3a: - dsp1_state.Freeze = TRUE; - break; - - // normal cases - default: - dsp1_state.DataCounter = 0; - dsp1_state.FsmMajorState = READ_DATA; - dsp1_state.Sr &= ~DRC; - break; - } - } - break; - - case READ_DATA: - dsp1_state.Sr ^= DRS; - if (!(dsp1_state.Sr & DRS)) - { - dsp1_state.ReadBuffer[dsp1_state.DataCounter++] = (INT16)(dsp1_state.Dr); - if (dsp1_state.DataCounter >= mCommandTable[dsp1_state.Command].reads) - { - (*mCommandTable[dsp1_state.Command].callback)(dsp1_state.ReadBuffer, dsp1_state.WriteBuffer); - if (0 != mCommandTable[dsp1_state.Command].writes) // any output? - { - dsp1_state.DataCounter = 0; - dsp1_state.Dr = (UINT16)(dsp1_state.WriteBuffer[dsp1_state.DataCounter]); - dsp1_state.FsmMajorState = WRITE_DATA; - } - else - { - dsp1_state.Dr = 0x0080; // valid command completion - dsp1_state.FsmMajorState = WAIT_COMMAND; - dsp1_state.Sr |= DRC; - } - } - } - break; - - case WRITE_DATA: - dsp1_state.Sr ^= DRS; - if (!(dsp1_state.Sr & DRS)) - { - ++dsp1_state.DataCounter; - if (dsp1_state.DataCounter >= mCommandTable[dsp1_state.Command].writes) - { - if ((dsp1_state.Command == 0x0a) && (dsp1_state.Dr != 0x8000)) - { - // works in continuous mode - dsp1_state.ReadBuffer[0]++; // next raster line - (*mCommandTable[dsp1_state.Command].callback)(dsp1_state.ReadBuffer, dsp1_state.WriteBuffer); - dsp1_state.DataCounter = 0; - dsp1_state.Dr = (UINT16)(dsp1_state.WriteBuffer[dsp1_state.DataCounter]); - } - else - { - dsp1_state.Dr = 0x0080; // valid command completion - dsp1_state.FsmMajorState = WAIT_COMMAND; - dsp1_state.Sr |= DRC; - } - } - else - { - dsp1_state.Dr = (UINT16)(dsp1_state.WriteBuffer[dsp1_state.DataCounter]); - } - } - break; - } - - - - // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-). - if (dsp1_state.Freeze) - dsp1_state.Sr &= ~RQM; -} - -////////////////////////////////////////////////////////////////// - -static void dsp1_memory_test( INT16 *input, INT16 *output ) -{ -// INT16 *Size = &input[0]; - INT16 *Result = &output[0]; - - *Result = 0x0000; -} - -////////////////////////////////////////////////////////////////// - -static void dsp1_memory_dump( INT16 *input, INT16 *output ) -{ - memcpy(output, dsp1_state.DataRom, 1024); -} - -////////////////////////////////////////////////////////////////// - -static void dsp1_memory_size( INT16 *input, INT16 *output ) -{ - INT16* Size = &output[0]; - - *Size = 0x0100; -} - -////////////////////////////////////////////////////////////////// - -// 16-bit multiplication - -static void dsp1_multiply( INT16 *input, INT16 *output ) -{ - INT16 Multiplicand = input[0]; - INT16 Multiplier = input[1]; - INT16* Product = &output[0]; - - *Product = Multiplicand * Multiplier >> 15; -} - -////////////////////////////////////////////////////////////////// - -// 16-bit multiplication. 'Alternative' method. Can anyone check this carefully? - -static void dsp1_multiply2( INT16 *input, INT16 *output ) -{ - INT16 Multiplicand = input[0]; - INT16 Multiplier = input[1]; - INT16* Product = &output[0]; - - *Product = (Multiplicand * Multiplier >> 15) + 1; -} - -////////////////////////////////////////////////////////////////// - -// This command determines the inverse of a floating point decimal number. - -static void dsp1_inverse( INT16 *input, INT16 *output ) -{ - INT16 Coefficient = input[0]; - INT16 Exponent = input[1]; - INT16* iCoefficient = &output[0]; - INT16* iExponent = &output[1]; - - inverse(Coefficient, Exponent, iCoefficient, iExponent); -} - -////////////////////////////////////////////////////////////////// - -// Vector component calculation. Determines the X and Y components for a -// two-dimensional vector whose size and direction is known. -// Y = Radius * sin(Angle) -// X = Radius * cos(Angle) - -static void dsp1_triangle( INT16 *input, INT16 *output ) -{ - INT16 Angle = input[0]; - INT16 Radius = input[1]; - INT16* Y = &output[0]; - INT16* X = &output[1]; - - *Y = dsp1_sin(Angle) * Radius >> 15; - *X = dsp1_cos(Angle) * Radius >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Determines the squared norm of a vector (X,Y,Z) -// The output is Radius = X^2+Y^2+Z^2 (double integer) - -static void dsp1_radius( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* RadiusLow = &output[0]; - INT16* RadiusHigh = &output[1]; - - INT32 Radius; - - Radius = (X * X + Y * Y + Z * Z) << 1; - *RadiusLow = (INT16)(Radius); - *RadiusHigh = (INT16)(Radius >> 16); -} - -////////////////////////////////////////////////////////////////// - -// Vector size comparison. This command compares the size of the vector (X,Y,Z) and the distance (R) -// from a particular point, and so may be used to determine if a point is within the sphere or radius R. -// The output is D = X^2+Y^2+Z^2-R^2 - -static void dsp1_range( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16 Radius = input[3]; - INT16* Range = &output[0]; - - *Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Vector size comparison. 'Alternative' method. - -static void dsp1_range2( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16 Radius = input[3]; - INT16* Range = &output[0]; - - *Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1; -} - -////////////////////////////////////////////////////////////////// - -// This command calculates the norm of a (X,Y,Z) vector, or the distance from -// the point (X,Y,Z) to (0,0,0), as you prefer to see it. -// Distance = sqrt(X^2+Y^2+Z^2) -// The square root of a number 'a' is calculated by doing this: you -// write 'a' as b*2^2n, with 'b' between 1/4 and 1; then, you calculate -// c=sqrt(b) by using lineal interpolation between points of a -// look-up table and, finally, you output the result as c*2^n. - -static void dsp1_distance( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* Distance = &output[0]; - INT16 Pos, Node1, Node2; - - INT32 Radius = X * X + Y * Y + Z * Z; - - - if (Radius == 0) - Distance = 0; - else - { - INT16 C, E; - normalize_double(Radius, &C, &E); - if (E & 1) - C = C * 0x4000 >> 15; - - Pos = C * 0x0040 >> 15; - - Node1 = dsp1_state.DataRom[0x00d5 + Pos]; - Node2 = dsp1_state.DataRom[0x00d6 + Pos]; - - *Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; - -#if dsp1_VERSION < 0x0102 - if (Pos & 1) - *Distance -= (Node2 - Node1); -#endif - *Distance >>= (E >> 1); - } -} - -////////////////////////////////////////////////////////////////// - -// Determines the (X2, Y2) coordinates obtained by rotating (X1, Y1) -// clockwise for an angle 'Angle'. The official documentation says -// 'counterclockwise', but it's obviously wrong (surprise! :P) -// -// In matrix notation: -// |X2| |cos(Angle) sin(Angle)| |X1| -// | | = | | | | -// |Y2| |-sin(Angle cos(Angle)| |Y1| - -static void dsp1_rotate( INT16 *input, INT16 *output ) -{ - INT16 Angle = input[0]; - INT16 X1 = input[1]; - INT16 Y1 = input[2]; - INT16* X2 = &output[0]; - INT16* Y2 = &output[1]; - - *X2 = (Y1 * dsp1_sin(Angle) >> 15) + (X1 * dsp1_cos(Angle) >> 15); - *Y2 = (Y1 * dsp1_cos(Angle) >> 15) - (X1 * dsp1_sin(Angle) >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Calculate the coordinates (X2, Y2, Z2) obtained when rotating (X1, Y1, Z1) -// three-dimensionally. Rotation is done in the order of Az around the Z axis, -// Ay around the Y axis and Ax around the X axis. As occur with the "attitude" commands -// (see comments in the "gyrate" command), qthis doesn't match what explained in -// the official documentation, but it's coherent with what it is done in the "attitude" -// command (but not with the "gyrate" command). -// -// In matrix notation: -// |X2| |1 0 0 | |cosRy 0 -sinRy| | cosRz sinRz 0| |X1| -// |Y2| = |0 cosRx sinRx| | 0 1 0 | |-sinRz cosRz 0| |Y1| -// |Z2| |0 -sinRx cosRx| |sinRy 0 cosRy| | 0 0 1| |Z1| - -static void dsp1_polar( INT16 *input, INT16 *output ) -{ - INT16 Az = input[0]; - INT16 Ay = input[1]; - INT16 Ax = input[2]; - INT16 X1 = input[3]; - INT16 Y1 = input[4]; - INT16 Z1 = input[5]; - INT16* X2 = &output[0]; - INT16* Y2 = &output[1]; - INT16* Z2 = &output[2]; - - INT16 X, Y, Z; - - // Rotate Around Z - X = (Y1 * dsp1_sin(Az) >> 15) + (X1 * dsp1_cos(Az) >> 15); - Y = (Y1 * dsp1_cos(Az) >> 15) - (X1 * dsp1_sin(Az) >> 15); - X1 = X; Y1 = Y; - - // Rotate Around Y - Z = (X1 * dsp1_sin(Ay) >> 15) + (Z1 * dsp1_cos(Ay) >> 15); - X = (X1 * dsp1_cos(Ay) >> 15) - (Z1 * dsp1_sin(Ay) >> 15); - *X2 = X; Z1 = Z; - - // Rotate Around X - Y = (Z1 * dsp1_sin(Ax) >> 15) + (Y1 * dsp1_cos(Ax) >> 15); - Z = (Z1 * dsp1_cos(Ax) >> 15) - (Y1 * dsp1_sin(Ax) >> 15); - *Y2 = Y; *Z2 = Z; -} - -////////////////////////////////////////////////////////////////// - -// Set up the elements of an "attitude matrix" (there are other ones): -// S | cosRz sinRz 0| |cosRy 0 -sinRy| |1 0 0 | -// MatrixA = - |-sinRz cosRz 0| | 0 1 0 | |0 cosRx sinRx| -// 2 | 0 0 1| |sinRy 0 cosRy| |0 -sinRx cosRx| -// This matrix is thought to be used within the following framework: -// let's suppose we define positive rotations around a system of orthogonal axes in this manner: -// a rotation of +90 degrees around axis3 converts axis2 into axis1 -// a rotation of +90 degrees around axis2 converts axis1 into axis3 -// a rotation of +90 degrees around axis1 converts axis3 into axis2 -// and let's suppose that we have defined a new orthonormal axes system (FLU) -// by doing the following operations about the standard one (XYZ): -// first rotating the XYZ system around Z by an angle Rz (obtaining X'Y'Z'), -// then rotating the resulting system around Y by an angle Ry (obtaining X''Y''Z'') -// and, finally, rotating the resulting system around X by an angle Rx (obtaining FLU) -// This FLU (forward/left/up) system represents an "attitude" and, then, the matrix here defined -// is the change of coordinates matrix that transform coordinates in the FLU -// system (the "object coordinates") into the standard XYZ system (the "global coordinates"), -// multiplied by a scale factor S/2, that is: -// |x| S |f| -// |y| * - = MatrixA * |l| -// |z| 2 |u| -// In a similar way, if we use the transpose of the matrix, we can transform global coordinates -// into object coordinates: -// |f| S |x| -// |l| * - = MatrixA_transposed * |y| -// |u| 2 |z| -// -// input[0]: S -// input[1]: Rz -// input[2]: Ry -// input[3]: Rx - -static void dsp1_attitudeA( INT16 *input, INT16 *output ) -{ - INT16 S = input[0]; - INT16 Rz = input[1]; - INT16 Ry = input[2]; - INT16 Rx = input[3]; - - INT16 SinRz = dsp1_sin(Rz); - INT16 CosRz = dsp1_cos(Rz); - INT16 SinRy = dsp1_sin(Ry); - INT16 CosRy = dsp1_cos(Ry); - INT16 SinRx = dsp1_sin(Rx); - INT16 CosRx = dsp1_cos(Rx); - - S >>= 1; - - dsp1_state.shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15; - dsp1_state.shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - dsp1_state.shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - dsp1_state.shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - dsp1_state.shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - dsp1_state.shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - dsp1_state.shared.MatrixA[2][0] = S * SinRy >> 15; - dsp1_state.shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - dsp1_state.shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'attitudeA', but with a difference attitude matrix (matrixB) - -static void dsp1_attitudeB( INT16 *input, INT16 *output ) -{ - INT16 S = input[0]; - INT16 Rz = input[1]; - INT16 Ry = input[2]; - INT16 Rx = input[3]; - - INT16 SinRz = dsp1_sin(Rz); - INT16 CosRz = dsp1_cos(Rz); - INT16 SinRy = dsp1_sin(Ry); - INT16 CosRy = dsp1_cos(Ry); - INT16 SinRx = dsp1_sin(Rx); - INT16 CosRx = dsp1_cos(Rx); - - S >>= 1; - - dsp1_state.shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15; - dsp1_state.shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - dsp1_state.shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - dsp1_state.shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - dsp1_state.shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - dsp1_state.shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - dsp1_state.shared.MatrixB[2][0] = S * SinRy >> 15; - dsp1_state.shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - dsp1_state.shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'attitudeA', but with a difference attitude matrix (matrixC) - -static void dsp1_attitudeC( INT16 *input, INT16 *output ) -{ - INT16 S = input[0]; - INT16 Rz = input[1]; - INT16 Ry = input[2]; - INT16 Rx = input[3]; - - INT16 SinRz = dsp1_sin(Rz); - INT16 CosRz = dsp1_cos(Rz); - INT16 SinRy = dsp1_sin(Ry); - INT16 CosRy = dsp1_cos(Ry); - INT16 SinRx = dsp1_sin(Rx); - INT16 CosRx = dsp1_cos(Rx); - - S >>= 1; - - dsp1_state.shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15; - dsp1_state.shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - dsp1_state.shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - dsp1_state.shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - dsp1_state.shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - dsp1_state.shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - dsp1_state.shared.MatrixC[2][0] = S * SinRy >> 15; - dsp1_state.shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - dsp1_state.shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Convert global coordinates (X,Y,Z) to object coordinates (F,L,U) -// See the comment in "attitudeA" for a explanation about the calculation. -// -// input[0]: X ; input[1]: Y ; input[2]: Z -// &output[0]: F ; &output[1]: L ; &output[2]: U - -static void dsp1_objectiveA( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* F = &output[0]; - INT16* L = &output[1]; - INT16* U = &output[2]; - - *F = (dsp1_state.shared.MatrixA[0][0] * X >> 15) + (dsp1_state.shared.MatrixA[1][0] * Y >> 15) + (dsp1_state.shared.MatrixA[2][0] * Z >> 15); - *L = (dsp1_state.shared.MatrixA[0][1] * X >> 15) + (dsp1_state.shared.MatrixA[1][1] * Y >> 15) + (dsp1_state.shared.MatrixA[2][1] * Z >> 15); - *U = (dsp1_state.shared.MatrixA[0][2] * X >> 15) + (dsp1_state.shared.MatrixA[1][2] * Y >> 15) + (dsp1_state.shared.MatrixA[2][2] * Z >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'objectiveA', but for the 'B' attitude - -static void dsp1_objectiveB( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* F = &output[0]; - INT16* L = &output[1]; - INT16* U = &output[2]; - - *F = (dsp1_state.shared.MatrixB[0][0] * X >> 15) + (dsp1_state.shared.MatrixB[1][0] * Y >> 15) + (dsp1_state.shared.MatrixB[2][0] * Z >> 15); - *L = (dsp1_state.shared.MatrixB[0][1] * X >> 15) + (dsp1_state.shared.MatrixB[1][1] * Y >> 15) + (dsp1_state.shared.MatrixB[2][1] * Z >> 15); - *U = (dsp1_state.shared.MatrixB[0][2] * X >> 15) + (dsp1_state.shared.MatrixB[1][2] * Y >> 15) + (dsp1_state.shared.MatrixB[2][2] * Z >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'objectiveA', but for the 'C' attitude - -static void dsp1_objectiveC( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* F = &output[0]; - INT16* L = &output[1]; - INT16* U = &output[2]; - - *F = (dsp1_state.shared.MatrixC[0][0] * X >> 15) + (dsp1_state.shared.MatrixC[1][0] * Y >> 15) + (dsp1_state.shared.MatrixC[2][0] * Z >> 15); - *L = (dsp1_state.shared.MatrixC[0][1] * X >> 15) + (dsp1_state.shared.MatrixC[1][1] * Y >> 15) + (dsp1_state.shared.MatrixC[2][1] * Z >> 15); - *U = (dsp1_state.shared.MatrixC[0][2] * X >> 15) + (dsp1_state.shared.MatrixC[1][2] * Y >> 15) + (dsp1_state.shared.MatrixC[2][2] * Z >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Convert object coordinates (F,L,U) to object coordinates (X,Y,Z) -// See the comment in "attitudeA" for a explanation about the calculation. -// -// input[0]: F ; input[1]: L ; input[2]: U -// &output[0]: X ; &output[1]: Y ; &output[2]: Z - -static void dsp1_subjectiveA( INT16 *input, INT16 *output ) -{ - INT16 F = input[0]; - INT16 L = input[1]; - INT16 U = input[2]; - INT16* X = &output[0]; - INT16* Y = &output[1]; - INT16* Z = &output[2]; - - *X = (dsp1_state.shared.MatrixA[0][0] * F >> 15) + (dsp1_state.shared.MatrixA[0][1] * L >> 15) + (dsp1_state.shared.MatrixA[0][2] * U >> 15); - *Y = (dsp1_state.shared.MatrixA[1][0] * F >> 15) + (dsp1_state.shared.MatrixA[1][1] * L >> 15) + (dsp1_state.shared.MatrixA[1][2] * U >> 15); - *Z = (dsp1_state.shared.MatrixA[2][0] * F >> 15) + (dsp1_state.shared.MatrixA[2][1] * L >> 15) + (dsp1_state.shared.MatrixA[2][2] * U >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'subjectiveA', but for the 'B' attitude - -static void dsp1_subjectiveB( INT16 *input, INT16 *output ) -{ - INT16 F = input[0]; - INT16 L = input[1]; - INT16 U = input[2]; - INT16* X = &output[0]; - INT16* Y = &output[1]; - INT16* Z = &output[2]; - - *X = (dsp1_state.shared.MatrixB[0][0] * F >> 15) + (dsp1_state.shared.MatrixB[0][1] * L >> 15) + (dsp1_state.shared.MatrixB[0][2] * U >> 15); - *Y = (dsp1_state.shared.MatrixB[1][0] * F >> 15) + (dsp1_state.shared.MatrixB[1][1] * L >> 15) + (dsp1_state.shared.MatrixB[1][2] * U >> 15); - *Z = (dsp1_state.shared.MatrixB[2][0] * F >> 15) + (dsp1_state.shared.MatrixB[2][1] * L >> 15) + (dsp1_state.shared.MatrixB[2][2] * U >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Same than 'subjectiveA', but for the 'C' attitude - -static void dsp1_subjectiveC(INT16 *input, INT16 *output) -{ - INT16 F = input[0]; - INT16 L = input[1]; - INT16 U = input[2]; - INT16* X = &output[0]; - INT16* Y = &output[1]; - INT16* Z = &output[2]; - - *X = (dsp1_state.shared.MatrixC[0][0] * F >> 15) + (dsp1_state.shared.MatrixC[0][1] * L >> 15) + (dsp1_state.shared.MatrixC[0][2] * U >> 15); - *Y = (dsp1_state.shared.MatrixC[1][0] * F >> 15) + (dsp1_state.shared.MatrixC[1][1] * L >> 15) + (dsp1_state.shared.MatrixC[1][2] * U >> 15); - *Z = (dsp1_state.shared.MatrixC[2][0] * F >> 15) + (dsp1_state.shared.MatrixC[2][1] * L >> 15) + (dsp1_state.shared.MatrixC[2][2] * U >> 15); -} - -////////////////////////////////////////////////////////////////// - -// This command calculates the inner product (S) of a vector (X,Y,Z) and -// the first column of MatrixA. It should be noted that that first column -// represent the global coordinates of an unity vector in the forward -// direction in the object coordinate system (coordinates (1,0,0) in the FLU -// axes system). -// -// input[0]: X ; input[1]: Y ; input[2]: Z -// &output[0]: S - -static void dsp1_scalarA( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* S = &output[0]; - - *S = (X * dsp1_state.shared.MatrixA[0][0] + Y * dsp1_state.shared.MatrixA[1][0] + Z * dsp1_state.shared.MatrixA[2][0]) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'scalarA', but for the 'B' attitude - -static void dsp1_scalarB( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* S = &output[0]; - - *S = (X * dsp1_state.shared.MatrixB[0][0] + Y * dsp1_state.shared.MatrixB[1][0] + Z * dsp1_state.shared.MatrixB[2][0]) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'scalarA', but for the 'C' attitude - -static void dsp1_scalarC( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* S = &output[0]; - - *S = (X * dsp1_state.shared.MatrixC[0][0] + Y * dsp1_state.shared.MatrixC[1][0] + Z * dsp1_state.shared.MatrixC[2][0]) >> 15; -} - -////////////////////////////////////////////////////////////////// - -// This command determines the final attitude angles after the body with attitude angles (Ax, Ay, Az) with -// respect to the global coordinates is rotated by the minor angular displacements (DeltaF, DeltaL, DeltaU). -// It means that the XYZ axes are rotated by (Ax, Ay, Az) to obtain the FLU axes and, then, these -// are rotated by (DeltaF, DeltaL, DeltaU). The command calculates and return the new FLU angles respect to the -// XYZ system (Rx, Ry, Rz) -// The formulae are: -// Rx = Ax + (DeltaU*sin(Ay)+DeltaF*cos(Ay)) -// Ry = Ay + DeltaL - tan(Ax)*(DeltaU*cos(Ay)+DeltaF*sin(Ay)) -// Rz = Az + sec(Ax)*(DeltaU*cos(Ay)-DeltaF*sin(Ay)) -// -// Now the discussion: according to the official documentation, as described in various commands, you pass from -// XYZ to FLU by doing the rotations in the order Y, X, Z. In this command, the formulae are coherent with the -// fact that Y is the first axis to do a rotation around it. However, in the "attitude" command, while the official -// document describe it that way, we have discovered, when reverse engineering the command, that the calculated -// matrix do the rotation around Y in the second place. This incoherent behaviour of various commands is, in my -// opinion, a pretty severe implementation error. However, if you only use small "minor displacements", the error term -// introduced by that incoherence should be almost negligible. - -static void dsp1_gyrate( INT16 *input, INT16 *output ) -{ - INT16 Az = input[0]; - INT16 Ax = input[1]; - INT16 Ay = input[2]; - INT16 U = input[3]; - INT16 F = input[4]; - INT16 L = input[5]; - INT16* Rz = &output[0]; - INT16* Rx = &output[1]; - INT16* Ry = &output[2]; - - INT16 CSec, ESec, CSin, C, E; - INT16 SinAy = dsp1_sin(Ay); - INT16 CosAy = dsp1_cos(Ay); - - inverse(dsp1_cos(Ax), 0, &CSec, &ESec); - - // Rotation Around Z - normalize_double(U * CosAy - F * SinAy, &C, &E); - - E = ESec - E; - - normalize(C * CSec >> 15, &C, &E); - - *Rz = Az + denormalize_and_clip(C, E); - - // Rotation Around X - *Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15); - - // Rotation Around Y - normalize_double(U * CosAy + F * SinAy, &C, &E); - - E = ESec - E; - - normalize(dsp1_sin(Ax), &CSin, &E); - - normalize(-(C * (CSec * CSin >> 15) >> 15), &C, &E); - - *Ry = Ay + denormalize_and_clip(C, E) + L; -} - -////////////////////////////////////////////////////////////////// - - -// Set-up the projection framework. Besides returning some values, it store in RAM some values that -// will be used by the other three projection commands (raster, target an project) -// Input: -// (Fx, Fy, Fz)-> coordinates of base point (global coordinates) -// Lfe-> distance between the base point and the viewpoint (center of projection) -// Les-> distance between the base point and the screen -// Aas-> azimuth angle (0 degrees is east; 90 degrees is north) -// Azs-> zenith angle (0 degrees is zenith) -// Output: -// Vof-> raster line of imaginary center (whatever it means ;) ) -// Vva-> raster line representing the horizon line -// (Cx, Cy)-> coordinates of the projection of the center of the screen over the ground (ground coordinates) - -static void dsp1_parameter( INT16 *input, INT16 *output ) -{ - INT16 Fx = input[0]; - INT16 Fy = input[1]; - INT16 Fz = input[2]; - INT16 Lfe = input[3]; - INT16 Les = input[4]; - INT16 Aas = input[5]; - INT16 Azs = input[6]; - INT16* Vof = &output[0]; - INT16* Vva = &output[1]; - INT16* Cx = &output[2]; - INT16* Cy = &output[3]; - - INT16 CSec, C, E; - INT16 LfeNx, LfeNy, LfeNz; - INT16 LesNx, LesNy, LesNz; - INT16 AZS, MaxAZS; - - // Copy Zenith angle for clipping - AZS = Azs; - - // Store Les and his coefficient and exponent when normalized - dsp1_state.shared.Les = Les; - dsp1_state.shared.E_Les = 0; - normalize(Les, &dsp1_state.shared.C_Les, &dsp1_state.shared.E_Les); - - // Store Sine and Cosine of Azimuth and Zenith angle - dsp1_state.shared.SinAas = dsp1_sin(Aas); - dsp1_state.shared.CosAas = dsp1_cos(Aas); - dsp1_state.shared.SinAzs = dsp1_sin(Azs); - dsp1_state.shared.CosAzs = dsp1_cos(Azs); - - // normal vector to the screen (norm 1, points toward the center of projection) - dsp1_state.shared.Nx = dsp1_state.shared.SinAzs * -dsp1_state.shared.SinAas >> 15; - dsp1_state.shared.Ny = dsp1_state.shared.SinAzs * dsp1_state.shared.CosAas >> 15; - dsp1_state.shared.Nz = dsp1_state.shared.CosAzs * 0x7fff >> 15; - - // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) - dsp1_state.shared.Hx = dsp1_state.shared.CosAas*0x7fff>>15; - dsp1_state.shared.Hy = dsp1_state.shared.SinAas*0x7fff>>15; - - // vertical vector of the screen (norm 1, points toward the top of the screen) - dsp1_state.shared.Vx = dsp1_state.shared.CosAzs * -dsp1_state.shared.SinAas >> 15; - dsp1_state.shared.Vy = dsp1_state.shared.CosAzs * dsp1_state.shared.CosAas >> 15; - dsp1_state.shared.Vz = -dsp1_state.shared.SinAzs * 0x7fff>>15; - - LfeNx = Lfe * dsp1_state.shared.Nx >> 15; - LfeNy = Lfe * dsp1_state.shared.Ny >> 15; - LfeNz = Lfe * dsp1_state.shared.Nz >> 15; - - // Center of Projection - dsp1_state.shared.CentreX = Fx + LfeNx; - dsp1_state.shared.CentreY = Fy + LfeNy; - dsp1_state.shared.CentreZ = Fz + LfeNz; - - LesNx = Les * dsp1_state.shared.Nx >> 15; - LesNy = Les * dsp1_state.shared.Ny >> 15; - LesNz = Les * dsp1_state.shared.Nz >> 15; - - // center of the screen (global coordinates) - dsp1_state.shared.Gx = dsp1_state.shared.CentreX - LesNx; - dsp1_state.shared.Gy = dsp1_state.shared.CentreY - LesNy; - dsp1_state.shared.Gz = dsp1_state.shared.CentreZ - LesNz; - - E = 0; - normalize(dsp1_state.shared.CentreZ, &C, &E); - - dsp1_state.shared.CentreZ_C = C; - dsp1_state.shared.CentreZ_E = E; - - // Determine clip boundary and clip Zenith angle if necessary - // (Why to clip? Maybe to avoid the screen can only show sky with no ground? Only a guess...) - MaxAZS = dsp1_MaxAZS_Exp[-E]; - - if (AZS < 0) - { - MaxAZS = -MaxAZS; - if (AZS < MaxAZS + 1) - AZS = MaxAZS + 1; - } - else - { - if (AZS > MaxAZS) - AZS = MaxAZS; - } - - // Store Sine and Cosine of clipped Zenith angle - dsp1_state.shared.SinAZS = dsp1_sin(AZS); - dsp1_state.shared.CosAZS = dsp1_cos(AZS); - - // calculate the separation of (cx, cy) from the projection of - // the 'centre of projection' over the ground... (CentreZ*tg(AZS)) - inverse(dsp1_state.shared.CosAZS, 0, &dsp1_state.shared.SecAZS_C1, &dsp1_state.shared.SecAZS_E1); - normalize(C * dsp1_state.shared.SecAZS_C1 >> 15, &C, &E); - E += dsp1_state.shared.SecAZS_E1; - C = denormalize_and_clip(C, E) * dsp1_state.shared.SinAZS >> 15; - - // ... and then take into account the position of the centre of - // projection and the azimuth angle - dsp1_state.shared.CentreX += C * dsp1_state.shared.SinAas >> 15; - dsp1_state.shared.CentreY -= C * dsp1_state.shared.CosAas >> 15; - - *Cx = dsp1_state.shared.CentreX; - *Cy = dsp1_state.shared.CentreY; - - // Raster number of imaginary center and horizontal line - *Vof = 0; - - if ((Azs != AZS) || (Azs == MaxAZS)) - { - INT16 Aux; - - // correct vof and vva when Azs is outside the 'non-clipping interval' - // we have only some few Taylor coefficients, so we cannot guess which ones - // are the approximated functions and, what is worse, we don't know why - // the own clipping stuff (and, particularly, this correction) is done - if (Azs == -32768) - Azs = -32767; - - C = Azs - MaxAZS; - if (C >= 0) - C--; - Aux = ~(C << 2); - - // Vof += x+(1/3)*x^3, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 - C = Aux * dsp1_state.DataRom[0x0328] >> 15; - C = (C * Aux >> 15) + dsp1_state.DataRom[0x0327]; - *Vof -= (C * Aux >> 15) * Les >> 15; - - // CosAZS *= 1+(1/2)*x^2+(5/24)*x^24, where x ranges from 0 to PI/4 when Azs-MaxAZS goes from 0 to 0x2000 - C = Aux * Aux >> 15; - Aux = (C * dsp1_state.DataRom[0x0324] >> 15) + dsp1_state.DataRom[0x0325]; - dsp1_state.shared.CosAZS += (C * Aux >> 15) * dsp1_state.shared.CosAZS >> 15; - } - - // vertical offset of the screen with regard to the horizontal plane - // containing the centre of projection - dsp1_state.shared.VOffset = Les * dsp1_state.shared.CosAZS >> 15; - - // The horizon line (the line in the screen that is crossed by the horizon plane - // -the horizontal plane containing the 'centre of projection'-), - // will be at distance Les*cotg(AZS) from the centre of the screen. This is difficult - // to explain but easily seen in a graph. To better see it, consider it in this way: - // Les*tg(AZS-90), draw some lines and apply basic trigonometry. ;) - inverse(dsp1_state.shared.SinAZS, 0, &CSec, &E); - normalize(dsp1_state.shared.VOffset, &C, &E); - normalize(C * CSec >> 15, &C, &E); - - if (C == -32768) - { - C >>= 1; - E++; - } - - *Vva = denormalize_and_clip(-C, E); - - // Store Secant of clipped Zenith angle - inverse(dsp1_state.shared.CosAZS, 0, &dsp1_state.shared.SecAZS_C2, &dsp1_state.shared.SecAZS_E2); -} - -////////////////////////////////////////////////////////////////// - -// Calculates the matrix which transform an object situated on a raster line (Vs) into -// his projection over the ground. The modified SecAZS is used here, so -// i don't understand the fine details, but, basically, it's done -// this way: The vertical offset between the point of projection and the -// raster line is calculated (Vs*SinAzs>>15)+VOffset, then the height of -// the center of projection is measured in that units (*CentreZ_C). If, now -// you consider the "reference case" (center of projection at an unit of height), -// the projection of a thin strip containing the raster line will have the same -// width (as the raster line would be on the ground in this case, but will suffer a -// change of scale in height (as the ground and the vertical axis would form an angle of 180-Azs degrees). -// This scale factor, when the angle 'center of screen-center of projection-raster line' is small, -// can be aproximated by the one of the center of the screen, 1/cos(Azs).(**) (Here is when it's used -// SecAZS). By last, you have to consider the effect of the azimuth angle Aas, and you are done. -// -// Using matrix notation: -// |A B| Centre_ZS | cos(Aas) -sin(Aas)| | 1 0 | -// ProjectionMatrix = | | = ----------- * | | * | | -// |C D| Vs*sin(Azs) | sin(Aas) cos(Aas)| | 0 sec(Azs)| -// -// (**) -// If Les=1, the vertical offset between the center -// of projection and the center of the screen is Cos(Azs); then, if the vertical -// offset is 1, the ratio of the projection over the ground respect to the -// line on the screen is 1/cos(Azs). - -static void dsp1_raster( INT16 *input, INT16 *output ) -{ - INT16 Vs = input[0]; - INT16* An = &output[0]; - INT16* Bn = &output[1]; - INT16* Cn = &output[2]; - INT16* Dn = &output[3]; - - INT16 C, E, C1, E1; - - inverse((Vs * dsp1_state.shared.SinAzs >> 15) + dsp1_state.shared.VOffset, 7, &C, &E); - - E += dsp1_state.shared.CentreZ_E; - C1 = C * dsp1_state.shared.CentreZ_C >> 15; - - E1 = E + dsp1_state.shared.SecAZS_E2; - - normalize(C1, &C, &E); - C = denormalize_and_clip(C, E); - - *An = C * dsp1_state.shared.CosAas >> 15; - *Cn = C * dsp1_state.shared.SinAas >> 15; - - normalize(C1 * dsp1_state.shared.SecAZS_C2 >> 15, &C, &E1); - C = denormalize_and_clip(C, E1); - - *Bn = C * -dsp1_state.shared.SinAas >> 15; - *Dn = C * dsp1_state.shared.CosAas >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Calculate the projection over the ground of a selected point of screen -// It simply apply the projection matrix described in the "Raster" command -// to the vector (H,V) transposed, and add the result to the position of -// the centre of projection. -// The only special point to take into account is the directions on the screen: -// H is positive rightward, but V is positive downward; this is why -// the signs take that configuration - -static void dsp1_target( INT16 *input, INT16 *output ) -{ - INT16 H = input[0]; - INT16 V = input[1]; - INT16* X = &output[0]; - INT16* Y = &output[1]; - - INT16 C, E, C1, E1; - - inverse((V * dsp1_state.shared.SinAzs >> 15) + dsp1_state.shared.VOffset, 8, &C, &E); - - E += dsp1_state.shared.CentreZ_E; - C1 = C * dsp1_state.shared.CentreZ_C >> 15; - - E1 = E + dsp1_state.shared.SecAZS_E1; - - H <<= 8; - normalize(C1, &C, &E); - C = denormalize_and_clip(C, E) * H >> 15; - - *X = dsp1_state.shared.CentreX + (C * dsp1_state.shared.CosAas >> 15); - *Y = dsp1_state.shared.CentreY - (C * dsp1_state.shared.SinAas >> 15); - - V <<= 8; - normalize(C1 * dsp1_state.shared.SecAZS_C1 >> 15, &C, &E1); - C = denormalize_and_clip(C, E1) * V >> 15; - - *X += C * -dsp1_state.shared.SinAas >> 15; - *Y += C * dsp1_state.shared.CosAas >> 15; -} - -////////////////////////////////////////////////////////////////// - -// Calculation of the projection over the screen (H,V) of an object (X,Y,Z) and his -// 'enlargement ratio' (M). The positive directions on the screen are as described -// in the targe command. M is scaled down by 2^-7, that is, M==0x0100 means ratio 1:1 - -static void dsp1_project( INT16 *input, INT16 *output ) -{ - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* H = &output[0]; - INT16* V = &output[1]; - INT16* M = &output[2]; - - INT32 aux, aux4; - INT16 E, E2, E3, E4, E5, refE, E6, E7; - INT16 C2, C4, C6, C8, C9, C10, C11, C12, C16, C17, C18, C19, C20, C21, C22, C23, C24, C25, C26; - INT16 Px, Py, Pz; - - E4 = E3 = E2 = E = E5 = 0; - - normalize_double((INT32)(X) - dsp1_state.shared.Gx, &Px, &E4); - normalize_double((INT32)(Y) - dsp1_state.shared.Gy, &Py, &E); - normalize_double((INT32)(Z) - dsp1_state.shared.Gz, &Pz, &E3); - Px >>= 1; E4--; // to avoid overflows when calculating the scalar products - Py >>= 1; E--; - Pz >>= 1; E3--; - - refE = (E < E3) ? E : E3; - refE = (refE < E4) ? refE : E4; - - Px = shiftR(Px, E4 - refE); // normalize them to the same exponent - Py = shiftR(Py, E - refE); - Pz = shiftR(Pz, E3 - refE); - - C11 = -(Px * dsp1_state.shared.Nx >> 15); - C8 = -(Py * dsp1_state.shared.Ny >> 15); - C9 = -(Pz * dsp1_state.shared.Nz >> 15); - C12 = C11 + C8 + C9; // this cannot overflow! - - aux4 = C12; // de-normalization with 32-bits arithmetic - refE = 16 - refE; // refE can be up to 3 - if (refE >= 0) - aux4 <<= (refE); - else - aux4 >>= -(refE); - if (aux4 == -1) - aux4 = 0; // why? - aux4 >>= 1; - - aux = (UINT16)(dsp1_state.shared.Les) + aux4; // Les - the scalar product of P with the normal vector of the screen - normalize_double(aux, &C10, &E2); - E2 = 15 - E2; - - inverse(C10, 0, &C4, &E4); - C2 = C4 * dsp1_state.shared.C_Les >> 15; // scale factor - - - // H - E7 = 0; - C16 = (Px * dsp1_state.shared.Hx >> 15); - C20 = (Py * dsp1_state.shared.Hy >> 15); - C17 = C16 + C20; // scalar product of P with the normalized horizontal vector of the screen... - - C18 = C17 * C2 >> 15; // ... multiplied by the scale factor - normalize(C18, &C19, &E7); - *H = denormalize_and_clip(C19, dsp1_state.shared.E_Les - E2 + refE + E7); - - // V - E6 = 0; - C21 = Px * dsp1_state.shared.Vx >> 15; - C22 = Py * dsp1_state.shared.Vy >> 15; - C23 = Pz * dsp1_state.shared.Vz >> 15; - C24 = C21 + C22 + C23; // scalar product of P with the normalized vertical vector of the screen... - - C26 = C24 * C2 >> 15; // ... multiplied by the scale factor - normalize(C26, &C25, &E6); - *V = denormalize_and_clip(C25, dsp1_state.shared.E_Les - E2 + refE + E6); - - // M - normalize(C2, &C6, &E4); - *M = denormalize_and_clip(C6, E4 + dsp1_state.shared.E_Les - E2 - 7); // M is the scale factor divided by 2^7 -} - -////////////////////////////////////////////////////////////////// - -// Calculate the sine of the input parameter -// this is done by linear interpolation between -// the points of a look-up table - -static INT16 dsp1_sin( INT16 Angle ) -{ - INT32 S; - - if (Angle < 0) - { - if (Angle == -32768) - return 0; - - return -dsp1_sin(-Angle); - } - S = dsp1_sin_table[Angle >> 8] + (dsp1_mul_table[Angle & 0xff] * dsp1_sin_table[0x40 + (Angle >> 8)] >> 15); - if (S > 32767) - S = 32767; - return (INT16) S; -} - -////////////////////////////////////////////////////////////////// - -// Calculate the cosine of the input parameter. -// It's used the same method than in sin(INT16) - -static INT16 dsp1_cos( INT16 Angle ) -{ - INT32 S; - - if (Angle < 0) - { - if (Angle == -32768) - return -32768; - Angle = -Angle; - } - S = dsp1_sin_table[0x40 + (Angle >> 8)] - (dsp1_mul_table[Angle & 0xff] * dsp1_sin_table[Angle >> 8] >> 15); - if (S < -32768) - S = -32767; - return (INT16) S; -} - -////////////////////////////////////////////////////////////////// - -// Determines the inverse of a floating point decimal number -// iCoefficient*2^iExponent = 1/(Coefficient*2^Exponent), with the output -// normalized (iCoefficient represents a number whose absolute value is between 1/2 and 1) -// To invert 'Coefficient' a first initial guess is taken from a look-up table -// and, then, two iterations of the Newton method (applied to the function -// f(x)=1/(2*x)-Coefficient) are done. This results in a close approximation (iCoefficient) to a number 'y' -// that verify Coefficient*y=1/2. This is why you have to correct the exponent by one -// unit at the end. - -static void inverse( INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent ) -{ - // Step One: Division by Zero - if (Coefficient == 0x0000) - { - *iCoefficient = 0x7fff; - *iExponent = 0x002f; - } - else - { - INT16 Sign = 1; - - // Step Two: Remove Sign - if (Coefficient < 0) - { - if (Coefficient < -32767) - Coefficient = -32767; - Coefficient = -Coefficient; - Sign = -1; - } - - // Step Three: Normalize - while (Coefficient < 0x4000) - { - Coefficient <<= 1; - Exponent--; - } - - // Step Four: Special Case - if (Coefficient == 0x4000) - if (Sign == 1) *iCoefficient = 0x7fff; - else { - *iCoefficient = -0x4000; - Exponent--; - } - else { - // Step Five: Initial Guess - INT16 i = dsp1_state.DataRom[((Coefficient - 0x4000) >> 7) + 0x0065]; - - // Step Six: Iterate Newton's Method - i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; - i = (i + (-i * (Coefficient * i >> 15) >> 15)) << 1; - - *iCoefficient = i * Sign; - } - - *iExponent = 1 - Exponent; - } -} - -////////////////////////////////////////////////////////////////// - -static INT16 denormalize_and_clip( INT16 C, INT16 E ) -{ - if (E > 0) - { - if (C > 0) - return 32767; - else if (C < 0) - return -32767; - } - else - { - if (E < 0) - return C * dsp1_state.DataRom[0x0031 + E] >> 15; - } - return C; -} - -////////////////////////////////////////////////////////////////// - -// Normalize the input number (m), understood as ranging from -1 to 1, -// to the form: Coefficient*2^Exponent, -// where the absolute value of Coefficient is >= 1/2 -// (Coefficient>=0x4000 or Coefficient <= (INT16)0xc001) - -static void normalize( INT16 m, INT16 *Coefficient, INT16 *Exponent ) -{ - INT16 i = 0x4000; - INT16 e = 0; - - if (m < 0) - while ((m & i) && i) - { - i >>= 1; - e++; - } - else - while (!(m & i) && i) - { - i >>= 1; - e++; - } - - if (e > 0) - *Coefficient = m * dsp1_state.DataRom[0x21 + e] << 1; - else - *Coefficient = m; - - *Exponent -= e; -} - -////////////////////////////////////////////////////////////////// - -// Same than 'normalize' but with an INT32 input - -static void normalize_double( INT32 Product, INT16 *Coefficient, INT16 *Exponent ) -{ - INT16 n = Product & 0x7fff; - INT16 m = Product >> 15; - INT16 i = 0x4000; - INT16 e = 0; - - if (m < 0) - while ((m & i) && i) - { - i >>= 1; - e++; - } - else - while (!(m & i) && i) - { - i >>= 1; - e++; - } - - if (e > 0) - { - *Coefficient = m * dsp1_state.DataRom[0x0021 + e] << 1; - - if (e < 15) - *Coefficient += n * dsp1_state.DataRom[0x0040 - e] >> 15; - else - { - i = 0x4000; - - if (m < 0) - while ((n & i) && i) - { - i >>= 1; - e++; - } - else - while (!(n & i) && i) - { - i >>= 1; - e++; - } - - if (e > 15) - *Coefficient = n * dsp1_state.DataRom[0x0012 + e] << 1; - else - *Coefficient += n; - } - } - else - *Coefficient = m; - - *Exponent = e; -} - -////////////////////////////////////////////////////////////////// - -// Shift to the right - -static INT16 shiftR( INT16 C, INT16 E ) -{ - return (C * dsp1_state.DataRom[0x0031 + E] >> 15); -} - -////////////////////////////////////////////////////////////////// - -// Save DSP1 variables - -static void dsp1_register_save( running_machine *machine ) -{ - state_save_register_global(machine, dsp1_state.Sr); - state_save_register_global(machine, dsp1_state.Dr); - state_save_register_global(machine, dsp1_state.SrLowByteAccess); - state_save_register_global(machine, dsp1_state.FsmMajorState); - state_save_register_global(machine, dsp1_state.Command); - state_save_register_global(machine, dsp1_state.DataCounter); - state_save_register_global(machine, dsp1_state.Freeze); - state_save_register_global_array(machine, dsp1_state.ReadBuffer); - state_save_register_global_array(machine, dsp1_state.WriteBuffer); - state_save_register_global_array(machine, dsp1_state.shared.MatrixA[0]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixA[1]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixA[2]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixB[0]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixB[1]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixB[2]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixC[0]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixC[1]); - state_save_register_global_array(machine, dsp1_state.shared.MatrixC[2]); - state_save_register_global(machine, dsp1_state.shared.CentreX); - state_save_register_global(machine, dsp1_state.shared.CentreY); - state_save_register_global(machine, dsp1_state.shared.CentreZ); - state_save_register_global(machine, dsp1_state.shared.CentreZ_C); - state_save_register_global(machine, dsp1_state.shared.CentreZ_E); - state_save_register_global(machine, dsp1_state.shared.VOffset); - state_save_register_global(machine, dsp1_state.shared.Les); - state_save_register_global(machine, dsp1_state.shared.C_Les); - state_save_register_global(machine, dsp1_state.shared.E_Les); - state_save_register_global(machine, dsp1_state.shared.SinAas); - state_save_register_global(machine, dsp1_state.shared.CosAas); - state_save_register_global(machine, dsp1_state.shared.SinAzs); - state_save_register_global(machine, dsp1_state.shared.CosAzs); - state_save_register_global(machine, dsp1_state.shared.SinAZS); - state_save_register_global(machine, dsp1_state.shared.CosAZS); - state_save_register_global(machine, dsp1_state.shared.SecAZS_C1); - state_save_register_global(machine, dsp1_state.shared.SecAZS_E1); - state_save_register_global(machine, dsp1_state.shared.SecAZS_C2); - state_save_register_global(machine, dsp1_state.shared.SecAZS_E2); - state_save_register_global(machine, dsp1_state.shared.Nx); - state_save_register_global(machine, dsp1_state.shared.Ny); - state_save_register_global(machine, dsp1_state.shared.Nz); - state_save_register_global(machine, dsp1_state.shared.Gx); - state_save_register_global(machine, dsp1_state.shared.Gy); - state_save_register_global(machine, dsp1_state.shared.Gz); - state_save_register_global(machine, dsp1_state.shared.Hx); - state_save_register_global(machine, dsp1_state.shared.Hy); - state_save_register_global(machine, dsp1_state.shared.Vx); - state_save_register_global(machine, dsp1_state.shared.Vy); - state_save_register_global(machine, dsp1_state.shared.Vz); -} diff --git a/src/mame/machine/snesdsp2.c b/src/mame/machine/snesdsp2.c deleted file mode 100644 index bb58a259438..00000000000 --- a/src/mame/machine/snesdsp2.c +++ /dev/null @@ -1,412 +0,0 @@ -/*************************************************************************** - - snesdsp2.c - - File to handle emulation of the SNES "DSP-2" add-on chip. - - Original C++ code by byuu, based on research by Overload. - Byuu's code is released under GNU General Public License - version 2 as published by the Free Software Foundation. - The implementation below is released under the MAME license - for use in MAME, MESS and derivatives by permission of the - author - -***************************************************************************/ - -struct _snes_dsp2_state -{ - int waiting_for_command; - int command; - int in_count, in_index; - int out_count, out_index; - - UINT8 parameters[512]; - UINT8 output[512]; - - UINT8 op05transparent; - int op05haslen; - int op05len; - int op06haslen; - int op06len; - UINT16 op09word1; - UINT16 op09word2; - int op0dhaslen; - int op0doutlen; - int op0dinlen; -}; - -static struct _snes_dsp2_state dsp2_state; - - -static void dsp2_register_save(running_machine *machine); - -//convert bitmap to bitplane tile -static void dsp2_op01( void ) -{ -//op01 size is always 32 bytes input and output -//the hardware does strange things if you vary the size - - unsigned char c0, c1, c2, c3; - unsigned char *p1 = dsp2_state.parameters; - unsigned char *p2a = dsp2_state.output; - unsigned char *p2b = dsp2_state.output + 16; //halfway - int j; - -//process 8 blocks of 4 bytes each - for (j = 0; j < 8; j++) - { - c0 = *p1++; - c1 = *p1++; - c2 = *p1++; - c3 = *p1++; - - *p2a++ = (c0 & 0x10) << 3 | - (c0 & 0x01) << 6 | - (c1 & 0x10) << 1 | - (c1 & 0x01) << 4 | - (c2 & 0x10) >> 1 | - (c2 & 0x01) << 2 | - (c3 & 0x10) >> 3 | - (c3 & 0x01); - - *p2a++ = (c0 & 0x20) << 2 | - (c0 & 0x02) << 5 | - (c1 & 0x20) | - (c1 & 0x02) << 3 | - (c2 & 0x20) >> 2 | - (c2 & 0x02) << 1 | - (c3 & 0x20) >> 4 | - (c3 & 0x02) >> 1; - - *p2b++ = (c0 & 0x40) << 1 | - (c0 & 0x04) << 4 | - (c1 & 0x40) >> 1 | - (c1 & 0x04) << 2 | - (c2 & 0x40) >> 3 | - (c2 & 0x04) | - (c3 & 0x40) >> 5 | - (c3 & 0x04) >> 2; - - *p2b++ = (c0 & 0x80) | - (c0 & 0x08) << 3 | - (c1 & 0x80) >> 2 | - (c1 & 0x08) << 1 | - (c2 & 0x80) >> 4 | - (c2 & 0x08) >> 1 | - (c3 & 0x80) >> 6 | - (c3 & 0x08) >> 3; - } -} - -//set transparent color -static void dsp2_op03( void ) -{ - dsp2_state.op05transparent = dsp2_state.parameters[0]; -} - -//replace bitmap using transparent color -static void dsp2_op05( void ) -{ - UINT8 color; -// Overlay bitmap with transparency. -// Input: -// -// Bitmap 1: i[0] <=> i[size-1] -// Bitmap 2: i[size] <=> i[2*size-1] -// -// Output: -// -// Bitmap 3: o[0] <=> o[size-1] -// -// Processing: -// -// Process all 4-bit pixels (nibbles) in the bitmap -// -// if ( BM2_pixel == transparent_color ) -// pixelout = BM1_pixel -// else -// pixelout = BM2_pixel - -// The max size bitmap is limited to 255 because the size parameter is a byte -// I think size=0 is an error. The behavior of the chip on size=0 is to -// return the last value written to DR if you read DR on Op05 with -// size = 0. I don't think it's worth implementing this quirk unless it's -// proven necessary. - - unsigned char c1, c2; - unsigned char *p1 = dsp2_state.parameters; - unsigned char *p2 = dsp2_state.parameters + dsp2_state.op05len; - unsigned char *p3 = dsp2_state.output; - int n; - - color = dsp2_state.op05transparent & 0x0f; - - for (n = 0; n < dsp2_state.op05len; n++) - { - c1 = *p1++; - c2 = *p2++; - *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0 : c2 & 0xf0) | - (((c2 & 0x0f) == color) ? c1 & 0x0f : c2 & 0x0f); - } -} - -//reverse bitmap -static void dsp2_op06( void ) -{ -// Input: -// size -// bitmap - int i, j; - for (i = 0, j = dsp2_state.op06len - 1; i < dsp2_state.op06len; i++, j--) - { - dsp2_state.output[j] = (dsp2_state.parameters[i] << 4) | (dsp2_state.parameters[i] >> 4); - } -} - -//multiply -static void dsp2_op09( void ) -{ - UINT32 r = 0; - dsp2_state.out_count = 4; - - dsp2_state.op09word1 = dsp2_state.parameters[0] | (dsp2_state.parameters[1] << 8); - dsp2_state.op09word2 = dsp2_state.parameters[2] | (dsp2_state.parameters[3] << 8); - - r = dsp2_state.op09word1 * dsp2_state.op09word2; - dsp2_state.output[0] = r; - dsp2_state.output[1] = r >> 8; - dsp2_state.output[2] = r >> 16; - dsp2_state.output[3] = r >> 24; -} - -//scale bitmap -static void dsp2_op0d( void ) -{ -// Bit accurate hardware algorithm - uses fixed point math -// This should match the DSP2 Op0D output exactly -// I wouldn't recommend using this unless you're doing hardware debug. -// In some situations it has small visual artifacts that -// are not readily apparent on a TV screen but show up clearly -// on a monitor. Use Overload's scaling instead. -// This is for hardware verification testing. -// -// One note: the HW can do odd byte scaling but since we divide -// by two to get the count of bytes this won't work well for -// odd byte scaling (in any of the current algorithm implementations). -// So far I haven't seen Dungeon Master use it. -// If it does we can adjust the parameters and code to work with it - - UINT32 multiplier; // Any size int >= 32-bits - UINT32 pixloc; // match size of multiplier - int i, j; - UINT8 pixelarray[512]; - if (dsp2_state.op0dinlen <= dsp2_state.op0doutlen) - { - multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 - } - else - { - multiplier = (dsp2_state.op0dinlen << 17) / ((dsp2_state.op0doutlen << 1) + 1); - } - - pixloc = 0; - for (i = 0; i < dsp2_state.op0doutlen * 2; i++) - { - j = pixloc >> 16; - - if (j & 1) - pixelarray[i] = (dsp2_state.parameters[j >> 1] & 0x0f); - else - pixelarray[i] = (dsp2_state.parameters[j >> 1] & 0xf0) >> 4; - - pixloc += multiplier; - } - - for (i = 0; i < dsp2_state.op0doutlen; i++) - { - dsp2_state.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; - } -} - - -static void dsp2_init( running_machine *machine ) -{ - dsp2_state.waiting_for_command = 1; - dsp2_state.in_count = 0; - dsp2_state.in_index = 0; - dsp2_state.out_count = 0; - dsp2_state.out_index = 0; - - memset(dsp2_state.parameters, 0 , ARRAY_LENGTH(dsp2_state.parameters)); - memset(dsp2_state.output, 0 , ARRAY_LENGTH(dsp2_state.output)); - - dsp2_state.op05transparent = 0; - dsp2_state.op05haslen = 0; - dsp2_state.op05len = 0; - dsp2_state.op06haslen = 0; - dsp2_state.op06len = 0; - dsp2_state.op09word1 = 0; - dsp2_state.op09word2 = 0; - dsp2_state.op0dhaslen = 0; - dsp2_state.op0doutlen = 0; - dsp2_state.op0dinlen = 0; - - dsp2_register_save(machine); -} - -static UINT8 dsp2_dr_read( void ) -{ - UINT8 r = 0xff; - if (dsp2_state.out_count) - { - r = dsp2_state.output[dsp2_state.out_index++]; - dsp2_state.out_index &= 511; - if (dsp2_state.out_count == dsp2_state.out_index) - dsp2_state.out_count = 0; - } - return r; -} - -static void dsp2_dr_write(UINT8 data) -{ - if (dsp2_state.waiting_for_command) - { - dsp2_state.command = data; - dsp2_state.in_index = 0; - dsp2_state.waiting_for_command = 0; - - switch (data) - { - case 0x01: dsp2_state.in_count = 32; break; - case 0x03: dsp2_state.in_count = 1; break; - case 0x05: dsp2_state.in_count = 1; break; - case 0x06: dsp2_state.in_count = 1; break; - case 0x07: break; - case 0x08: break; - case 0x09: dsp2_state.in_count = 4; break; - case 0x0d: dsp2_state.in_count = 2; break; - case 0x0f: dsp2_state.in_count = 0; break; - } - } - else - { - dsp2_state.parameters[dsp2_state.in_index++] = data; - dsp2_state.in_index &= 511; - } - - if (dsp2_state.in_count == dsp2_state.in_index) - { - dsp2_state.waiting_for_command = 1; - dsp2_state.out_index = 0; - switch (dsp2_state.command) - { - case 0x01: - dsp2_state.out_count = 32; - dsp2_op01(); - break; - - case 0x03: - dsp2_op03(); - break; - - case 0x05: - if (dsp2_state.op05haslen) - { - dsp2_state.op05haslen = 0; - dsp2_state.out_count = dsp2_state.op05len; - dsp2_op05(); - } - else - { - dsp2_state.op05len = dsp2_state.parameters[0]; - dsp2_state.in_index = 0; - dsp2_state.in_count = dsp2_state.op05len * 2; - dsp2_state.op05haslen = 1; - if (data) - dsp2_state.waiting_for_command = 0; - } - break; - - case 0x06: - if (dsp2_state.op06haslen) - { - dsp2_state.op06haslen = 0; - dsp2_state.out_count = dsp2_state.op06len; - dsp2_op06(); - } - else - { - dsp2_state.op06len = dsp2_state.parameters[0]; - dsp2_state.in_index = 0; - dsp2_state.in_count = dsp2_state.op06len; - dsp2_state.op06haslen = 1; - if (data) - dsp2_state.waiting_for_command = 0; - } - break; - - case 0x07: break; - case 0x08: break; - - case 0x09: - dsp2_op09(); - break; - - case 0x0d: - if (dsp2_state.op0dhaslen) - { - dsp2_state.op0dhaslen = 0; - dsp2_state.out_count = dsp2_state.op0doutlen; - dsp2_op0d(); - } - else - { - dsp2_state.op0dinlen = dsp2_state.parameters[0]; - dsp2_state.op0doutlen = dsp2_state.parameters[1]; - dsp2_state.in_index = 0; - dsp2_state.in_count = (dsp2_state.op0dinlen + 1) >> 1; - dsp2_state.op0dhaslen = 1; - if (data) - dsp2_state.waiting_for_command = 0; - } - break; - - case 0x0f: - break; - } - } -} - -static UINT8 dsp2_sr_read( void ) -{ - return 0x00; -} - -static void dsp2_sr_write( UINT8 data ) -{ - // do nothing -} - -static void dsp2_register_save( running_machine *machine ) -{ - state_save_register_global(machine, dsp2_state.waiting_for_command); - state_save_register_global(machine, dsp2_state.command); - state_save_register_global(machine, dsp2_state.in_count); - state_save_register_global(machine, dsp2_state.in_index); - state_save_register_global(machine, dsp2_state.out_count); - state_save_register_global(machine, dsp2_state.out_index); - - state_save_register_global_array(machine, dsp2_state.parameters); - state_save_register_global_array(machine, dsp2_state.output); - - state_save_register_global(machine, dsp2_state.op05transparent); - state_save_register_global(machine, dsp2_state.op05haslen); - state_save_register_global(machine, dsp2_state.op05len); - state_save_register_global(machine, dsp2_state.op06haslen); - state_save_register_global(machine, dsp2_state.op06len); - state_save_register_global(machine, dsp2_state.op09word1); - state_save_register_global(machine, dsp2_state.op09word2); - state_save_register_global(machine, dsp2_state.op0dhaslen); - state_save_register_global(machine, dsp2_state.op0doutlen); - state_save_register_global(machine, dsp2_state.op0dinlen); -} diff --git a/src/mame/machine/snesdsp3.c b/src/mame/machine/snesdsp3.c deleted file mode 100644 index 6b6dd2376b2..00000000000 --- a/src/mame/machine/snesdsp3.c +++ /dev/null @@ -1,1113 +0,0 @@ -/************************************************************************ - - DSP-3 emulator code - - Copyright (c) 2003-2009 John Weidman, Kris Bleakley, Lancer, Nach, - z80 gaiden, and Jonas Quinn - - This code is released by ZSNES Team under GNU General Public License - version 2 as published by the Free Software Foundation. - The implementation below is released under the MAME license for use - in MAME, MESS and derivatives by permission of the authors. - -************************************************************************/ - -static void dsp3_Command(void); - -struct _snes_dsp3_state -{ - UINT16 DR; - UINT16 SR; - UINT16 MemoryIndex; - - INT16 AddLo; - INT16 AddHi; - INT16 WinLo; - INT16 WinHi; - UINT16 Codewords; - UINT16 Outwords; - UINT16 Symbol; - UINT16 BitCount; - UINT16 Index; - UINT16 Codes[512]; - UINT16 BitsLeft; - UINT16 ReqBits; - UINT16 ReqData; - UINT16 BitCommand; - UINT8 BaseLength; - UINT16 BaseCodes; - UINT16 BaseCode; - UINT8 CodeLengths[8]; - UINT16 CodeOffsets[8]; - UINT16 LZCode; - UINT8 LZLength; - - UINT16 X; - UINT16 Y; - - UINT8 Bitmap[8]; - UINT8 Bitplane[8]; - UINT16 BMIndex; - UINT16 BPIndex; - UINT16 Count; - - INT16 op3e_x; - INT16 op3e_y; - - INT16 op1e_terrain[0x2000]; - INT16 op1e_cost[0x2000]; - INT16 op1e_weight[0x2000]; - - INT16 op1e_cell; - INT16 op1e_turn; - INT16 op1e_search; - - INT16 op1e_x; - INT16 op1e_y; - - INT16 op1e_min_radius; - INT16 op1e_max_radius; - - INT16 op1e_max_search_radius; - INT16 op1e_max_path_radius; - - INT16 op1e_lcv_radius; - INT16 op1e_lcv_steps; - INT16 op1e_lcv_turns; - - void(*SetDSP3)(void); - - UINT16 DataROM[1024]; -}; - -static struct _snes_dsp3_state dsp3_state; - - -static void dsp3_Reset(void) -{ - dsp3_state.DR = 0x0080; - dsp3_state.SR = 0x0084; - dsp3_state.SetDSP3 = &dsp3_Command; -} - -#ifdef UNUSED_FUNCTION -void dsp3_MemorySize(void) -{ - dsp3_state.DR = 0x0300; - dsp3_state.SetDSP3 = &dsp3_Reset; -} -#endif - -static void dsp3_TestMemory(void) -{ - dsp3_state.DR = 0x0000; - dsp3_state.SetDSP3 = &dsp3_Reset; -} - -static void dsp3_DumpDataROM(void) -{ - dsp3_state.DR = dsp3_state.DataROM[dsp3_state.MemoryIndex++]; - if (dsp3_state.MemoryIndex == 1024) - dsp3_state.SetDSP3 = &dsp3_Reset; -} - -static void dsp3_MemoryDump(void) -{ - dsp3_state.MemoryIndex = 0; - dsp3_state.SetDSP3 = &dsp3_DumpDataROM; - dsp3_DumpDataROM(); -} - -static void dsp3_OP06(void) -{ - dsp3_state.WinLo = (UINT8)(dsp3_state.DR); - dsp3_state.WinHi = (UINT8)(dsp3_state.DR >> 8); - dsp3_Reset(); -} - -static void dsp3_OP03(void) -{ - INT16 Lo = (UINT8)(dsp3_state.DR); - INT16 Hi = (UINT8)(dsp3_state.DR >> 8); - INT16 Ofs = (dsp3_state.WinLo * Hi << 1) + (Lo << 1); - dsp3_state.DR = Ofs >> 1; - dsp3_state.SetDSP3 = &dsp3_Reset; -} - -static void dsp3_OP07_B(void) -{ - INT16 Ofs = (dsp3_state.WinLo * dsp3_state.AddHi << 1) + (dsp3_state.AddLo << 1); - dsp3_state.DR = Ofs >> 1; - dsp3_state.SetDSP3 = &dsp3_Reset; -} - -static void dsp3_OP07_A(void) -{ - INT16 Lo = (UINT8)(dsp3_state.DR); - INT16 Hi = (UINT8)(dsp3_state.DR >> 8); - - if (Lo & 1) - Hi += (dsp3_state.AddLo & 1); - - dsp3_state.AddLo += Lo; - dsp3_state.AddHi += Hi; - - if (dsp3_state.AddLo < 0) - dsp3_state.AddLo += dsp3_state.WinLo; - else if (dsp3_state.AddLo >= dsp3_state.WinLo) - dsp3_state.AddLo -= dsp3_state.WinLo; - - if (dsp3_state.AddHi < 0) - dsp3_state.AddHi += dsp3_state.WinHi; - else if (dsp3_state.AddHi >= dsp3_state.WinHi) - dsp3_state.AddHi -= dsp3_state.WinHi; - - dsp3_state.DR = dsp3_state.AddLo | (dsp3_state.AddHi << 8) | ((dsp3_state.AddHi >> 8) & 0xff); - dsp3_state.SetDSP3 = &dsp3_OP07_B; -} - -static void dsp3_OP07(void) -{ - UINT32 dataOfs = ((dsp3_state.DR << 1) + 0x03b2) & 0x03ff; - - dsp3_state.AddHi = dsp3_state.DataROM[dataOfs]; - dsp3_state.AddLo = dsp3_state.DataROM[dataOfs + 1]; - - dsp3_state.SetDSP3 = &dsp3_OP07_A; - dsp3_state.SR = 0x0080; -} - -static void dsp3_Coordinate(void) -{ - dsp3_state.Index++; - - switch (dsp3_state.Index) - { - case 3: - if (dsp3_state.DR == 0xffff) - dsp3_Reset(); - break; - case 4: - dsp3_state.X = dsp3_state.DR; - break; - case 5: - dsp3_state.Y = dsp3_state.DR; - dsp3_state.DR = 1; - break; - case 6: - dsp3_state.DR = dsp3_state.X; - break; - case 7: - dsp3_state.DR = dsp3_state.Y; - dsp3_state.Index = 0; - break; - } -} - -static void dsp3_Convert_A(void) -{ - if (dsp3_state.BMIndex < 8) - { - dsp3_state.Bitmap[dsp3_state.BMIndex++] = (UINT8) (dsp3_state.DR); - dsp3_state.Bitmap[dsp3_state.BMIndex++] = (UINT8) (dsp3_state.DR >> 8); - - if (dsp3_state.BMIndex == 8) - { - short i, j; - for (i = 0; i < 8; i++) - for (j = 0; j < 8; j++) - { - dsp3_state.Bitplane[j] <<= 1; - dsp3_state.Bitplane[j] |= (dsp3_state.Bitmap[i] >> j) & 1; - } - - dsp3_state.BPIndex = 0; - dsp3_state.Count--; - } - } - - if (dsp3_state.BMIndex == 8) - { - if (dsp3_state.BPIndex == 8) - { - if (!dsp3_state.Count) - dsp3_Reset(); - dsp3_state.BMIndex = 0; - } - else - { - dsp3_state.DR = dsp3_state.Bitplane[dsp3_state.BPIndex++]; - dsp3_state.DR |= dsp3_state.Bitplane[dsp3_state.BPIndex++] << 8; - } - } -} - -static void dsp3_Convert(void) -{ - dsp3_state.Count = dsp3_state.DR; - dsp3_state.BMIndex = 0; - dsp3_state.SetDSP3 = &dsp3_Convert_A; -} - -static UINT8 dsp3_GetBits(UINT8 Count) -{ - if (!dsp3_state.BitsLeft) - { - dsp3_state.BitsLeft = Count; - dsp3_state.ReqBits = 0; - } - - do { - if (!dsp3_state.BitCount) - { - dsp3_state.SR = 0xC0; - return 0; - } - - dsp3_state.ReqBits <<= 1; - if (dsp3_state.ReqData & 0x8000) - dsp3_state.ReqBits++; - dsp3_state.ReqData <<= 1; - - dsp3_state.BitCount--; - dsp3_state.BitsLeft--; - - } while (dsp3_state.BitsLeft); - - return 1; -} - -static void dsp3_Decode_Data(void) -{ - if (!dsp3_state.BitCount) - { - if (dsp3_state.SR & 0x40) - { - dsp3_state.ReqData = dsp3_state.DR; - dsp3_state.BitCount += 16; - } - else - { - dsp3_state.SR = 0xC0; - return; - } - } - - if (dsp3_state.LZCode == 1) - { - if (!dsp3_GetBits(1)) - return; - - if (dsp3_state.ReqBits) - dsp3_state.LZLength = 12; - else - dsp3_state.LZLength = 8; - - dsp3_state.LZCode++; - } - - if (dsp3_state.LZCode == 2) - { - if (!dsp3_GetBits(dsp3_state.LZLength)) - return; - - dsp3_state.LZCode = 0; - dsp3_state.Outwords--; - if (!dsp3_state.Outwords) dsp3_state.SetDSP3 = &dsp3_Reset; - - dsp3_state.SR = 0x80; - dsp3_state.DR = dsp3_state.ReqBits; - return; - } - - if (dsp3_state.BaseCode == 0xffff) - { - if (!dsp3_GetBits(dsp3_state.BaseLength)) - return; - - dsp3_state.BaseCode = dsp3_state.ReqBits; - } - - if (!dsp3_GetBits(dsp3_state.CodeLengths[dsp3_state.BaseCode])) - return; - - dsp3_state.Symbol = dsp3_state.Codes[dsp3_state.CodeOffsets[dsp3_state.BaseCode] + dsp3_state.ReqBits]; - dsp3_state.BaseCode = 0xffff; - - if (dsp3_state.Symbol & 0xff00) - { - dsp3_state.Symbol += 0x7f02; - dsp3_state.LZCode++; - } - else - { - dsp3_state.Outwords--; - if (!dsp3_state.Outwords) - dsp3_state.SetDSP3 = &dsp3_Reset; - } - - dsp3_state.SR = 0x80; - dsp3_state.DR = dsp3_state.Symbol; -} - -static void dsp3_Decode_Tree(void) -{ - if (!dsp3_state.BitCount) - { - dsp3_state.ReqData = dsp3_state.DR; - dsp3_state.BitCount += 16; - } - - if (!dsp3_state.BaseCodes) - { - dsp3_GetBits(1); - if (dsp3_state.ReqBits) - { - dsp3_state.BaseLength = 3; - dsp3_state.BaseCodes = 8; - } - else - { - dsp3_state.BaseLength = 2; - dsp3_state.BaseCodes = 4; - } - } - - while (dsp3_state.BaseCodes) - { - if (!dsp3_GetBits(3)) - return; - - dsp3_state.ReqBits++; - - dsp3_state.CodeLengths[dsp3_state.Index] = (UINT8) dsp3_state.ReqBits; - dsp3_state.CodeOffsets[dsp3_state.Index] = dsp3_state.Symbol; - dsp3_state.Index++; - - dsp3_state.Symbol += 1 << dsp3_state.ReqBits; - dsp3_state.BaseCodes--; - } - - dsp3_state.BaseCode = 0xffff; - dsp3_state.LZCode = 0; - - dsp3_state.SetDSP3 = &dsp3_Decode_Data; - if (dsp3_state.BitCount) - dsp3_Decode_Data(); -} - -static void dsp3_Decode_Symbols(void) -{ - dsp3_state.ReqData = dsp3_state.DR; - dsp3_state.BitCount += 16; - - do { - - if (dsp3_state.BitCommand == 0xffff) - { - if (!dsp3_GetBits(2)) return; - dsp3_state.BitCommand = dsp3_state.ReqBits; - } - - switch (dsp3_state.BitCommand) - { - case 0: - { - if (!dsp3_GetBits(9)) return; - dsp3_state.Symbol = dsp3_state.ReqBits; - break; - } - case 1: - { - dsp3_state.Symbol++; - break; - } - case 2: - { - if (!dsp3_GetBits(1)) return; - dsp3_state.Symbol += 2 + dsp3_state.ReqBits; - break; - } - case 3: - { - if (!dsp3_GetBits(4)) return; - dsp3_state.Symbol += 4 + dsp3_state.ReqBits; - break; - } - } - - dsp3_state.BitCommand = 0xffff; - - dsp3_state.Codes[dsp3_state.Index++] = dsp3_state.Symbol; - dsp3_state.Codewords--; - - } while (dsp3_state.Codewords); - - dsp3_state.Index = 0; - dsp3_state.Symbol = 0; - dsp3_state.BaseCodes = 0; - - dsp3_state.SetDSP3 = &dsp3_Decode_Tree; - if (dsp3_state.BitCount) dsp3_Decode_Tree(); -} - -static void dsp3_Decode_A(void) -{ - dsp3_state.Outwords = dsp3_state.DR; - dsp3_state.SetDSP3 = &dsp3_Decode_Symbols; - dsp3_state.BitCount = 0; - dsp3_state.BitsLeft = 0; - dsp3_state.Symbol = 0; - dsp3_state.Index = 0; - dsp3_state.BitCommand = 0xffff; - dsp3_state.SR = 0xC0; -} - -static void dsp3_Decode(void) -{ - dsp3_state.Codewords = dsp3_state.DR; - dsp3_state.SetDSP3 = &dsp3_Decode_A; -} - - -// Opcodes 1E/3E bit-perfect to 'dsp3-intro' log -// src: adapted from SD Gundam X/G-Next - -static void dsp3_OP3E(void) -{ - dsp3_state.op3e_x = (UINT8)(dsp3_state.DR & 0x00ff); - dsp3_state.op3e_y = (UINT8)((dsp3_state.DR & 0xff00) >> 8); - - dsp3_OP03(); - - dsp3_state.op1e_terrain[dsp3_state.DR] = 0x00; - dsp3_state.op1e_cost[dsp3_state.DR] = 0xff; - dsp3_state.op1e_weight[dsp3_state.DR] = 0; - - dsp3_state.op1e_max_search_radius = 0; - dsp3_state.op1e_max_path_radius = 0; -} - -static void dsp3_OP1E_A(void); -static void dsp3_OP1E_A1(void); -static void dsp3_OP1E_A2(void); -static void dsp3_OP1E_A3(void); - -static void dsp3_OP1E_B(void); -static void dsp3_OP1E_B1(void); -static void dsp3_OP1E_B2(void); - -static void dsp3_OP1E_C(void); -static void dsp3_OP1E_C1(void); -static void dsp3_OP1E_C2(void); - -static void dsp3_OP1E_D(INT16, INT16 *, INT16 *); -static void dsp3_OP1E_D1(INT16 move, INT16 *lo, INT16 *hi); - -static void dsp3_OP1E(void) -{ - int lcv; - - dsp3_state.op1e_min_radius = (UINT8)(dsp3_state.DR & 0x00ff); - dsp3_state.op1e_max_radius = (UINT8)((dsp3_state.DR & 0xff00)>>8); - - if (dsp3_state.op1e_min_radius == 0) - dsp3_state.op1e_min_radius++; - - if (dsp3_state.op1e_max_search_radius >= dsp3_state.op1e_min_radius) - dsp3_state.op1e_min_radius = dsp3_state.op1e_max_search_radius + 1; - - if (dsp3_state.op1e_max_radius > dsp3_state.op1e_max_search_radius) - dsp3_state.op1e_max_search_radius = dsp3_state.op1e_max_radius; - - dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - - dsp3_state.op1e_lcv_turns = 6; - dsp3_state.op1e_turn = 0; - - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - - for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++) - dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - - dsp3_OP1E_A(); -} - -static void dsp3_OP1E_A(void) -{ - int lcv; - - if (dsp3_state.op1e_lcv_steps == 0) - { - dsp3_state.op1e_lcv_radius++; - - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius; - - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - - for (lcv = 0; lcv < dsp3_state.op1e_lcv_radius; lcv++) - dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - } - - if (dsp3_state.op1e_lcv_radius > dsp3_state.op1e_max_radius) - { - dsp3_state.op1e_turn++; - dsp3_state.op1e_lcv_turns--; - - dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - - for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++) - dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - } - - if (dsp3_state.op1e_lcv_turns == 0) - { - dsp3_state.DR = 0xffff; - dsp3_state.SR = 0x0080; - dsp3_state.SetDSP3 = &dsp3_OP1E_B; - return; - } - - dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8); - dsp3_OP03(); - - dsp3_state.op1e_cell = dsp3_state.DR; - - dsp3_state.SR = 0x0080; - dsp3_state.SetDSP3 = &dsp3_OP1E_A1; -} - -static void dsp3_OP1E_A1(void) -{ - dsp3_state.SR = 0x0084; - dsp3_state.SetDSP3 = &dsp3_OP1E_A2; -} - -static void dsp3_OP1E_A2(void) -{ - dsp3_state.op1e_terrain[dsp3_state.op1e_cell] = (UINT8)(dsp3_state.DR & 0x00ff); - - dsp3_state.SR = 0x0084; - dsp3_state.SetDSP3 = &dsp3_OP1E_A3; -} - -static void dsp3_OP1E_A3(void) -{ - dsp3_state.op1e_cost[dsp3_state.op1e_cell] = (UINT8)(dsp3_state.DR & 0x00ff); - - if (dsp3_state.op1e_lcv_radius == 1) - { - if (dsp3_state.op1e_terrain[dsp3_state.op1e_cell] & 1) - { - dsp3_state.op1e_weight[dsp3_state.op1e_cell] = 0xff; - } - else - { - dsp3_state.op1e_weight[dsp3_state.op1e_cell] = dsp3_state.op1e_cost[dsp3_state.op1e_cell]; - } - } - else - { - dsp3_state.op1e_weight[dsp3_state.op1e_cell] = 0xff; - } - - dsp3_OP1E_D((INT16)(dsp3_state.op1e_turn + 2), &dsp3_state.op1e_x, &dsp3_state.op1e_y); - dsp3_state.op1e_lcv_steps--; - - dsp3_state.SR = 0x0080; - dsp3_OP1E_A(); -} - - -static void dsp3_OP1E_B(void) -{ - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - dsp3_state.op1e_lcv_radius = 1; - - dsp3_state.op1e_search = 0; - - dsp3_OP1E_B1(); - - dsp3_state.SetDSP3 = &dsp3_OP1E_C; -} - - -static void dsp3_OP1E_B1(void) -{ - while (dsp3_state.op1e_lcv_radius < dsp3_state.op1e_max_radius) - { - dsp3_state.op1e_y--; - - dsp3_state.op1e_lcv_turns = 6; - dsp3_state.op1e_turn = 5; - - while (dsp3_state.op1e_lcv_turns) - { - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius; - - while (dsp3_state.op1e_lcv_steps) - { - dsp3_OP1E_D1(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - - if (0 <= dsp3_state.op1e_y && dsp3_state.op1e_y < dsp3_state.WinHi && - 0 <= dsp3_state.op1e_x && dsp3_state.op1e_x < dsp3_state.WinLo ) - { - dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8); - dsp3_OP03(); - - dsp3_state.op1e_cell = dsp3_state.DR; - if (dsp3_state.op1e_cost[dsp3_state.op1e_cell ] < 0x80 && dsp3_state.op1e_terrain[dsp3_state.op1e_cell] < 0x40) - { - dsp3_OP1E_B2(); - } // end cell perimeter - } - - dsp3_state.op1e_lcv_steps--; - } // end search line - - dsp3_state.op1e_turn--; - if (dsp3_state.op1e_turn == 0) - dsp3_state.op1e_turn = 6; - - dsp3_state.op1e_lcv_turns--; - } // end circle search - - dsp3_state.op1e_lcv_radius++; - } // end radius search -} - - -static void dsp3_OP1E_B2(void) -{ - INT16 cell; - INT16 path; - INT16 x,y; - INT16 lcv_turns; - - path = 0xff; - lcv_turns = 6; - - while (lcv_turns) - { - x = dsp3_state.op1e_x; - y = dsp3_state.op1e_y; - - dsp3_OP1E_D1(lcv_turns, &x, &y); - - dsp3_state.DR = (UINT8)(x) | ((UINT8)(y)<<8); - dsp3_OP03(); - - cell = dsp3_state.DR; - - if (0 <= y && y < dsp3_state.WinHi && 0 <= x && x < dsp3_state.WinLo) - { - if (dsp3_state.op1e_terrain[cell] < 0x80 || dsp3_state.op1e_weight[cell] == 0) - { - if (dsp3_state.op1e_weight[cell] < path) - path = dsp3_state.op1e_weight[cell]; - } - } // end step travel - - lcv_turns--; - } // end while turns - - if (path != 0xff) - dsp3_state.op1e_weight[dsp3_state.op1e_cell] = path + dsp3_state.op1e_cost[dsp3_state.op1e_cell]; -} - - -static void dsp3_OP1E_C(void) -{ - int lcv; - - dsp3_state.op1e_min_radius = (UINT8)(dsp3_state.DR & 0x00ff); - dsp3_state.op1e_max_radius = (UINT8)((dsp3_state.DR & 0xff00) >> 8); - - if (dsp3_state.op1e_min_radius == 0) - dsp3_state.op1e_min_radius++; - - if (dsp3_state.op1e_max_path_radius >= dsp3_state.op1e_min_radius) - dsp3_state.op1e_min_radius = dsp3_state.op1e_max_path_radius + 1; - - if (dsp3_state.op1e_max_radius > dsp3_state.op1e_max_path_radius) - dsp3_state.op1e_max_path_radius = dsp3_state.op1e_max_radius; - - dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - - dsp3_state.op1e_lcv_turns = 6; - dsp3_state.op1e_turn = 0; - - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - - for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++) - dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - - dsp3_OP1E_C1(); -} - - -static void dsp3_OP1E_C1(void) -{ - int lcv; - - if (dsp3_state.op1e_lcv_steps == 0) - { - dsp3_state.op1e_lcv_radius++; - - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius; - - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - - for (lcv = 0; lcv < dsp3_state.op1e_lcv_radius; lcv++) - dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - } - - if (dsp3_state.op1e_lcv_radius > dsp3_state.op1e_max_radius) - { - dsp3_state.op1e_turn++; - dsp3_state.op1e_lcv_turns--; - - dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; - dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - - dsp3_state.op1e_x = dsp3_state.op3e_x; - dsp3_state.op1e_y = dsp3_state.op3e_y; - - for (lcv = 0; lcv < dsp3_state.op1e_min_radius; lcv++) - dsp3_OP1E_D(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - } - - if (dsp3_state.op1e_lcv_turns == 0) - { - dsp3_state.DR = 0xffff; - dsp3_state.SR = 0x0080; - dsp3_state.SetDSP3 = &dsp3_Reset; - return; - } - - dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8); - dsp3_OP03(); - - dsp3_state.op1e_cell = dsp3_state.DR; - - dsp3_state.SR = 0x0080; - dsp3_state.SetDSP3 = &dsp3_OP1E_C2; -} - - -static void dsp3_OP1E_C2(void) -{ - dsp3_state.DR = dsp3_state.op1e_weight[dsp3_state.op1e_cell]; - - dsp3_OP1E_D((INT16)(dsp3_state.op1e_turn + 2), &dsp3_state.op1e_x, &dsp3_state.op1e_y); - dsp3_state.op1e_lcv_steps--; - - dsp3_state.SR = 0x0084; - dsp3_state.SetDSP3 = &dsp3_OP1E_C1; -} - - -static void dsp3_OP1E_D( INT16 move, INT16 *lo, INT16 *hi ) -{ - UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; - INT16 Lo; - INT16 Hi; - - dsp3_state.AddHi = dsp3_state.DataROM[dataOfs]; - dsp3_state.AddLo = dsp3_state.DataROM[dataOfs + 1]; - - Lo = (UINT8)(*lo); - Hi = (UINT8)(*hi); - - if (Lo & 1) Hi += (dsp3_state.AddLo & 1); - - dsp3_state.AddLo += Lo; - dsp3_state.AddHi += Hi; - - if (dsp3_state.AddLo < 0) - dsp3_state.AddLo += dsp3_state.WinLo; - else if (dsp3_state.AddLo >= dsp3_state.WinLo) - dsp3_state.AddLo -= dsp3_state.WinLo; - - if (dsp3_state.AddHi < 0) - dsp3_state.AddHi += dsp3_state.WinHi; - else if (dsp3_state.AddHi >= dsp3_state.WinHi) - dsp3_state.AddHi -= dsp3_state.WinHi; - - *lo = dsp3_state.AddLo; - *hi = dsp3_state.AddHi; -} - - -static void dsp3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi ) -{ - //UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; - INT16 Lo; - INT16 Hi; - - const unsigned short HiAdd[] = { - 0x00, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, - 0x00, 0xFF, 0xFF, 0x00, 0x01, 0x00, 0xFF, 0x00 - }; - const unsigned short LoAdd[] = { - 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 - }; - - if ((*lo) & 1) - dsp3_state.AddHi = HiAdd[move + 8]; - else - dsp3_state.AddHi = HiAdd[move + 0]; - dsp3_state.AddLo = LoAdd[move]; - - Lo = (UINT8)(*lo); - Hi = (UINT8)(*hi); - - if (Lo & 1) - Hi += (dsp3_state.AddLo & 1); - - dsp3_state.AddLo += Lo; - dsp3_state.AddHi += Hi; - - *lo = dsp3_state.AddLo; - *hi = dsp3_state.AddHi; -} - - -static void dsp3_OP10(void) -{ - if (dsp3_state.DR == 0xffff ) - dsp3_Reset(); - else - { - // absorb 2 bytes - dsp3_state.DR = dsp3_state.DR; - } -} - -#ifdef UNUSED_FUNCTION -static void dsp3_OP0C_A(void) -{ - // absorb 2 bytes - - dsp3_state.DR = 0; - dsp3_state.SetDSP3 = &dsp3_Reset; -} -#endif - -static void dsp3_OP0C(void) -{ - // absorb 2 bytes - - dsp3_state.DR = 0; - //dsp3_state.SetDSP3 = &dsp3_OP0C_A; - dsp3_state.SetDSP3 = &dsp3_Reset; -} - - -static void dsp3_OP1C_C(void) -{ - // return 2 bytes - dsp3_state.DR = 0; - dsp3_state.SetDSP3 = &dsp3_Reset; -} - - -static void dsp3_OP1C_B(void) -{ - // absorb 2 bytes - - // return 2 bytes - dsp3_state.DR = 0; - dsp3_state.SetDSP3 = &dsp3_OP1C_C; -} - - -static void dsp3_OP1C_A(void) -{ - // absorb 2 bytes - - dsp3_state.SetDSP3 = &dsp3_OP1C_B; -} - - -static void dsp3_OP1C(void) -{ - // absorb 2 bytes - - dsp3_state.SetDSP3 = &dsp3_OP1C_A; -} - - -static void dsp3_Command(void) -{ - if (dsp3_state.DR < 0x40) - { - switch (dsp3_state.DR) - { - case 0x02: dsp3_state.SetDSP3 = &dsp3_Coordinate; break; - case 0x03: dsp3_state.SetDSP3 = &dsp3_OP03; break; - case 0x06: dsp3_state.SetDSP3 = &dsp3_OP06; break; - case 0x07: dsp3_state.SetDSP3 = &dsp3_OP07; return; - case 0x0c: dsp3_state.SetDSP3 = &dsp3_OP0C; break; - case 0x0f: dsp3_state.SetDSP3 = &dsp3_TestMemory; break; - case 0x10: dsp3_state.SetDSP3 = &dsp3_OP10; break; - case 0x18: dsp3_state.SetDSP3 = &dsp3_Convert; break; - case 0x1c: dsp3_state.SetDSP3 = &dsp3_OP1C; break; - case 0x1e: dsp3_state.SetDSP3 = &dsp3_OP1E; break; - case 0x1f: dsp3_state.SetDSP3 = &dsp3_MemoryDump; break; - case 0x38: dsp3_state.SetDSP3 = &dsp3_Decode; break; - case 0x3e: dsp3_state.SetDSP3 = &dsp3_OP3E; break; - default: return; - } - - dsp3_state.SR = 0x0080; - dsp3_state.Index = 0; - } -} - - -static void dsp3_write( UINT16 dsp3_address, UINT8 dsp3_byte ) -{ - if (dsp3_address < 0xC000) - { - if (dsp3_state.SR & 0x04) - { - dsp3_state.DR = (dsp3_state.DR & 0xff00) + dsp3_byte; - (*dsp3_state.SetDSP3)(); - } - else - { - dsp3_state.SR ^= 0x10; - - if (dsp3_state.SR & 0x10) - dsp3_state.DR = (dsp3_state.DR & 0xff00) + dsp3_byte; - else - { - dsp3_state.DR = (dsp3_state.DR & 0x00ff) + (dsp3_byte << 8); - (*dsp3_state.SetDSP3)(); - } - } - } -} - -static UINT8 dsp3_read( UINT16 dsp3_address ) -{ - UINT8 value; - if (dsp3_address < 0xC000) - { - if (dsp3_state.SR & 0x04) - { - value = (UINT8) dsp3_state.DR; - (*dsp3_state.SetDSP3)(); - } - else - { - dsp3_state.SR ^= 0x10; - - if (dsp3_state.SR & 0x10) - value = (UINT8) (dsp3_state.DR); - else - { - value = (UINT8) (dsp3_state.DR >> 8); - (*dsp3_state.SetDSP3)(); - } - } - - } - else - { - value = (UINT8) dsp3_state.SR; - } - - return value; -} - -static void dsp3_register_save( running_machine *machine ) -{ - state_save_register_global(machine, dsp3_state.DR); - state_save_register_global(machine, dsp3_state.SR); - state_save_register_global(machine, dsp3_state.MemoryIndex); - - state_save_register_global(machine, dsp3_state.AddLo); - state_save_register_global(machine, dsp3_state.AddHi); - state_save_register_global(machine, dsp3_state.WinLo); - state_save_register_global(machine, dsp3_state.WinHi); - state_save_register_global(machine, dsp3_state.Codewords); - state_save_register_global(machine, dsp3_state.Outwords); - state_save_register_global(machine, dsp3_state.Symbol); - state_save_register_global(machine, dsp3_state.BitCount); - state_save_register_global(machine, dsp3_state.Index); - state_save_register_global_array(machine, dsp3_state.Codes); - state_save_register_global(machine, dsp3_state.BitsLeft); - state_save_register_global(machine, dsp3_state.ReqBits); - state_save_register_global(machine, dsp3_state.ReqData); - state_save_register_global(machine, dsp3_state.BitCommand); - state_save_register_global(machine, dsp3_state.BaseLength); - state_save_register_global(machine, dsp3_state.BaseCodes); - state_save_register_global(machine, dsp3_state.BaseCode); - state_save_register_global_array(machine, dsp3_state.CodeLengths); - state_save_register_global_array(machine, dsp3_state.CodeOffsets); - state_save_register_global(machine, dsp3_state.LZCode); - state_save_register_global(machine, dsp3_state.LZLength); - - state_save_register_global(machine, dsp3_state.X); - state_save_register_global(machine, dsp3_state.Y); - - state_save_register_global_array(machine, dsp3_state.Bitmap); - state_save_register_global_array(machine, dsp3_state.Bitplane); - state_save_register_global(machine, dsp3_state.BMIndex); - state_save_register_global(machine, dsp3_state.BPIndex); - state_save_register_global(machine, dsp3_state.Count); - - state_save_register_global(machine, dsp3_state.op3e_x); - state_save_register_global(machine, dsp3_state.op3e_y); - - state_save_register_global_array(machine, dsp3_state.op1e_terrain); - state_save_register_global_array(machine, dsp3_state.op1e_cost); - state_save_register_global_array(machine, dsp3_state.op1e_weight); - - state_save_register_global(machine, dsp3_state.op1e_cell); - state_save_register_global(machine, dsp3_state.op1e_turn); - state_save_register_global(machine, dsp3_state.op1e_search); - - state_save_register_global(machine, dsp3_state.op1e_x); - state_save_register_global(machine, dsp3_state.op1e_y); - - state_save_register_global(machine, dsp3_state.op1e_min_radius); - state_save_register_global(machine, dsp3_state.op1e_max_radius); - - state_save_register_global(machine, dsp3_state.op1e_max_search_radius); - state_save_register_global(machine, dsp3_state.op1e_max_path_radius); - - state_save_register_global(machine, dsp3_state.op1e_lcv_radius); - state_save_register_global(machine, dsp3_state.op1e_lcv_steps); - state_save_register_global(machine, dsp3_state.op1e_lcv_turns); - -} - -static void dsp3_init( running_machine *machine ) -{ - UINT32 i; - UINT8 *dspin = machine->region("addons")->base(); - - dsp3_Reset(); - - // expand the DSP-3 data ROM - for (i = 0; i < 2048; i += 2) - { - dsp3_state.DataROM[i / 2] = dspin[0x800 + i] << 8 | dspin[0x800 + i + 1]; - } - - dsp3_register_save(machine); -} diff --git a/src/mame/machine/snesdsp4.c b/src/mame/machine/snesdsp4.c deleted file mode 100644 index 064cc0ffc30..00000000000 --- a/src/mame/machine/snesdsp4.c +++ /dev/null @@ -1,2264 +0,0 @@ -/************************************************************************ - - DSP-4 emulator code - - Copyright (c) 2004-2009 Dreamer Nom, John Weidman, Kris Bleakley, - Nach, z80 gaiden, and Jonas Quinn - - This code is released by ZSNES Team under GNU General Public License - version 2 as published by the Free Software Foundation. - The implementation below is released under the MAME license for use - in MAME, MESS and derivatives by permission of the authors. - -************************************************************************/ - - -/* -Due recognition and credit are given on Overload's DSP website. -Thank those contributors for their hard work on this chip. - - -Fixed-point math reminder: - -[sign, integer, fraction] -1.15.00 * 1.15.00 = 2.30.00 -> 1.30.00 (DSP) -> 1.31.00 (LSB is '0') -1.15.00 * 1.00.15 = 2.15.15 -> 1.15.15 (DSP) -> 1.15.16 (LSB is '0') -*/ - -#include "snesdsp4.h" - -static struct dsp4_t dsp4; -static struct dsp4_vars_t dsp4_vars; - -INLINE UINT16 READ_WORD(UINT8 *addr) -{ - return (addr[0]) + (addr[1] << 8); -} - -INLINE UINT32 READ_DWORD(UINT8 *addr) -{ - return (addr[0]) + (addr[1] << 8) + (addr[2] << 16) + (addr[3] << 24); -} - -INLINE void WRITE_WORD(UINT8 *addr, UINT16 data) -{ - addr[0] = data; - addr[1] = data >> 8; -} - - -////////////////////////////////////////////////////////////// - -// input protocol - -static INT16 DSP4_READ_WORD( void ) -{ - INT16 out; - - out = READ_WORD(dsp4.parameters + dsp4.in_index); - dsp4.in_index += 2; - - return out; -} - -static INT32 DSP4_READ_DWORD( void ) -{ - INT32 out; - - out = READ_DWORD(dsp4.parameters + dsp4.in_index); - dsp4.in_index += 4; - - return out; -} - - -////////////////////////////////////////////////////////////// - -// output protocol - -#define DSP4_CLEAR_OUT() \ -{ dsp4.out_count = 0; dsp4.out_index = 0; } - -#define DSP4_WRITE_BYTE( d ) \ -{ WRITE_WORD( dsp4.output + dsp4.out_count, ( d ) ); dsp4.out_count++; } - -#define DSP4_WRITE_WORD( d ) \ -{ WRITE_WORD( dsp4.output + dsp4.out_count, ( d ) ); dsp4.out_count += 2; } - -#ifndef MSB_FIRST -#define DSP4_WRITE_16_WORD( d ) \ -{ memcpy(dsp4.output + dsp4.out_count, ( d ), 32); dsp4.out_count += 32; } -#else -#define DSP4_WRITE_16_WORD( d ) \ -{ \ - INT16 *p = ( d ), *end = ( d )+16; \ - for (; p != end; p++) \ - { \ - WRITE_WORD( dsp4.output + dsp4.out_count, *p ); \ - } \ - dsp4.out_count += 32; \ -} -#endif - -#ifdef PRINT_OP -#define DSP4_WRITE_DEBUG( x, d ) \ - WRITE_WORD( nop + x, d ); -#endif - -#ifdef DEBUG_DSP -#define DSP4_WRITE_DEBUG( x, d ) \ - WRITE_WORD( nop + x, d ); -#endif - -////////////////////////////////////////////////////////////// - -// used to wait for dsp i/o - -#define DSP4_WAIT( x ) \ - dsp4.in_index = 0; dsp4_vars.Logic = x; return; - -////////////////////////////////////////////////////////////// - -// 1.7.8 -> 1.15.16 -#define SEX78( a ) ( ( (INT32) ( (INT16) (a) ) ) << 8 ) - -// 1.15.0 -> 1.15.16 -#define SEX16( a ) ( ( (INT32) ( (INT16) (a) ) ) << 16 ) - -#ifdef PRINT_OP -#define U16( a ) ( (UINT16) ( a ) ) -#endif - -#ifdef DEBUG_DSP -#define U16( a ) ( (UINT16) ( a ) ) -#endif - -////////////////////////////////////////////////////////////// - -// Attention: This lookup table is not verified -static const UINT16 div_lut[64] = { 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x1999, 0x1555, 0x1249, 0x1000, 0x0e38, - 0x0ccc, 0x0ba2, 0x0aaa, 0x09d8, 0x0924, 0x0888, 0x0800, 0x0787, 0x071c, 0x06bc, - 0x0666, 0x0618, 0x05d1, 0x0590, 0x0555, 0x051e, 0x04ec, 0x04bd, 0x0492, 0x0469, - 0x0444, 0x0421, 0x0400, 0x03e0, 0x03c3, 0x03a8, 0x038e, 0x0375, 0x035e, 0x0348, - 0x0333, 0x031f, 0x030c, 0x02fa, 0x02e8, 0x02d8, 0x02c8, 0x02b9, 0x02aa, 0x029c, - 0x028f, 0x0282, 0x0276, 0x026a, 0x025e, 0x0253, 0x0249, 0x023e, 0x0234, 0x022b, - 0x0222, 0x0219, 0x0210, 0x0208, }; -static INT16 dsp4_Inverse(INT16 value) -{ - // saturate bounds - if (value < 0) - { - value = 0; - } - if (value > 63) - { - value = 63; - } - - return div_lut[value]; -} - -////////////////////////////////////////////////////////////// - -// Prototype -static void dsp4_OP0B(UINT8 *draw, INT16 sp_x, INT16 sp_y, INT16 sp_attr, UINT8 size, UINT8 stop); - -////////////////////////////////////////////////////////////// - -// OP00 -static void dsp4_Multiply(INT16 Multiplicand, INT16 Multiplier, INT32 *Product) -{ - *Product = (Multiplicand * Multiplier << 1) >> 1; -} - -////////////////////////////////////////////////////////////// - - -static void dsp4_OP01( void ) -{ - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - 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_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 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; - - // 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; - - // 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(1) resume1 : - - // check for termination - dsp4_vars.distance = DSP4_READ_WORD(); - if (dsp4_vars.distance == -0x8000) - break; - - // road turnoff - if( (UINT16) dsp4_vars.distance == 0x8001 ) - { - dsp4.in_count = 6; - DSP4_WAIT(2) resume2: - - 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(1) - } - - // already have 2 bytes read - dsp4.in_count = 6; - DSP4_WAIT(3) resume3 : - - // 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 = 1; -} - -////////////////////////////////////////////////////////////// - - -static void dsp4_OP03( void ) -{ - dsp4_vars.OAM_RowMax = 33; - memset(dsp4_vars.OAM_Row, 0, 64); -} - - -////////////////////////////////////////////////////////////// - - -static void dsp4_OP05( void ) -{ - dsp4_vars.OAM_index = 0; - dsp4_vars.OAM_bits = 0; - memset(dsp4_vars.OAM_attr, 0, 32); - dsp4_vars.sprite_count = 0; -} - - -////////////////////////////////////////////////////////////// - -static void dsp4_OP06( void ) -{ - DSP4_CLEAR_OUT(); - DSP4_WRITE_16_WORD(dsp4_vars.OAM_attr); -} - -////////////////////////////////////////////////////////////// - - -static void dsp4_OP07( void ) -{ - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - } - - //////////////////////////////////////////////////// - // sort inputs - - 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) - { - 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 = 1; -} - -////////////////////////////////////////////////////////////// - -static void dsp4_OP08( void ) -{ - INT16 wleft, wright; - INT16 view_x[2], view_y[2]; - INT16 envelope[2][2]; - - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.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 - wleft = dsp4_vars.poly_cx[0][0] - view_x[0] + envelope[0][0]; - wright = dsp4_vars.poly_cx[0][1] - view_x[0] + envelope[0][1]; - - // saturate offscreen data for polygon #1 - if (wleft < dsp4_vars.poly_clipLf[0][0]) - { - wleft = dsp4_vars.poly_clipLf[0][0]; - } - if (wleft > dsp4_vars.poly_clipRt[0][0]) - { - wleft = dsp4_vars.poly_clipRt[0][0]; - } - if (wright < dsp4_vars.poly_clipLf[0][1]) - { - wright = dsp4_vars.poly_clipLf[0][1]; - } - if (wright > dsp4_vars.poly_clipRt[0][1]) - { - wright = dsp4_vars.poly_clipRt[0][1]; - } - - // SR = 0x80 - - // initial output for polygon #1 - DSP4_CLEAR_OUT(); - DSP4_WRITE_BYTE(wleft & 0xff); - DSP4_WRITE_BYTE(wright & 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) - x_left = (INT16)(win_left >> 16); - x_right = (INT16)(win_right >> 16); - - // saturate offscreen data - if (x_left < dsp4_vars.poly_clipLf[polygon][0]) - x_left = dsp4_vars.poly_clipLf[polygon][0]; - if (x_left > dsp4_vars.poly_clipRt[polygon][0]) - x_left = dsp4_vars.poly_clipRt[polygon][0]; - if (x_right < dsp4_vars.poly_clipLf[polygon][1]) - x_right = dsp4_vars.poly_clipLf[polygon][1]; - if (x_right > dsp4_vars.poly_clipRt[polygon][1]) - x_right = dsp4_vars.poly_clipRt[polygon][1]; - - // 1. HDMA memory pointer - // 2. Left window position ($2126/$2128) - // 3. Right window position ($2127/$2129) - - DSP4_WRITE_WORD(dsp4_vars.poly_ptr[polygon][0]); - DSP4_WRITE_BYTE(x_left & 0xff); - DSP4_WRITE_BYTE(x_right & 0xff); - - - // update memory pointers - dsp4_vars.poly_ptr[polygon][0] -= 4; - dsp4_vars.poly_ptr[polygon][1] -= 4; - } // end rasterize line - } - - //////////////////////////////////////////////// - // Post-update - - // new projection spot to continue rasterizing from - dsp4_vars.poly_start[polygon] = view_x[poly]; - } // end polygon rasterizer - } - while (1); - - // unknown output - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(0); - - - dsp4.waiting4command = 1; -} - -////////////////////////////////////////////////////////////// - -static void dsp4_OP09( void ) -{ - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.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; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // grab screen information - dsp4_vars.viewport_cx = DSP4_READ_WORD(); - dsp4_vars.viewport_cy = DSP4_READ_WORD(); - DSP4_READ_WORD(); // 0x0000 - dsp4_vars.viewport_left = DSP4_READ_WORD(); - dsp4_vars.viewport_right = DSP4_READ_WORD(); - dsp4_vars.viewport_top = DSP4_READ_WORD(); - dsp4_vars.viewport_bottom = DSP4_READ_WORD(); - - // starting dsp4_vars.raster line below the horizon - dsp4_vars.poly_bottom[0][0] = dsp4_vars.viewport_bottom - dsp4_vars.viewport_cy; - dsp4_vars.poly_raster[0][0] = 0x100; - - do - { - //////////////////////////////////////////////////// - // check for new sprites - - dsp4.in_count = 4; - DSP4_WAIT(1) resume1 : - - //////////////////////////////////////////////// - // dsp4_vars.raster overdraw check - - dsp4_vars.raster = DSP4_READ_WORD(); - - // continue updating the dsp4_vars.raster line where overdraw begins - if (dsp4_vars.raster < dsp4_vars.poly_raster[0][0]) - { - dsp4_vars.sprite_clipy = dsp4_vars.viewport_bottom - (dsp4_vars.poly_bottom[0][0] - dsp4_vars.raster); - dsp4_vars.poly_raster[0][0] = dsp4_vars.raster; - } - - ///////////////////////////////////////////////// - // identify sprite - - // op termination - dsp4_vars.distance = DSP4_READ_WORD(); - if (dsp4_vars.distance == -0x8000) - goto terminate; - - - // no sprite - if (dsp4_vars.distance == 0x0000) - { - continue; - } - - //////////////////////////////////////////////////// - // process projection information - - // vehicle sprite - if ((UINT16) dsp4_vars.distance == 0x9000) - { - INT16 car_left, car_right, car_back; - INT16 impact_left, impact_back; - INT16 world_spx, world_spy; - INT16 view_spx, view_spy; - UINT16 energy; - - // we already have 4 bytes we want - dsp4.in_count = 14; - DSP4_WAIT(2) resume2 : - - // filter inputs - energy = DSP4_READ_WORD(); - impact_back = DSP4_READ_WORD(); - car_back = DSP4_READ_WORD(); - impact_left = DSP4_READ_WORD(); - car_left = DSP4_READ_WORD(); - dsp4_vars.distance = DSP4_READ_WORD(); - car_right = DSP4_READ_WORD(); - - // calculate car's world (x,y) values - world_spx = car_right - car_left; - world_spy = car_back; - - // add in collision vector [needs bit-twiddling] - world_spx -= energy * (impact_left - car_left) >> 16; - world_spy -= energy * (car_back - impact_back) >> 16; - - // perspective correction for world (x,y) - view_spx = world_spx * dsp4_vars.distance >> 15; - view_spy = world_spy * dsp4_vars.distance >> 15; - - // convert to screen values - dsp4_vars.sprite_x = dsp4_vars.viewport_cx + view_spx; - dsp4_vars.sprite_y = dsp4_vars.viewport_bottom - (dsp4_vars.poly_bottom[0][0] - view_spy); - - // make the car's (x)-coordinate available - DSP4_CLEAR_OUT(); - DSP4_WRITE_WORD(world_spx); - - // grab a few remaining vehicle values - dsp4.in_count = 4; - DSP4_WAIT(3) resume3 : - - // add vertical lift factor - dsp4_vars.sprite_y += DSP4_READ_WORD(); - } - // terrain sprite - else - { - INT16 world_spx, world_spy; - INT16 view_spx, view_spy; - - // we already have 4 bytes we want - dsp4.in_count = 10; - DSP4_WAIT(4) resume4 : - - // sort loop inputs - dsp4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - dsp4_vars.poly_raster[0][1] = DSP4_READ_WORD(); - world_spx = DSP4_READ_WORD(); - world_spy = DSP4_READ_WORD(); - - // compute base dsp4_vars.raster line from the bottom - dsp4_vars.segments = dsp4_vars.poly_bottom[0][0] - dsp4_vars.raster; - - // perspective correction for world (x,y) - view_spx = world_spx * dsp4_vars.distance >> 15; - view_spy = world_spy * dsp4_vars.distance >> 15; - - // convert to screen values - dsp4_vars.sprite_x = dsp4_vars.viewport_cx + view_spx - dsp4_vars.poly_cx[0][0]; - dsp4_vars.sprite_y = dsp4_vars.viewport_bottom - dsp4_vars.segments + view_spy; - } - - // default sprite size: 16x16 - dsp4_vars.sprite_size = 1; - dsp4_vars.sprite_attr = DSP4_READ_WORD(); - - //////////////////////////////////////////////////// - // convert tile data to SNES OAM format - - do - { - UINT16 header; - - INT16 sp_x, sp_y, sp_attr, sp_dattr; - INT16 sp_dx, sp_dy; - INT16 pixels; - - UINT8 draw; - - dsp4.in_count = 2; - DSP4_WAIT(5) resume5 : - - draw = 1; - - // opcode termination - dsp4_vars.raster = DSP4_READ_WORD(); - if (dsp4_vars.raster == -0x8000) - goto terminate; - - // stop code - if (dsp4_vars.raster == 0x0000 && !dsp4_vars.sprite_size) - break; - - // toggle sprite size - if (dsp4_vars.raster == 0x0000) - { - dsp4_vars.sprite_size = !dsp4_vars.sprite_size; - continue; - } - - // check for valid sprite header - header = dsp4_vars.raster; - header >>= 8; - if (header != 0x20 && - header != 0x2e && //This is for attractor sprite - header != 0x40 && - header != 0x60 && - header != 0xa0 && - header != 0xc0 && - header != 0xe0) - break; - - // read in rest of sprite data - dsp4.in_count = 4; - DSP4_WAIT(6) resume6 : - - draw = 1; - - ///////////////////////////////////// - // process tile data - - // sprite deltas - sp_dattr = dsp4_vars.raster; - sp_dy = DSP4_READ_WORD(); - sp_dx = DSP4_READ_WORD(); - - // update coordinates to screen space - sp_x = dsp4_vars.sprite_x + sp_dx; - sp_y = dsp4_vars.sprite_y + sp_dy; - - // update sprite nametable/attribute information - sp_attr = dsp4_vars.sprite_attr + sp_dattr; - - // allow partially visibile tiles - pixels = dsp4_vars.sprite_size ? 15 : 7; - - DSP4_CLEAR_OUT(); - - // transparent tile to clip off parts of a sprite (overdraw) - if (dsp4_vars.sprite_clipy - pixels <= sp_y && - sp_y <= dsp4_vars.sprite_clipy && - sp_x >= dsp4_vars.viewport_left - pixels && - sp_x <= dsp4_vars.viewport_right && - dsp4_vars.sprite_clipy >= dsp4_vars.viewport_top - pixels && - dsp4_vars.sprite_clipy <= dsp4_vars.viewport_bottom) - { - dsp4_OP0B(&draw, sp_x, dsp4_vars.sprite_clipy, 0x00EE, dsp4_vars.sprite_size, 0); - } - - - // normal sprite tile - if (sp_x >= dsp4_vars.viewport_left - pixels && - sp_x <= dsp4_vars.viewport_right && - sp_y >= dsp4_vars.viewport_top - pixels && - sp_y <= dsp4_vars.viewport_bottom && - sp_y <= dsp4_vars.sprite_clipy) - { - dsp4_OP0B(&draw, sp_x, sp_y, sp_attr, dsp4_vars.sprite_size, 0); - } - - - // no following OAM data - dsp4_OP0B(&draw, 0, 0x0100, 0, 0, 1); - } - while (1); - } - while (1); - - terminate : dsp4.waiting4command = 1; -} - -////////////////////////////////////////////////////////////// - -static const UINT16 OP0A_Values[16] = { 0x0000, 0x0030, 0x0060, 0x0090, 0x00c0, 0x00f0, 0x0120, 0x0150, 0xfe80, - 0xfeb0, 0xfee0, 0xff10, 0xff40, 0xff70, 0xffa0, 0xffd0 }; - -static void dsp4_OP0A(INT16 n2, INT16 *o1, INT16 *o2, INT16 *o3, INT16 *o4) -{ - *o4 = OP0A_Values[(n2 & 0x000f)]; - *o3 = OP0A_Values[(n2 & 0x00f0) >> 4]; - *o2 = OP0A_Values[(n2 & 0x0f00) >> 8]; - *o1 = OP0A_Values[(n2 & 0xf000) >> 12]; -} - -////////////////////////////////////////////////////////////// - -static void dsp4_OP0B(UINT8 *draw, INT16 sp_x, INT16 sp_y, INT16 sp_attr, UINT8 size, UINT8 stop) -{ - INT16 Row1, Row2; - - // SR = 0x00 - - // align to nearest 8-pixel row - Row1 = (sp_y >> 3) & 0x1f; - Row2 = (Row1 + 1) & 0x1f; - - // check boundaries - if (!((sp_y < 0) || ((sp_y & 0x01ff) < 0x00eb))) - { - *draw = 0; - } - if (size) - { - if (dsp4_vars.OAM_Row[Row1] + 1 >= dsp4_vars.OAM_RowMax) - *draw = 0; - if (dsp4_vars.OAM_Row[Row2] + 1 >= dsp4_vars.OAM_RowMax) - *draw = 0; - } - else - { - if (dsp4_vars.OAM_Row[Row1] >= dsp4_vars.OAM_RowMax) - { - *draw = 0; - } - } - - // emulator fail-safe (unknown if this really exists) - if (dsp4_vars.sprite_count >= 128) - { - *draw = 0; - } - - // SR = 0x80 - - if (*draw) - { - // Row tiles - if (size) - { - dsp4_vars.OAM_Row[Row1] += 2; - dsp4_vars.OAM_Row[Row2] += 2; - } - else - { - dsp4_vars.OAM_Row[Row1]++; - } - - // yield OAM output - DSP4_WRITE_WORD(1); - - // pack OAM data: x,y,name,attr - DSP4_WRITE_BYTE(sp_x & 0xff); - DSP4_WRITE_BYTE(sp_y & 0xff); - DSP4_WRITE_WORD(sp_attr); - - dsp4_vars.sprite_count++; - - // OAM: size,msb data - // save post-oam table data for future retrieval - dsp4_vars.OAM_attr[dsp4_vars.OAM_index] |= ((sp_x <0 || sp_x> 255) << dsp4_vars.OAM_bits); - dsp4_vars.OAM_bits++; - - dsp4_vars.OAM_attr[dsp4_vars.OAM_index] |= (size << dsp4_vars.OAM_bits); - dsp4_vars.OAM_bits++; - - // move to next byte in buffer - if (dsp4_vars.OAM_bits == 16) - { - dsp4_vars.OAM_bits = 0; - dsp4_vars.OAM_index++; - } - } - else if (stop) - { - // yield no OAM output - DSP4_WRITE_WORD(0); - } -} - -////////////////////////////////////////////////////////////// - -static void dsp4_OP0D( void ) -{ - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs - - // sort inputs - 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 = 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 = 1; -} - -////////////////////////////////////////////////////////////// - - -static void dsp4_OP0E( void ) -{ - dsp4_vars.OAM_RowMax = 16; - memset(dsp4_vars.OAM_Row, 0, 64); -} - - -////////////////////////////////////////////////////////////// - -static void dsp4_OP0F( void ) -{ - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.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 = 1; -} - -////////////////////////////////////////////////////////////// - - -static void dsp4_OP10( void ) -{ - dsp4.waiting4command = 0; - - // op flow control - switch (dsp4_vars.Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - } - - //////////////////////////////////////////////////// - // 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 = 1; -} - -////////////////////////////////////////////////////////////// - -static 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 -///////////////////////////////////////////////////////////// - -static void dsp4_register_save( running_machine *machine ) -{ - state_save_register_global(machine, dsp4.waiting4command); - state_save_register_global(machine, dsp4.half_command); - state_save_register_global(machine, dsp4.command); - state_save_register_global(machine, dsp4.in_count); - state_save_register_global(machine, dsp4.in_index); - state_save_register_global(machine, dsp4.out_count); - state_save_register_global(machine, dsp4.out_index); - state_save_register_global_array(machine, dsp4.parameters); - state_save_register_global_array(machine, dsp4.output); - - state_save_register_global(machine, dsp4_vars.Logic); - state_save_register_global(machine, dsp4_vars.lcv); - state_save_register_global(machine, dsp4_vars.distance); - state_save_register_global(machine, dsp4_vars.raster); - state_save_register_global(machine, dsp4_vars.segments); - - state_save_register_global(machine, dsp4_vars.world_x); - state_save_register_global(machine, dsp4_vars.world_y); - state_save_register_global(machine, dsp4_vars.world_dx); - state_save_register_global(machine, dsp4_vars.world_dy); - state_save_register_global(machine, dsp4_vars.world_ddx); - state_save_register_global(machine, dsp4_vars.world_ddy); - state_save_register_global(machine, dsp4_vars.world_xenv); - state_save_register_global(machine, dsp4_vars.world_yofs); - - state_save_register_global(machine, dsp4_vars.view_x1); - state_save_register_global(machine, dsp4_vars.view_y1); - state_save_register_global(machine, dsp4_vars.view_x2); - state_save_register_global(machine, dsp4_vars.view_y2); - state_save_register_global(machine, dsp4_vars.view_dx); - state_save_register_global(machine, dsp4_vars.view_dy); - state_save_register_global(machine, dsp4_vars.view_xofs1); - state_save_register_global(machine, dsp4_vars.view_yofs1); - state_save_register_global(machine, dsp4_vars.view_xofs2); - state_save_register_global(machine, dsp4_vars.view_yofs2); - state_save_register_global(machine, dsp4_vars.view_yofsenv); - state_save_register_global(machine, dsp4_vars.view_turnoff_x); - state_save_register_global(machine, dsp4_vars.view_turnoff_dx); - - - state_save_register_global(machine, dsp4_vars.viewport_cx); - state_save_register_global(machine, dsp4_vars.viewport_cy); - state_save_register_global(machine, dsp4_vars.viewport_left); - state_save_register_global(machine, dsp4_vars.viewport_right); - state_save_register_global(machine, dsp4_vars.viewport_top); - state_save_register_global(machine, dsp4_vars.viewport_bottom); - - - state_save_register_global(machine, dsp4_vars.sprite_x); - state_save_register_global(machine, dsp4_vars.sprite_y); - state_save_register_global(machine, dsp4_vars.sprite_attr); - state_save_register_global(machine, dsp4_vars.sprite_size); - state_save_register_global(machine, dsp4_vars.sprite_clipy); - state_save_register_global(machine, dsp4_vars.sprite_count); - - state_save_register_global_array(machine, dsp4_vars.poly_clipLf[0]); - state_save_register_global_array(machine, dsp4_vars.poly_clipLf[1]); - state_save_register_global_array(machine, dsp4_vars.poly_clipRt[0]); - state_save_register_global_array(machine, dsp4_vars.poly_clipRt[1]); - state_save_register_global_array(machine, dsp4_vars.poly_ptr[0]); - state_save_register_global_array(machine, dsp4_vars.poly_ptr[1]); - state_save_register_global_array(machine, dsp4_vars.poly_raster[0]); - state_save_register_global_array(machine, dsp4_vars.poly_raster[1]); - state_save_register_global_array(machine, dsp4_vars.poly_top[0]); - state_save_register_global_array(machine, dsp4_vars.poly_top[1]); - state_save_register_global_array(machine, dsp4_vars.poly_bottom[0]); - state_save_register_global_array(machine, dsp4_vars.poly_bottom[1]); - state_save_register_global_array(machine, dsp4_vars.poly_cx[0]); - state_save_register_global_array(machine, dsp4_vars.poly_cx[1]); - state_save_register_global_array(machine, dsp4_vars.poly_start); - state_save_register_global_array(machine, dsp4_vars.poly_plane); - - state_save_register_global_array(machine, dsp4_vars.OAM_attr); - state_save_register_global(machine, dsp4_vars.OAM_index); - state_save_register_global(machine, dsp4_vars.OAM_bits); - - state_save_register_global(machine, dsp4_vars.OAM_RowMax); - state_save_register_global_array(machine, dsp4_vars.OAM_Row); -} - -static void dsp4_init( running_machine *machine ) -{ - memset(&dsp4, 0, sizeof(dsp4)); - dsp4.waiting4command = 1; - - dsp4_register_save(machine); -} - -static void dsp4_write( UINT8 dsp4_byte ) -{ - // 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 = 0; - dsp4.half_command = 0; - dsp4.out_count = 0; - dsp4.out_index = 0; - - dsp4_vars.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 = 1; - break; - } - } - else - { - dsp4.command = dsp4_byte; - dsp4.half_command = 1; - } - } - 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 = 1; - 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 in2a; - INT16 out1a, out2a, out3a, out4a; - - /* in1a = */ DSP4_READ_WORD(); - in2a = DSP4_READ_WORD(); - /* in3a = */ DSP4_READ_WORD(); - - 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(); - UINT8 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; - } - } -} - -static UINT8 dsp4_read( void ) -{ - UINT8 value; - - if (dsp4.out_count) - { - value = (UINT8) dsp4.output[dsp4.out_index&0x1FF]; - dsp4.out_index++; - if (dsp4.out_count == dsp4.out_index) - dsp4.out_count = 0; - } - else - { - value = 0xff; - } - - return value; -} diff --git a/src/mame/machine/snesdsp4.h b/src/mame/machine/snesdsp4.h deleted file mode 100644 index fd3fd0bceb7..00000000000 --- a/src/mame/machine/snesdsp4.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef SNESDSP4_H -#define SNESDSP4_H - -#define FALSE 0 -#define TRUE 1 - - -struct dsp4_t -{ - UINT8 waiting4command; - UINT8 half_command; - UINT16 command; - UINT32 in_count; - UINT32 in_index; - UINT32 out_count; - UINT32 out_index; - UINT8 parameters[512]; - UINT8 output[512]; -}; - -struct dsp4_vars_t -{ - // op control - INT8 Logic; // controls op flow - - - // projection format - INT16 lcv; // loop-control variable - INT16 distance; // z-position into virtual world - INT16 raster; // current raster line - INT16 segments; // number of raster lines drawn - - // 1.15.16 or 1.15.0 [sign, INTeger, fraction] - INT32 world_x; // line of x-projection in world - INT32 world_y; // line of y-projection in world - INT32 world_dx; // projection line x-delta - INT32 world_dy; // projection line y-delta - INT16 world_ddx; // x-delta increment - INT16 world_ddy; // y-delta increment - INT32 world_xenv; // world x-shaping factor - INT16 world_yofs; // world y-vertical scroll - - INT16 view_x1; // current viewer-x - INT16 view_y1; // current viewer-y - INT16 view_x2; // future viewer-x - INT16 view_y2; // future viewer-y - INT16 view_dx; // view x-delta factor - INT16 view_dy; // view y-delta factor - INT16 view_xofs1; // current viewer x-vertical scroll - INT16 view_yofs1; // current viewer y-vertical scroll - INT16 view_xofs2; // future viewer x-vertical scroll - INT16 view_yofs2; // future viewer y-vertical scroll - INT16 view_yofsenv; // y-scroll shaping factor - INT16 view_turnoff_x; // road turnoff data - INT16 view_turnoff_dx; // road turnoff delta factor - - - // drawing area - - INT16 viewport_cx; // x-center of viewport window - INT16 viewport_cy; // y-center of render window - INT16 viewport_left; // x-left of viewport - INT16 viewport_right; // x-right of viewport - INT16 viewport_top; // y-top of viewport - INT16 viewport_bottom; // y-bottom of viewport - - - // sprite structure - - INT16 sprite_x; // projected x-pos of sprite - INT16 sprite_y; // projected y-pos of sprite - INT16 sprite_attr; // obj attributes - UINT8 sprite_size; // sprite size: 8x8 or 16x16 - INT16 sprite_clipy; // visible line to clip pixels off - INT16 sprite_count; - - // generic projection variables designed for - // two solid polygons + two polygon sides - - INT16 poly_clipLf[2][2]; // left clip boundary - INT16 poly_clipRt[2][2]; // right clip boundary - INT16 poly_ptr[2][2]; // HDMA structure pointers - INT16 poly_raster[2][2]; // current raster line below horizon - INT16 poly_top[2][2]; // top clip boundary - INT16 poly_bottom[2][2]; // bottom clip boundary - INT16 poly_cx[2][2]; // center for left/right points - INT16 poly_start[2]; // current projection points - INT16 poly_plane[2]; // previous z-plane distance - - - // OAM - INT16 OAM_attr[16]; // OAM (size,MSB) data - INT16 OAM_index; // index into OAM table - INT16 OAM_bits; // offset into OAM table - - INT16 OAM_RowMax; // maximum number of tiles per 8 aligned pixels (row) - INT16 OAM_Row[32]; // current number of tiles per row -}; - -#endif