/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and * Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). * * (c) Copyright 2014 - 2016 Daniel De Matteis. (UNDER NO CIRCUMSTANCE * WILL COMMERCIAL RIGHTS EVER BE APPROPRIATED TO ANY PARTY) * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: http://www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */ #include "snes9x.h" #include "dsp1.h" #include "missing.h" #include "memmap.h" #include #include "dsp1emu_gp32.c" void S9xInitDSP1() { static bool8 init = FALSE; if (!init) { InitDSP(); init = TRUE; } } void S9xResetDSP1() { S9xInitDSP1(); DSP1.waiting4command = TRUE; DSP1.in_count = 0; DSP1.out_count = 0; DSP1.in_index = 0; DSP1.out_index = 0; DSP1.first_parameter = TRUE; } uint8 S9xGetDSP(uint16 address) { uint8 t; if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) { if (DSP1.out_count) { if ((address & 1) == 0) t = (uint8) DSP1.output [DSP1.out_index]; else { t = (uint8)(DSP1.output [DSP1.out_index] >> 8); DSP1.out_index++; if (--DSP1.out_count == 0) { if (DSP1.command == 0x1a || DSP1.command == 0x0a) { DSPOp0A(); DSP1.out_count = 4; DSP1.out_index = 0; DSP1.output [0] = Op0AA; DSP1.output [1] = Op0AB; DSP1.output [2] = Op0AC; DSP1.output [3] = Op0AD; } } DSP1.waiting4command = TRUE; } } else { // Top Gear 3000 requires this value.... t = 0xff; } } else t = 0x80; return (t); } void S9xSetDSP(uint8 byte, uint16 address) { if ((address & 0xf000) == 0x6000 || (address >= 0x8000 && address < 0xc000)) { if ((address & 1) == 0) { if (DSP1.waiting4command) { DSP1.command = byte; DSP1.in_index = 0; DSP1.waiting4command = FALSE; DSP1.first_parameter = TRUE; // Mario Kart uses 0x00, 0x02, 0x06, 0x0c, 0x28, 0x0a switch (byte) { case 0x00: DSP1.in_count = 2; break; case 0x10: DSP1.in_count = 2; break; case 0x04: DSP1.in_count = 2; break; case 0x08: DSP1.in_count = 3; break; case 0x18: DSP1.in_count = 4; break; case 0x28: DSP1.in_count = 3; break; case 0x0c: DSP1.in_count = 3; break; case 0x1c: DSP1.in_count = 6; break; case 0x02: DSP1.in_count = 7; break; case 0x0a: DSP1.in_count = 1; break; case 0x1a: DSP1.in_count = 1; break; case 0x06: DSP1.in_count = 3; break; case 0x0e: DSP1.in_count = 2; break; case 0x01: DSP1.in_count = 4; break; case 0x11: DSP1.in_count = 4; break; case 0x21: DSP1.in_count = 4; break; case 0x0d: DSP1.in_count = 3; break; case 0x1d: DSP1.in_count = 3; break; case 0x2d: DSP1.in_count = 3; break; case 0x03: DSP1.in_count = 3; break; case 0x13: DSP1.in_count = 3; break; case 0x23: DSP1.in_count = 3; break; case 0x0b: DSP1.in_count = 3; break; case 0x1b: DSP1.in_count = 3; break; case 0x2b: DSP1.in_count = 3; break; case 0x14: DSP1.in_count = 6; break; // case 0x80: DSP1.in_count = 2; break; default: case 0x80: DSP1.in_count = 0; DSP1.waiting4command = TRUE; DSP1.first_parameter = TRUE; break; } } else { DSP1.parameters [DSP1.in_index] = byte; DSP1.first_parameter = FALSE; } } else { if (DSP1.waiting4command || (DSP1.first_parameter && byte == 0x80)) { DSP1.waiting4command = TRUE; DSP1.first_parameter = FALSE; } else if (DSP1.first_parameter) { } else { if (DSP1.in_count) { DSP1.parameters [DSP1.in_index] |= (byte << 8); if (--DSP1.in_count == 0) { // Actually execute the command DSP1.waiting4command = TRUE; DSP1.out_index = 0; switch (DSP1.command) { case 0x00: // Multiple Op00Multiplicand = (int16) DSP1.parameters [0]; Op00Multiplier = (int16) DSP1.parameters [1]; DSPOp00(); DSP1.out_count = 1; DSP1.output [0] = Op00Result; break; case 0x10: // Inverse Op10Coefficient = (int16) DSP1.parameters [0]; Op10Exponent = (int16) DSP1.parameters [1]; DSPOp10(); DSP1.out_count = 2; DSP1.output [0] = (uint16)(int16) Op10CoefficientR; DSP1.output [1] = (uint16)(int16) Op10ExponentR; break; case 0x04: // Sin and Cos of angle Op04Angle = (int16) DSP1.parameters [0]; Op04Radius = (uint16) DSP1.parameters [1]; DSPOp04(); DSP1.out_count = 2; DSP1.output [0] = (uint16) Op04Sin; DSP1.output [1] = (uint16) Op04Cos; break; case 0x08: // Radius Op08X = (int16) DSP1.parameters [0]; Op08Y = (int16) DSP1.parameters [1]; Op08Z = (int16) DSP1.parameters [2]; DSPOp08(); DSP1.out_count = 2; DSP1.output [0] = (int16) Op08Ll; DSP1.output [1] = (int16) Op08Lh; break; case 0x18: // Range Op18X = (int16) DSP1.parameters [0]; Op18Y = (int16) DSP1.parameters [1]; Op18Z = (int16) DSP1.parameters [2]; Op18R = (int16) DSP1.parameters [3]; DSPOp18(); DSP1.out_count = 1; DSP1.output [0] = Op18D; break; case 0x28: // Distance (vector length) Op28X = (int16) DSP1.parameters [0]; Op28Y = (int16) DSP1.parameters [1]; Op28Z = (int16) DSP1.parameters [2]; DSPOp28(); DSP1.out_count = 1; DSP1.output [0] = (uint16) Op28R; break; case 0x0c: // Rotate (2D rotate) Op0CA = (int16) DSP1.parameters [0]; Op0CX1 = (int16) DSP1.parameters [1]; Op0CY1 = (int16) DSP1.parameters [2]; DSPOp0C(); DSP1.out_count = 2; DSP1.output [0] = (uint16) Op0CX2; DSP1.output [1] = (uint16) Op0CY2; break; case 0x1c: // Polar (3D rotate) Op1CZ = DSP1.parameters [0]; Op1CX = DSP1.parameters [1]; Op1CY = DSP1.parameters [2]; Op1CXBR = DSP1.parameters [3]; Op1CYBR = DSP1.parameters [4]; Op1CZBR = DSP1.parameters [5]; DSPOp1C(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op1CXAR; DSP1.output [1] = (uint16) Op1CYAR; DSP1.output [2] = (uint16) Op1CZAR; break; case 0x02: // Parameter (Projection) Op02FX = DSP1.parameters [0]; Op02FY = DSP1.parameters [1]; Op02FZ = DSP1.parameters [2]; Op02LFE = DSP1.parameters [3]; Op02LES = DSP1.parameters [4]; Op02AAS = DSP1.parameters [5]; Op02AZS = DSP1.parameters [6]; DSPOp02(); DSP1.out_count = 4; DSP1.output [0] = Op02VOF; DSP1.output [1] = Op02VVA; DSP1.output [2] = Op02CX; DSP1.output [3] = Op02CY; break; case 0x1a: // Raster mode 7 matrix data case 0x0a: Op0AVS = DSP1.parameters [0]; DSPOp0A(); DSP1.out_count = 4; DSP1.output [0] = Op0AA; DSP1.output [1] = Op0AB; DSP1.output [2] = Op0AC; DSP1.output [3] = Op0AD; break; case 0x06: // Project object Op06X = (int16) DSP1.parameters [0]; Op06Y = (int16) DSP1.parameters [1]; Op06Z = (int16) DSP1.parameters [2]; DSPOp06(); DSP1.out_count = 3; DSP1.output [0] = Op06H; DSP1.output [1] = Op06V; DSP1.output [2] = Op06S; break; case 0x0e: // Target Op0EH = (int16) DSP1.parameters [0]; Op0EV = (int16) DSP1.parameters [1]; DSPOp0E(); DSP1.out_count = 2; DSP1.output [0] = Op0EX; DSP1.output [1] = Op0EY; break; // Extra commands used by Pilot Wings case 0x01: // Set attitude matrix A Op01m = (int16) DSP1.parameters [0]; Op01Zr = (int16) DSP1.parameters [1]; Op01Xr = (int16) DSP1.parameters [2]; Op01Yr = (int16) DSP1.parameters [3]; DSPOp01(); break; case 0x11: // Set attitude matrix B Op11m = (int16) DSP1.parameters [0]; Op11Zr = (int16) DSP1.parameters [1]; Op11Xr = (int16) DSP1.parameters [2]; Op11Yr = (int16) DSP1.parameters [3]; DSPOp11(); break; case 0x21: // Set attitude matrix C Op21m = (int16) DSP1.parameters [0]; Op21Zr = (int16) DSP1.parameters [1]; Op21Xr = (int16) DSP1.parameters [2]; Op21Yr = (int16) DSP1.parameters [3]; DSPOp21(); break; case 0x0d: // Objective matrix A Op0DX = (int16) DSP1.parameters [0]; Op0DY = (int16) DSP1.parameters [1]; Op0DZ = (int16) DSP1.parameters [2]; DSPOp0D(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op0DF; DSP1.output [1] = (uint16) Op0DL; DSP1.output [2] = (uint16) Op0DU; break; case 0x1d: // Objective matrix B Op1DX = (int16) DSP1.parameters [0]; Op1DY = (int16) DSP1.parameters [1]; Op1DZ = (int16) DSP1.parameters [2]; DSPOp1D(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op1DF; DSP1.output [1] = (uint16) Op1DL; DSP1.output [2] = (uint16) Op1DU; break; case 0x2d: // Objective matrix C Op2DX = (int16) DSP1.parameters [0]; Op2DY = (int16) DSP1.parameters [1]; Op2DZ = (int16) DSP1.parameters [2]; DSPOp2D(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op2DF; DSP1.output [1] = (uint16) Op2DL; DSP1.output [2] = (uint16) Op2DU; break; case 0x03: // Subjective matrix A Op03F = (int16) DSP1.parameters [0]; Op03L = (int16) DSP1.parameters [1]; Op03U = (int16) DSP1.parameters [2]; DSPOp03(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op03X; DSP1.output [1] = (uint16) Op03Y; DSP1.output [2] = (uint16) Op03Z; break; case 0x13: // Subjective matrix B Op13F = (int16) DSP1.parameters [0]; Op13L = (int16) DSP1.parameters [1]; Op13U = (int16) DSP1.parameters [2]; DSPOp13(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op13X; DSP1.output [1] = (uint16) Op13Y; DSP1.output [2] = (uint16) Op13Z; break; case 0x23: // Subjective matrix C Op23F = (int16) DSP1.parameters [0]; Op23L = (int16) DSP1.parameters [1]; Op23U = (int16) DSP1.parameters [2]; DSPOp23(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op23X; DSP1.output [1] = (uint16) Op23Y; DSP1.output [2] = (uint16) Op23Z; break; case 0x0b: Op0BX = (int16) DSP1.parameters [0]; Op0BY = (int16) DSP1.parameters [1]; Op0BZ = (int16) DSP1.parameters [2]; DSPOp0B(); DSP1.out_count = 1; DSP1.output [0] = (uint16) Op0BS; break; case 0x1b: Op1BX = (int16) DSP1.parameters [0]; Op1BY = (int16) DSP1.parameters [1]; Op1BZ = (int16) DSP1.parameters [2]; DSPOp1B(); DSP1.out_count = 1; DSP1.output [0] = (uint16) Op1BS; break; case 0x2b: Op2BX = (int16) DSP1.parameters [0]; Op2BY = (int16) DSP1.parameters [1]; Op2BZ = (int16) DSP1.parameters [2]; DSPOp0B(); DSP1.out_count = 1; DSP1.output [0] = (uint16) Op2BS; break; case 0x14: // Gyrate Op14Zr = (int16) DSP1.parameters [0]; Op14Xr = (int16) DSP1.parameters [1]; Op14Yr = (int16) DSP1.parameters [2]; Op14U = (int16) DSP1.parameters [3]; Op14F = (int16) DSP1.parameters [4]; Op14L = (int16) DSP1.parameters [5]; DSPOp14(); DSP1.out_count = 3; DSP1.output [0] = (uint16) Op14Zrr; DSP1.output [1] = (uint16) Op14Xrr; DSP1.output [2] = (uint16) Op14Yrr; break; default: break; } } else DSP1.in_index++; } } } } }