diff options
author | Fabio Priuli <etabeta78@users.noreply.github.com> | 2010-03-22 18:00:22 +0000 |
---|---|---|
committer | Fabio Priuli <etabeta78@users.noreply.github.com> | 2010-03-22 18:00:22 +0000 |
commit | 00cf9859782e74ceadd47f1b1cb41fa837a9d287 (patch) | |
tree | 15accdd43499a9911c0f62015d5ab58ac53ee5b5 | |
parent | ef6e27822afc242027df6ea32db31ad7f4fe7aa6 (diff) |
snes.c: updated DSP1, DSP2, DSP3, DSP4, OBC1, SRTC and ST010 addon chips to store their variables in struct and to save them [Fabio Priuli]
-rw-r--r-- | src/mame/machine/snes.c | 76 | ||||
-rw-r--r-- | src/mame/machine/snesdsp1.c | 2128 | ||||
-rw-r--r-- | src/mame/machine/snesdsp2.c | 368 | ||||
-rw-r--r-- | src/mame/machine/snesdsp3.c | 1192 | ||||
-rw-r--r-- | src/mame/machine/snesdsp4.c | 3843 | ||||
-rw-r--r-- | src/mame/machine/snesdsp4.h | 172 | ||||
-rw-r--r-- | src/mame/machine/snesobc1.c | 54 | ||||
-rw-r--r-- | src/mame/machine/snesrtc.c | 135 | ||||
-rw-r--r-- | src/mame/machine/snesst10.c | 591 |
9 files changed, 4463 insertions, 4096 deletions
diff --git a/src/mame/machine/snes.c b/src/mame/machine/snes.c index 761b5419b2c..04b2d5d89b9 100644 --- a/src/mame/machine/snes.c +++ b/src/mame/machine/snes.c @@ -365,7 +365,7 @@ READ8_HANDLER( snes_r_io ) { if (offset == 0x2800 || offset == 0x2801) { - return srtc_mmio_read(space->machine, offset); + return srtc_read(space->machine, offset); } } else if (snes_has_addon_chip == HAS_SDD1) @@ -731,7 +731,7 @@ WRITE8_HANDLER( snes_w_io ) { if (offset == 0x2800 || offset == 0x2801) { - srtc_mmio_write(space->machine, offset, data); + srtc_write(space->machine, offset, data); return; } } @@ -1443,9 +1443,9 @@ READ8_HANDLER( snes_r_bank1 ) else if (snes_has_addon_chip == HAS_OBC1) value = obc1_read(space, offset); else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000)) - value = (address < 0x7000) ? DSP2_read() : 0x00; + value = (address < 0x7000) ? dsp2_read() : 0x00; else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000)) - value = (address < 0x7000) ? DSP1_getDr() : DSP1_getSr(); + value = (address < 0x7000) ? dsp1_get_dr() : dsp1_get_sr(); else if (snes_has_addon_chip == HAS_CX4) value = CX4_read(address - 0x6000); else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) @@ -1459,11 +1459,11 @@ READ8_HANDLER( snes_r_bank1 ) } } else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) - value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr(); + value = (address < 0xc000) ? dsp1_get_dr() : dsp1_get_sr(); else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000)) - value = (address < 0xc000) ? DSP2_read() : 0x00; + value = (address < 0xc000) ? dsp2_read() : 0x00; else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000)) - value = DSP3_read(address); + value = dsp3_read(address); else value = snes_ram[offset]; @@ -1485,7 +1485,7 @@ READ8_HANDLER( snes_r_bank2 ) if (snes_has_addon_chip == HAS_OBC1) value = obc1_read (space, offset); else if (snes_has_addon_chip == HAS_DSP2) - value = (address < 0x7000) ? DSP2_read() : 0x00; + value = (address < 0x7000) ? dsp2_read() : 0x00; else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) { value = snes_ram[0x306000 + (offset & 0x1fff)]; @@ -1504,13 +1504,13 @@ READ8_HANDLER( snes_r_bank2 ) } /* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */ else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1)) - value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr(); + value = (address < 0xc000) ? dsp1_get_dr() : dsp1_get_sr(); else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2)) - value = (address < 0xc000) ? DSP2_read() : 0x00; + value = (address < 0xc000) ? dsp2_read() : 0x00; else if (snes_has_addon_chip == HAS_DSP3) - value = DSP3_read(address); + value = dsp3_read(address); else if (snes_has_addon_chip == HAS_DSP4) - value = (address < 0xc000) ? DSP4_read() : 0x80; + value = (address < 0xc000) ? dsp4_read() : 0x80; else value = snes_ram[0x300000 + offset]; @@ -1565,7 +1565,7 @@ READ8_HANDLER( snes_r_bank4 ) value = snes_ram[0x600000 + offset]; /* some other dsp1 games use these banks 0x60 to 0x6f at address 0x0000 */ else if (snes_has_addon_chip == HAS_DSP1) - value = (address >= 0x4000) ? DSP1_getSr() : DSP1_getDr(); + value = (address >= 0x4000) ? dsp1_get_sr() : dsp1_get_dr(); else { logerror( "snes_r_bank4: Unmapped external chip read: %04x\n", address ); @@ -1645,13 +1645,13 @@ READ8_HANDLER( snes_r_bank6 ) } } else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) - value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr(); + value = (address < 0xc000) ? dsp1_get_dr() : dsp1_get_sr(); else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000)) - value = (address < 0xc000) ? DSP2_read() : 0x00; + value = (address < 0xc000) ? dsp2_read() : 0x00; else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000)) - value = DSP3_read(address); + value = dsp3_read(address); else if ((snes_has_addon_chip == HAS_DSP4) && (offset >= 0x300000)) - value = (address < 0xc000) ? DSP4_read() : 0x80; + value = (address < 0xc000) ? dsp4_read() : 0x80; else value = snes_ram[0x800000 + offset]; @@ -1709,9 +1709,9 @@ WRITE8_HANDLER( snes_w_bank1 ) else if (snes_has_addon_chip == HAS_OBC1) obc1_write(space, offset, data); else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000)) - DSP2_write(data); + dsp2_write(data); else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000)) - DSP1_setDr(data); + dsp1_set_dr(data); else if (snes_has_addon_chip == HAS_CX4) CX4_write(space->machine, address - 0x6000, data); else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) @@ -1722,11 +1722,11 @@ WRITE8_HANDLER( snes_w_bank1 ) logerror( "snes_w_bank1: Attempt to write to reserved address: %x = %02x\n", offset, data ); } else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) - DSP1_setDr(data); + dsp1_set_dr(data); else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000)) - DSP2_write(data); + dsp2_write(data); else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000)) - DSP3_write(address, data); + dsp3_write(address, data); else logerror( "Attempt to write to ROM address: %X\n", offset ); } @@ -1745,7 +1745,7 @@ WRITE8_HANDLER( snes_w_bank2 ) if (snes_has_addon_chip == HAS_OBC1) obc1_write(space, offset, data); else if (snes_has_addon_chip == HAS_DSP2) - DSP2_write(data); + dsp2_write(data); else if (snes_has_addon_chip == HAS_SPC7110 || snes_has_addon_chip == HAS_SPC7110_RTC) { snes_ram[0x306000 + (offset & 0x1fff)] = data; @@ -1762,13 +1762,13 @@ WRITE8_HANDLER( snes_w_bank2 ) } /* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */ else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1)) - DSP1_setDr(data); + dsp1_set_dr(data); else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (address < 0xc000)) - DSP2_write(data); + dsp2_write(data); else if (snes_has_addon_chip == HAS_DSP3) - DSP3_write(address, data); + dsp3_write(address, data); else if ((snes_has_addon_chip == HAS_DSP4) && (address < 0xc000)) - DSP4_write(data); + dsp4_write(data); else logerror("Attempt to write to ROM address: %X\n", offset + 0x300000); } @@ -1795,7 +1795,7 @@ WRITE8_HANDLER( snes_w_bank4 ) } else if (snes_has_addon_chip == HAS_DSP1) { - DSP1_setDr(data); + dsp1_set_dr(data); } else { @@ -1880,13 +1880,13 @@ WRITE8_HANDLER( snes_w_bank6 ) } } else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) - DSP1_setDr(data); + dsp1_set_dr(data); else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000)) - DSP2_write(data); + dsp2_write(data); else if ((snes_has_addon_chip == HAS_DSP3) && (offset >= 0x200000)) - DSP3_write(address, data); + dsp3_write(address, data); else if ((snes_has_addon_chip == HAS_DSP4) && (offset >= 0x300000) && (address < 0xc000)) - DSP4_write(data); + dsp4_write(data); else if (snes_has_addon_chip == HAS_SUPERFX && state->superfx != NULL) logerror( "snes_w_bank6 hit (ROM) in Super FX mode, please fix me\n" ); else @@ -2103,23 +2103,23 @@ static void snes_init_ram( running_machine *machine ) switch (snes_has_addon_chip) { case HAS_DSP1: - DSP1_reset(machine); + dsp1_init(machine); break; case HAS_DSP2: - DSP2_reset(); + dsp2_init(machine); break; case HAS_DSP3: - InitDSP3(machine); + dsp3_init(machine); break; case HAS_DSP4: - InitDSP4(); + dsp4_init(machine); break; case HAS_RTC: - srtc_reset(machine); + srtc_init(machine); break; case HAS_SDD1: @@ -2127,7 +2127,7 @@ static void snes_init_ram( running_machine *machine ) break; case HAS_OBC1: - obc1_init(); + obc1_init(machine); break; case HAS_ST010: diff --git a/src/mame/machine/snesdsp1.c b/src/mame/machine/snesdsp1.c index 3680bf32bbc..31c89917827 100644 --- a/src/mame/machine/snesdsp1.c +++ b/src/mame/machine/snesdsp1.c @@ -12,34 +12,70 @@ ***************************************************************************/ -#define DSP1_VERSION 0x0102 +#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}; +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. +// 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. +// 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. +// 0: Internal Data Register Transfer. +// 1: External Data Register Transfer. -enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA}; -enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024}; +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 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? ;) + + ////////////////////////////////////////////////////////////////// @@ -54,166 +90,145 @@ struct DSP1_Command { // 257-points arccos table that, apparently, have been not used anywhere // (maybe for the MaxAZS_Exp table?). -static UINT16 DSP1_DataRom[1024]; - -static 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) - -} shared; - -static UINT8 mSr; // status register -static int mSrLowByteAccess; -static UINT16 mDr; // "internal" representation of the data register -static enum FsmMajorState mFsmMajorState; // current major state of the FSM -static UINT8 mCommand; // current command processed by the FSM -static UINT8 mDataCounter; // #UINT16 read/writes counter used by the FSM -static INT16 mReadBuffer[MAX_READS]; -static INT16 mWriteBuffer[MAX_WRITES]; -static UINT8 mFreeze; // need explanation? ;) - -static void DSP1_fsmStep(UINT8 read, UINT8 *data); // FSM logic + 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_memoryTest(INT16 *input, INT16 *output); -static void DSP1_memoryDump(INT16 *input, INT16 *output); -static void DSP1_memorySize(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); +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 INT16 dsp1_sin(INT16 Angle); +static INT16 dsp1_cos(INT16 Angle); static void inverse(INT16 Coefficient, INT16 Exponent, INT16 *iCoefficient, INT16 *iExponent); -static INT16 denormalizeAndClip(INT16 C, INT16 E); +static INT16 denormalize_and_clip(INT16 C, INT16 E); static void normalize(INT16 m, INT16 *Coefficient, INT16 *Exponent); -static void normalizeDouble(INT32 Product, 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] = +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_memoryTest, 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_memoryTest, 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_memoryDump, 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_memoryDump, 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_memorySize, 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_memorySize, 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_memoryDump, 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_memoryDump, 1, 1024}, //0x1f + {&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] = { +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_SinTable[256] = { +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, @@ -250,7 +265,7 @@ static const INT16 DSP1_SinTable[256] = { ////////////////////////////////////////////////////////////////// // Optimised for Performance -static const INT16 DSP1_MulTable[256] = { +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, @@ -286,55 +301,54 @@ static const INT16 DSP1_MulTable[256] = { ////////////////////////////////////////////////////////////////// -static UINT8 DSP1_getSr(void) +static UINT8 dsp1_get_sr( void ) { - mSrLowByteAccess = ~mSrLowByteAccess; - if (mSrLowByteAccess) - { - return 0; - } - else - { - return mSr; - } + dsp1_state.SrLowByteAccess = ~dsp1_state.SrLowByteAccess; + + if (dsp1_state.SrLowByteAccess) + return 0; + else + return dsp1_state.Sr; } ////////////////////////////////////////////////////////////////// -static UINT8 DSP1_getDr(void) +static UINT8 dsp1_get_dr( void ) { - UINT8 oDr; + UINT8 oDr; - DSP1_fsmStep(1, &oDr); - return oDr; + dsp1_fsm_step(1, &oDr); + return oDr; } ////////////////////////////////////////////////////////////////// -static void DSP1_setDr(UINT8 iDr) +static void dsp1_set_dr( UINT8 iDr ) { - DSP1_fsmStep(0, &iDr); + dsp1_fsm_step(0, &iDr); } ////////////////////////////////////////////////////////////////// -static void DSP1_reset(running_machine *machine) +static void dsp1_init( running_machine *machine ) { UINT32 i; UINT8 *dspin = memory_region(machine, "addons"); - mSr = DRC|RQM; - mSrLowByteAccess = FALSE; - mDr = 0x0080; // Only a supposition. Is this correct? - mFreeze = FALSE; - mFsmMajorState = WAIT_COMMAND; - memset(&shared, 0, sizeof(struct SharedData)); // another supposition + 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) + for (i = 0; i < 2048; i += 2) { - DSP1_DataRom[i/2] = dspin[i]<<8 | dspin[i+1]; + dsp1_state.DataRom[i / 2] = (dspin[i] << 8) | dspin[i + 1]; } + + dsp1_register_save(machine); } ////////////////////////////////////////////////////////////////// @@ -344,183 +358,188 @@ static void DSP1_reset(running_machine *machine) // is responsible for maintaining the binding between the // "external" and "internal" representations of the DR (data register). -static void DSP1_fsmStep(UINT8 read, UINT8 *data) +static void dsp1_fsm_step( UINT8 read, UINT8 *data ) { - if (0 == (mSr&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 (mSr&DRS) - *data = (UINT8)(mDr>>8); - else - *data = (UINT8)(mDr); - } - else - { - if (mSr&DRS) - { - mDr &= 0x00ff; - mDr |= *data<<8; - } - else - { - mDr &= 0xff00; - mDr |= *data; - } - } - - - switch (mFsmMajorState) - { - case WAIT_COMMAND: - mCommand = (UINT8)(mDr); - if (!(mCommand & 0xc0)) // valid command? - { - switch(mCommand) - { - // freeze cases - case 0x1a: - case 0x2a: - case 0x3a: - mFreeze = TRUE; - break; - // normal cases - default: - mDataCounter=0; - mFsmMajorState = READ_DATA; - mSr &= ~DRC; - break; - } - } - break; - case READ_DATA: - mSr ^= DRS; - if (!(mSr&DRS)) - { - mReadBuffer[mDataCounter++] = (INT16)(mDr); - if (mDataCounter >= mCommandTable[mCommand].reads) - { - (*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); - if (0 != mCommandTable[mCommand].writes) // any output? - { - mDataCounter = 0; - mDr = (UINT16)(mWriteBuffer[mDataCounter]); - mFsmMajorState = WRITE_DATA; - } - else - { - mDr = 0x0080; // valid command completion - mFsmMajorState = WAIT_COMMAND; - mSr |= DRC; - } - } - } - break; - case WRITE_DATA: - mSr ^= DRS; - if (!(mSr&DRS)) - { - ++mDataCounter; - if (mDataCounter >= mCommandTable[mCommand].writes) - { - if ((mCommand == 0x0a)&&(mDr != 0x8000)) - { - // works in continuous mode - mReadBuffer[0]++; // next raster line - (*mCommandTable[mCommand].callback)(mReadBuffer, mWriteBuffer); - mDataCounter = 0; - mDr = (UINT16)(mWriteBuffer[mDataCounter]); - } - else - { - mDr = 0x0080; // valid command completion - mFsmMajorState = WAIT_COMMAND; - mSr |= DRC; - } - } - else - { - mDr = (UINT16)(mWriteBuffer[mDataCounter]); - } - } - break; - } - - - - // Now RQM would be set (except when executing Op1A -command equals 0x1a, 0x2a or 0x3a-). - if (mFreeze) - mSr &= ~RQM; + 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_memoryTest(INT16 *input, INT16 *output) +static void dsp1_memory_test( INT16 *input, INT16 *output ) { -// INT16 *Size = &input[0]; - INT16 *Result = &output[0]; +// INT16 *Size = &input[0]; + INT16 *Result = &output[0]; - *Result = 0x0000; + *Result = 0x0000; } ////////////////////////////////////////////////////////////////// -static void DSP1_memoryDump(INT16 *input, INT16 *output) +static void dsp1_memory_dump( INT16 *input, INT16 *output ) { - memcpy(output, DSP1_DataRom, 1024); + memcpy(output, dsp1_state.DataRom, 1024); } ////////////////////////////////////////////////////////////////// -static void DSP1_memorySize(INT16 *input, INT16 *output) +static void dsp1_memory_size( INT16 *input, INT16 *output ) { - INT16* Size = &output[0]; + INT16* Size = &output[0]; - *Size = 0x0100; + *Size = 0x0100; } ////////////////////////////////////////////////////////////////// // 16-bit multiplication -static void DSP1_multiply(INT16 *input, INT16 *output) +static void dsp1_multiply( INT16 *input, INT16 *output ) { - INT16 Multiplicand = input[0]; - INT16 Multiplier = input[1]; - INT16* Product = &output[0]; + INT16 Multiplicand = input[0]; + INT16 Multiplier = input[1]; + INT16* Product = &output[0]; - *Product = Multiplicand * Multiplier >> 15; + *Product = Multiplicand * Multiplier >> 15; } ////////////////////////////////////////////////////////////////// // 16-bit multiplication. 'Alternative' method. Can anyone check this carefully? -static void DSP1_multiply2(INT16 *input, INT16 *output) +static void dsp1_multiply2( INT16 *input, INT16 *output ) { - INT16 Multiplicand = input[0]; - INT16 Multiplier = input[1]; - INT16* Product = &output[0]; + INT16 Multiplicand = input[0]; + INT16 Multiplier = input[1]; + INT16* Product = &output[0]; - *Product = (Multiplicand * Multiplier >> 15)+1; + *Product = (Multiplicand * Multiplier >> 15) + 1; } ////////////////////////////////////////////////////////////////// // This command determines the inverse of a floating point decimal number. -static void DSP1_inverse(INT16 *input, INT16 *output) +static void dsp1_inverse( INT16 *input, INT16 *output ) { - INT16 Coefficient = input[0]; - INT16 Exponent = input[1]; - INT16* iCoefficient = &output[0]; - INT16* iExponent = &output[1]; + INT16 Coefficient = input[0]; + INT16 Exponent = input[1]; + INT16* iCoefficient = &output[0]; + INT16* iExponent = &output[1]; - inverse(Coefficient, Exponent, iCoefficient, iExponent); + inverse(Coefficient, Exponent, iCoefficient, iExponent); } ////////////////////////////////////////////////////////////////// @@ -530,15 +549,15 @@ static void DSP1_inverse(INT16 *input, INT16 *output) // Y = Radius * sin(Angle) // X = Radius * cos(Angle) -static void DSP1_triangle(INT16 *input, INT16 *output) +static void dsp1_triangle( INT16 *input, INT16 *output ) { - INT16 Angle = input[0]; - INT16 Radius = input[1]; - INT16* Y = &output[0]; - INT16* X = &output[1]; + 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; + *Y = dsp1_sin(Angle) * Radius >> 15; + *X = dsp1_cos(Angle) * Radius >> 15; } ////////////////////////////////////////////////////////////////// @@ -546,19 +565,19 @@ static void DSP1_triangle(INT16 *input, INT16 *output) // 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) +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]; + INT16 X = input[0]; + INT16 Y = input[1]; + INT16 Z = input[2]; + INT16* RadiusLow = &output[0]; + INT16* RadiusHigh = &output[1]; - INT32 Radius; + INT32 Radius; - Radius = (X * X + Y * Y + Z * Z) << 1; - *RadiusLow = (INT16)(Radius); - *RadiusHigh = (INT16)(Radius>>16); + Radius = (X * X + Y * Y + Z * Z) << 1; + *RadiusLow = (INT16)(Radius); + *RadiusHigh = (INT16)(Radius >> 16); } ////////////////////////////////////////////////////////////////// @@ -567,30 +586,30 @@ static void DSP1_radius(INT16 *input, INT16 *output) // 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) +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]; + 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; + *Range = (X * X + Y * Y + Z * Z - Radius * Radius) >> 15; } ////////////////////////////////////////////////////////////////// // Vector size comparison. 'Alternative' method. -static void DSP1_range2(INT16 *input, INT16 *output) +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]; + 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; + *Range = ((X * X + Y * Y + Z * Z - Radius * Radius) >> 15) + 1; } ////////////////////////////////////////////////////////////////// @@ -603,36 +622,39 @@ static void DSP1_range2(INT16 *input, INT16 *output) // 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) +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; + 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; + INT32 Radius = X * X + Y * Y + Z * Z; - if (Radius == 0) Distance = 0; - else - { - INT16 C, E; - normalizeDouble(Radius, &C, &E); - if (E & 1) C = C * 0x4000 >> 15; + 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; + Pos = C * 0x0040 >> 15; - Node1 = DSP1_DataRom[0x00d5 + Pos]; - Node2 = DSP1_DataRom[0x00d6 + Pos]; + Node1 = dsp1_state.DataRom[0x00d5 + Pos]; + Node2 = dsp1_state.DataRom[0x00d6 + Pos]; - *Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; + *Distance = ((Node2 - Node1) * (C & 0x1ff) >> 9) + Node1; -#if DSP1_VERSION < 0x0102 - if (Pos & 1) *Distance -= (Node2 - Node1); +#if dsp1_VERSION < 0x0102 + if (Pos & 1) + *Distance -= (Node2 - Node1); #endif *Distance >>= (E >> 1); - } + } } ////////////////////////////////////////////////////////////////// @@ -642,20 +664,20 @@ static void DSP1_distance(INT16 *input, INT16 *output) // 'counterclockwise', but it's obviously wrong (surprise! :P) // // In matrix notation: -// |X2| |cos(Angle) sin(Angle)| |X1| -// | | = | | | | -// |Y2| |-sin(Angle cos(Angle)| |Y1| +// |X2| |cos(Angle) sin(Angle)| |X1| +// | | = | | | | +// |Y2| |-sin(Angle cos(Angle)| |Y1| -static void DSP1_rotate(INT16 *input, INT16 *output) +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); + 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); } ////////////////////////////////////////////////////////////////// @@ -668,46 +690,46 @@ static void DSP1_rotate(INT16 *input, INT16 *output) // 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| +// |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) +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; + 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| +// 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 @@ -736,99 +758,99 @@ static void DSP1_polar(INT16 *input, INT16 *output) // input[2]: Ry // input[3]: Rx -static void DSP1_attitudeA(INT16 *input, INT16 *output) +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; - - shared.MatrixA[0][0] = (S * CosRz >> 15) * CosRy >> 15; - shared.MatrixA[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixA[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixA[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - shared.MatrixA[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixA[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixA[2][0] = S * SinRy >> 15; - shared.MatrixA[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - shared.MatrixA[2][2] = (S * CosRx >> 15) * CosRy >> 15; + 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) +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; - - shared.MatrixB[0][0] = (S * CosRz >> 15) * CosRy >> 15; - shared.MatrixB[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixB[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixB[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - shared.MatrixB[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixB[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixB[2][0] = S * SinRy >> 15; - shared.MatrixB[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - shared.MatrixB[2][2] = (S * CosRx >> 15) * CosRy >> 15; + 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) +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; - - shared.MatrixC[0][0] = (S * CosRz >> 15) * CosRy >> 15; - shared.MatrixC[0][1] = ((S * SinRz >> 15) * CosRx >> 15) + (((S * CosRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixC[0][2] = ((S * SinRz >> 15) * SinRx >> 15) - (((S * CosRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixC[1][0] = -((S * SinRz >> 15) * CosRy >> 15); - shared.MatrixC[1][1] = ((S * CosRz >> 15) * CosRx >> 15) - (((S * SinRz >> 15) * SinRx >> 15) * SinRy >> 15); - shared.MatrixC[1][2] = ((S * CosRz >> 15) * SinRx >> 15) + (((S * SinRz >> 15) * CosRx >> 15) * SinRy >> 15); - - shared.MatrixC[2][0] = S * SinRy >> 15; - shared.MatrixC[2][1] = -((S * SinRx >> 15) * CosRy >> 15); - shared.MatrixC[2][2] = (S * CosRx >> 15) * CosRy >> 15; + 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; } ////////////////////////////////////////////////////////////////// @@ -839,54 +861,54 @@ static void DSP1_attitudeC(INT16 *input, INT16 *output) // 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) +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 = (shared.MatrixA[0][0] * X >> 15) + (shared.MatrixA[1][0] * Y >> 15) + (shared.MatrixA[2][0] * Z >> 15); - *L = (shared.MatrixA[0][1] * X >> 15) + (shared.MatrixA[1][1] * Y >> 15) + (shared.MatrixA[2][1] * Z >> 15); - *U = (shared.MatrixA[0][2] * X >> 15) + (shared.MatrixA[1][2] * Y >> 15) + (shared.MatrixA[2][2] * Z >> 15); + 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) +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 = (shared.MatrixB[0][0] * X >> 15) + (shared.MatrixB[1][0] * Y >> 15) + (shared.MatrixB[2][0] * Z >> 15); - *L = (shared.MatrixB[0][1] * X >> 15) + (shared.MatrixB[1][1] * Y >> 15) + (shared.MatrixB[2][1] * Z >> 15); - *U = (shared.MatrixB[0][2] * X >> 15) + (shared.MatrixB[1][2] * Y >> 15) + (shared.MatrixB[2][2] * Z >> 15); + 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) +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 = (shared.MatrixC[0][0] * X >> 15) + (shared.MatrixC[1][0] * Y >> 15) + (shared.MatrixC[2][0] * Z >> 15); - *L = (shared.MatrixC[0][1] * X >> 15) + (shared.MatrixC[1][1] * Y >> 15) + (shared.MatrixC[2][1] * Z >> 15); - *U = (shared.MatrixC[0][2] * X >> 15) + (shared.MatrixC[1][2] * Y >> 15) + (shared.MatrixC[2][2] * Z >> 15); + 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); } ////////////////////////////////////////////////////////////////// @@ -897,54 +919,54 @@ static void DSP1_objectiveC(INT16 *input, INT16 *output) // 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) +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 = (shared.MatrixA[0][0] * F >> 15) + (shared.MatrixA[0][1] * L >> 15) + (shared.MatrixA[0][2] * U >> 15); - *Y = (shared.MatrixA[1][0] * F >> 15) + (shared.MatrixA[1][1] * L >> 15) + (shared.MatrixA[1][2] * U >> 15); - *Z = (shared.MatrixA[2][0] * F >> 15) + (shared.MatrixA[2][1] * L >> 15) + (shared.MatrixA[2][2] * U >> 15); + 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) +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 = (shared.MatrixB[0][0] * F >> 15) + (shared.MatrixB[0][1] * L >> 15) + (shared.MatrixB[0][2] * U >> 15); - *Y = (shared.MatrixB[1][0] * F >> 15) + (shared.MatrixB[1][1] * L >> 15) + (shared.MatrixB[1][2] * U >> 15); - *Z = (shared.MatrixB[2][0] * F >> 15) + (shared.MatrixB[2][1] * L >> 15) + (shared.MatrixB[2][2] * U >> 15); + 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) +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 = (shared.MatrixC[0][0] * F >> 15) + (shared.MatrixC[0][1] * L >> 15) + (shared.MatrixC[0][2] * U >> 15); - *Y = (shared.MatrixC[1][0] * F >> 15) + (shared.MatrixC[1][1] * L >> 15) + (shared.MatrixC[1][2] * U >> 15); - *Z = (shared.MatrixC[2][0] * F >> 15) + (shared.MatrixC[2][1] * L >> 15) + (shared.MatrixC[2][2] * U >> 15); + 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); } ////////////////////////////////////////////////////////////////// @@ -958,42 +980,42 @@ static void DSP1_subjectiveC(INT16 *input, INT16 *output) // input[0]: X ; input[1]: Y ; input[2]: Z // &output[0]: S -static void DSP1_scalarA(INT16 *input, INT16 *output) +static void dsp1_scalarA( INT16 *input, INT16 *output ) { - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* S = &output[0]; + INT16 X = input[0]; + INT16 Y = input[1]; + INT16 Z = input[2]; + INT16* S = &output[0]; - *S = (X * shared.MatrixA[0][0] + Y * shared.MatrixA[1][0] + Z * shared.MatrixA[2][0]) >> 15; + *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) +static void dsp1_scalarB( INT16 *input, INT16 *output ) { - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* S = &output[0]; + INT16 X = input[0]; + INT16 Y = input[1]; + INT16 Z = input[2]; + INT16* S = &output[0]; - *S = (X * shared.MatrixB[0][0] + Y * shared.MatrixB[1][0] + Z * shared.MatrixB[2][0]) >> 15; + *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) +static void dsp1_scalarC( INT16 *input, INT16 *output ) { - INT16 X = input[0]; - INT16 Y = input[1]; - INT16 Z = input[2]; - INT16* S = &output[0]; + INT16 X = input[0]; + INT16 Y = input[1]; + INT16 Z = input[2]; + INT16* S = &output[0]; - *S = (X * shared.MatrixC[0][0] + Y * shared.MatrixC[1][0] + Z * shared.MatrixC[2][0]) >> 15; + *S = (X * dsp1_state.shared.MatrixC[0][0] + Y * dsp1_state.shared.MatrixC[1][0] + Z * dsp1_state.shared.MatrixC[2][0]) >> 15; } ////////////////////////////////////////////////////////////////// @@ -1016,46 +1038,46 @@ static void DSP1_scalarC(INT16 *input, INT16 *output) // 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) +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 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); + INT16 CSec, ESec, CSin, C, E; + INT16 SinAy = dsp1_sin(Ay); + INT16 CosAy = dsp1_cos(Ay); - inverse(DSP1_cos(Ax), 0, &CSec, &ESec); + inverse(dsp1_cos(Ax), 0, &CSec, &ESec); - // Rotation Around Z - normalizeDouble(U * CosAy - F * SinAy, &C, &E); + // Rotation Around Z + normalize_double(U * CosAy - F * SinAy, &C, &E); - E = ESec - E; + E = ESec - E; - normalize(C * CSec >> 15, &C, &E); + normalize(C * CSec >> 15, &C, &E); - *Rz = Az + denormalizeAndClip(C, E); + *Rz = Az + denormalize_and_clip(C, E); - // Rotation Around X - *Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15); + // Rotation Around X + *Rx = Ax + (U * SinAy >> 15) + (F * CosAy >> 15); - // Rotation Around Y - normalizeDouble(U * CosAy + F * SinAy, &C, &E); + // Rotation Around Y + normalize_double(U * CosAy + F * SinAy, &C, &E); - E = ESec - E; + E = ESec - E; - normalize(DSP1_sin(Ax), &CSin, &E); + normalize(dsp1_sin(Ax), &CSin, &E); - normalize(-(C * (CSec * CSin >> 15) >> 15), &C, &E); + normalize(-(C * (CSec * CSin >> 15) >> 15), &C, &E); - *Ry = Ay + denormalizeAndClip(C, E) + L; + *Ry = Ay + denormalize_and_clip(C, E) + L; } ////////////////////////////////////////////////////////////////// @@ -1074,155 +1096,165 @@ static void DSP1_gyrate(INT16 *input, INT16 *output) // 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) +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 - shared.Les = Les; - shared.E_Les=0; - normalize(Les, &shared.C_Les, &shared.E_Les); - - // Store Sine and Cosine of Azimuth and Zenith angle - shared.SinAas = DSP1_sin(Aas); - shared.CosAas = DSP1_cos(Aas); - shared.SinAzs = DSP1_sin(Azs); - shared.CosAzs = DSP1_cos(Azs); - - // normal vector to the screen (norm 1, points toward the center of projection) - shared.Nx = shared.SinAzs * -shared.SinAas >> 15; - shared.Ny = shared.SinAzs * shared.CosAas >> 15; - shared.Nz = shared.CosAzs * 0x7fff >> 15; - - // horizontal vector of the screen (Hz=0, norm 1, points toward the right of the screen) - shared.Hx = shared.CosAas*0x7fff>>15; - shared.Hy = shared.SinAas*0x7fff>>15; - - // vertical vector of the screen (norm 1, points toward the top of the screen) - shared.Vx = shared.CosAzs*-shared.SinAas>>15; - shared.Vy = shared.CosAzs*shared.CosAas>>15; - shared.Vz = -shared.SinAzs*0x7fff>>15; - - LfeNx = Lfe*shared.Nx>>15; - LfeNy = Lfe*shared.Ny>>15; - LfeNz = Lfe*shared.Nz>>15; - - // Center of Projection - shared.CentreX = Fx+LfeNx; - shared.CentreY = Fy+LfeNy; - shared.CentreZ = Fz+LfeNz; - - LesNx = Les*shared.Nx>>15; - LesNy = Les*shared.Ny>>15; - LesNz = Les*shared.Nz>>15; - - // center of the screen (global coordinates) - shared.Gx=shared.CentreX-LesNx; - shared.Gy=shared.CentreY-LesNy; - shared.Gz=shared.CentreZ-LesNz; - - - E = 0; - normalize(shared.CentreZ, &C, &E); - - shared.CentreZ_C = C; - 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 - shared.SinAZS = DSP1_sin(AZS); - 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(shared.CosAZS, 0, &shared.SecAZS_C1, &shared.SecAZS_E1); - normalize(C * shared.SecAZS_C1 >> 15, &C, &E); - E += shared.SecAZS_E1; - C = denormalizeAndClip(C, E) * shared.SinAZS >> 15; - - // ... and then take into account the position of the centre of - // projection and the azimuth angle - shared.CentreX += C * shared.SinAas >> 15; - shared.CentreY -= C * shared.CosAas >> 15; - - *Cx = shared.CentreX; - *Cy = 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_DataRom[0x0328] >> 15; - C = (C * Aux >> 15) + DSP1_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_DataRom[0x0324] >> 15) + DSP1_DataRom[0x0325]; - shared.CosAZS += (C * Aux >> 15) * shared.CosAZS >> 15; - } - - // vertical offset of the screen with regard to the horizontal plane - // containing the centre of projection - shared.VOffset = Les * 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(shared.SinAZS, 0, &CSec, &E); - normalize(shared.VOffset, &C, &E); - normalize(C * CSec >> 15, &C, &E); - - if (C == -32768) { C >>= 1; E++; } - - *Vva = denormalizeAndClip(-C, E); - - // Store Secant of clipped Zenith angle - inverse(shared.CosAZS, 0, &shared.SecAZS_C2, &shared.SecAZS_E2); + 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); } ////////////////////////////////////////////////////////////////// @@ -1242,9 +1274,9 @@ static void DSP1_parameter(INT16 *input, INT16 *output) // 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)| +// |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 @@ -1252,34 +1284,34 @@ static void DSP1_parameter(INT16 *input, INT16 *output) // 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) +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 Vs = input[0]; + INT16* An = &output[0]; + INT16* Bn = &output[1]; + INT16* Cn = &output[2]; + INT16* Dn = &output[3]; - INT16 C, E, C1, E1; + INT16 C, E, C1, E1; - inverse((Vs * shared.SinAzs >> 15) + shared.VOffset, 7, &C, &E); + inverse((Vs * dsp1_state.shared.SinAzs >> 15) + dsp1_state.shared.VOffset, 7, &C, &E); - E += shared.CentreZ_E; - C1 = C * shared.CentreZ_C >> 15; + E += dsp1_state.shared.CentreZ_E; + C1 = C * dsp1_state.shared.CentreZ_C >> 15; - E1 = E + shared.SecAZS_E2; + E1 = E + dsp1_state.shared.SecAZS_E2; - normalize(C1, &C, &E); - C = denormalizeAndClip(C, E); + normalize(C1, &C, &E); + C = denormalize_and_clip(C, E); - *An = C * shared.CosAas >> 15; - *Cn = C * shared.SinAas >> 15; + *An = C * dsp1_state.shared.CosAas >> 15; + *Cn = C * dsp1_state.shared.SinAas >> 15; - normalize(C1 * shared.SecAZS_C2 >> 15, &C, &E1); - C = denormalizeAndClip(C, E1); + normalize(C1 * dsp1_state.shared.SecAZS_C2 >> 15, &C, &E1); + C = denormalize_and_clip(C, E1); - *Bn = C * -shared.SinAas >> 15; - *Dn = C * shared.CosAas >> 15; + *Bn = C * -dsp1_state.shared.SinAas >> 15; + *Dn = C * dsp1_state.shared.CosAas >> 15; } ////////////////////////////////////////////////////////////////// @@ -1292,35 +1324,35 @@ static void DSP1_raster(INT16 *input, INT16 *output) // 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) +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 H = input[0]; + INT16 V = input[1]; + INT16* X = &output[0]; + INT16* Y = &output[1]; - INT16 C, E, C1, E1; + INT16 C, E, C1, E1; - inverse((V * shared.SinAzs >> 15) + shared.VOffset, 8, &C, &E); + inverse((V * dsp1_state.shared.SinAzs >> 15) + dsp1_state.shared.VOffset, 8, &C, &E); - E += shared.CentreZ_E; - C1 = C * shared.CentreZ_C >> 15; + E += dsp1_state.shared.CentreZ_E; + C1 = C * dsp1_state.shared.CentreZ_C >> 15; - E1 = E + shared.SecAZS_E1; + E1 = E + dsp1_state.shared.SecAZS_E1; - H <<= 8; - normalize(C1, &C, &E); - C = denormalizeAndClip(C, E) * H >> 15; + H <<= 8; + normalize(C1, &C, &E); + C = denormalize_and_clip(C, E) * H >> 15; - *X = shared.CentreX + (C * shared.CosAas >> 15); - *Y = shared.CentreY - (C * shared.SinAas >> 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 * shared.SecAZS_C1 >> 15, &C, &E1); - C = denormalizeAndClip(C, E1) * V >> 15; + V <<= 8; + normalize(C1 * dsp1_state.shared.SecAZS_C1 >> 15, &C, &E1); + C = denormalize_and_clip(C, E1) * V >> 15; - *X += C * -shared.SinAas >> 15; - *Y += C * shared.CosAas >> 15; + *X += C * -dsp1_state.shared.SinAas >> 15; + *Y += C * dsp1_state.shared.CosAas >> 15; } ////////////////////////////////////////////////////////////////// @@ -1329,82 +1361,83 @@ static void DSP1_target(INT16 *input, INT16 *output) // '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) +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; - - normalizeDouble((INT32)(X)-shared.Gx, &Px, &E4); - normalizeDouble((INT32)(Y)-shared.Gy, &Py, &E); - normalizeDouble((INT32)(Z)-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*shared.Nx>>15); - C8= -(Py*shared.Ny>>15); - C9= -(Pz*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)(shared.Les) + aux4; // Les - the scalar product of P with the normal vector of the screen - normalizeDouble(aux, &C10, &E2); - E2 = 15-E2; - - inverse(C10, 0, &C4, &E4); - C2=C4*shared.C_Les>>15; // scale factor - - - // H - E7=0; - C16= (Px*shared.Hx>>15); - C20= (Py*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=denormalizeAndClip(C19, shared.E_Les-E2+refE+E7); - - // V - E6=0; - C21 = Px*shared.Vx>>15; - C22 = Py*shared.Vy>>15; - C23 = Pz*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=denormalizeAndClip(C25, shared.E_Les-E2+refE+E6); - - // M - normalize(C2, &C6, &E4); - *M=denormalizeAndClip(C6, E4+shared.E_Les-E2-7); // M is the scale factor divided by 2^7 + 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 } ////////////////////////////////////////////////////////////////// @@ -1413,17 +1446,21 @@ static void DSP1_project(INT16 *input, INT16 *output) // this is done by linear interpolation between // the points of a look-up table -static INT16 DSP1_sin(INT16 Angle) +static INT16 dsp1_sin( INT16 Angle ) { - INT32 S; - - if (Angle < 0) { - if (Angle == -32768) return 0; - return -DSP1_sin(-Angle); - } - S = DSP1_SinTable[Angle >> 8] + (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[0x40 + (Angle >> 8)] >> 15); - if (S > 32767) S = 32767; - return (INT16) S; + 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; } ////////////////////////////////////////////////////////////////// @@ -1431,17 +1468,20 @@ static INT16 DSP1_sin(INT16 Angle) // Calculate the cosine of the input parameter. // It's used the same method than in sin(INT16) -static INT16 DSP1_cos(INT16 Angle) +static INT16 dsp1_cos( INT16 Angle ) { - INT32 S; - - if (Angle < 0) { - if (Angle == -32768) return -32768; - Angle = -Angle; - } - S = DSP1_SinTable[0x40 + (Angle >> 8)] - (DSP1_MulTable[Angle & 0xff] * DSP1_SinTable[Angle >> 8] >> 15); - if (S < -32768) S = -32767; - return (INT16) S; + 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; } ////////////////////////////////////////////////////////////////// @@ -1455,65 +1495,73 @@ static INT16 DSP1_cos(INT16 Angle) // 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) +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_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; - } + // 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 denormalizeAndClip(INT16 C, INT16 E) +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_DataRom[0x0031 + E] >> 15; - } - return C; + 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; } ////////////////////////////////////////////////////////////////// @@ -1523,96 +1571,152 @@ static INT16 denormalizeAndClip(INT16 C, INT16 E) // where the absolute value of Coefficient is >= 1/2 // (Coefficient>=0x4000 or Coefficient <= (INT16)0xc001) -static void normalize(INT16 m, INT16 *Coefficient, INT16 *Exponent) +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_DataRom[0x21 + e] << 1; - else - *Coefficient = m; - - *Exponent -= e; + 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 normalizeDouble(INT32 Product, INT16 *Coefficient, INT16 *Exponent) +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_DataRom[0x0021 + e] << 1; - - if (e < 15) - *Coefficient += n * DSP1_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_DataRom[0x0012 + e] << 1; - else - *Coefficient += n; - } - } - else - *Coefficient = m; - - *Exponent = e; + 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) +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 ) { - return (C * DSP1_DataRom[0x0031 + E] >> 15); + 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 index de4f9557999..bbdce8179e3 100644 --- a/src/mame/machine/snesdsp2.c +++ b/src/mame/machine/snesdsp2.c @@ -13,36 +13,43 @@ ***************************************************************************/ -static int DSP2_waiting_for_command = 0; -static int DSP2_command = 0; -static int DSP2_in_count = 0, DSP2_in_index = 0; -static int DSP2_out_count = 0, DSP2_out_index = 0; - -static UINT8 DSP2_parameters[512] = {0}; -static UINT8 DSP2_output[512] = {0}; - -static UINT8 DSP2_op05transparent = 0; -static int DSP2_op05haslen = 0; -static int DSP2_op05len = 0; -static int DSP2_op06haslen = 0; -static int DSP2_op06len = 0; -static UINT16 DSP2_op09word1 = 0; -static UINT16 DSP2_op09word2 = 0; -static int DSP2_op0dhaslen = 0; -static int DSP2_op0doutlen = 0; -static int DSP2_op0dinlen = 0; +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 ) +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_parameters; - unsigned char *p2a = DSP2_output; - unsigned char *p2b = DSP2_output + 16; //halfway + 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 @@ -92,13 +99,13 @@ static void DSP2_op01( void ) } //set transparent color -static void DSP2_op03( void ) +static void dsp2_op03( void ) { - DSP2_op05transparent = DSP2_parameters[0]; + dsp2_state.op05transparent = dsp2_state.parameters[0]; } //replace bitmap using transparent color -static void DSP2_op05( void ) +static void dsp2_op05( void ) { UINT8 color; // Overlay bitmap with transparency. @@ -127,53 +134,53 @@ static void DSP2_op05( void ) // proven necessary. unsigned char c1, c2; - unsigned char *p1 = DSP2_parameters; - unsigned char *p2 = DSP2_parameters + DSP2_op05len; - unsigned char *p3 = DSP2_output; + 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_op05transparent & 0x0f; + color = dsp2_state.op05transparent & 0x0f; - for (n = 0; n < DSP2_op05len; n++) + 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 ); + *p3++ = (((c2 >> 4) == color) ? c1 & 0xf0 : c2 & 0xf0) | + (((c2 & 0x0f) == color) ? c1 & 0x0f : c2 & 0x0f); } } //reverse bitmap -static void DSP2_op06( void ) +static void dsp2_op06( void ) { // Input: // size // bitmap int i, j; - for (i = 0, j = DSP2_op06len - 1; i < DSP2_op06len; i++, j--) + for (i = 0, j = dsp2_state.op06len - 1; i < dsp2_state.op06len; i++, j--) { - DSP2_output[j] = (DSP2_parameters[i] << 4) | (DSP2_parameters[i] >> 4); + dsp2_state.output[j] = (dsp2_state.parameters[i] << 4) | (dsp2_state.parameters[i] >> 4); } } //multiply -static void DSP2_op09( void ) +static void dsp2_op09( void ) { UINT32 r = 0; - DSP2_out_count = 4; + dsp2_state.out_count = 4; - DSP2_op09word1 = DSP2_parameters[0] | (DSP2_parameters[1] << 8); - DSP2_op09word2 = DSP2_parameters[2] | (DSP2_parameters[3] << 8); + 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_op09word1 * DSP2_op09word2; - DSP2_output[0] = r; - DSP2_output[1] = r >> 8; - DSP2_output[2] = r >> 16; - DSP2_output[3] = r >> 24; + 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 ) +static void dsp2_op0d( void ) { // Bit accurate hardware algorithm - uses fixed point math // This should match the DSP2 Op0D output exactly @@ -193,174 +200,203 @@ static void DSP2_op0d( void ) UINT32 pixloc; // match size of multiplier int i, j; UINT8 pixelarray[512]; - if (DSP2_op0dinlen <= DSP2_op0doutlen) + if (dsp2_state.op0dinlen <= dsp2_state.op0doutlen) { multiplier = 0x10000; // In our self defined fixed point 0x10000 == 1 } else { - multiplier = (DSP2_op0dinlen << 17) / ((DSP2_op0doutlen << 1) + 1); + multiplier = (dsp2_state.op0dinlen << 17) / ((dsp2_state.op0doutlen << 1) + 1); } pixloc = 0; - for (i = 0; i < DSP2_op0doutlen * 2; i++) + for (i = 0; i < dsp2_state.op0doutlen * 2; i++) { j = pixloc >> 16; if (j & 1) - pixelarray[i] = (DSP2_parameters[j >> 1] & 0x0f); + pixelarray[i] = (dsp2_state.parameters[j >> 1] & 0x0f); else - pixelarray[i] = (DSP2_parameters[j >> 1] & 0xf0) >> 4; + pixelarray[i] = (dsp2_state.parameters[j >> 1] & 0xf0) >> 4; pixloc += multiplier; } - for (i = 0; i < DSP2_op0doutlen; i++) + for (i = 0; i < dsp2_state.op0doutlen; i++) { - DSP2_output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; + dsp2_state.output[i] = (pixelarray[i << 1] << 4) | pixelarray[(i << 1) + 1]; } } -static void DSP2_reset( void ) +static void dsp2_init( running_machine *machine ) { - DSP2_waiting_for_command = 1; - DSP2_in_count = 0; - DSP2_in_index = 0; - DSP2_out_count = 0; - DSP2_out_index = 0; - - DSP2_op05transparent = 0; - DSP2_op05haslen = 0; - DSP2_op05len = 0; - DSP2_op06haslen = 0; - DSP2_op06len = 0; - DSP2_op09word1 = 0; - DSP2_op09word2 = 0; - DSP2_op0dhaslen = 0; - DSP2_op0doutlen = 0; - DSP2_op0dinlen = 0; + 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_read( void ) +static UINT8 dsp2_read( void ) { UINT8 r = 0xff; - if (DSP2_out_count) + if (dsp2_state.out_count) { - r = DSP2_output[DSP2_out_index++]; - DSP2_out_index &= 511; - if (DSP2_out_count == DSP2_out_index) - DSP2_out_count = 0; + 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_write(UINT8 data) +static void dsp2_write(UINT8 data) { - if(DSP2_waiting_for_command) + if (dsp2_state.waiting_for_command) { - DSP2_command = data; - DSP2_in_index = 0; - DSP2_waiting_for_command = 0; + dsp2_state.command = data; + dsp2_state.in_index = 0; + dsp2_state.waiting_for_command = 0; switch (data) { - case 0x01: DSP2_in_count = 32; break; - case 0x03: DSP2_in_count = 1; break; - case 0x05: DSP2_in_count = 1; break; - case 0x06: DSP2_in_count = 1; break; + 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_in_count = 4; break; - case 0x0d: DSP2_in_count = 2; break; - case 0x0f: DSP2_in_count = 0; 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_parameters[DSP2_in_index++] = data; - DSP2_in_index &= 511; + dsp2_state.parameters[dsp2_state.in_index++] = data; + dsp2_state.in_index &= 511; } - if (DSP2_in_count == DSP2_in_index) + if (dsp2_state.in_count == dsp2_state.in_index) { - DSP2_waiting_for_command = 1; - DSP2_out_index = 0; - switch (DSP2_command) + dsp2_state.waiting_for_command = 1; + dsp2_state.out_index = 0; + switch (dsp2_state.command) { - case 0x01: - DSP2_out_count = 32; - DSP2_op01(); - break; - - case 0x03: - DSP2_op03(); - break; - - case 0x05: - if (DSP2_op05haslen) - { - DSP2_op05haslen = 0; - DSP2_out_count = DSP2_op05len; - DSP2_op05(); - } - else - { - DSP2_op05len = DSP2_parameters[0]; - DSP2_in_index = 0; - DSP2_in_count = DSP2_op05len * 2; - DSP2_op05haslen = 1; - if (data) - DSP2_waiting_for_command = 0; - } - break; - - case 0x06: - if (DSP2_op06haslen) - { - DSP2_op06haslen = 0; - DSP2_out_count = DSP2_op06len; - DSP2_op06(); - } - else - { - DSP2_op06len = DSP2_parameters[0]; - DSP2_in_index = 0; - DSP2_in_count = DSP2_op06len; - DSP2_op06haslen = 1; - if (data) - DSP2_waiting_for_command = 0; - } - break; - - case 0x07: break; - case 0x08: break; - - case 0x09: - DSP2_op09(); - break; - - case 0x0d: - if (DSP2_op0dhaslen) - { - DSP2_op0dhaslen = 0; - DSP2_out_count = DSP2_op0doutlen; - DSP2_op0d(); - } - else - { - DSP2_op0dinlen = DSP2_parameters[0]; - DSP2_op0doutlen = DSP2_parameters[1]; - DSP2_in_index = 0; - DSP2_in_count = (DSP2_op0dinlen + 1) >> 1; - DSP2_op0dhaslen = 1; - if(data) - DSP2_waiting_for_command = 0; - } - break; - - case 0x0f: - break; + 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 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 index 3fb621f1f19..8a3d086832d 100644 --- a/src/mame/machine/snesdsp3.c +++ b/src/mame/machine/snesdsp3.c @@ -12,670 +12,680 @@ ************************************************************************/ -static UINT16 DSP3_DataROM[1024]; +static void dsp3_Command(void); -static void(*SetDSP3)(void); -static void DSP3_Command(void); - -static UINT16 DSP3_DR; -static UINT16 DSP3_SR; -static UINT16 DSP3_MemoryIndex; - -static void DSP3_Reset(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_DR = 0x0080; - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_Command; + dsp3_state.DR = 0x0080; + dsp3_state.SR = 0x0084; + dsp3_state.SetDSP3 = &dsp3_Command; } #ifdef UNUSED_FUNCTION -void DSP3_MemorySize(void) +void dsp3_MemorySize(void) { - DSP3_DR = 0x0300; - SetDSP3 = &DSP3_Reset; + dsp3_state.DR = 0x0300; + dsp3_state.SetDSP3 = &dsp3_Reset; } #endif -static void DSP3_TestMemory(void) +static void dsp3_TestMemory(void) { - DSP3_DR = 0x0000; - SetDSP3 = &DSP3_Reset; + dsp3_state.DR = 0x0000; + dsp3_state.SetDSP3 = &dsp3_Reset; } -static void DSP3_DumpDataROM(void) +static void dsp3_DumpDataROM(void) { - DSP3_DR = DSP3_DataROM[DSP3_MemoryIndex++]; - if (DSP3_MemoryIndex == 1024) - SetDSP3 = &DSP3_Reset; + dsp3_state.DR = dsp3_state.DataROM[dsp3_state.MemoryIndex++]; + if (dsp3_state.MemoryIndex == 1024) + dsp3_state.SetDSP3 = &dsp3_Reset; } -static void DSP3_MemoryDump(void) +static void dsp3_MemoryDump(void) { - DSP3_MemoryIndex = 0; - SetDSP3 = &DSP3_DumpDataROM; - DSP3_DumpDataROM(); + dsp3_state.MemoryIndex = 0; + dsp3_state.SetDSP3 = &dsp3_DumpDataROM; + dsp3_DumpDataROM(); } -static INT16 DSP3_WinLo; -static INT16 DSP3_WinHi; - -static void DSP3_OP06(void) +static void dsp3_OP06(void) { - DSP3_WinLo = (UINT8)(DSP3_DR); - DSP3_WinHi = (UINT8)(DSP3_DR >> 8); - DSP3_Reset(); + dsp3_state.WinLo = (UINT8)(dsp3_state.DR); + dsp3_state.WinHi = (UINT8)(dsp3_state.DR >> 8); + dsp3_Reset(); } -static void DSP3_OP03(void) +static void dsp3_OP03(void) { - INT16 Lo = (UINT8)(DSP3_DR); - INT16 Hi = (UINT8)(DSP3_DR >> 8); - INT16 Ofs = (DSP3_WinLo * Hi << 1) + (Lo << 1); - DSP3_DR = Ofs >> 1; - SetDSP3 = &DSP3_Reset; + 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 INT16 DSP3_AddLo; -static INT16 DSP3_AddHi; - -static void DSP3_OP07_B(void) +static void dsp3_OP07_B(void) { - INT16 Ofs = (DSP3_WinLo * DSP3_AddHi << 1) + (DSP3_AddLo << 1); - DSP3_DR = Ofs >> 1; - SetDSP3 = &DSP3_Reset; + 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) +static void dsp3_OP07_A(void) { - INT16 Lo = (UINT8)(DSP3_DR); - INT16 Hi = (UINT8)(DSP3_DR >> 8); + INT16 Lo = (UINT8)(dsp3_state.DR); + INT16 Hi = (UINT8)(dsp3_state.DR >> 8); - if (Lo & 1) Hi += (DSP3_AddLo & 1); + if (Lo & 1) + Hi += (dsp3_state.AddLo & 1); - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; + dsp3_state.AddLo += Lo; + dsp3_state.AddHi += Hi; - if (DSP3_AddLo < 0) - DSP3_AddLo += DSP3_WinLo; - else - if (DSP3_AddLo >= DSP3_WinLo) - DSP3_AddLo -= DSP3_WinLo; + 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_AddHi < 0) - DSP3_AddHi += DSP3_WinHi; - else - if (DSP3_AddHi >= DSP3_WinHi) - DSP3_AddHi -= DSP3_WinHi; + 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_DR = DSP3_AddLo | (DSP3_AddHi << 8) | ((DSP3_AddHi >> 8) & 0xff); - SetDSP3 = &DSP3_OP07_B; + 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) +static void dsp3_OP07(void) { - UINT32 dataOfs = ((DSP3_DR << 1) + 0x03b2) & 0x03ff; + UINT32 dataOfs = ((dsp3_state.DR << 1) + 0x03b2) & 0x03ff; - DSP3_AddHi = DSP3_DataROM[dataOfs]; - DSP3_AddLo = DSP3_DataROM[dataOfs + 1]; + dsp3_state.AddHi = dsp3_state.DataROM[dataOfs]; + dsp3_state.AddLo = dsp3_state.DataROM[dataOfs + 1]; - SetDSP3 = &DSP3_OP07_A; - DSP3_SR = 0x0080; + dsp3_state.SetDSP3 = &dsp3_OP07_A; + dsp3_state.SR = 0x0080; } -static UINT16 DSP3_Codewords; -static UINT16 DSP3_Outwords; -static UINT16 DSP3_Symbol; -static UINT16 DSP3_BitCount; -static UINT16 DSP3_Index; -static UINT16 DSP3_Codes[512]; -static UINT16 DSP3_BitsLeft; -static UINT16 DSP3_ReqBits; -static UINT16 DSP3_ReqData; -static UINT16 DSP3_BitCommand; -static UINT8 DSP3_BaseLength; -static UINT16 DSP3_BaseCodes; -static UINT16 DSP3_BaseCode; -static UINT8 DSP3_CodeLengths[8]; -static UINT16 DSP3_CodeOffsets[8]; -static UINT16 DSP3_LZCode; -static UINT8 DSP3_LZLength; - -static UINT16 DSP3_X; -static UINT16 DSP3_Y; - -static void DSP3_Coordinate(void) +static void dsp3_Coordinate(void) { - DSP3_Index++; + dsp3_state.Index++; - switch (DSP3_Index) + switch (dsp3_state.Index) { case 3: - { - if (DSP3_DR == 0xffff) - DSP3_Reset(); - break; - } + if (dsp3_state.DR == 0xffff) + dsp3_Reset(); + break; case 4: - { - DSP3_X = DSP3_DR; - break; - } + dsp3_state.X = dsp3_state.DR; + break; case 5: - { - DSP3_Y = DSP3_DR; - DSP3_DR = 1; - break; - } + dsp3_state.Y = dsp3_state.DR; + dsp3_state.DR = 1; + break; case 6: - { - DSP3_DR = DSP3_X; - break; - } + dsp3_state.DR = dsp3_state.X; + break; case 7: - { - DSP3_DR = DSP3_Y; - DSP3_Index = 0; - break; - } + dsp3_state.DR = dsp3_state.Y; + dsp3_state.Index = 0; + break; } } -static UINT8 DSP3_Bitmap[8]; -static UINT8 DSP3_Bitplane[8]; -static UINT16 DSP3_BMIndex; -static UINT16 DSP3_BPIndex; -static UINT16 DSP3_Count; - -static void DSP3_Convert_A(void) +static void dsp3_Convert_A(void) { - if (DSP3_BMIndex < 8) + if (dsp3_state.BMIndex < 8) { - DSP3_Bitmap[DSP3_BMIndex++] = (UINT8) (DSP3_DR); - DSP3_Bitmap[DSP3_BMIndex++] = (UINT8) (DSP3_DR >> 8); + dsp3_state.Bitmap[dsp3_state.BMIndex++] = (UINT8) (dsp3_state.DR); + dsp3_state.Bitmap[dsp3_state.BMIndex++] = (UINT8) (dsp3_state.DR >> 8); - if (DSP3_BMIndex == 8) + if (dsp3_state.BMIndex == 8) { - short i, j; - for (i=0; i < 8; i++) - for (j=0; j < 8; j++) + short i, j; + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) { - DSP3_Bitplane[j] <<= 1; - DSP3_Bitplane[j] |= (DSP3_Bitmap[i] >> j) & 1; + dsp3_state.Bitplane[j] <<= 1; + dsp3_state.Bitplane[j] |= (dsp3_state.Bitmap[i] >> j) & 1; } - DSP3_BPIndex = 0; - DSP3_Count--; + dsp3_state.BPIndex = 0; + dsp3_state.Count--; } } - if (DSP3_BMIndex == 8) + if (dsp3_state.BMIndex == 8) { - if (DSP3_BPIndex == 8) + if (dsp3_state.BPIndex == 8) { - if (!DSP3_Count) DSP3_Reset(); - DSP3_BMIndex = 0; + if (!dsp3_state.Count) + dsp3_Reset(); + dsp3_state.BMIndex = 0; } else { - DSP3_DR = DSP3_Bitplane[DSP3_BPIndex++]; - DSP3_DR |= DSP3_Bitplane[DSP3_BPIndex++] << 8; + dsp3_state.DR = dsp3_state.Bitplane[dsp3_state.BPIndex++]; + dsp3_state.DR |= dsp3_state.Bitplane[dsp3_state.BPIndex++] << 8; } } } -static void DSP3_Convert(void) +static void dsp3_Convert(void) { - DSP3_Count = DSP3_DR; - DSP3_BMIndex = 0; - SetDSP3 = &DSP3_Convert_A; + dsp3_state.Count = dsp3_state.DR; + dsp3_state.BMIndex = 0; + dsp3_state.SetDSP3 = &dsp3_Convert_A; } -static UINT8 DSP3_GetBits(UINT8 Count) +static UINT8 dsp3_GetBits(UINT8 Count) { - if (!DSP3_BitsLeft) + if (!dsp3_state.BitsLeft) { - DSP3_BitsLeft = Count; - DSP3_ReqBits = 0; + dsp3_state.BitsLeft = Count; + dsp3_state.ReqBits = 0; } do { - if (!DSP3_BitCount) + if (!dsp3_state.BitCount) { - DSP3_SR = 0xC0; + dsp3_state.SR = 0xC0; return 0; } - DSP3_ReqBits <<= 1; - if (DSP3_ReqData & 0x8000) DSP3_ReqBits++; - DSP3_ReqData <<= 1; + dsp3_state.ReqBits <<= 1; + if (dsp3_state.ReqData & 0x8000) + dsp3_state.ReqBits++; + dsp3_state.ReqData <<= 1; - DSP3_BitCount--; - DSP3_BitsLeft--; + dsp3_state.BitCount--; + dsp3_state.BitsLeft--; - } while (DSP3_BitsLeft); + } while (dsp3_state.BitsLeft); return 1; } -static void DSP3_Decode_Data(void) +static void dsp3_Decode_Data(void) { - if (!DSP3_BitCount) + if (!dsp3_state.BitCount) { - if (DSP3_SR & 0x40) + if (dsp3_state.SR & 0x40) { - DSP3_ReqData = DSP3_DR; - DSP3_BitCount += 16; + dsp3_state.ReqData = dsp3_state.DR; + dsp3_state.BitCount += 16; } else { - DSP3_SR = 0xC0; + dsp3_state.SR = 0xC0; return; } } - if (DSP3_LZCode == 1) + if (dsp3_state.LZCode == 1) { - if (!DSP3_GetBits(1)) + if (!dsp3_GetBits(1)) return; - if (DSP3_ReqBits) - DSP3_LZLength = 12; + if (dsp3_state.ReqBits) + dsp3_state.LZLength = 12; else - DSP3_LZLength = 8; + dsp3_state.LZLength = 8; - DSP3_LZCode++; + dsp3_state.LZCode++; } - if (DSP3_LZCode == 2) + if (dsp3_state.LZCode == 2) { - if (!DSP3_GetBits(DSP3_LZLength)) + if (!dsp3_GetBits(dsp3_state.LZLength)) return; - DSP3_LZCode = 0; - DSP3_Outwords--; - if (!DSP3_Outwords) SetDSP3 = &DSP3_Reset; + dsp3_state.LZCode = 0; + dsp3_state.Outwords--; + if (!dsp3_state.Outwords) dsp3_state.SetDSP3 = &dsp3_Reset; - DSP3_SR = 0x80; - DSP3_DR = DSP3_ReqBits; + dsp3_state.SR = 0x80; + dsp3_state.DR = dsp3_state.ReqBits; return; } - if (DSP3_BaseCode == 0xffff) + if (dsp3_state.BaseCode == 0xffff) { - if (!DSP3_GetBits(DSP3_BaseLength)) + if (!dsp3_GetBits(dsp3_state.BaseLength)) return; - DSP3_BaseCode = DSP3_ReqBits; + dsp3_state.BaseCode = dsp3_state.ReqBits; } - if (!DSP3_GetBits(DSP3_CodeLengths[DSP3_BaseCode])) + if (!dsp3_GetBits(dsp3_state.CodeLengths[dsp3_state.BaseCode])) return; - DSP3_Symbol = DSP3_Codes[DSP3_CodeOffsets[DSP3_BaseCode] + DSP3_ReqBits]; - DSP3_BaseCode = 0xffff; + dsp3_state.Symbol = dsp3_state.Codes[dsp3_state.CodeOffsets[dsp3_state.BaseCode] + dsp3_state.ReqBits]; + dsp3_state.BaseCode = 0xffff; - if (DSP3_Symbol & 0xff00) + if (dsp3_state.Symbol & 0xff00) { - DSP3_Symbol += 0x7f02; - DSP3_LZCode++; + dsp3_state.Symbol += 0x7f02; + dsp3_state.LZCode++; } else { - DSP3_Outwords--; - if (!DSP3_Outwords) - SetDSP3 = &DSP3_Reset; + dsp3_state.Outwords--; + if (!dsp3_state.Outwords) + dsp3_state.SetDSP3 = &dsp3_Reset; } - DSP3_SR = 0x80; - DSP3_DR = DSP3_Symbol; + dsp3_state.SR = 0x80; + dsp3_state.DR = dsp3_state.Symbol; } -static void DSP3_Decode_Tree(void) +static void dsp3_Decode_Tree(void) { - if (!DSP3_BitCount) + if (!dsp3_state.BitCount) { - DSP3_ReqData = DSP3_DR; - DSP3_BitCount += 16; + dsp3_state.ReqData = dsp3_state.DR; + dsp3_state.BitCount += 16; } - if (!DSP3_BaseCodes) + if (!dsp3_state.BaseCodes) { - DSP3_GetBits(1); - if (DSP3_ReqBits) + dsp3_GetBits(1); + if (dsp3_state.ReqBits) { - DSP3_BaseLength = 3; - DSP3_BaseCodes = 8; + dsp3_state.BaseLength = 3; + dsp3_state.BaseCodes = 8; } else { - DSP3_BaseLength = 2; - DSP3_BaseCodes = 4; + dsp3_state.BaseLength = 2; + dsp3_state.BaseCodes = 4; } } - while (DSP3_BaseCodes) + while (dsp3_state.BaseCodes) { - if (!DSP3_GetBits(3)) + if (!dsp3_GetBits(3)) return; - DSP3_ReqBits++; + dsp3_state.ReqBits++; - DSP3_CodeLengths[DSP3_Index] = (UINT8) DSP3_ReqBits; - DSP3_CodeOffsets[DSP3_Index] = DSP3_Symbol; - DSP3_Index++; + dsp3_state.CodeLengths[dsp3_state.Index] = (UINT8) dsp3_state.ReqBits; + dsp3_state.CodeOffsets[dsp3_state.Index] = dsp3_state.Symbol; + dsp3_state.Index++; - DSP3_Symbol += 1 << DSP3_ReqBits; - DSP3_BaseCodes--; + dsp3_state.Symbol += 1 << dsp3_state.ReqBits; + dsp3_state.BaseCodes--; } - DSP3_BaseCode = 0xffff; - DSP3_LZCode = 0; + dsp3_state.BaseCode = 0xffff; + dsp3_state.LZCode = 0; - SetDSP3 = &DSP3_Decode_Data; - if (DSP3_BitCount) DSP3_Decode_Data(); + dsp3_state.SetDSP3 = &dsp3_Decode_Data; + if (dsp3_state.BitCount) + dsp3_Decode_Data(); } -static void DSP3_Decode_Symbols(void) +static void dsp3_Decode_Symbols(void) { - DSP3_ReqData = DSP3_DR; - DSP3_BitCount += 16; + dsp3_state.ReqData = dsp3_state.DR; + dsp3_state.BitCount += 16; do { - if (DSP3_BitCommand == 0xffff) + if (dsp3_state.BitCommand == 0xffff) { - if (!DSP3_GetBits(2)) return; - DSP3_BitCommand = DSP3_ReqBits; + if (!dsp3_GetBits(2)) return; + dsp3_state.BitCommand = dsp3_state.ReqBits; } - switch (DSP3_BitCommand) + switch (dsp3_state.BitCommand) { case 0: { - if (!DSP3_GetBits(9)) return; - DSP3_Symbol = DSP3_ReqBits; + if (!dsp3_GetBits(9)) return; + dsp3_state.Symbol = dsp3_state.ReqBits; break; } case 1: { - DSP3_Symbol++; + dsp3_state.Symbol++; break; } case 2: { - if (!DSP3_GetBits(1)) return; - DSP3_Symbol += 2 + DSP3_ReqBits; + if (!dsp3_GetBits(1)) return; + dsp3_state.Symbol += 2 + dsp3_state.ReqBits; break; } case 3: { - if (!DSP3_GetBits(4)) return; - DSP3_Symbol += 4 + DSP3_ReqBits; + if (!dsp3_GetBits(4)) return; + dsp3_state.Symbol += 4 + dsp3_state.ReqBits; break; } } - DSP3_BitCommand = 0xffff; + dsp3_state.BitCommand = 0xffff; - DSP3_Codes[DSP3_Index++] = DSP3_Symbol; - DSP3_Codewords--; + dsp3_state.Codes[dsp3_state.Index++] = dsp3_state.Symbol; + dsp3_state.Codewords--; - } while (DSP3_Codewords); + } while (dsp3_state.Codewords); - DSP3_Index = 0; - DSP3_Symbol = 0; - DSP3_BaseCodes = 0; + dsp3_state.Index = 0; + dsp3_state.Symbol = 0; + dsp3_state.BaseCodes = 0; - SetDSP3 = &DSP3_Decode_Tree; - if (DSP3_BitCount) DSP3_Decode_Tree(); + dsp3_state.SetDSP3 = &dsp3_Decode_Tree; + if (dsp3_state.BitCount) dsp3_Decode_Tree(); } -static void DSP3_Decode_A(void) +static void dsp3_Decode_A(void) { - DSP3_Outwords = DSP3_DR; - SetDSP3 = &DSP3_Decode_Symbols; - DSP3_BitCount = 0; - DSP3_BitsLeft = 0; - DSP3_Symbol = 0; - DSP3_Index = 0; - DSP3_BitCommand = 0xffff; - DSP3_SR = 0xC0; + 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) +static void dsp3_Decode(void) { - DSP3_Codewords = DSP3_DR; - SetDSP3 = &DSP3_Decode_A; + 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 INT16 op3e_x; -static INT16 op3e_y; - -static INT16 op1e_terrain[0x2000]; -static INT16 op1e_cost[0x2000]; -static INT16 op1e_weight[0x2000]; - -static INT16 op1e_cell; -static INT16 op1e_turn; -static INT16 op1e_search; - -static INT16 op1e_x; -static INT16 op1e_y; - -static INT16 op1e_min_radius; -static INT16 op1e_max_radius; - -static INT16 op1e_max_search_radius; -static INT16 op1e_max_path_radius; - -static INT16 op1e_lcv_radius; -static INT16 op1e_lcv_steps; -static INT16 op1e_lcv_turns; - -static void DSP3_OP3E(void) +static void dsp3_OP3E(void) { - op3e_x = (UINT8)(DSP3_DR & 0x00ff); - op3e_y = (UINT8)((DSP3_DR & 0xff00)>>8); + dsp3_state.op3e_x = (UINT8)(dsp3_state.DR & 0x00ff); + dsp3_state.op3e_y = (UINT8)((dsp3_state.DR & 0xff00) >> 8); - DSP3_OP03(); + dsp3_OP03(); - op1e_terrain[ DSP3_DR ] = 0x00; - op1e_cost[ DSP3_DR ] = 0xff; - op1e_weight[ DSP3_DR ] = 0; + dsp3_state.op1e_terrain[dsp3_state.DR] = 0x00; + dsp3_state.op1e_cost[dsp3_state.DR] = 0xff; + dsp3_state.op1e_weight[dsp3_state.DR] = 0; - op1e_max_search_radius = 0; - op1e_max_path_radius = 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_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_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_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_D(INT16, INT16 *, INT16 *); +static void dsp3_OP1E_D1(INT16 move, INT16 *lo, INT16 *hi); -static void DSP3_OP1E(void) +static void dsp3_OP1E(void) { int lcv; - op1e_min_radius = (UINT8)(DSP3_DR & 0x00ff); - op1e_max_radius = (UINT8)((DSP3_DR & 0xff00)>>8); + dsp3_state.op1e_min_radius = (UINT8)(dsp3_state.DR & 0x00ff); + dsp3_state.op1e_max_radius = (UINT8)((dsp3_state.DR & 0xff00)>>8); - if( op1e_min_radius == 0 ) - op1e_min_radius++; + if (dsp3_state.op1e_min_radius == 0) + dsp3_state.op1e_min_radius++; - if( op1e_max_search_radius >= op1e_min_radius ) - op1e_min_radius = op1e_max_search_radius+1; + 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( op1e_max_radius > op1e_max_search_radius ) - op1e_max_search_radius = op1e_max_radius; + if (dsp3_state.op1e_max_radius > dsp3_state.op1e_max_search_radius) + dsp3_state.op1e_max_search_radius = dsp3_state.op1e_max_radius; - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; + dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - op1e_lcv_turns = 6; - op1e_turn = 0; + dsp3_state.op1e_lcv_turns = 6; + dsp3_state.op1e_turn = 0; - op1e_x = op3e_x; - op1e_y = op3e_y; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_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(); + dsp3_OP1E_A(); } -static void DSP3_OP1E_A(void) +static void dsp3_OP1E_A(void) { int lcv; - if( op1e_lcv_steps == 0 ) { - op1e_lcv_radius++; + if (dsp3_state.op1e_lcv_steps == 0) + { + dsp3_state.op1e_lcv_radius++; - op1e_lcv_steps = op1e_lcv_radius; + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius; - op1e_x = op3e_x; - op1e_y = op3e_y; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; - for( lcv = 0; lcv < op1e_lcv_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_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( op1e_lcv_radius > op1e_max_radius ) { - op1e_turn++; - op1e_lcv_turns--; + if (dsp3_state.op1e_lcv_radius > dsp3_state.op1e_max_radius) + { + dsp3_state.op1e_turn++; + dsp3_state.op1e_lcv_turns--; - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; + dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - op1e_x = op3e_x; - op1e_y = op3e_y; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_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( op1e_lcv_turns == 0 ) { - DSP3_DR = 0xffff; - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_OP1E_B; + if (dsp3_state.op1e_lcv_turns == 0) + { + dsp3_state.DR = 0xffff; + dsp3_state.SR = 0x0080; + dsp3_state.SetDSP3 = &dsp3_OP1E_B; return; } - DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8); - DSP3_OP03(); + dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8); + dsp3_OP03(); - op1e_cell = DSP3_DR; + dsp3_state.op1e_cell = dsp3_state.DR; - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_OP1E_A1; + dsp3_state.SR = 0x0080; + dsp3_state.SetDSP3 = &dsp3_OP1E_A1; } -static void DSP3_OP1E_A1(void) +static void dsp3_OP1E_A1(void) { - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_OP1E_A2; + dsp3_state.SR = 0x0084; + dsp3_state.SetDSP3 = &dsp3_OP1E_A2; } -static void DSP3_OP1E_A2(void) +static void dsp3_OP1E_A2(void) { - op1e_terrain[ op1e_cell ] = (UINT8)(DSP3_DR & 0x00ff); + dsp3_state.op1e_terrain[dsp3_state.op1e_cell] = (UINT8)(dsp3_state.DR & 0x00ff); - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_OP1E_A3; + dsp3_state.SR = 0x0084; + dsp3_state.SetDSP3 = &dsp3_OP1E_A3; } -static void DSP3_OP1E_A3(void) +static void dsp3_OP1E_A3(void) { - op1e_cost[ op1e_cell ] = (UINT8)(DSP3_DR & 0x00ff); + dsp3_state.op1e_cost[dsp3_state.op1e_cell] = (UINT8)(dsp3_state.DR & 0x00ff); - if( op1e_lcv_radius == 1 ) { - if( op1e_terrain[ op1e_cell ] & 1 ) { - op1e_weight[ op1e_cell ] = 0xff; - } else { - op1e_weight[ op1e_cell ] = op1e_cost[ op1e_cell ]; + 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 { - op1e_weight[ op1e_cell ] = 0xff; + else + { + dsp3_state.op1e_weight[dsp3_state.op1e_cell] = 0xff; } - DSP3_OP1E_D( (INT16)(op1e_turn+2), &op1e_x, &op1e_y ); - op1e_lcv_steps--; + dsp3_OP1E_D((INT16)(dsp3_state.op1e_turn + 2), &dsp3_state.op1e_x, &dsp3_state.op1e_y); + dsp3_state.op1e_lcv_steps--; - DSP3_SR = 0x0080; - DSP3_OP1E_A(); + dsp3_state.SR = 0x0080; + dsp3_OP1E_A(); } -static void DSP3_OP1E_B(void) +static void dsp3_OP1E_B(void) { - op1e_x = op3e_x; - op1e_y = op3e_y; - op1e_lcv_radius = 1; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; + dsp3_state.op1e_lcv_radius = 1; - op1e_search = 0; + dsp3_state.op1e_search = 0; - DSP3_OP1E_B1(); + dsp3_OP1E_B1(); - SetDSP3 = &DSP3_OP1E_C; + dsp3_state.SetDSP3 = &dsp3_OP1E_C; } -static void DSP3_OP1E_B1(void) +static void dsp3_OP1E_B1(void) { - while( op1e_lcv_radius < op1e_max_radius ) { - op1e_y--; + while (dsp3_state.op1e_lcv_radius < dsp3_state.op1e_max_radius) + { + dsp3_state.op1e_y--; - op1e_lcv_turns = 6; - op1e_turn = 5; + dsp3_state.op1e_lcv_turns = 6; + dsp3_state.op1e_turn = 5; - while( op1e_lcv_turns ) { - op1e_lcv_steps = op1e_lcv_radius; + while (dsp3_state.op1e_lcv_turns) + { + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius; - while( op1e_lcv_steps ) { - DSP3_OP1E_D1( op1e_turn, &op1e_x, &op1e_y ); + while (dsp3_state.op1e_lcv_steps) + { + dsp3_OP1E_D1(dsp3_state.op1e_turn, &dsp3_state.op1e_x, &dsp3_state.op1e_y); - if( 0 <= op1e_y && op1e_y < DSP3_WinHi && - 0 <= op1e_x && op1e_x < DSP3_WinLo ) { - DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8); - DSP3_OP03(); + 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(); - op1e_cell = DSP3_DR; - if( op1e_cost[ op1e_cell ] < 0x80 && - op1e_terrain[ op1e_cell ] < 0x40 ) { - DSP3_OP1E_B2(); + 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 } - op1e_lcv_steps--; + dsp3_state.op1e_lcv_steps--; } // end search line - op1e_turn--; - if( op1e_turn == 0 ) op1e_turn = 6; + dsp3_state.op1e_turn--; + if (dsp3_state.op1e_turn == 0) + dsp3_state.op1e_turn = 6; - op1e_lcv_turns--; + dsp3_state.op1e_lcv_turns--; } // end circle search - op1e_lcv_radius++; + dsp3_state.op1e_lcv_radius++; } // end radius search } -static void DSP3_OP1E_B2(void) +static void dsp3_OP1E_B2(void) { INT16 cell; INT16 path; @@ -685,162 +695,162 @@ static void DSP3_OP1E_B2(void) path = 0xff; lcv_turns = 6; - while( lcv_turns ) { - x = op1e_x; - y = op1e_y; - - DSP3_OP1E_D1( lcv_turns, &x, &y ); + while (lcv_turns) + { + x = dsp3_state.op1e_x; + y = dsp3_state.op1e_y; - DSP3_DR = (UINT8)(x) | ((UINT8)(y)<<8); - DSP3_OP03(); + dsp3_OP1E_D1(lcv_turns, &x, &y); - cell = DSP3_DR; + dsp3_state.DR = (UINT8)(x) | ((UINT8)(y)<<8); + dsp3_OP03(); - if( 0 <= y && y < DSP3_WinHi && - 0 <= x && x < DSP3_WinLo ) { + cell = dsp3_state.DR; - if( op1e_terrain[ cell ] < 0x80 || op1e_weight[ cell ] == 0 ) { - if( op1e_weight[ cell ] < path ) { - path = op1e_weight[ cell ]; - } + 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 ) { - op1e_weight[ op1e_cell ] = path + op1e_cost[ op1e_cell ]; - } + 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) +static void dsp3_OP1E_C(void) { int lcv; - op1e_min_radius = (UINT8)(DSP3_DR & 0x00ff); - op1e_max_radius = (UINT8)((DSP3_DR & 0xff00)>>8); + dsp3_state.op1e_min_radius = (UINT8)(dsp3_state.DR & 0x00ff); + dsp3_state.op1e_max_radius = (UINT8)((dsp3_state.DR & 0xff00) >> 8); - if( op1e_min_radius == 0 ) - op1e_min_radius++; + if (dsp3_state.op1e_min_radius == 0) + dsp3_state.op1e_min_radius++; - if( op1e_max_path_radius >= op1e_min_radius ) - op1e_min_radius = op1e_max_path_radius+1; + 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( op1e_max_radius > op1e_max_path_radius ) - op1e_max_path_radius = op1e_max_radius; + if (dsp3_state.op1e_max_radius > dsp3_state.op1e_max_path_radius) + dsp3_state.op1e_max_path_radius = dsp3_state.op1e_max_radius; - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; + dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - op1e_lcv_turns = 6; - op1e_turn = 0; + dsp3_state.op1e_lcv_turns = 6; + dsp3_state.op1e_turn = 0; - op1e_x = op3e_x; - op1e_y = op3e_y; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_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(); + dsp3_OP1E_C1(); } -static void DSP3_OP1E_C1(void) +static void dsp3_OP1E_C1(void) { int lcv; - if( op1e_lcv_steps == 0 ) { - op1e_lcv_radius++; + if (dsp3_state.op1e_lcv_steps == 0) + { + dsp3_state.op1e_lcv_radius++; - op1e_lcv_steps = op1e_lcv_radius; + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_lcv_radius; - op1e_x = op3e_x; - op1e_y = op3e_y; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; - for( lcv = 0; lcv < op1e_lcv_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_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( op1e_lcv_radius > op1e_max_radius ) { - op1e_turn++; - op1e_lcv_turns--; + if (dsp3_state.op1e_lcv_radius > dsp3_state.op1e_max_radius) + { + dsp3_state.op1e_turn++; + dsp3_state.op1e_lcv_turns--; - op1e_lcv_radius = op1e_min_radius; - op1e_lcv_steps = op1e_min_radius; + dsp3_state.op1e_lcv_radius = dsp3_state.op1e_min_radius; + dsp3_state.op1e_lcv_steps = dsp3_state.op1e_min_radius; - op1e_x = op3e_x; - op1e_y = op3e_y; + dsp3_state.op1e_x = dsp3_state.op3e_x; + dsp3_state.op1e_y = dsp3_state.op3e_y; - for( lcv = 0; lcv < op1e_min_radius; lcv++ ) - DSP3_OP1E_D( op1e_turn, &op1e_x, &op1e_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( op1e_lcv_turns == 0 ) { - DSP3_DR = 0xffff; - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_Reset; + if (dsp3_state.op1e_lcv_turns == 0) + { + dsp3_state.DR = 0xffff; + dsp3_state.SR = 0x0080; + dsp3_state.SetDSP3 = &dsp3_Reset; return; } - DSP3_DR = (UINT8)(op1e_x) | ((UINT8)(op1e_y)<<8); - DSP3_OP03(); + dsp3_state.DR = (UINT8)(dsp3_state.op1e_x) | ((UINT8)(dsp3_state.op1e_y) << 8); + dsp3_OP03(); - op1e_cell = DSP3_DR; + dsp3_state.op1e_cell = dsp3_state.DR; - DSP3_SR = 0x0080; - SetDSP3 = &DSP3_OP1E_C2; + dsp3_state.SR = 0x0080; + dsp3_state.SetDSP3 = &dsp3_OP1E_C2; } -static void DSP3_OP1E_C2(void) +static void dsp3_OP1E_C2(void) { - DSP3_DR = op1e_weight[ op1e_cell ]; + dsp3_state.DR = dsp3_state.op1e_weight[dsp3_state.op1e_cell]; - DSP3_OP1E_D( (INT16)(op1e_turn+2), &op1e_x, &op1e_y ); - op1e_lcv_steps--; + dsp3_OP1E_D((INT16)(dsp3_state.op1e_turn + 2), &dsp3_state.op1e_x, &dsp3_state.op1e_y); + dsp3_state.op1e_lcv_steps--; - DSP3_SR = 0x0084; - SetDSP3 = &DSP3_OP1E_C1; + dsp3_state.SR = 0x0084; + dsp3_state.SetDSP3 = &dsp3_OP1E_C1; } -static void DSP3_OP1E_D( INT16 move, INT16 *lo, INT16 *hi ) +static void dsp3_OP1E_D( INT16 move, INT16 *lo, INT16 *hi ) { UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; INT16 Lo; INT16 Hi; - DSP3_AddHi = DSP3_DataROM[dataOfs]; - DSP3_AddLo = DSP3_DataROM[dataOfs + 1]; + 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_AddLo & 1); + if (Lo & 1) Hi += (dsp3_state.AddLo & 1); - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; + dsp3_state.AddLo += Lo; + dsp3_state.AddHi += Hi; - if (DSP3_AddLo < 0) - DSP3_AddLo += DSP3_WinLo; - else - if (DSP3_AddLo >= DSP3_WinLo) - DSP3_AddLo -= DSP3_WinLo; + 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_AddHi < 0) - DSP3_AddHi += DSP3_WinHi; - else - if (DSP3_AddHi >= DSP3_WinHi) - DSP3_AddHi -= DSP3_WinHi; + 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_AddLo; - *hi = DSP3_AddHi; + *lo = dsp3_state.AddLo; + *hi = dsp3_state.AddHi; } -static void DSP3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi ) +static void dsp3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi ) { //UINT32 dataOfs = ((move << 1) + 0x03b2) & 0x03ff; INT16 Lo; @@ -854,183 +864,249 @@ static void DSP3_OP1E_D1( INT16 move, INT16 *lo, INT16 *hi ) 0x00, 0x00, 0x01, 0x01, 0x00, 0xFF, 0xFF, 0x00 }; - if( (*lo) & 1 ) - DSP3_AddHi = HiAdd[ move + 8 ]; + if ((*lo) & 1) + dsp3_state.AddHi = HiAdd[move + 8]; else - DSP3_AddHi = HiAdd[ move + 0 ]; - DSP3_AddLo = LoAdd[ move ]; + dsp3_state.AddHi = HiAdd[move + 0]; + dsp3_state.AddLo = LoAdd[move]; Lo = (UINT8)(*lo); Hi = (UINT8)(*hi); - if (Lo & 1) Hi += (DSP3_AddLo & 1); + if (Lo & 1) + Hi += (dsp3_state.AddLo & 1); - DSP3_AddLo += Lo; - DSP3_AddHi += Hi; + dsp3_state.AddLo += Lo; + dsp3_state.AddHi += Hi; - *lo = DSP3_AddLo; - *hi = DSP3_AddHi; + *lo = dsp3_state.AddLo; + *hi = dsp3_state.AddHi; } -static void DSP3_OP10(void) +static void dsp3_OP10(void) { - if( DSP3_DR == 0xffff ) { - DSP3_Reset(); - } else { + if (dsp3_state.DR == 0xffff ) + dsp3_Reset(); + else + { // absorb 2 bytes - DSP3_DR = DSP3_DR; + dsp3_state.DR = dsp3_state.DR; } } #ifdef UNUSED_FUNCTION -static void DSP3_OP0C_A(void) +static void dsp3_OP0C_A(void) { // absorb 2 bytes - DSP3_DR = 0; - SetDSP3 = &DSP3_Reset; + dsp3_state.DR = 0; + dsp3_state.SetDSP3 = &dsp3_Reset; } #endif -static void DSP3_OP0C(void) +static void dsp3_OP0C(void) { // absorb 2 bytes - DSP3_DR = 0; - //SetDSP3 = &DSP3_OP0C_A; - SetDSP3 = &DSP3_Reset; + dsp3_state.DR = 0; + //dsp3_state.SetDSP3 = &dsp3_OP0C_A; + dsp3_state.SetDSP3 = &dsp3_Reset; } -static void DSP3_OP1C_C(void) +static void dsp3_OP1C_C(void) { // return 2 bytes - DSP3_DR = 0; - SetDSP3 = &DSP3_Reset; + dsp3_state.DR = 0; + dsp3_state.SetDSP3 = &dsp3_Reset; } -static void DSP3_OP1C_B(void) +static void dsp3_OP1C_B(void) { // absorb 2 bytes // return 2 bytes - DSP3_DR = 0; - SetDSP3 = &DSP3_OP1C_C; + dsp3_state.DR = 0; + dsp3_state.SetDSP3 = &dsp3_OP1C_C; } -static void DSP3_OP1C_A(void) +static void dsp3_OP1C_A(void) { // absorb 2 bytes - SetDSP3 = &DSP3_OP1C_B; + dsp3_state.SetDSP3 = &dsp3_OP1C_B; } -static void DSP3_OP1C(void) +static void dsp3_OP1C(void) { // absorb 2 bytes - SetDSP3 = &DSP3_OP1C_A; + dsp3_state.SetDSP3 = &dsp3_OP1C_A; } -static void DSP3_Command(void) +static void dsp3_Command(void) { - if (DSP3_DR < 0x40) + if (dsp3_state.DR < 0x40) { - switch (DSP3_DR) + switch (dsp3_state.DR) { - case 0x02: SetDSP3 = &DSP3_Coordinate; break; - case 0x03: SetDSP3 = &DSP3_OP03; break; - case 0x06: SetDSP3 = &DSP3_OP06; break; - case 0x07: SetDSP3 = &DSP3_OP07; return; - case 0x0c: SetDSP3 = &DSP3_OP0C; break; - case 0x0f: SetDSP3 = &DSP3_TestMemory; break; - case 0x10: SetDSP3 = &DSP3_OP10; break; - case 0x18: SetDSP3 = &DSP3_Convert; break; - case 0x1c: SetDSP3 = &DSP3_OP1C; break; - case 0x1e: SetDSP3 = &DSP3_OP1E; break; - case 0x1f: SetDSP3 = &DSP3_MemoryDump; break; - case 0x38: SetDSP3 = &DSP3_Decode; break; - case 0x3e: SetDSP3 = &DSP3_OP3E; break; - default: - return; + 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_SR = 0x0080; - DSP3_Index = 0; + + dsp3_state.SR = 0x0080; + dsp3_state.Index = 0; } } -static void DSP3_write( UINT16 dsp3_address, UINT8 dsp3_byte ) +static void dsp3_write( UINT16 dsp3_address, UINT8 dsp3_byte ) { - if (dsp3_address < 0xC000) - { - if (DSP3_SR & 0x04) + if (dsp3_address < 0xC000) + { + if (dsp3_state.SR & 0x04) { - DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte; - (*SetDSP3)(); + dsp3_state.DR = (dsp3_state.DR & 0xff00) + dsp3_byte; + (*dsp3_state.SetDSP3)(); } else { - DSP3_SR ^= 0x10; + dsp3_state.SR ^= 0x10; - if (DSP3_SR & 0x10) - DSP3_DR = (DSP3_DR & 0xff00) + dsp3_byte; + if (dsp3_state.SR & 0x10) + dsp3_state.DR = (dsp3_state.DR & 0xff00) + dsp3_byte; else { - DSP3_DR = (DSP3_DR & 0x00ff) + (dsp3_byte << 8); - (*SetDSP3)(); + dsp3_state.DR = (dsp3_state.DR & 0x00ff) + (dsp3_byte << 8); + (*dsp3_state.SetDSP3)(); } } - } + } } -static UINT8 DSP3_read( UINT16 dsp3_address ) +static UINT8 dsp3_read( UINT16 dsp3_address ) { - UINT8 value; - if (dsp3_address < 0xC000) - { - if (DSP3_SR & 0x04) + UINT8 value; + if (dsp3_address < 0xC000) + { + if (dsp3_state.SR & 0x04) { - value = (UINT8) DSP3_DR; - (*SetDSP3)(); + value = (UINT8) dsp3_state.DR; + (*dsp3_state.SetDSP3)(); } else { - DSP3_SR ^= 0x10; + dsp3_state.SR ^= 0x10; - if (DSP3_SR & 0x10) - value = (UINT8) (DSP3_DR); + if (dsp3_state.SR & 0x10) + value = (UINT8) (dsp3_state.DR); else { - value = (UINT8) (DSP3_DR >> 8); - (*SetDSP3)(); + value = (UINT8) (dsp3_state.DR >> 8); + (*dsp3_state.SetDSP3)(); } } - } - else - { - value = (UINT8) DSP3_SR; - } + } + 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); - return value; } -static void InitDSP3( running_machine *machine ) +static void dsp3_init( running_machine *machine ) { UINT32 i; UINT8 *dspin = memory_region(machine, "addons"); - DSP3_Reset(); // expand the DSP-3 data ROM - for (i = 0; i < 2048; i+=2) + for (i = 0; i < 2048; i += 2) { - DSP3_DataROM[i/2] = dspin[0x800 + i] << 8 | dspin[0x800 + i + 1]; + 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 index f62073b4158..064cc0ffc30 100644 --- a/src/mame/machine/snesdsp4.c +++ b/src/mame/machine/snesdsp4.c @@ -27,8 +27,8 @@ Fixed-point math reminder: #include "snesdsp4.h" -static struct DSP4_t DSP4; -static struct DSP4_vars_t DSP4_vars; +static struct dsp4_t dsp4; +static struct dsp4_vars_t dsp4_vars; INLINE UINT16 READ_WORD(UINT8 *addr) { @@ -53,22 +53,22 @@ INLINE void WRITE_WORD(UINT8 *addr, UINT16 data) static INT16 DSP4_READ_WORD( void ) { - INT16 out; + INT16 out; - out = READ_WORD(DSP4.parameters + DSP4.in_index); - DSP4.in_index += 2; + out = READ_WORD(dsp4.parameters + dsp4.in_index); + dsp4.in_index += 2; - return out; + return out; } static INT32 DSP4_READ_DWORD( void ) { - INT32 out; + INT32 out; - out = READ_DWORD(DSP4.parameters + DSP4.in_index); - DSP4.in_index += 4; + out = READ_DWORD(dsp4.parameters + dsp4.in_index); + dsp4.in_index += 4; - return out; + return out; } @@ -77,36 +77,37 @@ static INT32 DSP4_READ_DWORD( void ) // output protocol #define DSP4_CLEAR_OUT() \ -{ DSP4.out_count = 0; DSP4.out_index = 0; } +{ dsp4.out_count = 0; dsp4.out_index = 0; } #define DSP4_WRITE_BYTE( d ) \ -{ WRITE_WORD( DSP4.output + DSP4.out_count, ( d ) ); DSP4.out_count++; } +{ 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; } +{ 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; } +{ 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; \ +#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 ); + WRITE_WORD( nop + x, d ); #endif #ifdef DEBUG_DSP #define DSP4_WRITE_DEBUG( x, d ) \ - WRITE_WORD( nop + x, d ); + WRITE_WORD( nop + x, d ); #endif ////////////////////////////////////////////////////////////// @@ -114,7 +115,7 @@ static INT32 DSP4_READ_DWORD( void ) // used to wait for dsp i/o #define DSP4_WAIT( x ) \ - DSP4.in_index = 0; DSP4_vars.DSP4_Logic = x; return; + dsp4.in_index = 0; dsp4_vars.Logic = x; return; ////////////////////////////////////////////////////////////// @@ -142,1041 +143,1041 @@ static const UINT16 div_lut[64] = { 0x0000, 0x8000, 0x4000, 0x2aaa, 0x2000, 0x19 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) +static INT16 dsp4_Inverse(INT16 value) { - // saturate bounds - if (value < 0) - { - value = 0; - } - if (value > 63) - { - value = 63; - } - - return div_lut[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); +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) +static void dsp4_Multiply(INT16 Multiplicand, INT16 Multiplier, INT32 *Product) { - *Product = (Multiplicand * Multiplier << 1) >> 1; + *Product = (Multiplicand * Multiplier << 1) >> 1; } ////////////////////////////////////////////////////////////// -static void DSP4_OP01( void ) +static void dsp4_OP01( void ) { - DSP4.waiting4command = 0; - - // op flow control - switch (DSP4_vars.DSP4_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; - } - } + 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 + //////////////////////////////////////////////////// + // 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; + // 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); + // 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 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; + // update road turnoff position + dsp4_vars.view_turnoff_x += dsp4_vars.view_turnoff_dx; - //////////////////////////////////////////////////// - // command check + //////////////////////////////////////////////////// + // command check - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : + // 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; + // 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: + // 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(); + 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 ); + // 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; + // update stepping values + dsp4_vars.view_turnoff_x += dsp4_vars.view_turnoff_dx; - DSP4.in_count = 2; - DSP4_WAIT(1) - } + dsp4.in_count = 2; + DSP4_WAIT(1) + } - // already have 2 bytes read - DSP4.in_count = 6; - DSP4_WAIT(3) resume3 : + // 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); + // 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; + // terminate op + dsp4.waiting4command = 1; } ////////////////////////////////////////////////////////////// -static void DSP4_OP03( void ) +static void dsp4_OP03( void ) { - DSP4_vars.OAM_RowMax = 33; - memset(DSP4_vars.OAM_Row, 0, 64); + dsp4_vars.OAM_RowMax = 33; + memset(dsp4_vars.OAM_Row, 0, 64); } ////////////////////////////////////////////////////////////// -static void DSP4_OP05( void ) +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; + 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 ) +static void dsp4_OP06( void ) { - DSP4_CLEAR_OUT(); - DSP4_WRITE_16_WORD(DSP4_vars.OAM_attr); + DSP4_CLEAR_OUT(); + DSP4_WRITE_16_WORD(dsp4_vars.OAM_attr); } ////////////////////////////////////////////////////////////// -static void DSP4_OP07( void ) +static void dsp4_OP07( void ) { - DSP4.waiting4command = 0; - - // op flow control - switch (DSP4_vars.DSP4_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; - } - } + 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 + ///////////////////////////////////////////////////// + // 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; + // 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 + //////////////////////////////////////////////////// + // command check - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : + // 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; + // 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 : + // 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); + // 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; + dsp4.waiting4command = 1; } ////////////////////////////////////////////////////////////// -static void DSP4_OP08( void ) +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.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - } - - //////////////////////////////////////////////////// - // process initial inputs for two polygons - - // clip values - DSP4_vars.poly_clipRt[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipRt[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_clipRt[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipRt[1][1] = DSP4_READ_WORD(); - - DSP4_vars.poly_clipLf[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipLf[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_clipLf[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_clipLf[1][1] = DSP4_READ_WORD(); - - // unknown (constant) (ex. 1P/2P = $00A6, $00A6, $00A6, $00A6) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // unknown (constant) (ex. 1P/2P = $00A5, $00A5, $00A7, $00A7) - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // polygon centering (left,right) - DSP4_vars.poly_cx[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_cx[1][1] = DSP4_READ_WORD(); - - // HDMA pointer locations - DSP4_vars.poly_ptr[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_ptr[1][1] = DSP4_READ_WORD(); - - // starting DSP4_vars.raster line below the horizon - DSP4_vars.poly_bottom[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_bottom[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_bottom[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_bottom[1][1] = DSP4_READ_WORD(); - - // top boundary line to clip - DSP4_vars.poly_top[0][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[0][1] = DSP4_READ_WORD(); - DSP4_vars.poly_top[1][0] = DSP4_READ_WORD(); - DSP4_vars.poly_top[1][1] = DSP4_READ_WORD(); - - // unknown - // (ex. 1P = $2FC8, $0034, $FF5C, $0035) - // - // (ex. 2P = $3178, $0034, $FFCC, $0035) - // (ex. 2P = $2FC8, $0034, $FFCC, $0035) - - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - DSP4_READ_WORD(); - - // look at guidelines for both polygon shapes - DSP4_vars.distance = DSP4_READ_WORD(); - view_x[0] = DSP4_READ_WORD(); - view_y[0] = DSP4_READ_WORD(); - view_x[1] = DSP4_READ_WORD(); - view_y[1] = DSP4_READ_WORD(); - - // envelope shaping guidelines (one frame only) - envelope[0][0] = DSP4_READ_WORD(); - envelope[0][1] = DSP4_READ_WORD(); - envelope[1][0] = DSP4_READ_WORD(); - envelope[1][1] = DSP4_READ_WORD(); - - // starting base values to project from - DSP4_vars.poly_start[0] = view_x[0]; - DSP4_vars.poly_start[1] = view_x[1]; - - // starting DSP4_vars.raster lines to begin drawing - DSP4_vars.poly_raster[0][0] = view_y[0]; - DSP4_vars.poly_raster[0][1] = view_y[0]; - DSP4_vars.poly_raster[1][0] = view_y[1]; - DSP4_vars.poly_raster[1][1] = view_y[1]; - - // starting distances - DSP4_vars.poly_plane[0] = DSP4_vars.distance; - DSP4_vars.poly_plane[1] = DSP4_vars.distance; - - // SR = 0x00 - - // re-center coordinates - 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; + 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; + // road turnoff selection + if( (UINT16) envelope[ polygon ][ 0 ] == (UINT16) 0xc001 ) + poly = 1; + else if( envelope[ polygon ][ 1 ] == 0x3fff ) + poly = 1; - /////////////////////////////////////////////// - // left side of polygon + /////////////////////////////////////////////// + // 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; + // 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]; + // 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; + // 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 + /////////////////////////////////////////////// + // 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; + // 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]; + // 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; + // 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 + /////////////////////////////////////////////// + // 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]); + 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; + // 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; + // 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; + // 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); + // 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]; + // 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) + // 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); + 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 - } + // update memory pointers + dsp4_vars.poly_ptr[polygon][0] -= 4; + dsp4_vars.poly_ptr[polygon][1] -= 4; + } // end rasterize line + } - //////////////////////////////////////////////// - // Post-update + //////////////////////////////////////////////// + // Post-update - // new projection spot to continue rasterizing from - DSP4_vars.poly_start[polygon] = view_x[poly]; - } // end polygon rasterizer - } - while (1); + // 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); + // unknown output + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(0); - DSP4.waiting4command = 1; + dsp4.waiting4command = 1; } ////////////////////////////////////////////////////////////// -static void DSP4_OP09( void ) +static void dsp4_OP09( void ) { - DSP4.waiting4command = 0; - - // op flow control - switch (DSP4_vars.DSP4_Logic) - { - case 1: - goto resume1; break; - case 2: - goto resume2; break; - case 3: - goto resume3; break; - case 4: - goto resume4; break; - case 5: - goto resume5; break; - case 6: - goto resume6; break; - } - - //////////////////////////////////////////////////// - // 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; + 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; } ////////////////////////////////////////////////////////////// @@ -1184,764 +1185,764 @@ static void DSP4_OP09( void ) 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) +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]; + *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) +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); - } + 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 ) +static void dsp4_OP0D( void ) { - DSP4.waiting4command = 0; - - // op flow control - switch (DSP4_vars.DSP4_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; + 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; - } - } + // update screen values + x_scroll += px_dx; + y_scroll += py_dy; + } + } - ///////////////////////////////////////////////////// - // Post-update + ///////////////////////////////////////////////////// + // 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; + // 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); + // 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 projection lines + dsp4_vars.world_x += (dsp4_vars.world_dx + dsp4_vars.world_xenv); + dsp4_vars.world_y += dsp4_vars.world_dy; - //////////////////////////////////////////////////// - // command check + //////////////////////////////////////////////////// + // command check - // scan next command - DSP4.in_count = 2; - DSP4_WAIT(1) resume1 : + // scan next command + dsp4.in_count = 2; + DSP4_WAIT(1) resume1 : - // inspect input - DSP4_vars.distance = DSP4_READ_WORD(); + // inspect input + dsp4_vars.distance = DSP4_READ_WORD(); - // terminate op - if (DSP4_vars.distance == -0x8000) - break; + // terminate op + if (dsp4_vars.distance == -0x8000) + break; - // already have 2 bytes in queue - DSP4.in_count = 6; - DSP4_WAIT(2) resume2: + // 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(); + // 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); + // no envelope here + dsp4_vars.world_xenv = 0; + } + while (1); - DSP4.waiting4command = 1; + dsp4.waiting4command = 1; } ////////////////////////////////////////////////////////////// -static void DSP4_OP0E( void ) +static void dsp4_OP0E( void ) { - DSP4_vars.OAM_RowMax = 16; - memset(DSP4_vars.OAM_Row, 0, 64); + dsp4_vars.OAM_RowMax = 16; + memset(dsp4_vars.OAM_Row, 0, 64); } ////////////////////////////////////////////////////////////// -static void DSP4_OP0F( void ) +static void dsp4_OP0F( void ) { - DSP4.waiting4command = 0; - - // op flow control - switch (DSP4_vars.DSP4_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) - } + 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 : + // 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(); + // 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); + // no envelope here + dsp4_vars.world_xenv = 0; + } + while (1); - // terminate op - DSP4.waiting4command = 1; + // terminate op + dsp4.waiting4command = 1; } ////////////////////////////////////////////////////////////// -static void DSP4_OP10( void ) +static void dsp4_OP10( void ) { - DSP4.waiting4command = 0; - - // op flow control - switch (DSP4_vars.DSP4_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; + 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) +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); + // 0x155 = 341 = Horizontal Width of the Screen + *M = ((A * 0x0155 >> 2) & 0xf000) | + ((B * 0x0155 >> 6) & 0x0f00) | + ((C * 0x0155 >> 10) & 0x00f0) | + ((D * 0x0155 >> 14) & 0x000f); } @@ -1952,228 +1953,312 @@ static void DSP4_OP11(INT16 A, INT16 B, INT16 C, INT16 D, INT16 *M) //Processing Code ///////////////////////////////////////////////////////////// -static void InitDSP4( void ) +static void dsp4_register_save( running_machine *machine ) { - memset(&DSP4, 0, sizeof(DSP4)); - DSP4.waiting4command = 1; + 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_write( UINT8 dsp4_byte ) +static void dsp4_init( running_machine *machine ) { - // 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.DSP4_Logic = 0; - - - switch (DSP4.command) - { - case 0x0000: - DSP4.in_count = 4; break; - case 0x0001: - DSP4.in_count = 44; break; - case 0x0003: - DSP4.in_count = 0; break; - case 0x0005: - DSP4.in_count = 0; break; - case 0x0006: - DSP4.in_count = 0; break; - case 0x0007: - DSP4.in_count = 34; break; - case 0x0008: - DSP4.in_count = 90; break; - case 0x0009: - DSP4.in_count = 14; break; - case 0x000a: - DSP4.in_count = 6; break; - case 0x000b: - DSP4.in_count = 6; break; - case 0x000d: - DSP4.in_count = 42; break; - case 0x000e: - DSP4.in_count = 0; break; - case 0x000f: - DSP4.in_count = 46; break; - case 0x0010: - DSP4.in_count = 36; break; - case 0x0011: - DSP4.in_count = 8; break; - default: - DSP4.waiting4command = 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(); + memset(&dsp4, 0, sizeof(dsp4)); + dsp4.waiting4command = 1; - DSP4_OP11(a, b, c, d, &m); + 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; - } - } + DSP4_CLEAR_OUT(); + DSP4_WRITE_WORD(m); + + break; + } + + default: + break; + } + } } -static UINT8 DSP4_read( void ) +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; + 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 index c37d37a3a02..fd3fd0bceb7 100644 --- a/src/mame/machine/snesdsp4.h +++ b/src/mame/machine/snesdsp4.h @@ -5,96 +5,96 @@ #define TRUE 1 -struct DSP4_t +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]; + 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 +struct dsp4_vars_t { - // op control - INT8 DSP4_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 + // 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 diff --git a/src/mame/machine/snesobc1.c b/src/mame/machine/snesobc1.c index c1901d46f65..4720effa0cb 100644 --- a/src/mame/machine/snesobc1.c +++ b/src/mame/machine/snesobc1.c @@ -12,11 +12,15 @@ ***************************************************************************/ -#include "includes/snes.h" +struct _snes_obc1_state +{ + int address; + int offset; + int shift; +}; + +static struct _snes_obc1_state obc1_state; -static int obc1_address; -static int obc1_offset; -static int obc1_shift; static READ8_HANDLER( obc1_read ) { @@ -26,23 +30,23 @@ static READ8_HANDLER( obc1_read ) switch (address) { case 0x1ff0: - value = snes_ram[obc1_offset + (obc1_address << 2) + 0]; + value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 0]; break; case 0x1ff1: - value = snes_ram[obc1_offset + (obc1_address << 2) + 1]; + value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 1]; break; case 0x1ff2: - value = snes_ram[obc1_offset + (obc1_address << 2) + 2]; + value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 2]; break; case 0x1ff3: - value = snes_ram[obc1_offset + (obc1_address << 2) + 3]; + value = snes_ram[obc1_state.offset + (obc1_state.address << 2) + 3]; break; case 0x1ff4: - value = snes_ram[obc1_offset + (obc1_address >> 2) + 0x200]; + value = snes_ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200]; break; default: @@ -62,35 +66,35 @@ static WRITE8_HANDLER( obc1_write ) switch(address) { case 0x1ff0: - snes_ram[obc1_offset + (obc1_address << 2) + 0] = data; + snes_ram[obc1_state.offset + (obc1_state.address << 2) + 0] = data; break; case 0x1ff1: - snes_ram[obc1_offset + (obc1_address << 2) + 1] = data; + snes_ram[obc1_state.offset + (obc1_state.address << 2) + 1] = data; break; case 0x1ff2: - snes_ram[obc1_offset + (obc1_address << 2) + 2] = data; + snes_ram[obc1_state.offset + (obc1_state.address << 2) + 2] = data; break; case 0x1ff3: - snes_ram[obc1_offset + (obc1_address << 2) + 3] = data; + snes_ram[obc1_state.offset + (obc1_state.address << 2) + 3] = data; break; case 0x1ff4: - temp = snes_ram[obc1_offset + (obc1_address >> 2) + 0x200]; - temp = (temp & ~(3 << obc1_shift)) | ((data & 0x03) << obc1_shift); - snes_ram[obc1_offset + (obc1_address >> 2) + 0x200] = temp; + temp = snes_ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200]; + temp = (temp & ~(3 << obc1_state.shift)) | ((data & 0x03) << obc1_state.shift); + snes_ram[obc1_state.offset + (obc1_state.address >> 2) + 0x200] = temp; break; case 0x1ff5: - obc1_offset = (data & 0x01) ? 0x1800 : 0x1c00; + obc1_state.offset = (data & 0x01) ? 0x1800 : 0x1c00; snes_ram[address & 0x1fff] = data; break; case 0x1ff6: - obc1_address = data & 0x7f; - obc1_shift = (data & 0x03) << 1; + obc1_state.address = data & 0x7f; + obc1_state.shift = (data & 0x03) << 1; snes_ram[address & 0x1fff] = data; break; @@ -100,9 +104,13 @@ static WRITE8_HANDLER( obc1_write ) } } -static void obc1_init( void ) +static void obc1_init( running_machine *machine ) { - obc1_offset = (snes_ram[0x1ff5] & 0x01) ? 0x1800 : 0x1c00; - obc1_address = (snes_ram[0x1ff6] & 0x7f); - obc1_shift = (snes_ram[0x1ff6] & 0x03) << 1; + obc1_state.offset = (snes_ram[0x1ff5] & 0x01) ? 0x1800 : 0x1c00; + obc1_state.address = (snes_ram[0x1ff6] & 0x7f); + obc1_state.shift = (snes_ram[0x1ff6] & 0x03) << 1; + + state_save_register_global(machine, obc1_state.offset); + state_save_register_global(machine, obc1_state.address); + state_save_register_global(machine, obc1_state.shift); } diff --git a/src/mame/machine/snesrtc.c b/src/mame/machine/snesrtc.c index 26a4b6ced93..c69d4d56fd6 100644 --- a/src/mame/machine/snesrtc.c +++ b/src/mame/machine/snesrtc.c @@ -1,6 +1,6 @@ /*************************************************************************** - snessdd1.c + snesrtc.c File to handle emulation of the SNES "S-RTC" add-on chip. @@ -22,14 +22,14 @@ enum RTCM_Write }; -typedef struct +struct _snes_rtc_state { - UINT8 rtc_ram[13]; - INT32 rtc_mode; - INT8 rtc_index; -} _snes_rtc_t; + UINT8 ram[13]; + INT32 mode; + INT8 index; +}; -static _snes_rtc_t snes_rtc; +static _snes_rtc_state rtc_state; static const UINT8 srtc_months[12] = { @@ -39,29 +39,29 @@ static const UINT8 srtc_months[12] = 31, 30, 31 }; -static void srtc_update_time(running_machine *machine) +static void srtc_update_time( running_machine *machine ) { mame_system_time curtime, *systime = &curtime; mame_get_current_datetime(machine, &curtime); - snes_rtc.rtc_ram[0] = systime->local_time.second % 10; - snes_rtc.rtc_ram[1] = systime->local_time.second / 10; - snes_rtc.rtc_ram[2] = systime->local_time.minute % 10; - snes_rtc.rtc_ram[3] = systime->local_time.minute / 10; - snes_rtc.rtc_ram[4] = systime->local_time.hour % 10; - snes_rtc.rtc_ram[5] = systime->local_time.hour / 10; - snes_rtc.rtc_ram[6] = systime->local_time.mday % 10; - snes_rtc.rtc_ram[7] = systime->local_time.mday / 10; - snes_rtc.rtc_ram[8] = systime->local_time.month; - snes_rtc.rtc_ram[9] = (systime->local_time.year - 1900) % 10; - snes_rtc.rtc_ram[10] = ((systime->local_time.year - 1900) / 10) % 10; - snes_rtc.rtc_ram[11] = (systime->local_time.year - 1900) / 100; - snes_rtc.rtc_ram[12] = systime->local_time.weekday % 7; + rtc_state.ram[0] = systime->local_time.second % 10; + rtc_state.ram[1] = systime->local_time.second / 10; + rtc_state.ram[2] = systime->local_time.minute % 10; + rtc_state.ram[3] = systime->local_time.minute / 10; + rtc_state.ram[4] = systime->local_time.hour % 10; + rtc_state.ram[5] = systime->local_time.hour / 10; + rtc_state.ram[6] = systime->local_time.mday % 10; + rtc_state.ram[7] = systime->local_time.mday / 10; + rtc_state.ram[8] = systime->local_time.month; + rtc_state.ram[9] = (systime->local_time.year - 1900) % 10; + rtc_state.ram[10] = ((systime->local_time.year - 1900) / 10) % 10; + rtc_state.ram[11] = (systime->local_time.year - 1900) / 100; + rtc_state.ram[12] = systime->local_time.weekday % 7; } // Returns day-of-week for specified date // e.g. 0 = Sunday, 1 = Monday, ... 6 = Saturday // Usage: weekday(2008, 1, 1) returns the weekday of January 1st, 2008 -static UINT8 srtc_weekday(UINT32 year, UINT32 month, UINT32 day) +static UINT8 srtc_weekday( UINT32 year, UINT32 month, UINT32 day ) { UINT32 y = 1900, m = 1; // Epoch is 1900-01-01 UINT32 sum = 0; // Number of days passed since epoch @@ -70,13 +70,13 @@ static UINT8 srtc_weekday(UINT32 year, UINT32 month, UINT32 day) month = MAX(1, MIN(12, month)); day = MAX(1, MIN(31, day)); - while(y < year) + while (y < year) { UINT8 leapyear = 0; - if((y % 4) == 0) + if ((y % 4) == 0) { leapyear = 1; - if((y % 100) == 0 && (y % 400) != 0) + if ((y % 100) == 0 && (y % 400) != 0) { leapyear = 0; } @@ -85,16 +85,16 @@ static UINT8 srtc_weekday(UINT32 year, UINT32 month, UINT32 day) y++; } - while(m < month) + while (m < month) { UINT32 days = srtc_months[m - 1]; - if(days == 28) + if (days == 28) { UINT8 leapyear = 0; - if((y % 4) == 0) + if ((y % 4) == 0) { leapyear = 1; - if((y % 100) == 0 && (y % 400) != 0) + if ((y % 100) == 0 && (y % 400) != 0) { leapyear = 0; } @@ -109,111 +109,114 @@ static UINT8 srtc_weekday(UINT32 year, UINT32 month, UINT32 day) return (sum + 1) % 7; // 1900-01-01 was a Monday } -static UINT8 srtc_mmio_read(running_machine *machine, UINT16 addr) +static UINT8 srtc_read( running_machine *machine, UINT16 addr ) { addr &= 0xffff; - if(addr == 0x2800) + if (addr == 0x2800) { - if(snes_rtc.rtc_mode != RTCM_Read) + if (rtc_state.mode != RTCM_Read) { return 0x00; } - if(snes_rtc.rtc_index < 0) + if (rtc_state.index < 0) { srtc_update_time(machine); - snes_rtc.rtc_index++; + rtc_state.index++; return 0x0f; } - else if(snes_rtc.rtc_index > 12) + else if (rtc_state.index > 12) { - snes_rtc.rtc_index = -1; + rtc_state.index = -1; return 0x0f; } else { - return snes_rtc.rtc_ram[snes_rtc.rtc_index++]; + return rtc_state.ram[rtc_state.index++]; } } return 0xff; } -static void srtc_mmio_write(running_machine *machine, UINT16 addr, UINT8 data) +static void srtc_write( running_machine *machine, UINT16 addr, UINT8 data ) { addr &= 0xffff; - if(addr == 0x2801) + if (addr == 0x2801) { data &= 0x0f; // Only the low four bits are used - if(data == 0x0d) + if (data == 0x0d) { - snes_rtc.rtc_mode = RTCM_Read; - snes_rtc.rtc_index = -1; + rtc_state.mode = RTCM_Read; + rtc_state.index = -1; return; } - if(data == 0x0e) + if (data == 0x0e) { - snes_rtc.rtc_mode = RTCM_Command; + rtc_state.mode = RTCM_Command; return; } - if(data == 0x0f) + if (data == 0x0f) { return; // Unknown behaviour } - if(snes_rtc.rtc_mode == RTCM_Write) + if (rtc_state.mode == RTCM_Write) { - if(snes_rtc.rtc_index >= 0 && snes_rtc.rtc_index < 12) + if (rtc_state.index >= 0 && rtc_state.index < 12) { - snes_rtc.rtc_ram[snes_rtc.rtc_index++] = data; + rtc_state.ram[rtc_state.index++] = data; - if(snes_rtc.rtc_index == 12) + if (rtc_state.index == 12) { // Day of week is automatically calculated and written - UINT32 day = snes_rtc.rtc_ram[6] + snes_rtc.rtc_ram[7] * 10; - UINT32 month = snes_rtc.rtc_ram[8]; - UINT32 year = snes_rtc.rtc_ram[9] + snes_rtc.rtc_ram[10] * 10 + snes_rtc.rtc_ram[11] * 100; + UINT32 day = rtc_state.ram[6] + rtc_state.ram[7] * 10; + UINT32 month = rtc_state.ram[8]; + UINT32 year = rtc_state.ram[9] + rtc_state.ram[10] * 10 + rtc_state.ram[11] * 100; year += 1000; - snes_rtc.rtc_ram[snes_rtc.rtc_index++] = srtc_weekday(year, month, day); + rtc_state.ram[rtc_state.index++] = srtc_weekday(year, month, day); } } } - else if(snes_rtc.rtc_mode == RTCM_Command) + else if (rtc_state.mode == RTCM_Command) { - if(data == 0) + if (data == 0) { - snes_rtc.rtc_mode = RTCM_Write; - snes_rtc.rtc_index = 0; + rtc_state.mode = RTCM_Write; + rtc_state.index = 0; } - else if(data == 4) + else if (data == 4) { UINT8 i; - snes_rtc.rtc_mode = RTCM_Ready; - snes_rtc.rtc_index = -1; + rtc_state.mode = RTCM_Ready; + rtc_state.index = -1; for(i = 0; i < 13; i++) { - snes_rtc.rtc_ram[i] = 0; + rtc_state.ram[i] = 0; } } else { // Unknown behaviour - snes_rtc.rtc_mode = RTCM_Ready; + rtc_state.mode = RTCM_Ready; } } } } -static void srtc_reset(running_machine *machine) +static void srtc_init( running_machine *machine ) { - snes_rtc.rtc_mode = RTCM_Read; - snes_rtc.rtc_index = -1; + rtc_state.mode = RTCM_Read; + rtc_state.index = -1; srtc_update_time(machine); -} + state_save_register_global_array(machine, rtc_state.ram); + state_save_register_global(machine, rtc_state.mode); + state_save_register_global(machine, rtc_state.index); +} diff --git a/src/mame/machine/snesst10.c b/src/mame/machine/snesst10.c index 4485f8d35db..17a54b9e297 100644 --- a/src/mame/machine/snesst10.c +++ b/src/mame/machine/snesst10.c @@ -15,13 +15,13 @@ ***************************************************************************/ -typedef struct +struct _snes_st010_state { INT16 x1, y1, quadrant, theta, o1; UINT8 *ram; -} _snes_st010_t; +}; -static _snes_st010_t snes_st010; +static _snes_st010_state st010_state; static const INT16 st010_sin_table[256] = { 0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2, @@ -163,13 +163,12 @@ static INT16 st010_cos( INT16 theta ) static UINT8 st010_readb( UINT16 address ) { - return snes_st010.ram[address & 0xfff]; + return st010_state.ram[address & 0xfff]; } static UINT16 st010_readw( UINT16 address ) { - return (st010_readb(address + 0) << 0) | - (st010_readb(address + 1) << 8); + return (st010_readb(address + 0) << 0) | (st010_readb(address + 1) << 8); } static UINT32 st010_readd( UINT16 address ) @@ -182,7 +181,7 @@ static UINT32 st010_readd( UINT16 address ) static void st010_writeb( UINT16 address, UINT8 data ) { - snes_st010.ram[address & 0xfff] = data; + st010_state.ram[address & 0xfff] = data; } static void st010_writew( UINT16 address, UINT16 data ) @@ -201,292 +200,341 @@ static void st010_writed( UINT16 address, UINT32 data ) // -static void st010_op_01_do_work(INT16 x0, INT16 y0) { - if((x0 < 0) && (y0 < 0)) { - snes_st010.x1 = -x0; - snes_st010.y1 = -y0; - snes_st010.quadrant = -0x8000; - } else if(x0 < 0) { - snes_st010.x1 = y0; - snes_st010.y1 = -x0; - snes_st010.quadrant = -0x4000; - } else if(y0 < 0) { - snes_st010.x1 = -y0; - snes_st010.y1 = x0; - snes_st010.quadrant = 0x4000; - } else { - snes_st010.x1 = x0; - snes_st010.y1 = y0; - snes_st010.quadrant = 0x0000; - } - - while((snes_st010.x1 > 0x1f) || (snes_st010.y1 > 0x1f)) { - if(snes_st010.x1 > 1) { snes_st010.x1 >>= 1; } - if(snes_st010.y1 > 1) { snes_st010.y1 >>= 1; } - } - - if(snes_st010.y1 == 0) { snes_st010.quadrant += 0x4000; } - - snes_st010.theta = (st010_arctan[snes_st010.y1][snes_st010.x1] << 8) ^ snes_st010.quadrant; +static void st010_op_01_do_work( INT16 x0, INT16 y0 ) +{ + if ((x0 < 0) && (y0 < 0)) + { + st010_state.x1 = -x0; + st010_state.y1 = -y0; + st010_state.quadrant = -0x8000; + } + else if (x0 < 0) + { + st010_state.x1 = y0; + st010_state.y1 = -x0; + st010_state.quadrant = -0x4000; + } + else if (y0 < 0) + { + st010_state.x1 = -y0; + st010_state.y1 = x0; + st010_state.quadrant = 0x4000; + } + else + { + st010_state.x1 = x0; + st010_state.y1 = y0; + st010_state.quadrant = 0x0000; + } + + while((st010_state.x1 > 0x1f) || (st010_state.y1 > 0x1f)) + { + if (st010_state.x1 > 1) + st010_state.x1 >>= 1; + if (st010_state.y1 > 1) + st010_state.y1 >>= 1; + } + + if (st010_state.y1 == 0) + st010_state.quadrant += 0x4000; + + st010_state.theta = (st010_arctan[st010_state.y1][st010_state.x1] << 8) ^ st010_state.quadrant; } // -static void st010_op_01( void ) { - INT16 x0 = st010_readw(0x0000); - INT16 y0 = st010_readw(0x0002); +static void st010_op_01( void ) +{ + INT16 x0 = st010_readw(0x0000); + INT16 y0 = st010_readw(0x0002); - st010_op_01_do_work(x0, y0); + st010_op_01_do_work(x0, y0); - st010_writew(0x0000, snes_st010.x1); - st010_writew(0x0002, snes_st010.y1); - st010_writew(0x0004, snes_st010.quadrant); -//st010_writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees - st010_writew(0x0010, snes_st010.theta); + st010_writew(0x0000, st010_state.x1); + st010_writew(0x0002, st010_state.y1); + st010_writew(0x0004, st010_state.quadrant); + //st010_writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees + st010_writew(0x0010, st010_state.theta); } -static void st010_op_02( void ) { - INT16 positions = st010_readw(0x0024); - UINT16 *places = (UINT16*)(snes_st010.ram + 0x0040); - UINT16 *drivers = (UINT16*)(snes_st010.ram + 0x0080); - - UINT8 sorted; - UINT16 temp; - int i; - if(positions > 1) { - do { - sorted = 1; - for(i = 0; i < positions - 1; i++) { - if(places[i] < places[i + 1]) { - temp = places[i + 1]; - places[i + 1] = places[i]; - places[i] = temp; - - temp = drivers[i + 1]; - drivers[i + 1] = drivers[i]; - drivers[i] = temp; - - sorted = 0; - } - } - positions--; - } while(!sorted); - } +static void st010_op_02( void ) +{ + INT16 positions = st010_readw(0x0024); + UINT16 *places = (UINT16*)(st010_state.ram + 0x0040); + UINT16 *drivers = (UINT16*)(st010_state.ram + 0x0080); + + UINT8 sorted; + UINT16 temp; + int i; + + if (positions > 1) + { + do + { + sorted = 1; + for (i = 0; i < positions - 1; i++) + { + if (places[i] < places[i + 1]) + { + temp = places[i + 1]; + places[i + 1] = places[i]; + places[i] = temp; + + temp = drivers[i + 1]; + drivers[i + 1] = drivers[i]; + drivers[i] = temp; + + sorted = 0; + } + } + positions--; + } while(!sorted); + } } -static void st010_op_03( void ) { - INT16 x0 = st010_readw(0x0000); - INT16 y0 = st010_readw(0x0002); - INT16 multiplier = st010_readw(0x0004); - INT32 x1, y1; +static void st010_op_03( void ) +{ + INT16 x0 = st010_readw(0x0000); + INT16 y0 = st010_readw(0x0002); + INT16 multiplier = st010_readw(0x0004); + INT32 x1, y1; - x1 = x0 * multiplier << 1; - y1 = y0 * multiplier << 1; + x1 = x0 * multiplier << 1; + y1 = y0 * multiplier << 1; - st010_writed(0x0010, x1); - st010_writed(0x0014, y1); + st010_writed(0x0010, x1); + st010_writed(0x0014, y1); } -static void st010_op_04( void ) { - INT16 x = st010_readw(0x0000); - INT16 y = st010_readw(0x0002); - INT16 square; - //calculate the vector length of (x,y) - square = sqrt((double)(y * y + x * x)); +static void st010_op_04( void ) +{ + INT16 x = st010_readw(0x0000); + INT16 y = st010_readw(0x0002); + INT16 square; + //calculate the vector length of (x,y) + square = sqrt((double)(y * y + x * x)); - st010_writew(0x0010, square); + st010_writew(0x0010, square); } // same as op_01_do_work, but we are only interested in the angle! -static void st010_op_05_do_work(INT16 x0, INT16 y0) { - INT16 x1, y1, quadrant; - if((x0 < 0) && (y0 < 0)) { - x1 = -x0; - y1 = -y0; - quadrant = -0x8000; - } else if(x0 < 0) { - x1 = y0; - y1 = -x0; - quadrant = -0x4000; - } else if(y0 < 0) { - x1 = -y0; - y1 = x0; - quadrant = 0x4000; - } else { - x1 = x0; - y1 = y0; - quadrant = 0x0000; - } - - while((x1 > 0x1f) || (y1 > 0x1f)) { - if(x1 > 1) { x1 >>= 1; } - if(y1 > 1) { y1 >>= 1; } - } - - if(y1 == 0) { quadrant += 0x4000; } - - snes_st010.o1 = (st010_arctan[y1][x1] << 8) ^ quadrant; +static void st010_op_05_do_work( INT16 x0, INT16 y0 ) +{ + INT16 x1, y1, quadrant; + if ((x0 < 0) && (y0 < 0)) + { + x1 = -x0; + y1 = -y0; + quadrant = -0x8000; + } + else if (x0 < 0) + { + x1 = y0; + y1 = -x0; + quadrant = -0x4000; + } + else if (y0 < 0) + { + x1 = -y0; + y1 = x0; + quadrant = 0x4000; + } + else + { + x1 = x0; + y1 = y0; + quadrant = 0x0000; + } + + while((x1 > 0x1f) || (y1 > 0x1f)) + { + if (x1 > 1) + x1 >>= 1; + if (y1 > 1) + y1 >>= 1; + } + + if (y1 == 0) + quadrant += 0x4000; + + st010_state.o1 = (st010_arctan[y1][x1] << 8) ^ quadrant; } -static void st010_op_05( void ) { - INT32 dx, dy; - UINT16 o1 = 0; - UINT8 wrap = 0; - - //target (x,y) coordinates - INT16 ypos_max = st010_readw(0x00c0); - INT16 xpos_max = st010_readw(0x00c2); - - //current coordinates and direction - INT32 ypos = st010_readd(0x00c4); - INT32 xpos = st010_readd(0x00c8); - UINT16 rot = st010_readw(0x00cc); - - //physics - UINT16 speed = st010_readw(0x00d4); - UINT16 accel = st010_readw(0x00d6); - UINT16 speed_max = st010_readw(0x00d8); - UINT16 old_speed; - - //special condition acknowledgement - INT16 system = st010_readw(0x00da); - INT16 flags = st010_readw(0x00dc); - - //new target coordinates - INT16 ypos_new = st010_readw(0x00de); - INT16 xpos_new = st010_readw(0x00e0); - - //mask upper bit - xpos_new &= 0x7fff; - - //get the current distance - dx = xpos_max - (xpos >> 16); - dy = ypos_max - (ypos >> 16); - - //quirk: clear and move in9 - st010_writew(0x00d2, 0xffff); - st010_writew(0x00da, 0x0000); - - //grab the target angle - st010_op_05_do_work(dy, dx); - o1 = (UINT16)snes_st010.o1; - - //check for wrapping - if(abs(o1 - rot) > 0x8000) { - o1 += 0x8000; - rot += 0x8000; - wrap = 1; - } - - old_speed = speed; - - //special case - if(abs(o1 - rot) == 0x8000) { - speed = 0x100; - } - - //slow down for sharp curves - else if(abs(o1 - rot) >= 0x1000) { - UINT32 slow = abs(o1 - rot); - slow >>= 4; //scaling - speed -= slow; - } - - //otherwise accelerate - else { - speed += accel; - if(speed > speed_max) { - speed = speed_max; //clip speed - } - } - - //prevent negative/positive overflow - if(abs(old_speed - speed) > 0x8000) { - if(old_speed < speed) { speed = 0; } - else speed = 0xff00; - } - - //adjust direction by so many degrees - //be careful of negative adjustments - if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) { - if(o1 < rot) { rot -= 0x280; } - else if(o1 > rot) { rot += 0x280; } - } - - //turn off wrapping - if(wrap) { rot -= 0x8000; } - - //now check the distances (store for later) - dx = (xpos_max << 16) - xpos; - dy = (ypos_max << 16) - ypos; - dx >>= 16; - dy >>= 16; - - //if we're in so many units of the target, signal it - if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) { - //announce our new destination and flag it - xpos_max = xpos_new & 0x7fff; - ypos_max = ypos_new; - flags |= 0x08; - } - - //update position - xpos -= (st010_cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; - ypos -= (st010_sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; - - //quirk: mask upper byte - xpos &= 0x1fffffff; - ypos &= 0x1fffffff; - - st010_writew(0x00c0, ypos_max); - st010_writew(0x00c2, xpos_max); - st010_writed(0x00c4, ypos); - st010_writed(0x00c8, xpos); - st010_writew(0x00cc, rot); - st010_writew(0x00d4, speed); - st010_writew(0x00dc, flags); +static void st010_op_05( void ) +{ + INT32 dx, dy; + UINT16 o1 = 0; + UINT8 wrap = 0; + + //target (x,y) coordinates + INT16 ypos_max = st010_readw(0x00c0); + INT16 xpos_max = st010_readw(0x00c2); + + //current coordinates and direction + INT32 ypos = st010_readd(0x00c4); + INT32 xpos = st010_readd(0x00c8); + UINT16 rot = st010_readw(0x00cc); + + //physics + UINT16 speed = st010_readw(0x00d4); + UINT16 accel = st010_readw(0x00d6); + UINT16 speed_max = st010_readw(0x00d8); + UINT16 old_speed; + + //special condition acknowledgement + INT16 system = st010_readw(0x00da); + INT16 flags = st010_readw(0x00dc); + + //new target coordinates + INT16 ypos_new = st010_readw(0x00de); + INT16 xpos_new = st010_readw(0x00e0); + + //mask upper bit + xpos_new &= 0x7fff; + + //get the current distance + dx = xpos_max - (xpos >> 16); + dy = ypos_max - (ypos >> 16); + + //quirk: clear and move in9 + st010_writew(0x00d2, 0xffff); + st010_writew(0x00da, 0x0000); + + //grab the target angle + st010_op_05_do_work(dy, dx); + o1 = (UINT16)st010_state.o1; + + //check for wrapping + if (abs(o1 - rot) > 0x8000) + { + o1 += 0x8000; + rot += 0x8000; + wrap = 1; + } + + old_speed = speed; + + //special case + if (abs(o1 - rot) == 0x8000) + { + speed = 0x100; + } + //slow down for sharp curves + else if (abs(o1 - rot) >= 0x1000) + { + UINT32 slow = abs(o1 - rot); + slow >>= 4; //scaling + speed -= slow; + } + //otherwise accelerate + else + { + speed += accel; + if (speed > speed_max) + speed = speed_max; //clip speed + } + + //prevent negative/positive overflow + if (abs(old_speed - speed) > 0x8000) + { + if (old_speed < speed) + speed = 0; + else + speed = 0xff00; + } + + //adjust direction by so many degrees + //be careful of negative adjustments + if ((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) + { + if (o1 < rot) + rot -= 0x280; + else if (o1 > rot) + rot += 0x280; + } + + //turn off wrapping + if (wrap) + rot -= 0x8000; + + //now check the distances (store for later) + dx = (xpos_max << 16) - xpos; + dy = (ypos_max << 16) - ypos; + dx >>= 16; + dy >>= 16; + + //if we're in so many units of the target, signal it + if ((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) + { + //announce our new destination and flag it + xpos_max = xpos_new & 0x7fff; + ypos_max = ypos_new; + flags |= 0x08; + } + + //update position + xpos -= (st010_cos(rot) * 0x400 >> 15) * (speed >> 8) << 1; + ypos -= (st010_sin(rot) * 0x400 >> 15) * (speed >> 8) << 1; + + //quirk: mask upper byte + xpos &= 0x1fffffff; + ypos &= 0x1fffffff; + + st010_writew(0x00c0, ypos_max); + st010_writew(0x00c2, xpos_max); + st010_writed(0x00c4, ypos); + st010_writed(0x00c8, xpos); + st010_writew(0x00cc, rot); + st010_writew(0x00d4, speed); + st010_writew(0x00dc, flags); } -static void st010_op_06( void ) { - INT16 multiplicand = st010_readw(0x0000); - INT16 multiplier = st010_readw(0x0002); - INT32 product; +static void st010_op_06( void ) +{ + INT16 multiplicand = st010_readw(0x0000); + INT16 multiplier = st010_readw(0x0002); + INT32 product; - product = multiplicand * multiplier << 1; + product = multiplicand * multiplier << 1; - st010_writed(0x0010, product); + st010_writed(0x0010, product); } -static void st010_op_07( void ) { - INT16 theta = st010_readw(0x0000); +static void st010_op_07( void ) +{ + INT16 theta = st010_readw(0x0000); + + INT16 data; + int i, offset; + for (i = 0, offset = 0; i < 176; i++) + { + data = st010_mode7_scale[i] * st010_cos(theta) >> 15; + st010_writew(0x00f0 + offset, data); + st010_writew(0x0510 + offset, data); - INT16 data; - int i, offset; - for(i = 0, offset = 0; i < 176; i++) { - data = st010_mode7_scale[i] * st010_cos(theta) >> 15; - st010_writew(0x00f0 + offset, data); - st010_writew(0x0510 + offset, data); + data = st010_mode7_scale[i] * st010_sin(theta) >> 15; + st010_writew(0x0250 + offset, data); + if (data) + data = ~data; - data = st010_mode7_scale[i] * st010_sin(theta) >> 15; - st010_writew(0x0250 + offset, data); - if(data) { data = ~data; } - st010_writew(0x03b0 + offset, data); + st010_writew(0x03b0 + offset, data); - offset += 2; - } + offset += 2; + } } -static void st010_op_08( void ) { - INT16 x0 = st010_readw(0x0000); - INT16 y0 = st010_readw(0x0002); - INT16 theta = st010_readw(0x0004); - INT16 x1, y1; +static void st010_op_08( void ) +{ + INT16 x0 = st010_readw(0x0000); + INT16 y0 = st010_readw(0x0002); + INT16 theta = st010_readw(0x0004); + INT16 x1, y1; - x1 = (y0 * st010_sin(theta) >> 15) + (x0 * st010_cos(theta) >> 15); - y1 = (y0 * st010_cos(theta) >> 15) - (x0 * st010_sin(theta) >> 15); + x1 = (y0 * st010_sin(theta) >> 15) + (x0 * st010_cos(theta) >> 15); + y1 = (y0 * st010_cos(theta) >> 15) - (x0 * st010_sin(theta) >> 15); - st010_writew(0x0010, x1); - st010_writew(0x0012, y1); + st010_writew(0x0010, x1); + st010_writew(0x0012, y1); } // init, reset & handlers @@ -502,7 +550,7 @@ static void st010_write( UINT16 address, UINT8 data ) if ((address & 0xfff) == 0x0021 && (data & 0x80)) { - switch (snes_st010.ram[0x0020]) + switch (st010_state.ram[0x0020]) { case 0x01: st010_op_01(); break; case 0x02: st010_op_02(); break; @@ -514,21 +562,28 @@ static void st010_write( UINT16 address, UINT8 data ) case 0x08: st010_op_08(); break; } - snes_st010.ram[0x0021] &= ~0x80; + st010_state.ram[0x0021] &= ~0x80; } } static void st010_init( running_machine* machine ) { - snes_st010.ram = (UINT8*)auto_alloc_array(machine, UINT8, 0x1000); + st010_state.ram = (UINT8*)auto_alloc_array_clear(machine, UINT8, 0x1000); + + state_save_register_global(machine, st010_state.x1); + state_save_register_global(machine, st010_state.y1); + state_save_register_global(machine, st010_state.quadrant); + state_save_register_global(machine, st010_state.theta); + state_save_register_global(machine, st010_state.o1); + + state_save_register_global_pointer(machine, st010_state.ram, 0x1000); } static void st010_reset( void ) { - snes_st010.x1 = 0; - snes_st010.y1 = 0; - snes_st010.quadrant = 0; - snes_st010.theta = 0; - memset(snes_st010.ram, 0, 0x1000); + st010_state.x1 = 0; + st010_state.y1 = 0; + st010_state.quadrant = 0; + st010_state.theta = 0; } |