s32 BlockTransWrite(u8 *iopaddr, u32 size, s32 chan) { s32 core = chan & 1; BlockTransBuff[core] = 0; BlockTransSize[core] = size; BlockTransAddr[core] = (u32)iopaddr; if(*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS) return -1; if(*SD_DMA_CHCR(core) & SD_DMA_START) return -1; *SD_CORE_ATTR(core) &= 0xFFCF; *SD_A_TSA_HI(core) = 0; *SD_A_TSA_LO(core) = 0; *U16_REGISTER(0x1B0+(core*1024)) = 1 << core; SetDmaWrite(core); *SD_DMA_ADDR(core) = (u32)iopaddr; *SD_DMA_MODE(core) = 0x10; *SD_DMA_SIZE(core) = (size/64)+((size&63)>0); *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU; return 0; }
int Spu2Interrupt(void *data) { volatile u16 *reg1 = U16_REGISTER(0x7C2); if (Spu2IntrHandler != NULL) { Spu2IntrHandler((*reg1 & 0xC) >> 2, Spu2IntrData); } else {
s32 BlockTransWriteFrom(u8 *iopaddr, u32 size, s32 chan, u16 mode, u8 *startaddr) { s32 core = chan & 1; s32 offset; BlockTransBuff[core] = 0; BlockTransSize[core] = size; BlockTransAddr[core] = (u32)iopaddr; if(startaddr == 0) startaddr = iopaddr; offset = startaddr - iopaddr; if(offset > size) { if(mode & SD_TRANS_LOOP) { offset -= size; BlockTransBuff[core] = 1; } else { return -1; } } if(offset & 1023) offset += 1024; iopaddr += (BlockTransSize[core] * BlockTransBuff[core]) + offset; if(*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS) return -1; if(*SD_DMA_CHCR(core) & SD_DMA_START) return -1; *SD_CORE_ATTR(core) &= 0xFFCF; *SD_A_TSA_HI(core) = 0; *SD_A_TSA_LO(core) = 0; *U16_REGISTER(0x1B0+(core*1024)) = 1 << core; SetDmaWrite(core); *SD_DMA_ADDR(core) = (u32)iopaddr; *SD_DMA_MODE(core) = 0x10; *SD_DMA_SIZE(core) = (size/64)+((size&63)>0); *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU; return 0; }
void ResetAll() { u32 core; volatile u16 *statx; *SD_C_SPDIF_OUT = 0; nopdelay(); *SD_C_SPDIF_OUT = 0x8000; nopdelay(); *U32_REGISTER(0x10F0) |= 0xB0000; for(core=0; core < 2; core++) { VoiceTransIoMode[core] = 0; *U16_REGISTER(0x1B0) = 0; *SD_CORE_ATTR(core) = 0; nopdelay(); *SD_CORE_ATTR(core) = SD_SPU2_ON; *SD_P_MVOLL(core) = 0; *SD_P_MVOLR(core) = 0; statx = U16_REGISTER(0x344 + (core * 1024)); while(*statx & 0x7FF); *SD_A_KOFF_HI(core) = 0xFFFF; *SD_A_KOFF_LO(core) = 0xFFFF; // Should probably only be 0xFF } *SD_S_PMON_HI(1) = 0; *SD_S_PMON_LO(1) = 0; *SD_S_NON_HI(1) = 0; *SD_S_NON_LO(1) = 0; }
u32 sceSdBlockTransStatus(s16 chan, s16 flag) { u32 retval; chan &= 1; if(*U16_REGISTER(0x1B0 + (chan * 1024)) == 0) retval = 0; else retval = *SD_DMA_ADDR(chan); retval = (BlockTransBuff[chan] << 24) | (retval & 0xFFFFFF); return retval; }
s32 BlockTransRead(u8 *iopaddr, u32 size, s32 chan, s16 mode) { u32 i; s32 core = chan & 1; BlockTransBuff[core] = 0; BlockTransSize[core] = size; BlockTransAddr[core] = (u32)iopaddr; if(*SD_CORE_ATTR(core) & SD_DMA_IN_PROCESS) return -1; if(*SD_DMA_CHCR(core) & SD_DMA_START) return -1; *SD_CORE_ATTR(core) &= 0xFFCF; *SD_A_TSA_HI(core) = 0; *SD_A_TSA_LO(core) = ((mode & 0xF00) << 1) + 0x400; *U16_REGISTER(0x1AE + (core*1024)) = (mode & 0xF000) >> 11; i = 0x4937; while(i--); *U16_REGISTER(0x1B0+(core*1024)) = 4; SetDmaRead(core); *SD_DMA_ADDR(core) = (u32)iopaddr; *SD_DMA_MODE(core) = 0x10; *SD_DMA_SIZE(core) = (size/64)+((size&63)>0); *SD_DMA_CHCR(core) = SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_SPU2IOP; return 0; }
void InitSpdif() { *SD_C_SPDIF_MODE = 0x900; *SD_C_SPDIF_MEDIA = 0x200; *U16_REGISTER(0x7CA) = 8; }
void InitVoices() { s32 voice, i; volatile u16 *statx; // Set Start Address of data to transfer. *SD_A_TSA_HI(0) = 0; *SD_A_TSA_LO(0) = 0x5000 >> 1; // Fill with data. // First 16 bytes are reserved. for(i = 0; i < 16; i++) *SD_A_STD(0) = VoiceDataInit[i]; // Set Transfer mode to IO *SD_CORE_ATTR(0) = (*SD_CORE_ATTR(0) & ~SD_CORE_DMA) | SD_DMA_IO; statx = U16_REGISTER(0x344); // Wait for transfer to complete; while(*statx & SD_IO_IN_PROCESS); // Reset DMA settings *SD_CORE_ATTR(0) &= ~SD_CORE_DMA; // Init voices for(voice = 0; voice < 24; voice++) { *SD_VP_VOLL(0, voice) = 0; *SD_VP_VOLR(0, voice) = 0; *SD_VP_PITCH(0, voice) = 0x3FFF; *SD_VP_ADSR1(0, voice) = 0; *SD_VP_ADSR2(0, voice) = 0; *SD_VP_VOLL(1, voice) = 0; *SD_VP_VOLR(1, voice) = 0; *SD_VP_PITCH(1, voice) = 0x3FFF; *SD_VP_ADSR1(1, voice) = 0; *SD_VP_ADSR2(1, voice) = 0; // Top address of waveform data *SD_VA_SSA_HI(0, voice) = 0; *SD_VA_SSA_LO(0, voice) = 0x5000 >> 1; *SD_VA_SSA_HI(1, voice) = 0; *SD_VA_SSA_LO(1, voice) = 0x5000 >> 1; } // Set all voices to ON *SD_A_KON_HI(0) = 0xFFFF; *SD_A_KON_LO(0) = 0xFF; *SD_A_KON_HI(1) = 0xFFFF; *SD_A_KON_LO(1) = 0xFF; // There is no guarantee that voices will be turn on at once. // So we wait to make sure. nopdelay(); // Set all voices to OFF *SD_A_KOFF_HI(0) = 0xFFFF; *SD_A_KOFF_LO(0) = 0xFF; *SD_A_KOFF_HI(1) = 0xFFFF; *SD_A_KOFF_LO(1) = 0xFF; // There is no guarantee that voices will be turn off at once. // So we wait to make sure. nopdelay(); *SD_S_ENDX_HI(0) = 0; *SD_S_ENDX_LO(0) = 0; }
int TransInterrupt(void *data) { IntrData *intr = (IntrData*) data; s32 dir; s32 core; dir = ((intr->mode & 0x200) < 1); core = intr->mode & 0xFF; // Voice Transfer if((intr->mode & 0x100) == 0) { // SD_C_STATX(core) // If done elsewise, it doesn't work, havn't figured out why yet. volatile u16 *statx = U16_REGISTER(0x344 + (core * 1024)); if(!(*statx & 0x80)) while(!(*statx & 0x80)); *SD_CORE_ATTR(core) &= ~SD_CORE_DMA; if(*SD_CORE_ATTR(core) & 0x30) while((*SD_CORE_ATTR(core) & 0x30)); if(TransIntrHandlers[core]) goto intr_handler; if(TransIntrCallbacks[core]) goto IntrCallback; VoiceTransComplete[core] = 1; } else { // Block Transfer if(intr->mode & (SD_BLOCK_TRANS_LOOP << 8)) { // Switch buffers BlockTransBuff[core] = 1 - BlockTransBuff[core]; // Setup DMA & send *SD_DMA_ADDR(core) = (BlockTransSize[core] * BlockTransBuff[core])+BlockTransAddr[core]; *SD_DMA_SIZE(core) = (BlockTransSize[core]/64)+((BlockTransSize[core]&63)>0); *SD_DMA_CHCR(core) = SD_DMA_START | SD_DMA_CS | dir; } else { *SD_CORE_ATTR(core) &= ~SD_CORE_DMA; *SD_P_MMIX(core) &= 0xFF3F; *U16_REGISTER(0x1B0 + (core * 1024)) = 0; } if(TransIntrHandlers[core]) { intr_handler: TransIntrHandlers[core](core, intr->data); } else { if(TransIntrCallbacks[core]) { IntrCallback: TransIntrCallbacks[core](0); } } } if(dir == SD_DMA_DIR_SPU2IOP) FlushDcache(); return 1; }
volatile u16 *ParamRegList[] = { SD_VP_VOLL(0, 0), SD_VP_VOLR(0, 0), SD_VP_PITCH(0, 0), SD_VP_ADSR1(0, 0), SD_VP_ADSR2(0, 0), SD_VP_ENVX(0, 0), SD_VP_VOLXL(0, 0), SD_VP_VOLXR(0, 0), SD_P_MMIX(0), SD_P_MVOLL(0), SD_P_MVOLR(0), SD_P_EVOLL(0), SD_P_EVOLR(0), SD_P_AVOLL(0), SD_P_AVOLR(0), SD_P_BVOLL(0), SD_P_BVOLR(0), SD_P_MVOLXL(0), SD_P_MVOLXR(0), SD_S_PMON_HI(0), SD_S_NON_HI(0), SD_A_KON_HI(0), SD_A_KOFF_HI(0), SD_S_ENDX_HI(0), SD_S_VMIXL_HI(0), SD_S_VMIXEL_HI(0), SD_S_VMIXR_HI(0), SD_S_VMIXER_HI(0), SD_A_ESA_HI(0), SD_A_EEA_HI(0), SD_A_TSA_HI(0), SD_CORE_IRQA(0), SD_VA_SSA_HI(0, 0), SD_VA_LSAX(0,0), SD_VA_NAX(0, 0), SD_CORE_ATTR(0), SD_A_TSA_HI(0), SD_A_STD(0), // 1AE & 1B0 are both related to core attr & dma somehow U16_REGISTER(0x1AE), U16_REGISTER(0x1B0), (u16*)0xBF900334 }; u16 NotePitchTable[] = { 0x8000, 0x879C, 0x8FAC, 0x9837, 0xA145, 0xAADC, 0xB504, 0xBFC8, 0xCB2F, 0xD744, 0xE411, 0xF1A1, 0x8000, 0x800E, 0x801D, 0x802C, 0x803B, 0x804A, 0x8058, 0x8067, 0x8076, 0x8085, 0x8094, 0x80A3, 0x80B1, 0x80C0, 0x80CF, 0x80DE, 0x80ED, 0x80FC, 0x810B, 0x811A, 0x8129, 0x8138, 0x8146, 0x8155, 0x8164, 0x8173, 0x8182, 0x8191, 0x81A0, 0x81AF, 0x81BE, 0x81CD, 0x81DC, 0x81EB, 0x81FA, 0x8209, 0x8218, 0x8227, 0x8236, 0x8245, 0x8254, 0x8263, 0x8272, 0x8282, 0x8291, 0x82A0, 0x82AF, 0x82BE, 0x82CD, 0x82DC, 0x82EB,