summaryrefslogtreecommitdiff
path: root/Source/Core/DSPCore/Src/DSPAccelerator.cpp
diff options
context:
space:
mode:
authorhrydgard <hrydgard@gmail.com>2009-06-28 10:00:25 +0000
committerhrydgard <hrydgard@gmail.com>2009-06-28 10:00:25 +0000
commit895b02f4102885d8ab8c4419d76dfef7f4c21703 (patch)
treeea834590ba48451eeef493f22e4eddb57892e02d /Source/Core/DSPCore/Src/DSPAccelerator.cpp
parent7ea2bc5da9681bca748f783f433ccaf689f7b604 (diff)
DSP: Add txt file with luigi ucode comments (very basic). Rename some stuff. Remove function pointer in g_dsp structure, replace with a "Host" function call. Fix a problem where symbols weren't loaded into DSP debugger.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3563 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore/Src/DSPAccelerator.cpp')
-rw-r--r--Source/Core/DSPCore/Src/DSPAccelerator.cpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/Source/Core/DSPCore/Src/DSPAccelerator.cpp b/Source/Core/DSPCore/Src/DSPAccelerator.cpp
new file mode 100644
index 0000000000..11aa749a04
--- /dev/null
+++ b/Source/Core/DSPCore/Src/DSPAccelerator.cpp
@@ -0,0 +1,152 @@
+// Copyright (C) 2003-2009 Dolphin Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official SVN repository and contact information can be found at
+// http://code.google.com/p/dolphin-emu/
+
+#include "Common.h"
+#include "DSPCore.h"
+#include "DSPHost.h"
+#include "gdsp_interface.h"
+#include "gdsp_interpreter.h"
+
+// The hardware adpcm decoder :)
+s16 ADPCM_Step(u32& _rSamplePos)
+{
+ const s16 *pCoefTable = (const s16 *)&gdsp_ifx_regs[DSP_COEF_A1_0];
+
+ if (((_rSamplePos) & 15) == 0)
+ {
+ gdsp_ifx_regs[DSP_PRED_SCALE] = DSPHost_ReadHostMemory((_rSamplePos & ~15) >> 1);
+ _rSamplePos += 2;
+ }
+
+ int scale = 1 << (gdsp_ifx_regs[DSP_PRED_SCALE] & 0xF);
+ int coef_idx = gdsp_ifx_regs[DSP_PRED_SCALE] >> 4;
+
+ s32 coef1 = pCoefTable[coef_idx * 2 + 0];
+ s32 coef2 = pCoefTable[coef_idx * 2 + 1];
+
+ int temp = (_rSamplePos & 1) ?
+ (DSPHost_ReadHostMemory(_rSamplePos >> 1) & 0xF) :
+ (DSPHost_ReadHostMemory(_rSamplePos >> 1) >> 4);
+
+ if (temp >= 8)
+ temp -= 16;
+
+ // 0x400 = 0.5 in 11-bit fixed point
+ int val = (scale * temp) + ((0x400 + coef1 * (s16)gdsp_ifx_regs[DSP_YN1] + coef2 * (s16)gdsp_ifx_regs[DSP_YN2]) >> 11);
+
+ // Clamp values.
+ if (val > 0x7FFF)
+ val = 0x7FFF;
+ else if (val < -0x7FFF)
+ val = -0x7FFF;
+
+ gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
+ gdsp_ifx_regs[DSP_YN1] = val;
+
+ _rSamplePos++;
+
+ // The advanced interpolation (linear, polyphase,...) is done by the UCode, so we don't
+ // need to bother with it here.
+ return val;
+}
+
+u16 dsp_read_aram_d3()
+{
+ // Zelda ucode reads ARAM through 0xffd3.
+
+ u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
+ u8 value = 0;
+ switch (gdsp_ifx_regs[DSP_FORMAT]) {
+ case 0x5: // unsigned 8-bit reads .. I think.
+ value = DSPHost_ReadHostMemory(Address);
+ break;
+ default:
+ ERROR_LOG(DSPLLE, "dsp_write_aram_d3: Unseen Format %i", gdsp_ifx_regs[DSP_FORMAT]);
+ break;
+ }
+ return value;
+}
+
+void dsp_write_aram_d3(u16 value)
+{
+ // Zelda ucode writes a bunch of zeros to ARAM through d3 during initialization.
+ // Don't know if it ever does it later, too.
+
+ const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
+ u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
+ switch (gdsp_ifx_regs[DSP_FORMAT]) {
+ case 0xA: // 16-bit writes
+ DSPHost_WriteHostMemory(value >> 8, Address);
+ DSPHost_WriteHostMemory(value & 0xFF, Address + 1);
+ break;
+ default:
+ ERROR_LOG(DSPLLE, "dsp_write_aram_d3: Unseen Format %i", gdsp_ifx_regs[DSP_FORMAT]);
+ break;
+ }
+}
+
+u16 dsp_read_accelerator()
+{
+ const u32 EndAddress = (gdsp_ifx_regs[DSP_ACEAH] << 16) | gdsp_ifx_regs[DSP_ACEAL];
+ u32 Address = (gdsp_ifx_regs[DSP_ACCAH] << 16) | gdsp_ifx_regs[DSP_ACCAL];
+
+ u16 val;
+
+ // lets the "hardware" decode
+ switch (gdsp_ifx_regs[DSP_FORMAT])
+ {
+ case 0x00: // ADPCM audio
+ val = ADPCM_Step(Address);
+ break;
+
+ case 0x0A: // 16-bit PCM audio
+ val = (DSPHost_ReadHostMemory(Address) << 8) | DSPHost_ReadHostMemory(Address + 1);
+
+ gdsp_ifx_regs[DSP_YN2] = gdsp_ifx_regs[DSP_YN1];
+ gdsp_ifx_regs[DSP_YN1] = val;
+
+ Address += 2;
+ break;
+
+ default:
+ val = (DSPHost_ReadHostMemory(Address) << 8) | DSPHost_ReadHostMemory(Address + 1);
+ Address += 2;
+ ERROR_LOG(DSPLLE, "Unknown DSP Format %i", gdsp_ifx_regs[DSP_FORMAT]);
+ break;
+ }
+
+ // TODO: Take ifx GAIN into account.
+
+ // check for loop
+ if (Address >= EndAddress)
+ {
+ // Set address back to start address.
+ Address = (gdsp_ifx_regs[DSP_ACSAH] << 16) | gdsp_ifx_regs[DSP_ACSAL];
+
+ // Do we really need both?
+ DSPCore_SetException(3);
+ DSPCore_SetException(5);
+
+ // Somehow, YN1 and YN2 must be initialized with their "loop" values, so yeah,
+ // it seems likely that we should raise an exception to let the DSP program do that,
+ // at least if DSP_FORMAT == 0x0A.
+ }
+
+ gdsp_ifx_regs[DSP_ACCAH] = Address >> 16;
+ gdsp_ifx_regs[DSP_ACCAL] = Address & 0xffff;
+ return(val);
+}