void CALLBACK SPU2readDMAMem(u16 *pMem, int size, int channel) { u32 spuaddr = C_SPUADDR(channel); SPU2_LOG("SPU2 readDMAMem(%d) size %x, addr: %x\n", channel, size, pMem); for (uint i = 0; i < (uint)size; i++) { *pMem++ = *(u16*)(spu2mem + spuaddr); if (spu2attr(channel).irq && (C_IRQA(channel) == spuaddr)) { C_SPUADDR_SET(spuaddr, channel); IRQINFO |= (4 * (channel + 1)); SPU2_LOG("SPU2readDMAMem(%d):interrupt\n", channel); irqCallbackSPU2(); } spuaddr++; // inc spu addr if (spuaddr > 0x0fffff) spuaddr=0; // wrap at 2Mb } spuaddr += 19; //Transfer Local To Host TSAH/L + Data Size + 20 (already +1'd) C_SPUADDR_SET(spuaddr, channel); // DMA complete spu2stat_clear_80(channel); SPUStartCycle[channel] = SPUCycles; SPUTargetCycle[channel] = size; interrupt |= (1 << (1 + channel)); }
void SPU2writeDMAMem(u16* pMem, int size, int channel) { u32 spuaddr; ADMA *Adma = &adma[channel]; s32 offset = (channel == 0) ? 0 : 0x400; SPU2_LOG("SPU2 writeDMAMem size %x, addr: %x(spu2:%x)"/*, ctrl: %x, adma: %x\n"*/, \ size, pMem, C_SPUADDR(channel)/*, spu2Ru16(REG_C0_CTRL + offset), spu2Ru16(REG_C0_ADMAS + offset)*/); if (spu2admas(channel) && (spu2attr(channel).dma == 0) && size) { if (!Adma->Enabled ) Adma->Index = 0; Adma->MemAddr = pMem; Adma->AmountLeft = size; SPUTargetCycle[channel] = size; spu2stat_clear_80(channel); if (!Adma->Enabled || (Adma->Index > 384)) { C_SPUADDR_SET(0, channel); if (ADMASWrite(channel)) { SPUStartCycle[channel] = SPUCycles; interrupt |= (1 << (1 + channel)); } } Adma->Enabled = 1; return; } #ifdef ZEROSPU2_DEVBUILD if ((conf.Log && conf.options & OPTION_RECORDING) && (channel == 1)) LogPacketSound(pMem, 0x8000); #endif spuaddr = C_SPUADDR(channel); memcpy((u8*)(spu2mem + spuaddr),(u8*)pMem,size << 1); spuaddr += size; C_SPUADDR_SET(spuaddr, channel); if (spu2attr(channel).irq && (spuaddr < C_IRQA(channel) && (C_IRQA(channel) <= (spuaddr + 0x20)))) { IRQINFO |= 4 * (channel + 1); SPU2_LOG("SPU2writeDMAMem:interrupt\n"); irqCallbackSPU2(); } if (spuaddr > 0xFFFFE) spuaddr = 0x2800; C_SPUADDR_SET(spuaddr, channel); MemAddr[channel] += size << 1; spu2stat_clear_80(channel); SPUStartCycle[channel] = SPUCycles; SPUTargetCycle[channel] = size; interrupt |= (1 << (channel + 1)); }
s32 CALLBACK SPU2init() { LOG_CALLBACK("SPU2init()\n"); spu2Log = fopen("logs/spu2.txt", "w"); if (spu2Log) setvbuf(spu2Log, NULL, _IONBF, 0); SPU2_LOG("Spu2 null version %d,%d\n",SPU2_REVISION,SPU2_BUILD); SPU2_LOG("SPU2init\n"); #ifdef _WIN32 QueryPerformanceFrequency(&g_counterfreq); #endif InitApi(); spu2regs = (s8*)malloc(0x10000); spu2mem = (u16*)malloc(0x200000); // 2Mb memset(spu2regs, 0, 0x10000); memset(spu2mem, 0, 0x200000); if ((spu2mem == NULL) || (spu2regs == NULL)) { SysMessage("Error allocating Memory\n"); return -1; } memset(dwEndChannel2, 0, sizeof(dwEndChannel2)); memset(dwNewChannel2, 0, sizeof(dwNewChannel2)); memset(iFMod, 0, sizeof(iFMod)); memset(s_buffers, 0, sizeof(s_buffers)); InitADSR(); memset(voices, 0, sizeof(voices)); // last 24 channels have higher mem offset for (s32 i = 0; i < 24; ++i) voices[i+24].memoffset = 0x400; // init each channel for (u32 i = 0; i < ArraySize(voices); ++i) { voices[i].init(i); } return 0; }
void CALLBACK SPU2interruptDMA(int channel) { SPU2_LOG("SPU2 interruptDMA(%d)\n", channel); spu2attr(channel).dma = 0; spu2stat_set_80(channel); }