From 8ed23fe94562b0e0991d0ebdc1d0c703c5bc3bf0 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Tue, 7 Jun 2011 15:54:51 +0000 Subject: [PATCH] Rewrote SCSP DMA function from scratch [Angelo Salese] (port from MESS) --- src/emu/sound/scsp.c | 114 +++++++++++++++++++-------------------- src/mame/machine/stvcd.c | 44 ++++++++++++--- 2 files changed, 93 insertions(+), 65 deletions(-) diff --git a/src/emu/sound/scsp.c b/src/emu/sound/scsp.c index eab428a3c93..f258a353dbe 100644 --- a/src/emu/sound/scsp.c +++ b/src/emu/sound/scsp.c @@ -9,21 +9,22 @@ for the FM still comes from the wavetable RAM. ChangeLog: - * November 25, 2003 (ES) Fixed buggy timers and envelope overflows. - (RB) Improved sample rates other than 44100, multiple + * November 25, 2003 (ES) Fixed buggy timers and envelope overflows. + (RB) Improved sample rates other than 44100, multiple chips now works properly. - * December 02, 2003 (ES) Added DISDL register support, improves mix. - * April 28, 2004 (ES) Corrected envelope rates, added key-rate scaling, + * December 02, 2003 (ES) Added DISDL register support, improves mix. + * April 28, 2004 (ES) Corrected envelope rates, added key-rate scaling, added ringbuffer support. - * January 8, 2005 (RB) Added ability to specify region offset for RAM. - * January 26, 2007 (ES) Added on-board DSP capability + * January 8, 2005 (RB) Added ability to specify region offset for RAM. + * January 26, 2007 (ES) Added on-board DSP capability * September 24, 2007 (RB+ES) Removed fake reverb. Rewrote timers and IRQ handling. Fixed case where voice frequency is updated while looping. Enabled DSP again. - * December 16, 2007 (kingshriek) Many EG bug fixes, implemented effects mixer, + * December 16, 2007 (kingshriek) Many EG bug fixes, implemented effects mixer, implemented FM. - * January 5, 2008 (kingshriek+RB) Working, good-sounding FM, removed obsolete non-USEDSP code. - * April 22, 2009 ("PluginNinja") Improved slot monitor, misc cleanups + * January 5, 2008 (kingshriek+RB) Working, good-sounding FM, removed obsolete non-USEDSP code. + * April 22, 2009 ("PluginNinja") Improved slot monitor, misc cleanups + * June 6, 2011 (AS) Rewrote DMA from scratch, Darius 2 relies on it. */ #include "emu.h" @@ -218,6 +219,9 @@ struct _scsp_state UINT32 scsp_dmea; UINT16 scsp_drga; UINT16 scsp_dtlg; + UINT16 scsp_dmactrl; + + UINT16 dma_regs[3]; int ARTABLE[64], DRTABLE[64]; @@ -228,10 +232,11 @@ struct _scsp_state }; static void dma_scsp(address_space *space, scsp_state *scsp); /*state DMA transfer function*/ -#define scsp_dgate scsp_regs[0x16/2] & 0x4000 -#define scsp_ddir scsp_regs[0x16/2] & 0x2000 -#define scsp_dexe scsp_regs[0x16/2] & 0x1000 -#define dma_transfer_end ((scsp_regs[0x24/2] & 0x10)>>4)|(((scsp_regs[0x26/2] & 0x10)>>4)<<1)|(((scsp_regs[0x28/2] & 0x10)>>4)<<2) +#define scsp_dgate scsp->scsp_dmactrl & 0x4000 +#define scsp_ddir scsp->scsp_dmactrl & 0x2000 +#define scsp_dexe scsp->scsp_dmactrl & 0x1000 +/* TODO */ +//#define dma_transfer_end ((scsp_regs[0x24/2] & 0x10)>>4)|(((scsp_regs[0x26/2] & 0x10)>>4)<<1)|(((scsp_regs[0x28/2] & 0x10)>>4)<<2) static const float SDLT[8]={-1000000.0f,-36.0f,-30.0f,-24.0f,-18.0f,-12.0f,-6.0f,0.0f}; @@ -909,7 +914,7 @@ static void SCSP_w16(scsp_state *scsp,unsigned int addr,unsigned short val) if(addr==0xBF0) { SCSPDSP_Start(&scsp->DSP); - } + } } } } @@ -925,6 +930,8 @@ static unsigned short SCSP_r16(scsp_state *scsp, unsigned int addr) SCSP_UpdateSlotRegR(scsp, slot,addr&0x1f); v=*((unsigned short *) (scsp->Slots[slot].udata.datab+(addr))); } + else if(addr>=0x412 && addr <= 0x416) + v = scsp->dma_regs[((addr-0x412)/2) & 3]; else if(addr<0x600) { if (addr < 0x430) @@ -1167,11 +1174,21 @@ static void SCSP_DoMasterSamples(scsp_state *scsp, int nsamples) } } +/* TODO: this needs to be timer-ized */ static void dma_scsp(address_space *space, scsp_state *scsp) { - static UINT16 tmp_dma[3], *scsp_regs; + static UINT16 tmp_dma[3]; + int i; - scsp_regs = (UINT16 *)scsp->udata.datab; + scsp->scsp_dmactrl = scsp->dma_regs[2] & 0x7000; + + if(!(scsp_dexe)) //don't bother if DMA is off + return; + + /* calc the registers */ + scsp->scsp_dmea = ((scsp->dma_regs[1] & 0xf000) << 4) | (scsp->dma_regs[0] & 0xfffe); /* RAM address */ + scsp->scsp_drga = (scsp->dma_regs[1] & 0x0ffe); + scsp->scsp_dtlg = (scsp->dma_regs[2] & 0x0ffe); logerror("SCSP: DMA transfer START\n" "DMEA: %04x DRGA: %04x DTLG: %04x\n" @@ -1181,14 +1198,14 @@ static void dma_scsp(address_space *space, scsp_state *scsp) /* (DMA *can't* overwrite his parameters). */ if(!(scsp_ddir)) { - tmp_dma[0] = scsp_regs[0x12/2]; - tmp_dma[1] = scsp_regs[0x14/2]; - tmp_dma[2] = scsp_regs[0x16/2]; + for(i=0;i<3;i++) + tmp_dma[i] = scsp->dma_regs[i]; } + /* TODO: don't know if params auto-updates, I guess not ... */ if(scsp_ddir) { - for(;scsp->scsp_dtlg > 0;scsp->scsp_dtlg-=2) + for(i=0;i < scsp->scsp_dtlg;i+=2) { space->write_word(scsp->scsp_dmea, space->read_word(0x100000|scsp->scsp_drga)); scsp->scsp_dmea+=2; @@ -1197,7 +1214,7 @@ static void dma_scsp(address_space *space, scsp_state *scsp) } else { - for(;scsp->scsp_dtlg > 0;scsp->scsp_dtlg-=2) + for(i=0;i < scsp->scsp_dtlg;i+=2) { space->write_word(0x100000|scsp->scsp_drga,space->read_word(scsp->scsp_dmea)); scsp->scsp_dmea+=2; @@ -1208,14 +1225,18 @@ static void dma_scsp(address_space *space, scsp_state *scsp) /*Resume the values*/ if(!(scsp_ddir)) { - scsp_regs[0x12/2] = tmp_dma[0]; - scsp_regs[0x14/2] = tmp_dma[1]; - scsp_regs[0x16/2] = tmp_dma[2]; + for(i=0;i<3;i++) + scsp->dma_regs[i] = tmp_dma[i]; } - /*Job done,request a dma end irq*/ - if(scsp_regs[0x1e/2] & 0x10) - device_set_input_line(space->machine().device("audiocpu"),dma_transfer_end,HOLD_LINE); + /* Job done */ + scsp->dma_regs[2] &= ~0x1000; + /* request a dma end irq (TODO: make it inside the interface) */ + if(scsp->udata.data[0x1e/2] & 0x10) + { + popmessage("SCSP DMA IRQ triggered, contact MAMEdev"); + device_set_input_line(space->machine().device("audiocpu"),DecodeSCI(scsp,SCIDMA),HOLD_LINE); + } } #ifdef UNUSED_FUNCTION @@ -1279,8 +1300,6 @@ READ16_DEVICE_HANDLER( scsp_r ) return SCSP_r16(scsp, offset*2); } -UINT32* stv_scu; - WRITE16_DEVICE_HANDLER( scsp_w ) { scsp_state *scsp = get_safe_token(device); @@ -1298,40 +1317,19 @@ WRITE16_DEVICE_HANDLER( scsp_w ) { // check DMA case 0x412: - /*DMEA [15:1]*/ - /*Sound memory address*/ - scsp->scsp_dmea = (((scsp_regs[0x414/2] & 0xf000)>>12)*0x10000) | (scsp_regs[0x412/2] & 0xfffe); - break; case 0x414: - /*DMEA [19:16]*/ - scsp->scsp_dmea = (((scsp_regs[0x414/2] & 0xf000)>>12)*0x10000) | (scsp_regs[0x412/2] & 0xfffe); - /*DRGA [11:1]*/ - /*Register memory address*/ - scsp->scsp_drga = scsp_regs[0x414/2] & 0x0ffe; - break; case 0x416: - /*DGATE[14]*/ - /*DDIR[13]*/ - /*if 0 sound_mem -> reg*/ - /*if 1 sound_mem <- reg*/ - /*DEXE[12]*/ - /*starting bit*/ - /*DTLG[11:1]*/ - /*size of transfer*/ - scsp->scsp_dtlg = scsp_regs[0x416/2] & 0x0ffe; - if(scsp_dexe) - { - dma_scsp(device->machine().firstcpu->memory().space(AS_PROGRAM), scsp); - scsp_regs[0x416/2]^=0x1000;//disable starting bit - } - break; + COMBINE_DATA(&scsp->dma_regs[((offset-0x412)/2) & 3]); + if(ACCESSING_BITS_8_15 && offset*2 == 0x416) + dma_scsp(device->machine().firstcpu->memory().space(AS_PROGRAM), scsp); + break; case 0x42a: //check main cpu IRQ - scsp->main_irq(1); - break; + scsp->main_irq(1); + break; case 0x42c: - break; + break; case 0x42e: - break; + break; } } diff --git a/src/mame/machine/stvcd.c b/src/mame/machine/stvcd.c index 8f9fe033357..42898f9224b 100644 --- a/src/mame/machine/stvcd.c +++ b/src/mame/machine/stvcd.c @@ -576,7 +576,7 @@ static void cd_writeWord(running_machine &machine, UINT32 addr, UINT16 data) case 0x0026: // CDROM_LOG(("WW CR4: %04x\n", data)) cr4 = data; - if(cr1 != 0 && 0) + if(cr1 != 0 && 1) printf("CD: command exec %02x %02x %02x %02x %02x (stat %04x)\n", hirqreg, cr1, cr2, cr3, cr4, cd_stat); if (!cdrom) @@ -863,6 +863,31 @@ static void cd_writeWord(running_machine &machine, UINT32 addr, UINT16 data) break; + case 0x2000: // Get SubCode Q / RW Channel + switch(cr1 & 0xff) + { + case 0: // Get Q + cr1 = cd_stat | 0; + cr2 = 5; + cr3 = 0; + cr4 = 0; + + // ... + break; + + case 1: // Get RW + cr1 = cd_stat | 0; + cr2 = 12; + cr3 = 0; + cr4 = 0; + + // ... + break; + } + hirqreg |= CMOK|DRDY; + break; + + case 0x3000: // Set CD Device connection { UINT8 parm; @@ -1142,22 +1167,23 @@ static void cd_writeWord(running_machine &machine, UINT32 addr, UINT16 data) if (bufnum >= MAX_FILTERS) { - CDROM_LOG(("CD: invalid buffer number\n")) - cd_stat = 0xff; // ERROR + printf("CD: invalid buffer number\n"); + cd_stat = CD_STAT_REJECT; // ERROR hirqreg |= (CMOK|EHST); return; } if (partitions[bufnum].numblks == 0) { - CDROM_LOG(("CD: buffer is empty\n")) - cd_stat = 0xff; // ERROR + printf("CD: buffer is empty\n"); + cd_stat = CD_STAT_REJECT; // ERROR hirqreg |= (CMOK|EHST); return; } cd_getsectoroffsetnum(bufnum, §ofs, §num); + /* TODO: Cyber Doll crashes here with sectnum == 8*/ for (i = sectofs; i < (sectofs + sectnum); i++) { partitions[bufnum].size -= partitions[bufnum].blocks[i]->size; @@ -1349,8 +1375,12 @@ static void cd_writeWord(running_machine &machine, UINT32 addr, UINT16 data) case 0x7500: CDROM_LOG(("%s:CD: Abort File\n", machine.describe_context())) // bios expects "2bc" mask to work against this - hirqreg |= (CMOK|EFLS|EHST|ESEL|DCHG|PEND|BFUL|CSCT|DRDY); - cd_stat = CD_STAT_PERI|CD_STAT_PAUSE; // force to pause + hirqreg |= (CMOK|EFLS); + sectorstore = 0; + xfertype32 = XFERTYPE32_INVALID; + xferdnum = 0; + cd_stat = CD_STAT_PAUSE; // force to pause + cr1 = cd_stat; break; case 0xe000: // appears to be copy protection check. needs only to return OK.