From 3fdc34d03bb861ff90c5cd8bba54ce2db8e8a268 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Wed, 28 Aug 2013 18:49:04 +0000 Subject: [PATCH] AICA: Implemented DMA [Angelo Salese] --- src/emu/sound/aica.c | 129 +++++++++++++++++++++++++++++++++++++- src/mame/includes/dc.h | 4 +- src/mame/machine/dc.c | 26 +++----- src/mess/drivers/dccons.c | 2 +- 4 files changed, 136 insertions(+), 25 deletions(-) diff --git a/src/emu/sound/aica.c b/src/emu/sound/aica.c index 18d187cfbcd..3078253075e 100644 --- a/src/emu/sound/aica.c +++ b/src/emu/sound/aica.c @@ -194,9 +194,14 @@ struct aica_state emu_timer *timerA, *timerB, *timerC; // DMA stuff - UINT32 aica_dmea; - UINT16 aica_drga; - UINT16 aica_dtlg; + struct{ + UINT32 dmea; + UINT16 drga; + UINT16 dlg; + UINT8 dgate; + UINT8 ddir; + }dma; + int ARTABLE[64], DRTABLE[64]; @@ -204,6 +209,8 @@ struct aica_state device_t *device; }; +static void aica_exec_dma(aica_state *aica,address_space &space); /*state DMA transfer function*/ + static const float SDLT[16]={-1000000.0,-42.0,-39.0,-36.0,-33.0,-30.0,-27.0,-24.0,-21.0,-18.0,-15.0,-12.0,-9.0,-6.0,-3.0,0.0}; static stream_sample_t *bufferl; @@ -712,6 +719,32 @@ static void AICA_UpdateReg(aica_state *AICA, address_space &space, int reg) case 0x16: case 0x17: break; + + case 0x80: + case 0x81: + AICA->dma.dmea = ((AICA->udata.data[0x80/2] & 0xfe00) << 7) | (AICA->dma.dmea & 0xfffc); + /* TODO: $TSCD - MRWINH regs */ + break; + + case 0x84: + case 0x85: + AICA->dma.dmea = (AICA->udata.data[0x84/2] & 0xfffc) | (AICA->dma.dmea & 0x7f0000); + break; + + case 0x88: + case 0x89: + AICA->dma.drga = (AICA->udata.data[0x88/2] & 0x7ffc); + AICA->dma.dgate = (AICA->udata.data[0x88/2] & 0x8000) >> 15; + break; + + case 0x8c: + case 0x8d: + AICA->dma.dlg = (AICA->udata.data[0x8c/2] & 0x7ffc); + AICA->dma.ddir = (AICA->udata.data[0x8c/2] & 0x8000) >> 15; + if(AICA->udata.data[0x8c/2] & 1) // dexe + aica_exec_dma(AICA,space); + break; + case 0x90: case 0x91: if(AICA->Master) @@ -920,6 +953,7 @@ static void AICA_w16(aica_state *AICA,address_space &space,unsigned int addr,uns // printf("%x to AICA global @ %x\n", val, addr & 0xff); *((unsigned short *) (AICA->udata.datab+((addr&0xff)))) = val; AICA_UpdateReg(AICA, space, addr&0xff); + } else if (addr == 0x2d00) { @@ -986,6 +1020,16 @@ static unsigned short AICA_r16(aica_state *AICA, address_space &space, unsigned return AICA->IRQR; } } + else + { + if(addr<0x3200) //COEF + v= *((unsigned short *) (AICA->DSP.COEF+(addr-0x3000)/2)); + else if(addr<0x3400) + v= *((unsigned short *) (AICA->DSP.MADRS+(addr-0x3200)/2)); + else if(addr<0x3c00) + v= *((unsigned short *) (AICA->DSP.MPRO+(addr-0x3400)/2)); + + } // else if (addr<0x700) // v=AICA->RINGBUF[(addr-0x600)/2]; return v; @@ -1250,6 +1294,85 @@ static void AICA_DoMasterSamples(aica_state *AICA, int nsamples) } } +static void aica_exec_dma(aica_state *aica,address_space &space) +{ + static UINT16 tmp_dma[4]; + int i; + + printf("AICA: DMA transfer START\n" + "DMEA: %08x DRGA: %08x DLG: %04x\n" + "DGATE: %d DDIR: %d\n",aica->dma.dmea,aica->dma.drga,aica->dma.dlg,aica->dma.dgate,aica->dma.ddir); + + /* Copy the dma values in a temp storage for resuming later */ + /* (DMA *can't* overwrite his parameters). */ + if(!(aica->dma.ddir)) + { + for(i=0;i<4;i++) + tmp_dma[i] = aica->udata.data[(0x80+(i*4))/2]; + } + + /* TODO: don't know if params auto-updates, I guess not ... */ + if(aica->dma.ddir) + { + if(aica->dma.dgate) + { + for(i=0;i < aica->dma.dlg;i+=2) + { + aica->AICARAM[aica->dma.dmea] = 0; + aica->AICARAM[aica->dma.dmea+1] = 0; + aica->dma.dmea+=2; + } + } + else + { + for(i=0;i < aica->dma.dlg;i+=2) + { + UINT16 tmp; + tmp = AICA_r16(aica, space, aica->dma.drga);; + aica->AICARAM[aica->dma.dmea] = tmp & 0xff; + aica->AICARAM[aica->dma.dmea+1] = tmp>>8; + aica->dma.dmea+=4; + aica->dma.drga+=4; + } + } + } + else + { + if(aica->dma.dgate) + { + for(i=0;i < aica->dma.dlg;i+=2) + { + AICA_w16(aica, space, aica->dma.drga, 0); + aica->dma.drga+=4; + } + } + else + { + for(i=0;i < aica->dma.dlg;i+=2) + { + UINT16 tmp; + tmp = aica->AICARAM[aica->dma.dmea]; + tmp|= aica->AICARAM[aica->dma.dmea+1]<<8; + AICA_w16(aica, space, aica->dma.drga, tmp); + aica->dma.dmea+=4; + aica->dma.drga+=4; + } + } + } + + /*Resume the values*/ + if(!(aica->dma.ddir)) + { + for(i=0;i<4;i++) + aica->udata.data[(0x80+(i*4))/2] = tmp_dma[i]; + } + + /* Job done, clear DEXE */ + aica->udata.data[0x8c/2] &= ~1; + /* request a dma end irq (TBD) */ + // ... +} + #ifdef UNUSED_FUNCTION static int AICA_IRQCB(void *param) { diff --git a/src/mame/includes/dc.h b/src/mame/includes/dc.h index 86ee13d7a77..8415d9fd313 100644 --- a/src/mame/includes/dc.h +++ b/src/mame/includes/dc.h @@ -57,8 +57,8 @@ class dc_state : public driver_device TIMER_CALLBACK_MEMBER(ch2_dma_irq); TIMER_CALLBACK_MEMBER(yuv_fifo_irq); TIMER_CALLBACK_MEMBER(dc_rtc_increment); - DECLARE_READ64_MEMBER(dc_aica_reg_r); - DECLARE_WRITE64_MEMBER(dc_aica_reg_w); + DECLARE_READ32_MEMBER(dc_aica_reg_r); + DECLARE_WRITE32_MEMBER(dc_aica_reg_w); DECLARE_READ32_MEMBER(dc_arm_aica_r); DECLARE_WRITE32_MEMBER(dc_arm_aica_w); void wave_dma_execute(address_space &space); diff --git a/src/mame/machine/dc.c b/src/mame/machine/dc.c index 61435ff6aac..914778d332e 100644 --- a/src/mame/machine/dc.c +++ b/src/mame/machine/dc.c @@ -762,30 +762,18 @@ void dc_state::machine_reset() dc_sysctrl_regs[SB_SBREV] = 0x0b; } -READ64_MEMBER(dc_state::dc_aica_reg_r) +READ32_MEMBER(dc_state::dc_aica_reg_r) { - //int reg; - UINT64 shift; - - /*reg = */decode_reg32_64(offset, mem_mask, &shift); - // mame_printf_verbose("AICA REG: [%08x] read %" I64FMT "x, mask %" I64FMT "x\n", 0x700000+reg*4, (UINT64)offset, mem_mask); - return (UINT64) aica_r(machine().device("aica"), space, offset*2, 0xffff)<> shift); - - if (reg == (0x2c00/4)) + if (offset == (0x2c00/4)) { - if (dat & 1) + if (data & 1) { /* halt the ARM7 */ m_soundcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); @@ -797,9 +785,9 @@ WRITE64_MEMBER(dc_state::dc_aica_reg_w) } } - aica_w(machine().device("aica"), space, offset*2, dat, shift ? ((mem_mask>>32)&0xffff) : (mem_mask & 0xffff)); + aica_w(machine().device("aica"), space, offset*2, data, 0xffff); -// mame_printf_verbose("AICA REG: [%08x=%x] write %" I64FMT "x to %x, mask %" I64FMT "x\n", 0x700000+reg*4, dat, data, offset, mem_mask); +// mame_printf_verbose("AICA REG: [%08x=%x] write %x to %x, mask %" I64FMT "x\n", 0x700000+reg*4, data, offset, mem_mask); } READ32_MEMBER(dc_state::dc_arm_aica_r) diff --git a/src/mess/drivers/dccons.c b/src/mess/drivers/dccons.c index 8e9240a0c7b..6ab730d1247 100644 --- a/src/mess/drivers/dccons.c +++ b/src/mess/drivers/dccons.c @@ -371,7 +371,7 @@ static ADDRESS_MAP_START( dc_map, AS_PROGRAM, 64, dc_cons_state ) AM_RANGE(0x005f7c00, 0x005f7cff) AM_DEVICE32("powervr2", powervr2_device, pd_dma_map, U64(0xffffffffffffffff)) AM_RANGE(0x005f8000, 0x005f9fff) AM_DEVICE32("powervr2", powervr2_device, ta_map, U64(0xffffffffffffffff)) AM_RANGE(0x00600000, 0x006007ff) AM_READWRITE(dc_modem_r, dc_modem_w ) - AM_RANGE(0x00700000, 0x00707fff) AM_READWRITE(dc_aica_reg_r, dc_aica_reg_w ) + AM_RANGE(0x00700000, 0x00707fff) AM_READWRITE32(dc_aica_reg_r, dc_aica_reg_w, U64(0xffffffffffffffff)) AM_RANGE(0x00710000, 0x0071000f) AM_MIRROR(0x02000000) AM_READWRITE32(dc_rtc_r, dc_rtc_w, U64(0xffffffffffffffff) ) AM_RANGE(0x00800000, 0x009fffff) AM_READWRITE(dc_arm_r, dc_arm_w )