diff options
| author | hrydgard <hrydgard@gmail.com> | 2009-06-28 10:24:44 +0000 |
|---|---|---|
| committer | hrydgard <hrydgard@gmail.com> | 2009-06-28 10:24:44 +0000 |
| commit | 5c7fc8ed7b66c864a0cfe27cf451f43b68f9a856 (patch) | |
| tree | e617bae0df96a6b976e6c6437cc2774fad223d81 /Source/Core/DSPCore/Src/DSPHWInterface.cpp | |
| parent | 895b02f4102885d8ab8c4419d76dfef7f4c21703 (diff) | |
DSP: build fixin', more movin', some comments.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3564 8ced0084-cf51-0410-be5f-012b33b47a6e
Diffstat (limited to 'Source/Core/DSPCore/Src/DSPHWInterface.cpp')
| -rw-r--r-- | Source/Core/DSPCore/Src/DSPHWInterface.cpp | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/Source/Core/DSPCore/Src/DSPHWInterface.cpp b/Source/Core/DSPCore/Src/DSPHWInterface.cpp new file mode 100644 index 0000000000..1b11387c55 --- /dev/null +++ b/Source/Core/DSPCore/Src/DSPHWInterface.cpp @@ -0,0 +1,313 @@ +/*==================================================================== + + filename: gdsp_interface.h + project: GCemu + created: 2004-6-18 + mail: duddie@walla.com + + Copyright (c) 2005 Duddie & Tratax + + 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; either version 2 + of the License, or (at your option) any later version. + + 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 for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + ====================================================================*/ + +#include <stdlib.h> + +#include "Thread.h" +#include "MemoryUtil.h" + +#include "DSPCore.h" +#include "DSPHost.h" +#include "DSPTables.h" +#include "DSPAnalyzer.h" +#include "DSPAccelerator.h" +#include "DSPInterpreter.h" +#include "DSPHWInterface.h" + +void gdsp_dma(); + +Common::CriticalSection g_CriticalSection; + +static volatile u16 gdsp_mbox[2][2]; + +u16 gdsp_ifx_regs[256]; + +void gdsp_ifx_init() +{ + for (int i = 0; i < 256; i++) + { + gdsp_ifx_regs[i] = 0; + } + + gdsp_mbox[0][0] = 0; + gdsp_mbox[0][1] = 0; + gdsp_mbox[1][0] = 0; + gdsp_mbox[1][1] = 0; +} + + +u32 gdsp_mbox_peek(u8 mbx) +{ + if (DSPHost_OnThread()) + g_CriticalSection.Enter(); + u32 value = ((gdsp_mbox[mbx][0] << 16) | gdsp_mbox[mbx][1]); + if (DSPHost_OnThread()) + g_CriticalSection.Leave(); + return value; +} + +void gdsp_mbox_write_h(u8 mbx, u16 val) +{ + if (DSPHost_OnThread()) + g_CriticalSection.Enter(); + gdsp_mbox[mbx][0] = val & 0x7fff; + if (DSPHost_OnThread()) + g_CriticalSection.Leave(); +} + + +void gdsp_mbox_write_l(u8 mbx, u16 val) +{ + if (DSPHost_OnThread()) + g_CriticalSection.Enter(); + gdsp_mbox[mbx][1] = val; + gdsp_mbox[mbx][0] |= 0x8000; + if (DSPHost_OnThread()) + g_CriticalSection.Leave(); + + if (mbx == GDSP_MBOX_DSP) + { + DEBUG_LOG(DSPLLE, " - DSP writes mail to mbx %i: 0x%08x (pc=0x%04x)", mbx, gdsp_mbox_peek(GDSP_MBOX_DSP), g_dsp.pc); + } else { + // Trigger exception? + } +} + + +u16 gdsp_mbox_read_h(u8 mbx) +{ + return gdsp_mbox[mbx][0]; // TODO: mask away the top bit? +} + + +u16 gdsp_mbox_read_l(u8 mbx) +{ + if (DSPHost_OnThread()) + g_CriticalSection.Enter(); + + u16 val = gdsp_mbox[mbx][1]; + gdsp_mbox[mbx][0] &= ~0x8000; + + DEBUG_LOG(DSPLLE, "- DSP reads mail from mbx %i: %08x (pc=0x%04x)", mbx, gdsp_mbox_peek(mbx), g_dsp.pc); + + if (DSPHost_OnThread()) + g_CriticalSection.Leave(); + return val; +} + + +void gdsp_ifx_write(u16 addr, u16 val) +{ + switch (addr & 0xff) + { + case 0xfb: // DIRQ + if (val & 0x1) + DSPHost_InterruptRequest(); + break; + + case 0xfc: // DMBH + gdsp_mbox_write_h(GDSP_MBOX_DSP, val); + break; + + case 0xfd: // DMBL + gdsp_mbox_write_l(GDSP_MBOX_DSP, val); + break; + + case 0xcb: // DSBL + gdsp_ifx_regs[addr & 0xFF] = val; + gdsp_dma(); + gdsp_ifx_regs[DSP_DSCR] &= ~0x0004; + break; + + case 0xd3: // ZeldaUnk (accelerator WRITE) + ERROR_LOG(DSPLLE, "Write To ZeldaUnk pc=%04x (%04x)\n", g_dsp.pc, val); + dsp_write_aram_d3(val); + break; + + case 0xde: + //if (val) + // PanicAlert("Gain written: %04x", val); // BMX XXX does, and sounds HORRIBLE. + case 0xcd: + case 0xce: + case 0xcf: + case 0xc9: + gdsp_ifx_regs[addr & 0xFF] = val; + break; + + default: + if ((addr & 0xff) >= 0xa0) { + if (pdlabels[(addr & 0xFF) - 0xa0].name) { + INFO_LOG(DSPLLE, "%04x MW %s (%04x)\n", g_dsp.pc, pdlabels[(addr & 0xFF) - 0xa0].name, val); + } + else { + ERROR_LOG(DSPLLE, "%04x MW %04x (%04x)\n", g_dsp.pc, addr, val); + } + } + else { + ERROR_LOG(DSPLLE, "%04x MW %04x (%04x)\n", g_dsp.pc, addr, val); + } + gdsp_ifx_regs[addr & 0xFF] = val; + break; + } +} + +u16 gdsp_ifx_read(u16 addr) +{ + switch (addr & 0xff) + { + case 0xfc: // DMBH + return gdsp_mbox_read_h(GDSP_MBOX_DSP); + + case 0xfe: // CMBH + return gdsp_mbox_read_h(GDSP_MBOX_CPU); + + case 0xff: // CMBL + return gdsp_mbox_read_l(GDSP_MBOX_CPU); + + case 0xc9: + return gdsp_ifx_regs[addr & 0xFF]; + + case 0xdd: // ADPCM Accelerator reads + return dsp_read_accelerator(); + + case 0xd3: + ERROR_LOG(DSPLLE, "DSP read aram D3"); + return dsp_read_aram_d3(); + + default: + if ((addr & 0xff) >= 0xa0) { + if (pdlabels[(addr & 0xFF) - 0xa0].name) { + INFO_LOG(DSPLLE, "%04x MR %s (%04x)\n", g_dsp.pc, pdlabels[(addr & 0xFF) - 0xa0].name, gdsp_ifx_regs[addr & 0xFF]); + } + else { + ERROR_LOG(DSPLLE, "%04x MR %04x (%04x)\n", g_dsp.pc, addr, gdsp_ifx_regs[addr & 0xFF]); + } + } + else { + ERROR_LOG(DSPLLE, "%04x MR %04x (%04x)\n", g_dsp.pc, addr, gdsp_ifx_regs[addr & 0xFF]); + } + return gdsp_ifx_regs[addr & 0xFF]; + } +} + +void gdsp_idma_in(u16 dsp_addr, u32 addr, u32 size) +{ + UnWriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); + + u8* dst = ((u8*)g_dsp.iram); + for (u32 i = 0; i < size; i += 2) + { + // TODO : this may be different on Wii. + *(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x0fffffff]); + } + WriteProtectMemory(g_dsp.iram, DSP_IRAM_BYTE_SIZE, false); + + INFO_LOG(DSPLLE, "*** Copy new UCode from 0x%08x to 0x%04x (crc: %8x)\n", addr, dsp_addr, g_dsp.iram_crc); + g_dsp.iram_crc = DSPHost_CodeLoaded(g_dsp.cpu_ram + (addr & 0x0fffffff), size); + DSPAnalyzer::Analyze(); +} + + +void gdsp_idma_out(u16 dsp_addr, u32 addr, u32 size) +{ + ERROR_LOG(DSPLLE, "*** idma_out IRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size); +} + + +// TODO: These should eat clock cycles. +void gdsp_ddma_in(u16 dsp_addr, u32 addr, u32 size) +{ + if ((addr & 0x7FFFFFFF) > 0x01FFFFFF) + { + ERROR_LOG(DSPLLE, "*** ddma_in read from invalid addr (0x%08x)\n", addr); + return; + } + + u8* dst = ((u8*)g_dsp.dram); + + for (u32 i = 0; i < size; i += 2) + { + *(u16*)&dst[dsp_addr + i] = Common::swap16(*(const u16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF]); + } + + INFO_LOG(DSPLLE, "*** ddma_in RAM (0x%08x) -> DRAM_DSP (0x%04x) : size (0x%08x)\n", addr, dsp_addr / 2, size); +} + + +void gdsp_ddma_out(u16 dsp_addr, u32 addr, u32 size) +{ + if ((addr & 0x7FFFFFFF) > 0x01FFFFFF) + { + ERROR_LOG(DSPLLE, "*** gdsp_ddma_out to invalid addr (0x%08x)\n", addr); + return; + } + + const u8* src = ((const u8*)g_dsp.dram); + + for (u32 i = 0; i < size; i += 2) + { + *(u16*)&g_dsp.cpu_ram[(addr + i) & 0x7FFFFFFF] = Common::swap16(*(const u16*)&src[dsp_addr + i]); + } + + INFO_LOG(DSPLLE, "*** ddma_out DRAM_DSP (0x%04x) -> RAM (0x%08x) : size (0x%08x)\n", dsp_addr / 2, addr, size); +} + +void gdsp_dma() +{ + u16 ctl; + u32 addr; + u16 dsp_addr; + u16 len; + + addr = (gdsp_ifx_regs[DSP_DSMAH] << 16) | gdsp_ifx_regs[DSP_DSMAL]; + ctl = gdsp_ifx_regs[DSP_DSCR]; + dsp_addr = gdsp_ifx_regs[DSP_DSPA] * 2; + len = gdsp_ifx_regs[DSP_DSBL]; + + if ((ctl > 3) || (len > 0x4000)) + { + ERROR_LOG(DSPLLE, "DMA ERROR pc: %04x ctl: %04x addr: %08x da: %04x size: %04x\n", g_dsp.pc, ctl, addr, dsp_addr, len); + exit(0); + } + + switch (ctl & 0x3) + { + case (DSP_CR_DMEM | DSP_CR_TO_CPU): + gdsp_ddma_out(dsp_addr, addr, len); + break; + + case (DSP_CR_DMEM | DSP_CR_FROM_CPU): + gdsp_ddma_in(dsp_addr, addr, len); + break; + + case (DSP_CR_IMEM | DSP_CR_TO_CPU): + gdsp_idma_out(dsp_addr, addr, len); + break; + + case (DSP_CR_IMEM | DSP_CR_FROM_CPU): + gdsp_idma_in(dsp_addr, addr, len); + break; + } +} |
