diff options
| author | hrydgard <hrydgard@gmail.com> | 2009-06-28 10:00:25 +0000 |
|---|---|---|
| committer | hrydgard <hrydgard@gmail.com> | 2009-06-28 10:00:25 +0000 |
| commit | 895b02f4102885d8ab8c4419d76dfef7f4c21703 (patch) | |
| tree | ea834590ba48451eeef493f22e4eddb57892e02d /Source/Core/DSPCore/Src/DSPAccelerator.cpp | |
| parent | 7ea2bc5da9681bca748f783f433ccaf689f7b604 (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.cpp | 152 |
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); +} |
