diff --git a/common/include/libsd-common.h b/common/include/libsd-common.h index 26fc9f016d4..2bdef5fe5a4 100644 --- a/common/include/libsd-common.h +++ b/common/include/libsd-common.h @@ -118,7 +118,7 @@ #define SD_BATCH_WRITEIOP 0x5 #define SD_BATCH_WRITEEE 0x6 #define SD_BATCH_EERETURN 0x7 -#define SD_BATCH_GETPARAM 0x10 +#define SD_BATCH_GETPARAM 0x11 #define SD_BATCH_GETSWITCH 0x12 #define SD_BATCH_GETADDR 0x13 #define SD_BATCH_GETCORE 0x14 @@ -147,6 +147,7 @@ typedef struct typedef int (*sceSdSpu2IntrHandler)(int, void *); typedef int (*sceSdTransIntrHandler)(int, void *); typedef int (*SdIntrCallback)(void *data); +typedef int (*sceSdBlockTransHandler)(int channel, void *userdata, void **addr, int *size); #ifdef __cplusplus extern "C" { @@ -173,11 +174,11 @@ extern u32 sceSdGetSwitch(u16 entry); extern u16 sceSdNote2Pitch(u16 center_note, u16 center_fine, u16 note, s16 fine); extern u16 sceSdPitch2Note(u16 center_note, u16 center_fine, u16 pitch); -extern int sceSdSetEffectAttr(int core, sceSdEffectAttr *attr); +extern int sceSdSetEffectAttr(int core, const sceSdEffectAttr *attr); extern void sceSdGetEffectAttr(int core, sceSdEffectAttr *attr); -extern int sceSdProcBatch(sceSdBatch *batch, u32 *rets, u32 num); -extern int sceSdProcBatchEx(sceSdBatch *batch, u32 *rets, u32 num, u32 voice); +extern int sceSdProcBatch(const sceSdBatch *batch, u32 *rets, u32 num); +extern int sceSdProcBatchEx(const sceSdBatch *batch, u32 *rets, u32 num, u32 voice); extern int sceSdVoiceTrans(s16 chan, u16 mode, u8 *iopaddr, u32 *spuaddr, u32 size); extern int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...); @@ -189,10 +190,13 @@ extern sceSdSpu2IntrHandler sceSdSetSpu2IntrHandler(sceSdSpu2IntrHandler func, v extern void *sceSdGetTransIntrHandlerArgument(int arg); extern void *sceSdGetSpu2IntrHandlerArgument(); + +// The following was added in module version 3.1, export version 1.5, SDK 2.4.2 extern int sceSdStopTrans(int channel); +// The following was added in module version 3.3, export version 1.5, SDK 2.5 extern int sceSdCleanEffectWorkArea(int core, int channel, int effect_mode); -extern int sceSdSetEffectMode(int core, sceSdEffectAttr *param); -extern int sceSdSetEffectModeParams(int core, sceSdEffectAttr *attr); +extern int sceSdSetEffectMode(int core, const sceSdEffectAttr *param); +extern int sceSdSetEffectModeParams(int core, const sceSdEffectAttr *attr); #ifdef __cplusplus } diff --git a/common/include/spu2_mmio_hwport.h b/common/include/spu2_mmio_hwport.h new file mode 100644 index 00000000000..66f4e79cb1e --- /dev/null +++ b/common/include/spu2_mmio_hwport.h @@ -0,0 +1,162 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +/** + * @file + * Definitions for memory-mapped I/O for SPU2. + */ + +#ifndef __SPU2_MMIO_HWPORT__ +#define __SPU2_MMIO_HWPORT__ + +typedef struct spu2_u16pair_ +{ + vu16 m_pair[2]; +} spu2_u16pair_t; + +typedef struct spu2_voice_params_ +{ + vu16 m_voll; + vu16 m_volr; + vu16 m_pitch; + vu16 m_adsr1; + vu16 m_adsr2; + vu16 m_envx; + vu16 m_volxl; + vu16 m_volxr; +} spu2_voice_params_t; + +typedef struct spu2_voice_address_ +{ + spu2_u16pair_t m_ssa; + spu2_u16pair_t m_lsax; + spu2_u16pair_t m_nax; +} spu2_voice_address_t; + +typedef struct spu2_core_regs_ +{ + spu2_voice_params_t m_voice_params[24]; /* 0x000 */ + spu2_u16pair_t m_pmon; /* 0x180 */ + spu2_u16pair_t m_non; /* 0x184 */ + spu2_u16pair_t m_vmixl; /* 0x188 */ + spu2_u16pair_t m_vmixel; /* 0x18c */ + spu2_u16pair_t m_vmixr; /* 0x190 */ + spu2_u16pair_t m_vmixer; /* 0x194 */ + vu16 m_mmix; /* 0x198 */ + vu16 m_attr; /* 0x19a */ + spu2_u16pair_t m_irqa; /* 0x19c */ + spu2_u16pair_t m_kon; /* 0x1a0 */ + spu2_u16pair_t m_koff; /* 0x1a4 */ + spu2_u16pair_t m_tsa; /* 0x1a8 */ + vu16 m_xferdata; /* 0x1ac */ + vu16 m_unk1ae; /* 0x1ae */ + vu16 m_admas; /* 0x1b0 */ + vu16 unk1b2[7]; /* 0x1b2 */ + spu2_voice_address_t m_voice_address[24]; /* 0x1c0 */ + spu2_u16pair_t m_esa; /* 0x2e0 */ + spu2_u16pair_t m_apf1_size; /* 0x2e4 */ + spu2_u16pair_t m_apf2_size; /* 0x2e8 */ + spu2_u16pair_t m_same_l_dst; /* 0x2EC */ + spu2_u16pair_t m_same_r_dst; /* 0x2F0 */ + spu2_u16pair_t m_comb1_l_src; /* 0x2F4 */ + spu2_u16pair_t m_comb1_r_src; /* 0x2F8 */ + spu2_u16pair_t m_comb2_l_src; /* 0x2FC */ + spu2_u16pair_t m_comb2_r_src; /* 0x300 */ + spu2_u16pair_t m_same_l_src; /* 0x304 */ + spu2_u16pair_t m_same_r_src; /* 0x308 */ + spu2_u16pair_t m_diff_l_dst; /* 0x30C */ + spu2_u16pair_t m_diff_r_dst; /* 0x310 */ + spu2_u16pair_t m_comb3_l_src; /* 0x314 */ + spu2_u16pair_t m_comb3_r_src; /* 0x318 */ + spu2_u16pair_t m_comb4_l_src; /* 0x31C */ + spu2_u16pair_t m_comb4_r_src; /* 0x320 */ + spu2_u16pair_t m_diff_l_src; /* 0x324 */ + spu2_u16pair_t m_diff_r_src; /* 0x328 */ + spu2_u16pair_t m_apf1_l_dst; /* 0x32C */ + spu2_u16pair_t m_apf1_r_dst; /* 0x330 */ + spu2_u16pair_t m_apf2_l_dst; /* 0x334 */ + spu2_u16pair_t m_apf2_r_dst; /* 0x338 */ + vu16 m_eea; /* 0x33C */ + vu16 unk33e; /* 0x33E */ + spu2_u16pair_t m_endx; /* 0x340 */ + vu16 m_statx; /* 0x344 */ + vu16 unk346[13]; /* 0x346 */ +} spu2_core_regs_t; + +typedef struct spu2_different_regs_ +{ + vu16 m_mvoll; /* 0x760 */ + vu16 m_mvolr; /* 0x762 */ + vu16 m_evoll; /* 0x764 */ + vu16 m_evolr; /* 0x766 */ + vu16 m_avoll; /* 0x768 */ + vu16 m_avolr; /* 0x76A */ + vu16 m_bvoll; /* 0x76C */ + vu16 m_bvolr; /* 0x76E */ + vu16 m_mvolxl; /* 0x770 */ + vu16 m_mvolxr; /* 0x772 */ + vu16 m_iir_vol; /* 0x774 */ + vu16 m_comb1_vol; /* 0x776 */ + vu16 m_comb2_vol; /* 0x778 */ + vu16 m_comb3_vol; /* 0x77A */ + vu16 m_comb4_vol; /* 0x77C */ + vu16 m_wall_vol; /* 0x77E */ + vu16 m_apf1_vol; /* 0x780 */ + vu16 m_apf2_vol; /* 0x782 */ + vu16 m_in_coef_l; /* 0x784 */ + vu16 m_in_coef_r; /* 0x786 */ +} spu2_different_regs_t; + +typedef struct spu2_core_regs_padded_ +{ + spu2_core_regs_t m_cregs; + vu16 padding[80]; +} spu2_core_regs_padded_t; + +typedef struct spu2_regs_main_ +{ + spu2_core_regs_padded_t m_core_regs[2]; +} spu2_regs_main_t; + +typedef struct spu2_regs_extra_ +{ + spu2_core_regs_t core0_regs; + vu16 padding346[80]; + spu2_core_regs_t core1_regs; /* 0x400 */ + spu2_different_regs_t m_different_regs[2]; + vu16 unk7b0[8]; + vu16 m_spdif_out; /* 0x7c0 */ + vu16 m_spdif_irqinfo; /* 0x7c2 */ + vu16 unk7c4; /* 0x7c4 */ + vu16 m_spdif_mode; /* 0x7c6 */ + vu16 m_spdif_media; /* 0x7c8 */ + vu16 m_unknown7ca; /* 0x7ca */ + vu16 m_spdif_protect; /* 0x7cc */ + vu16 unk7ce[25]; +} spu2_regs_extra_t; + +typedef struct spu2_mmio_hwport_ /* base => 0xBF900000 */ +{ + union spu2_regs_union_ + { + spu2_regs_main_t m_m; + spu2_regs_extra_t m_e; + } m_u; +} spu2_mmio_hwport_t; + +#if !defined(USE_SPU2_MMIO_HWPORT) && defined(_IOP) +// cppcheck-suppress-macro constVariablePointer +#define USE_SPU2_MMIO_HWPORT() spu2_mmio_hwport_t *const spu2_mmio_hwport = (spu2_mmio_hwport_t *)0xBF900000 +#endif +#if !defined(USE_SPU2_MMIO_HWPORT) +#define USE_SPU2_MMIO_HWPORT() +#endif + +#endif /* __SPU2_MMIO_HWPORT__ */ diff --git a/ee/rpc/ps2snd/src/ps2snd.c b/ee/rpc/ps2snd/src/ps2snd.c index c5b6d3ebf42..67874adad0e 100644 --- a/ee/rpc/ps2snd/src/ps2snd.c +++ b/ee/rpc/ps2snd/src/ps2snd.c @@ -130,7 +130,7 @@ u16 sceSdPitch2Note(u16 center_note, u16 center_fine, u16 pitch) return(0); } -int sceSdProcBatch(sceSdBatch* batch, u32 returns[], u32 num) +int sceSdProcBatch(const sceSdBatch* batch, u32 returns[], u32 num) { (void)batch; (void)returns; @@ -140,7 +140,7 @@ int sceSdProcBatch(sceSdBatch* batch, u32 returns[], u32 num) return(-1); } -int sceSdProcBatchEx(sceSdBatch* batch, u32 returns[], u32 num, u32 voice) +int sceSdProcBatchEx(const sceSdBatch* batch, u32 returns[], u32 num, u32 voice) { (void)batch; (void)returns; @@ -198,7 +198,7 @@ u32 sceSdBlockTransStatus (s16 channel, s16 flag) //void* sceSdSetTransCallback (u16 channel, void SD_TRANS_CBProc(void *) ); //void *sceSdSetIRQCallback( void SD_IRQ_CBProc(void *) ); -int sceSdSetEffectAttr (int core, sceSdEffectAttr *attr) +int sceSdSetEffectAttr (int core, const sceSdEffectAttr *attr) { s32 buf[1+((sizeof(sceSdEffectAttr)+3)/4)] ALIGNED(64); buf[0] = core; diff --git a/iop/sound/libsd/Makefile b/iop/sound/libsd/Makefile index c9bfa3aca72..f3b693b2683 100644 --- a/iop/sound/libsd/Makefile +++ b/iop/sound/libsd/Makefile @@ -2,7 +2,7 @@ # ____| | ____| | | |____| # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. #----------------------------------------------------------------------- -# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Copyright ps2dev - http://www.ps2dev.org # Licenced under Academic Free License version 2.0 # Review ps2sdk README & LICENSE files for further details. @@ -13,9 +13,10 @@ IOP_INCS += \ -I$(PS2SDKSRC)/iop/system/loadcore/include \ -I$(PS2SDKSRC)/iop/system/sifman/include \ -I$(PS2SDKSRC)/iop/system/stdio/include \ - -I$(PS2SDKSRC)/iop/system/sysclib/include + -I$(PS2SDKSRC)/iop/system/sysclib/include \ + -I$(PS2SDKSRC)/iop/system/threadman/include -IOP_OBJS = freesd.o batch.o block.o effect.o voice.o exports.o imports.o +IOP_OBJS = libsd.o imports.o exports.o include $(PS2SDKSRC)/Defs.make include $(PS2SDKSRC)/iop/Rules.bin.make diff --git a/iop/sound/libsd/README b/iop/sound/libsd/README deleted file mode 100644 index 0d084989280..00000000000 --- a/iop/sound/libsd/README +++ /dev/null @@ -1,17 +0,0 @@ -FREESD v1.0 -Copyright (c) 2004 TyRaNiD -Copyright (c) 2004 Lukasz Bruun -Licensed under the Academic Free License version 2.0. --- - -FREESD is a LIBSD compatible sound driver for PS2. - -Some early Japanse PS2 models came without LIBSD -in the BIOS, this will work as a free replacement. - -Credits: -Neill Corlett for very valuable information on sound registers. -[RO]man for register information. -adresd , Nicholas Van Veen , Vzzrzzn, -MrHTFord for their work with libsd and thereby providing test data. - diff --git a/iop/sound/libsd/README.md b/iop/sound/libsd/README.md new file mode 100644 index 00000000000..a9d79a9eb23 --- /dev/null +++ b/iop/sound/libsd/README.md @@ -0,0 +1,24 @@ +# Sound Device Library + +This module is an abstraction layer for the SPU2 interface used for audio mixing and analog and digital audio output. + +## Configurations + +There are multiple configurations of this library, allowing the choice of +balancing between size, speed, and features. + +* `libsd` -> The recommended version. + +## How to use this module in your program + +In order to use this module in your program, use `LoadModule` or \ +`LoadModuleBuffer` with no arguments. + +## Credits + +Original FREESD 1.0 developer: TyRaNiD \ +Original FREESD 1.0 developer: Lukasz Bruun \ +Neill Corlett for very valuable information on sound registers.\ +\[RO]man for register information.\ +adresd , Nicholas Van Veen , Vzzrzzn, +MrHTFord for their work with libsd and thereby providing test data. diff --git a/iop/sound/libsd/include/libsd.h b/iop/sound/libsd/include/libsd.h index 21737cb7688..5f736d97635 100644 --- a/iop/sound/libsd/include/libsd.h +++ b/iop/sound/libsd/include/libsd.h @@ -3,7 +3,7 @@ # ____| | ____| | | |____| # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. #----------------------------------------------------------------------- -# Copyright 2001-2004, ps2dev - http://www.ps2dev.org +# Copyright ps2dev - http://www.ps2dev.org # Licenced under Academic Free License version 2.0 # Review ps2sdk README & LICENSE files for further details. */ @@ -20,7 +20,7 @@ #include #include -#define libsd_IMPORTS_start DECLARE_IMPORT_TABLE(libsd, 1, 4) +#define libsd_IMPORTS_start DECLARE_IMPORT_TABLE(libsd, 1, 5) #define libsd_IMPORTS_end END_IMPORT_TABLE #define I_sceSdQuit DECLARE_IMPORT(2, sceSdQuit); diff --git a/iop/sound/libsd/src/batch.c b/iop/sound/libsd/src/batch.c deleted file mode 100644 index 4126410bd5a..00000000000 --- a/iop/sound/libsd/src/batch.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2004 TyRaNiD - * Copyright (c) 2004,2007 Lukasz Bruun - * - * See the file LICENSE included with this distribution for licensing terms. - */ - -/** - * @file - * Part of the IOP Sound Driver - */ - -#include "types.h" -#include "sifman.h" -#include "intrman.h" -#include "libsd.h" -#include "spu2regs.h" - -u32 BatchData __attribute__((aligned(16))); - -s32 SifDmaBatch(u32 ee_addr, void *iop_addr, u32 size) -{ - SifDmaTransfer_t dma; - s32 intr_stat; - s32 dma_id; - - dma.src = iop_addr; - dma.dest = (void *)ee_addr; - dma.size = size; - dma.attr = 0; - - CpuSuspendIntr((int *)&intr_stat); - dma_id = SifSetDma(&dma, SIF_DMA_TO_EE); - CpuResumeIntr(intr_stat); - - while(SifDmaStat(dma_id) >= 0); - - if(dma_id == 0) return -1; - - return 0; -} - -int sceSdProcBatch(sceSdBatch *batch, u32 *rets, u32 num) -{ - s32 loop; - s32 ret; - - for(loop = 0; (u32)loop < num; loop++) - { - ret = 0; - - switch(batch[loop].func) - { - case SD_BATCH_SETPARAM: - sceSdSetParam(batch[loop].entry, batch[loop].value); - break; - case SD_BATCH_GETPARAM: - ret = sceSdGetParam(batch[loop].entry); - break; - case SD_BATCH_SETSWITCH: - sceSdSetSwitch(batch[loop].entry, batch[loop].value); - break; - case SD_BATCH_GETSWITCH: - ret = sceSdGetSwitch(batch[loop].entry); - break; - case SD_BATCH_SETADDR: - sceSdSetAddr(batch[loop].entry, batch[loop].value); - break; - case SD_BATCH_GETADDR: - ret = sceSdGetAddr(batch[loop].entry); - break; - case SD_BATCH_SETCORE: - sceSdSetCoreAttr(batch[loop].entry, batch[loop].value); - break; - case SD_BATCH_GETCORE: - ret = sceSdGetCoreAttr(batch[loop].entry); - break; - case SD_BATCH_WRITEIOP: - *((u32 *) batch[loop].value) = batch[loop].entry; - break; - case SD_BATCH_WRITEEE: - BatchData = batch[loop].entry; - SifDmaBatch(batch[loop].value, &BatchData, 4); - break; - case SD_BATCH_EERETURN: - SifDmaBatch(batch[loop].value, rets, batch[loop].entry); - break; - default: - return -1 - loop; - } - - if(rets) rets[loop] = ret; - } - - return loop; -} - -int sceSdProcBatchEx(sceSdBatch *batch, u32 *rets, u32 num, u32 voice) -{ - s32 loop; - s32 ret; - s32 voice_loop; - s32 cmd_count; - - cmd_count = 0; - - for(loop = 0; (u32)loop < num; loop++) - { - ret = 0; - switch(batch[loop].func) - { - case SD_BATCH_SETPARAM: - { - if((batch[loop].entry & 0x3E) != 0x3E) - { - sceSdSetParam(batch[loop].entry, batch[loop].value); - } - else - { - for(voice_loop = 0; voice_loop < 24; voice_loop++) - { - if(voice & (1 << voice_loop)) - { - sceSdSetParam((batch[loop].entry & 0xFFC1) | (1 << (voice_loop + 1)), batch[loop].value); - cmd_count++; - } - } - cmd_count--; - } - } break; - - case SD_BATCH_GETPARAM: - { - if((batch[loop].entry & 0x3E) != 0x3E) - { - ret = sceSdGetParam(batch[loop].entry); - } - else - { - for(voice_loop = 0; voice_loop < 24; voice_loop++) - { - if(voice & (1 << voice_loop)) - { - ret = sceSdGetParam((batch[loop].entry & 0xFFC1) | (1 << (voice_loop + 1))); - cmd_count++; - } - - if(rets) - { - rets[cmd_count] = ret; - } - } - - cmd_count--; - } - } break; - - case SD_BATCH_SETSWITCH: - sceSdSetSwitch(batch[loop].entry, batch[loop].value); - break; - - case SD_BATCH_GETSWITCH: - ret = sceSdGetSwitch(batch[loop].entry); - break; - - case SD_BATCH_SETADDR: - { - if((batch[loop].entry & 0x3E) != 0x3E) - { - sceSdSetAddr(batch[loop].entry, batch[loop].value); - } - else - { - for(voice_loop = 0; voice_loop < 24; voice_loop++) - { - if(voice & (1 << voice_loop)) - { - sceSdSetAddr((batch[loop].entry & 0xFFC1) | (1 << (voice_loop + 1)), batch[loop].value); - cmd_count++; - } - } - } - cmd_count--; - } break; - - case SD_BATCH_GETADDR: - { - if((batch[loop].entry & 0x3E) != 0x3E) - { - ret = sceSdGetAddr(batch[loop].entry); - } - else - { - for(voice_loop = 0; voice_loop < 24; voice_loop++) - { - if(voice & (1 << voice_loop)) - { - ret = sceSdGetAddr((batch[loop].entry & 0xFFC1) | (1 << (voice_loop + 1))); - cmd_count++; - } - - if(rets) - { - rets[cmd_count] = ret; - } - } - } - cmd_count--; - } break; - - case SD_BATCH_SETCORE: - sceSdSetCoreAttr(batch[loop].entry, batch[loop].value); - break; - - case SD_BATCH_GETCORE: - ret = sceSdGetCoreAttr(batch[loop].entry); - break; - - case SD_BATCH_WRITEIOP: - *((u32 *) batch[loop].value) = batch[loop].entry; - break; - - case SD_BATCH_WRITEEE: - BatchData = batch[loop].entry; - SifDmaBatch(batch[loop].value, &BatchData, 4); - break; - - case SD_BATCH_EERETURN: - SifDmaBatch(batch[loop].value, rets, batch[loop].entry); - break; - default: - return -1 - cmd_count; - } - - if(rets) - { - rets[cmd_count] = ret; - } - cmd_count++; - } - - return cmd_count; -} diff --git a/iop/sound/libsd/src/block.c b/iop/sound/libsd/src/block.c deleted file mode 100644 index b4e2eb46d50..00000000000 --- a/iop/sound/libsd/src/block.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2004 TyRaNiD - * Copyright (c) 2004,2007 Lukasz Bruun - * - * See the file LICENSE included with this distribution for licensing terms. - */ - -/** - * @file - * Part of the IOP Sound Driver - */ - -#include "types.h" -#include -#include "freesd.h" -#include "spu2regs.h" - -u32 BlockTransBuff[2]; -u32 BlockTransAddr[2]; -u32 BlockTransSize[2]; - -extern void SetDmaWrite(s32 chan); -extern void SetDmaRead(s32 chan); -extern IntrData TransIntrData[2]; -extern u32 DmaStop(u32 core); - - -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((u32)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(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_DMA_IN_PROCESS) return -1; - if(U32_REGISTER_READ(SD_DMA_CHCR(core)) & SD_DMA_START) return -1; - - U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), 0xFFCF); - - U16_REGISTER_WRITE(SD_A_TSA_HI(core), 0); - U16_REGISTER_WRITE(SD_A_TSA_LO(core), 0); - - U16_REGISTER_WRITE(U16_REGISTER(0x1B0+(core*1024)), 1 << core); - - SetDmaWrite(core); - - U32_REGISTER_WRITE(SD_DMA_ADDR(core), (u32)iopaddr); - U16_REGISTER_WRITE(SD_DMA_MODE(core), 0x10); - U16_REGISTER_WRITE(SD_DMA_SIZE(core), (size/64)+((size&63)>0)); - U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU); - - return 0; -} - -s32 BlockTransWrite(u8 *iopaddr, u32 size, s32 chan) -{ - s32 core = chan & 1; - - BlockTransBuff[core] = 0; - BlockTransSize[core] = size; - BlockTransAddr[core] = (u32)iopaddr; - - if(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_DMA_IN_PROCESS) return -1; - if(U32_REGISTER_READ(SD_DMA_CHCR(core)) & SD_DMA_START) return -1; - - U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), 0xFFCF); - - U16_REGISTER_WRITE(SD_A_TSA_HI(core), 0); - U16_REGISTER_WRITE(SD_A_TSA_LO(core), 0); - - U16_REGISTER_WRITE(U16_REGISTER(0x1B0+(core*1024)), 1 << core); - - SetDmaWrite(core); - - U32_REGISTER_WRITE(SD_DMA_ADDR(core), (u32)iopaddr); - U16_REGISTER_WRITE(SD_DMA_MODE(core), 0x10); - U16_REGISTER_WRITE(SD_DMA_SIZE(core), (size/64)+((size&63)>0)); - U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_IOP2SPU); - - return 0; -} - - -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(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_DMA_IN_PROCESS) return -1; - if(U32_REGISTER_READ(SD_DMA_CHCR(core)) & SD_DMA_START) return -1; - - U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), 0xFFCF); - - U16_REGISTER_WRITE(SD_A_TSA_HI(core), 0); - U16_REGISTER_WRITE(SD_A_TSA_LO(core), ((mode & 0xF00) << 1) + 0x400); - - U16_REGISTER_WRITE(U16_REGISTER(0x1AE + (core*1024)), (mode & 0xF000) >> 11); - - i = 0x4937; - - while(i--); - - U16_REGISTER_WRITE(U16_REGISTER(0x1B0+(core*1024)), 4); - - SetDmaRead(core); - - U32_REGISTER_WRITE(SD_DMA_ADDR(core), (u32)iopaddr); - U16_REGISTER_WRITE(SD_DMA_MODE(core), 0x10); - U16_REGISTER_WRITE(SD_DMA_SIZE(core), (size/64)+((size&63)>0)); - U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_CS | SD_DMA_START | SD_DMA_DIR_SPU2IOP); - - - return 0; -} - - -int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...) -{ - int transfer_dir = mode & 3; - int core = chan & 1; - int _size = size; - - switch(transfer_dir) - { - case SD_TRANS_WRITE: - { - TransIntrData[core].mode = 0x100 | core; - - if(mode & SD_TRANS_LOOP) - { - TransIntrData[core].mode |= SD_TRANS_LOOP << 8; - _size /= 2; - } - - if(BlockTransWrite(iopaddr, _size, core) >= 0) - return 0; - - } break; - - case SD_TRANS_READ: - { - TransIntrData[core].mode = 0x300 | core; - - if(mode & SD_TRANS_LOOP) - { - TransIntrData[core].mode |= SD_TRANS_LOOP << 8; - _size /= 2; - } - - if(BlockTransRead(iopaddr, _size, chan, mode) >= 0) - return 0; - - } break; - - case SD_TRANS_STOP: - { - return DmaStop(core); - - } break; - - case SD_TRANS_WRITE_FROM: - { - va_list alist; - u8* startaddr; - - va_start(alist, size); - startaddr = va_arg(alist, u8*); - va_end(alist); - - TransIntrData[core].mode = 0x100 | core; - - if(mode & SD_TRANS_LOOP) - { - TransIntrData[core].mode |= SD_TRANS_LOOP << 8; - _size /= 2; - } - - if(BlockTransWriteFrom(iopaddr, _size, core, mode, startaddr) >= 0) - return 0; - - - } break; - - } - return -1; -} - -u32 sceSdBlockTransStatus(s16 chan, s16 flag) -{ - u32 retval; - - (void)flag; - - chan &= 1; - - if(U16_REGISTER_READ(U16_REGISTER(0x1B0 + (chan * 1024))) == 0) - retval = 0; - else - retval = U32_REGISTER_READ(SD_DMA_ADDR(chan)); - - retval = (BlockTransBuff[chan] << 24) | (retval & 0xFFFFFF); - - return retval; -} diff --git a/iop/sound/libsd/src/effect.c b/iop/sound/libsd/src/effect.c deleted file mode 100644 index 3bac4c1bf7c..00000000000 --- a/iop/sound/libsd/src/effect.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2004 TyRaNiD - * Copyright (c) 2004,2007 Lukasz Bruun - * - * See the file LICENSE included with this distribution for licensing terms. - */ - -/** - * @file - * Part of the IOP Sound Driver - */ - -#include "types.h" -#include "libsd.h" -#include "spu2regs.h" -#include "sysclib.h" - - -extern u32 VoiceTransIoMode[2]; -extern sceSdTransIntrHandler TransIntrHandlers[2]; -extern SdIntrCallback TransIntrCallbacks[2]; - -sceSdEffectAttr EffectAttr[2]; -u32 EffectAddr[2]; - -// The values are more or less the same as on PSX (SPU) -u16 EffectSizes[10] = { 0x1, 0x26C, 0x1F4, 0x484, 0x6FE, 0xADE, 0xF6C, 0x1804, 0x1804, 0x3C0 }; - -u32 EffectParams[160] = { - // SD_EFFECT_MODE_OFF - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010001, 0x00000000, 0x00000000, - 0x00000000, 0x00010001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - // SD_EFFECT_MODE_ROOM - 0x005B007D, 0x54B86D80, 0x0000BED0, 0xBA800000, 0x53005800, 0x033304D6, 0x022703F0, 0x01EF0374, - 0x01B70336, 0x01B60335, 0x01B50334, 0x01B50334, 0x01B50334, 0x013601B4, 0x005C00B8, 0x80008000, - // SD_EFFECT_MODE_STUDIO_1 - 0x00250033, 0x4FA870F0, 0x4410BCE0, 0x9C00C0F0, 0x4EC05280, 0x031B03E4, 0x02AF03A4, 0x02660372, - 0x025D031C, 0x018E025C, 0x0135022F, 0x00B701D2, 0x00B5018F, 0x008000B4, 0x0026004C, 0x80008000, - // SD_EFFECT_MODE_STUDIO_2 - 0x007F00B1, 0x4FA870F0, 0x4510BCE0, 0xB4C0BEF0, 0x4EC05280, 0x076B0904, 0x065F0824, 0x061607A2, - 0x05ED076C, 0x042E05EC, 0x0305050F, 0x02B70462, 0x0265042F, 0x01B20264, 0x00800100, 0x80008000, - // SD_EFFECT_MODE_STUDIO_3 - 0x00A900E3, 0x4FA86F60, 0x4510BCE0, 0xA680BEF0, 0x52C05680, 0x0B580DFB, 0x0A3C0D09, 0x09730BD9, - 0x08DA0B59, 0x05E908D9, 0x04B007EC, 0x03D206EF, 0x031D05EA, 0x0238031C, 0x00AA0154, 0x80008000, - // SD_EFFECT_MODE_HALL - 0x013901A5, 0x50006000, 0xB8004C00, 0xC000BC00, 0x5C006000, 0x11BB15BA, 0x10BD14C2, 0x0DC111BC, - 0x0DC311C0, 0x09C10DC0, 0x07C10BC4, 0x06CD0A00, 0x05C109C2, 0x041A05C0, 0x013A0274, 0x80008000, - // SD_EFFECT_MODE_SPACE - 0x0231033D, 0x50007E00, 0xB000B400, 0xB0004C00, 0x54006000, 0x1A311ED6, 0x183B1D14, 0x16B21BC2, - 0x15EF1A32, 0x105515EE, 0x0F2D1334, 0x0C5D11F6, 0x0AE11056, 0x07A20AE0, 0x02320464, 0x80008000, - // SD_EFFECT_MODE_ECHO - 0x00030003, 0x7FFF7FFF, 0x00000000, 0x81000000, 0x00000000, 0x0FFD1FFD, 0x00091009, 0x00000000, - 0x00091009, 0x1FFF1FFF, 0x1FFE1FFE, 0x1FFE1FFE, 0x1FFE1FFE, 0x10041008, 0x00040008, 0x80008000, - // SD_EFFECT_MODE_DELAY - 0x00030003, 0x7FFF7FFF, 0x00000000, 0x00000000, 0x00000000, 0x0FFD1FFD, 0x00091009, 0x00000000, - 0x00091009, 0x1FFF1FFF, 0x1FFE1FFE, 0x1FFE1FFE, 0x1FFE1FFE, 0x10041008, 0x00040008, 0x80008000, - // SD_EFFECT_MODE_CLEAR - 0x00130017, 0x4FA870F0, 0x4510BCE0, 0x8500BEF0, 0x54C05F80, 0x02AF0371, 0x01DF02E5, 0x01D702B0, - 0x026A0358, 0x011E01D6, 0x00B1012D, 0x0059011F, 0x00E301A0, 0x00400058, 0x00140028, 0x80008000, -}; - - -const u32 ClearEffectData[256] __attribute__((aligned(16))) = -{ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; - - -u32 GetEEA(s32 core) -{ - return (U16_REGISTER_READ(SD_A_EEA_HI(core)) << 17) | 0x1FFFF; -} - -void SetESA(s32 core, u32 value) -{ - volatile u16 *reg = SD_A_ESA_HI(core); - - U16_REGISTER_WRITE(reg + 0, value >> 17); - U16_REGISTER_WRITE(reg + 1, value >> 1); - -} - -void SetEffectRegister(volatile u16* reg, u32 val) -{ - U16_REGISTER_WRITE(reg + 0, (u16)(val >> 14)); - U16_REGISTER_WRITE(reg + 1, (u16)(val << 2)); -} - -void SetEffectData(u16 *mode_data, u32 core) -{ - s32 i; - - SetEffectRegister(SD_R_FB_SRC_A(core), mode_data[0]); - SetEffectRegister(SD_R_FB_SRC_B(core), mode_data[1]); - - for(i=0; i < 8; i++) - U16_REGISTER_WRITE(SD_R_IIR_ALPHA(core)+i, mode_data[2+i]); - - for(i=0; i < 20; i++) - SetEffectRegister(SD_R_IIR_DEST_A0(core)+(i*2), mode_data[10+i]); - - U16_REGISTER_WRITE(SD_R_IN_COEF_L(core), mode_data[30]); - U16_REGISTER_WRITE(SD_R_IN_COEF_R(core), mode_data[31]); -} - -int sceSdSetEffectAttr(int core, sceSdEffectAttr *attr) -{ - u32 mode = attr->mode; - u32 clearram = 0; - u32 effects_disabled = 0; - u32 last_mode = 0; - u16 mode_data[32]; - - core &= 1; - - if(mode & SD_EFFECT_MODE_CLEAR) - { - mode &= ~SD_EFFECT_MODE_CLEAR; - clearram = 1; - last_mode = EffectAttr[core].mode; - } - - // Check if valid mode - if(mode > 9) return -1; - - EffectAddr[core] = GetEEA(core) - ((EffectSizes[mode] << 4) - 2); - - memcpy(mode_data, &EffectParams[mode * 16], 64); - - memcpy(&EffectAttr[core], attr, sizeof(sceSdEffectAttr)); - EffectAttr[core].core = core; - - switch(mode) - { - case SD_EFFECT_MODE_ECHO: - EffectAttr[core].feedback = 0x80; - EffectAttr[core].delay = 0x80; - break; - case SD_EFFECT_MODE_DELAY: - EffectAttr[core].feedback = 0; - EffectAttr[core].delay = 0x80; - break; - default: - EffectAttr[core].feedback = 0; - EffectAttr[core].delay = 0; - break; - } - - if((mode == SD_EFFECT_MODE_DELAY) || (mode == SD_EFFECT_MODE_ECHO)) - { - u16 delay = ((attr->delay+1) << 5); - u16 feedback = ((attr->feedback << 7) + attr->feedback) << 1; - - mode_data[7] = feedback; - mode_data[10] = (delay << 1) - mode_data[0]; - mode_data[11] = delay - mode_data[1]; - - mode_data[16] = mode_data[17] + delay; - mode_data[12] = mode_data[13] + delay; - mode_data[27] = mode_data[29] + delay; - mode_data[26] = mode_data[28] + delay; - } - - // Disable effects - if(U16_REGISTER_READ(SD_CORE_ATTR(core)) & SD_ENABLE_EFFECTS) - { - effects_disabled = 1; - U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), ~SD_ENABLE_EFFECTS); - } - - // Clean up after last mode - if((effects_disabled) && (clearram)) - sceSdClearEffectWorkArea(core, 0, last_mode); - - // Depth / Volume - *SD_P_EVOLL(core) = attr->depth_L; - *SD_P_EVOLR(core) = attr->depth_R; - - SetEffectData(mode_data, core); - - // Set effect start addr (ESA) - SetESA(core, EffectAddr[core]); - - - if(clearram) - sceSdClearEffectWorkArea(core, 0, mode); - - // Enable effects - if(effects_disabled) - U16_REGISTER_WRITEOR(SD_CORE_ATTR(core), SD_ENABLE_EFFECTS); - - return 0; -} - -void sceSdGetEffectAttr(int core, sceSdEffectAttr *attr) -{ - *attr = EffectAttr[core & 1]; -} - -int sceSdClearEffectWorkArea(int core, int chan, int effect_type) -{ - if(effect_type > 9) return -1; - - if(effect_type != SD_EFFECT_MODE_OFF) - { - u32 aligned_addr = 0; - u32 effect_addr; - s32 effect_size; - s32 old_iomode; - sceSdTransIntrHandler old_handler = NULL; - SdIntrCallback old_callback = NULL; - - effect_size = EffectSizes[effect_type] << 4; - - effect_addr = (GetEEA(core) - (effect_size - 2)); - - if(effect_size & 127) - { - effect_size &= ~127; - aligned_addr = (GetEEA(core) - (effect_size - 2)); - } - - old_iomode = VoiceTransIoMode[chan]; - - if(VoiceTransIoMode[chan] == 1) VoiceTransIoMode[chan] = 0; - - // Disable intr_handlers by removing them - if(TransIntrHandlers[chan]) - { - old_handler = TransIntrHandlers[chan]; - TransIntrHandlers[chan] = 0; - } - - if(TransIntrCallbacks[chan]) - { - old_callback = TransIntrCallbacks[chan]; - TransIntrCallbacks[chan] = NULL; - } - - if(aligned_addr) - { - sceSdVoiceTrans(chan, 0, (u8*)ClearEffectData, (u32*)effect_addr, 64); - sceSdVoiceTransStatus(chan, 1); - effect_addr = aligned_addr; - } - - - while(effect_size > 0) - { - u32 size; - - if(effect_size < 1024) - size = effect_size; - else - size = 1024; - - sceSdVoiceTrans(chan, 0, (u8*)ClearEffectData, (u32*)effect_addr, size); - sceSdVoiceTransStatus(chan, 1); // Wait for completion - - effect_size -= 1024; - effect_addr += 1024; - - } - - VoiceTransIoMode[chan] = old_iomode; - - // Enable intr_handlers by adding them again - if(old_handler) TransIntrHandlers[chan] = old_handler; - if(old_callback) TransIntrCallbacks[chan] = old_callback; - } - - return 0; -} - diff --git a/iop/sound/libsd/src/exports.tab b/iop/sound/libsd/src/exports.tab index 4fb74159258..14fbca248e1 100644 --- a/iop/sound/libsd/src/exports.tab +++ b/iop/sound/libsd/src/exports.tab @@ -1,33 +1,39 @@ -DECLARE_EXPORT_TABLE(libsd, 1, 4) - DECLARE_EXPORT(_start) - DECLARE_EXPORT(_retonly) - DECLARE_EXPORT(sceSdQuit) - DECLARE_EXPORT(_retonly) - DECLARE_EXPORT(sceSdInit) - DECLARE_EXPORT(sceSdSetParam) // 5 - DECLARE_EXPORT(sceSdGetParam) - DECLARE_EXPORT(sceSdSetSwitch) - DECLARE_EXPORT(sceSdGetSwitch) - DECLARE_EXPORT(sceSdSetAddr) - DECLARE_EXPORT(sceSdGetAddr) // 10 - DECLARE_EXPORT(sceSdSetCoreAttr) - DECLARE_EXPORT(sceSdGetCoreAttr) - DECLARE_EXPORT(sceSdNote2Pitch) - DECLARE_EXPORT(sceSdPitch2Note) - DECLARE_EXPORT(sceSdProcBatch) // 15 - DECLARE_EXPORT(sceSdProcBatchEx) - DECLARE_EXPORT(sceSdVoiceTrans) - DECLARE_EXPORT(sceSdBlockTrans) - DECLARE_EXPORT(sceSdVoiceTransStatus) - DECLARE_EXPORT(sceSdBlockTransStatus) // 20 - DECLARE_EXPORT(sceSdSetTransCallback) - DECLARE_EXPORT(sceSdSetIRQCallback) - DECLARE_EXPORT(sceSdSetEffectAttr) - DECLARE_EXPORT(sceSdGetEffectAttr) - DECLARE_EXPORT(sceSdClearEffectWorkArea) // 25 - DECLARE_EXPORT(sceSdSetTransIntrHandler) - DECLARE_EXPORT(sceSdSetSpu2IntrHandler) +DECLARE_EXPORT_TABLE(libsd, 1, 5) +DECLARE_EXPORT(_start) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sceSdQuit) +DECLARE_EXPORT(_retonly) +DECLARE_EXPORT(sceSdInit) +DECLARE_EXPORT(sceSdSetParam) +DECLARE_EXPORT(sceSdGetParam) +DECLARE_EXPORT(sceSdSetSwitch) +DECLARE_EXPORT(sceSdGetSwitch) +DECLARE_EXPORT(sceSdSetAddr) +DECLARE_EXPORT(sceSdGetAddr) +DECLARE_EXPORT(sceSdSetCoreAttr) +DECLARE_EXPORT(sceSdGetCoreAttr) +DECLARE_EXPORT(sceSdNote2Pitch) +DECLARE_EXPORT(sceSdPitch2Note) +DECLARE_EXPORT(sceSdProcBatch) +DECLARE_EXPORT(sceSdProcBatchEx) +DECLARE_EXPORT(sceSdVoiceTrans) +DECLARE_EXPORT(sceSdBlockTrans) +DECLARE_EXPORT(sceSdVoiceTransStatus) +DECLARE_EXPORT(sceSdBlockTransStatus) +DECLARE_EXPORT(sceSdSetTransCallback) +DECLARE_EXPORT(sceSdSetIRQCallback) +DECLARE_EXPORT(sceSdSetEffectAttr) +DECLARE_EXPORT(sceSdGetEffectAttr) +DECLARE_EXPORT(sceSdClearEffectWorkArea) +DECLARE_EXPORT(sceSdSetTransIntrHandler) +DECLARE_EXPORT(sceSdSetSpu2IntrHandler) +DECLARE_EXPORT(sceSdGetTransIntrHandlerArgument) +DECLARE_EXPORT(sceSdGetSpu2IntrHandlerArgument) +DECLARE_EXPORT(sceSdStopTrans) +DECLARE_EXPORT(sceSdCleanEffectWorkArea) +DECLARE_EXPORT(sceSdSetEffectMode) +DECLARE_EXPORT(sceSdSetEffectModeParams) END_EXPORT_TABLE void _retonly() {} diff --git a/iop/sound/libsd/src/freesd.c b/iop/sound/libsd/src/freesd.c deleted file mode 100644 index 0d510a91e6a..00000000000 --- a/iop/sound/libsd/src/freesd.c +++ /dev/null @@ -1,931 +0,0 @@ -/* - * Copyright (c) 2004 TyRaNiD - * Copyright (c) 2004,2007 Lukasz Bruun - * - * See the file LICENSE included with this distribution for licensing terms. - */ - -/** - * @file - * Part of the IOP Sound Driver - */ - -#include "types.h" -#include "irx.h" -#include "loadcore.h" -#include "stdio.h" -#include "intrman.h" -#include "freesd.h" -#include "spu2regs.h" - -extern struct irx_export_table _exp_libsd; - -#define BANNER "FREESD %s\n" -#define VERSION "v1.01" - -#define MODNAME "freesd" - -// TODO: last sdk 3.1.0 and sdk 3.0.3 has LIBSD module version 0x03,0x03 -// Check what was changed, and maybe port changes. -// Note: looks like this LIBSD has different version numbering, cause it is too old: -// 0x01,0x01 -IRX_ID(MODNAME, 1, 1); - -#define M_PRINTF(format, args...) printf(MODNAME ": " format, ## args) - -// block.c -extern u32 BlockTransBuff[2]; -extern u32 BlockTransAddr[2]; -extern u32 BlockTransSize[2]; - -// effect.c -extern u32 EffectSizes[10]; -extern void SetESA(s32 core, u32 value); -extern u32 GetEEA(int chan); -extern sceSdEffectAttr EffectAttr[2]; -extern u32 EffectAddr[2]; - -// voice.c -extern u32 VoiceTransStatus[2]; -extern volatile u16 VoiceTransComplete[2]; -extern u32 VoiceTransIoMode[2]; - -// Global -u16 SpdifSettings; -void *Spu2IntrData; -sceSdTransIntrHandler TransIntrHandlers[2]; -SdIntrCallback TransIntrCallbacks[2]; -sceSdSpu2IntrHandler Spu2IntrHandler; -SdIntrCallback Spu2IrqCallback; -IntrData TransIntrData[2]; - - -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, - 0x82FA, 0x830A, 0x8319, 0x8328, 0x8337, 0x8346, 0x8355, - 0x8364, 0x8374, 0x8383, 0x8392, 0x83A1, 0x83B0, 0x83C0, - 0x83CF, 0x83DE, 0x83ED, 0x83FD, 0x840C, 0x841B, 0x842A, - 0x843A, 0x8449, 0x8458, 0x8468, 0x8477, 0x8486, 0x8495, - 0x84A5, 0x84B4, 0x84C3, 0x84D3, 0x84E2, 0x84F1, 0x8501, - 0x8510, 0x8520, 0x852F, 0x853E, 0x854E, 0x855D, 0x856D, - 0x857C, 0x858B, 0x859B, 0x85AA, 0x85BA, 0x85C9, 0x85D9, - 0x85E8, 0x85F8, 0x8607, 0x8617, 0x8626, 0x8636, 0x8645, - 0x8655, 0x8664, 0x8674, 0x8683, 0x8693, 0x86A2, 0x86B2, - 0x86C1, 0x86D1, 0x86E0, 0x86F0, 0x8700, 0x870F, 0x871F, - 0x872E, 0x873E, 0x874E, 0x875D, 0x876D, 0x877D, 0x878C -}; - -void nopdelay() -{ - s32 i; - - for(i=0; i < 0x10000; i++) - asm volatile("nop\nnop\nnop\nnop\nnop"); -} - -void InitSpu2() -{ - - U32_REGISTER_WRITE(U32_REGISTER(0x1404), 0xBF900000); - U32_REGISTER_WRITE(U32_REGISTER(0x140C), 0xBF900800); - U32_REGISTER_WRITEOR(U32_REGISTER(0x10F0), 0x80000); - U32_REGISTER_WRITEOR(U32_REGISTER(0x1570), 8); - U32_REGISTER_WRITE(U32_REGISTER(0x1014), 0x200B31E1); - U32_REGISTER_WRITE(U32_REGISTER(0x1414), 0x200B31E1); -} - - -int _start(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - - printf(BANNER, VERSION); - - if(RegisterLibraryEntries(&_exp_libsd) != 0) return MODULE_NO_RESIDENT_END; - - InitSpu2(); - - return MODULE_RESIDENT_END; -} - -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)); - - while((U16_REGISTER_READ(statx) & 0x80) == 0); - - U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), ~SD_CORE_DMA); - - while((U16_REGISTER_READ(SD_CORE_ATTR(core)) & 0x30) != 0); - - if(TransIntrHandlers[core]) goto intr_handler; - if(TransIntrCallbacks[core]) goto SdIntrCallback; - - VoiceTransComplete[core] = 1; - } - else - { // Block Transfer - if(intr->mode & (SD_TRANS_LOOP << 8)) - { - // Switch buffers - BlockTransBuff[core] = 1 - BlockTransBuff[core]; - // Setup DMA & send - U32_REGISTER_WRITE(SD_DMA_ADDR(core), (BlockTransSize[core] * BlockTransBuff[core])+BlockTransAddr[core]); - U16_REGISTER_WRITE(SD_DMA_SIZE(core), (BlockTransSize[core]/64)+((BlockTransSize[core]&63)>0)); - U32_REGISTER_WRITE(SD_DMA_CHCR(core), SD_DMA_START | SD_DMA_CS | dir); - } - else - { - U16_REGISTER_WRITEAND(SD_CORE_ATTR(core), ~SD_CORE_DMA); - U16_REGISTER_WRITEAND(SD_P_MMIX(core), 0xFF3F); - U16_REGISTER_WRITE(U16_REGISTER(0x1B0 + (core * 1024)), 0); - } - - if(TransIntrHandlers[core]) - { - intr_handler: - TransIntrHandlers[core](core, intr->data); - } - else - { - if(TransIntrCallbacks[core]) - { - SdIntrCallback: - TransIntrCallbacks[core](0); - } - } - } - - if(dir == SD_DMA_DIR_SPU2IOP) FlushDcache(); - - return 1; -} - -int Spu2Interrupt(void *data) -{ - u16 val; - - (void)data; - - val = ((U16_REGISTER_READ(SD_C_IRQINFO))&0xc)>>2; - if (!val) - return 1; - - if (val&1) - U16_REGISTER_WRITE(SD_CORE_ATTR(0), U16_REGISTER_READ(SD_CORE_ATTR(0)) & 0xffbf); - - if (val&2) - U16_REGISTER_WRITE(SD_CORE_ATTR(1), U16_REGISTER_READ(SD_CORE_ATTR(1)) & 0xffbf); - - if(Spu2IntrHandler != NULL) - { - Spu2IntrHandler(val, Spu2IntrData); - } - else - { - if(Spu2IrqCallback) Spu2IrqCallback(0); - } - - return 1; -} - -void RegisterInterrupts() -{ - s32 ret; - - DisableIntr(0x24, (int *)&ret); - DisableIntr(0x28, (int *)&ret); - DisableIntr(0x9, (int *)&ret); - - ReleaseIntrHandler(0x24); - ReleaseIntrHandler(0x28); - - RegisterIntrHandler(0x24, 1, TransInterrupt, &TransIntrData[0]); - RegisterIntrHandler(0x28, 1, TransInterrupt, &TransIntrData[1]); - - VoiceTransComplete[0] = 0; - VoiceTransComplete[1] = 0; - - ReleaseIntrHandler(0x9); - RegisterIntrHandler(0x9, 1, Spu2Interrupt, &Spu2IntrData); -} - -void ResetAll() -{ - u32 core; - - U16_REGISTER_WRITE(SD_C_SPDIF_OUT, 0); - nopdelay(); - U16_REGISTER_WRITE(SD_C_SPDIF_OUT, 0x8000); - nopdelay(); - - U32_REGISTER_WRITEOR(U32_REGISTER(0x10F0), 0xB0000); - - for(core=0; core < 2; core++) - { - volatile u16 *statx; - - VoiceTransIoMode[core] = 0; - U16_REGISTER_WRITE(U16_REGISTER(0x1B0), 0); - U16_REGISTER_WRITE(SD_CORE_ATTR(core), 0); - nopdelay(); - U16_REGISTER_WRITE(SD_CORE_ATTR(core), SD_SPU2_ON); - - U16_REGISTER_WRITE(SD_P_MVOLL(core), 0); - U16_REGISTER_WRITE(SD_P_MVOLR(core), 0); - - statx = U16_REGISTER(0x344 + (core * 1024)); - - while(U16_REGISTER_READ(statx) & 0x7FF); - - U16_REGISTER_WRITE(SD_A_KOFF_HI(core), 0xFFFF); - U16_REGISTER_WRITE(SD_A_KOFF_LO(core), 0xFFFF); // Should probably only be 0xFF - } - - U16_REGISTER_WRITE(SD_S_PMON_HI(1), 0); - U16_REGISTER_WRITE(SD_S_PMON_LO(1), 0); - U16_REGISTER_WRITE(SD_S_NON_HI(1), 0); - U16_REGISTER_WRITE(SD_S_NON_LO(1), 0); -} - - - -void Reset(s32 flag) -{ - s32 core; - - if(flag == 0) ResetAll(); - - VoiceTransStatus[0] = 1; - VoiceTransStatus[1] = 1; - TransIntrCallbacks[0] = NULL; - TransIntrCallbacks[1] = NULL; - TransIntrHandlers[0] = NULL; - TransIntrHandlers[1] = NULL; - TransIntrData[0].mode = 0; - TransIntrData[1].mode = 1; - TransIntrData[0].data = NULL; - TransIntrData[1].data = NULL; - VoiceTransIoMode[0] = 0; - VoiceTransIoMode[1] = 0; - Spu2IntrHandler = NULL; - Spu2IrqCallback = NULL; - Spu2IntrData = NULL; - - RegisterInterrupts(); - - for(core = 0; core < 2; core++) - { - EffectAttr[core].core = core; - EffectAttr[core].mode = 0; - EffectAttr[core].depth_L = 0; - EffectAttr[core].depth_R = 0; - EffectAttr[core].delay = 0; - EffectAttr[core].feedback = 0; - } - - if(flag == 0) - { - for(core = 0; core < 2; core++) - { - EffectAddr[core] = GetEEA(core) - ((EffectSizes[0] << 4) - 2); - SetESA(core, EffectAddr[core]); - } - } -} - -sceSdSpu2IntrHandler sceSdSetSpu2IntrHandler(sceSdSpu2IntrHandler handler, void *data) -{ - sceSdSpu2IntrHandler old_handler; - - old_handler = Spu2IntrHandler; - Spu2IntrHandler = handler; - Spu2IntrData = data; - - return old_handler; -} - -u16 VoiceDataInit[16] = { 0x707, 0x707, 0x707, 0x707, 0x707, 0x707, 0x707, 0x707, - 0, 0, 0, 0, 0, 0, 0, 0 }; - -void InitVoices() -{ - s32 voice, i; - volatile u16 *statx; - - // Set Start Address of data to transfer. - U16_REGISTER_WRITE(SD_A_TSA_HI(0), 0); - U16_REGISTER_WRITE(SD_A_TSA_LO(0), 0x5000 >> 1); - - // Fill with data. - // First 16 bytes are reserved. - for(i = 0; i < 16; i++) U16_REGISTER_WRITE(SD_A_STD(0), VoiceDataInit[i]); - - // Set Transfer mode to IO - U16_REGISTER_WRITE(SD_CORE_ATTR(0), (U16_REGISTER_READ(SD_CORE_ATTR(0)) & ~SD_CORE_DMA) | SD_DMA_IO); - - statx = U16_REGISTER(0x344); - - // Wait for transfer to complete; - while(U16_REGISTER_READ(statx) & SD_IO_IN_PROCESS); - - // Reset DMA settings - U16_REGISTER_WRITEAND(SD_CORE_ATTR(0), ~SD_CORE_DMA); - - // Init voices - for(voice = 0; voice < 24; voice++) - { - U16_REGISTER_WRITE(SD_VP_VOLL(0, voice), 0); - U16_REGISTER_WRITE(SD_VP_VOLR(0, voice), 0); - U16_REGISTER_WRITE(SD_VP_PITCH(0, voice), 0x3FFF); - U16_REGISTER_WRITE(SD_VP_ADSR1(0, voice), 0); - U16_REGISTER_WRITE(SD_VP_ADSR2(0, voice), 0); - - U16_REGISTER_WRITE(SD_VP_VOLL(1, voice), 0); - U16_REGISTER_WRITE(SD_VP_VOLR(1, voice), 0); - U16_REGISTER_WRITE(SD_VP_PITCH(1, voice), 0x3FFF); - U16_REGISTER_WRITE(SD_VP_ADSR1(1, voice), 0); - U16_REGISTER_WRITE(SD_VP_ADSR2(1, voice), 0); - - // Top address of waveform data - U16_REGISTER_WRITE(SD_VA_SSA_HI(0, voice), 0); - U16_REGISTER_WRITE(SD_VA_SSA_LO(0, voice), 0x5000 >> 1); - U16_REGISTER_WRITE(SD_VA_SSA_HI(1, voice), 0); - U16_REGISTER_WRITE(SD_VA_SSA_LO(1, voice), 0x5000 >> 1); - } - - // Set all voices to ON - U16_REGISTER_WRITE(SD_A_KON_HI(0), 0xFFFF); - U16_REGISTER_WRITE(SD_A_KON_LO(0), 0xFF); - U16_REGISTER_WRITE(SD_A_KON_HI(1), 0xFFFF); - U16_REGISTER_WRITE(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 - U16_REGISTER_WRITE(SD_A_KOFF_HI(0), 0xFFFF); - U16_REGISTER_WRITE(SD_A_KOFF_LO(0), 0xFF); - U16_REGISTER_WRITE(SD_A_KOFF_HI(1), 0xFFFF); - U16_REGISTER_WRITE(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(); - - U16_REGISTER_WRITE(SD_S_ENDX_HI(0), 0); - U16_REGISTER_WRITE(SD_S_ENDX_LO(0), 0); -} - -// Core / Volume Registers -void InitCoreVolume(s32 flag) -{ - U16_REGISTER_WRITE(SD_C_SPDIF_OUT, 0xC032); - - if(flag) - { - U16_REGISTER_WRITE(SD_CORE_ATTR(0), SD_SPU2_ON | SD_ENABLE_EFFECTS | SD_MUTE); - U16_REGISTER_WRITE(SD_CORE_ATTR(1), SD_SPU2_ON | SD_ENABLE_EFFECTS | SD_MUTE | SD_ENABLE_EX_INPUT); - } - else - { - U16_REGISTER_WRITE(SD_CORE_ATTR(0), SD_SPU2_ON | SD_MUTE); - U16_REGISTER_WRITE(SD_CORE_ATTR(1), SD_SPU2_ON | SD_MUTE | SD_ENABLE_EX_INPUT); - } - - // HIgh is voices 0-15, LOw is 16-23, representing voices 0..23 (24) - U16_REGISTER_WRITE(SD_S_VMIXL_HI(0), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXL_LO(0), 0xFF); - U16_REGISTER_WRITE(SD_S_VMIXR_HI(0), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXR_LO(0), 0xFF); - U16_REGISTER_WRITE(SD_S_VMIXEL_HI(0), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXEL_LO(0), 0xFF); - U16_REGISTER_WRITE(SD_S_VMIXER_HI(0), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXER_LO(0), 0xFF); - - U16_REGISTER_WRITE(SD_S_VMIXL_HI(1), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXL_LO(1), 0xFF); - U16_REGISTER_WRITE(SD_S_VMIXR_HI(1), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXR_LO(1), 0xFF); - U16_REGISTER_WRITE(SD_S_VMIXEL_HI(1), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXEL_LO(1), 0xFF); - U16_REGISTER_WRITE(SD_S_VMIXER_HI(1), 0xFFFF); - U16_REGISTER_WRITE(SD_S_VMIXER_LO(1), 0xFF); - - U16_REGISTER_WRITE(SD_P_MMIX(0), 0xFF0); - U16_REGISTER_WRITE(SD_P_MMIX(1), 0xFFC); - - if(flag == 0) - { - U16_REGISTER_WRITE(SD_P_MVOLL(0), 0); - U16_REGISTER_WRITE(SD_P_MVOLR(0), 0); - U16_REGISTER_WRITE(SD_P_MVOLL(1), 0); - U16_REGISTER_WRITE(SD_P_MVOLR(1), 0); - - U16_REGISTER_WRITE(SD_P_EVOLL(0), 0); - U16_REGISTER_WRITE(SD_P_EVOLL(1), 0); - - U16_REGISTER_WRITE(SD_P_EVOLR(0), 0); - U16_REGISTER_WRITE(SD_P_EVOLR(1), 0); - - // Effect End Address, Upper part - U16_REGISTER_WRITE(SD_A_EEA_HI(0), 0xE); - U16_REGISTER_WRITE(SD_A_EEA_HI(1), 0xF); - } - - U16_REGISTER_WRITE(SD_P_AVOLL(0), 0); - U16_REGISTER_WRITE(SD_P_AVOLR(0), 0); - // Core 1 External Input Volume. - // The external Input is Core 0's output. - U16_REGISTER_WRITE(SD_P_AVOLL(1), 0x7FFF); - U16_REGISTER_WRITE(SD_P_AVOLR(1), 0x7FFF); - - U16_REGISTER_WRITE(SD_P_BVOLL(0), 0); - U16_REGISTER_WRITE(SD_P_BVOLR(0), 0); - U16_REGISTER_WRITE(SD_P_BVOLL(1), 0); - U16_REGISTER_WRITE(SD_P_BVOLR(1), 0); -} - -void InitSpdif() -{ - U16_REGISTER_WRITE(SD_C_SPDIF_MODE, 0x900); - U16_REGISTER_WRITE(SD_C_SPDIF_MEDIA, 0x200); - U16_REGISTER_WRITE(U16_REGISTER(0x7CA), 8); -} - -int sceSdInit(int flag) -{ - flag &= 1; - - InitSpu2(); - InitSpdif(); - - Reset(flag); - - InitVoices(); - InitCoreVolume(flag); - - EnableIntr(IOP_IRQ_DMA_SPU); - EnableIntr(IOP_IRQ_DMA_SPU2); - EnableIntr(IOP_IRQ_SPU); - - return 0; -} - -void sceSdSetParam(u16 reg, u16 val) -{ - u32 offs; - u32 voice; - u32 reg_index; - u32 core; - volatile u16 *reg_p; - - core = reg & 1; - - // Determine the channel offset - if(reg & 0x80) - offs = (40 * core) >> 1; - else - offs = (1024 * core) >> 1; - - reg_index = (reg >> 8) & 0xFF; - voice = (reg & 0x3E) << 2; - reg_p = ParamRegList[reg_index] + offs + voice; - - U16_REGISTER_WRITE(reg_p, val); -} - -u16 sceSdGetParam(u16 reg) -{ - u32 offs; - u32 voice; - u32 reg_index; - u32 core; - volatile u16 *reg_p; - - core = reg & 1; - - // Determine the channel offset - if(reg & 0x80) - offs = (40 * core) >> 1; - else - offs = (1024 * core) >> 1; - - reg_index = (reg >> 8) & 0xFF; - voice = (reg & 0x3E) << 2; - reg_p = ParamRegList[reg_index] + offs + voice; - - return U16_REGISTER_READ(reg_p); -} - -void sceSdSetSwitch(u16 reg, u32 val) -{ - u32 reg_index; - volatile u16 *reg_p; - - reg_index = (reg >> 8) & 0xFF; - reg_p = ParamRegList[reg_index] + ((reg & 1) << 9); - - U16_REGISTER_WRITE(reg_p + 0, (u16)val); - U16_REGISTER_WRITE(reg_p + 1, (u16)((val >> 16) & 0xFF)); -} - -u32 sceSdGetSwitch(u16 reg) -{ - u32 reg_index; - volatile u16 *reg_p; - u32 ret; - - reg_index = (reg >> 8) & 0xFF; - reg_p = ParamRegList[reg_index] + ((reg & 1) << 9); - - ret = U16_REGISTER_READ(reg_p + 0); - ret |= U16_REGISTER_READ(reg_p + 1) << 16; - - return ret; -} - - -u32 DmaStop(u32 core) -{ - u32 retval; - - core &= 1; - - if(U16_REGISTER_READ(U16_REGISTER(0x1B0 + (core * 1024))) == 0) - retval = 0; - else - retval = U32_REGISTER_READ(SD_DMA_ADDR(core)); - - U32_REGISTER_WRITEAND(SD_DMA_CHCR(core), ~SD_DMA_START); - U16_REGISTER_WRITE(U16_REGISTER(0x1B0 + (core * 1024)), 0); - - retval = (BlockTransBuff[core] << 24) | (retval & 0xFFFFFF); - - return retval; -} - -void SetDmaWrite(s32 chan) -{ - volatile u32 *reg = U32_REGISTER(0x1014 + (chan << 10)); - U32_REGISTER_WRITEOR(reg, (U32_REGISTER_READ(reg) & 0xF0FFFFFF) | 0x20000000); -} - -void SetDmaRead(s32 chan) -{ - volatile u32 *reg = U32_REGISTER(0x1014 + (chan << 10)); - U32_REGISTER_WRITEOR(reg, (U32_REGISTER_READ(reg) & 0xF0FFFFFF) | 0x22000000); -} - -u16 sceSdNote2Pitch (u16 center_note, u16 center_fine, u16 note, short fine) -{ - s32 _fine; - s32 _fine2; - s32 _note; - s32 offset1, offset2; - s32 val; - s32 val2; - s32 val3; - s32 ret; - - _fine = fine + (u16)center_fine; - _fine2 = _fine; - - if(_fine < 0) _fine2 = _fine + 127; - - _fine2 = _fine2 / 128; - _note = note + _fine2 - center_note; - val3 = _note / 6; - - if(_note < 0) val3--; - - offset2 = _fine - _fine2 * 128; - - if(_note < 0) val2 = -1; else val2 = 0; - if(val3 < 0) val3--; - - val2 = (val3 / 2) - val2; - val = val2 - 2; - offset1 = _note - (val2 * 12); - - if((offset1 < 0) || ((offset1 == 0) && (offset2 < 0))) - { - offset1 = offset1 + 12; - val = val2 - 3; - } - - if(offset2 < 0) - { - offset1 = (offset1-1) + _fine2; - offset2 += (_fine2+1) * 128; - } - - ret = (NotePitchTable[offset1] * NotePitchTable[offset2 + 12]) / 0x10000; - - if(val < 0) ret = (ret + (1 << (-val -1))) >> -val; - - return (u16)ret; -} - -u16 sceSdPitch2Note(u16 center_note, u16 center_fine, u16 pitch) -{ - s32 _pitch; - s32 i = 0; - s32 bit = 0; - s32 offset1 = 0; - s32 offset2 = 0; - s32 val; - s32 ret; - - if(((u16)pitch) >= 0x4000) pitch = 0x3FFF; - - _pitch = (u16)pitch; - - do - { - if((_pitch & 1) == 1) bit = i; - - _pitch >>= 1; - i++; - } while(i < 14); - - val = (u16)pitch << (15 - bit); - i = 11; - - do - { - if((u16)val >= NotePitchTable[i]) - { - offset1 = i; - break; - } - - i--; - } while(i >= 0); - - val = ((u16)val * 0x8000) / NotePitchTable[(u16)offset1]; - i = 127; - - do - { - if((u16)val >= NotePitchTable[12 + i]) - { - offset2 = i; - break; - } - - i--; - - } while(i >= 0); - - val = (u16)(center_fine + offset2 +1); - ret = (center_note + offset1 + ((bit - 12) * 12) + (val/128)) * 256; - ret = (ret + (val & 0x7E)) & 0xFFFE; - - return (u16)ret; -} - - -void SetSpdifMode(u16 val) -{ - u16 out, mode; - - out = U16_REGISTER_READ(SD_C_SPDIF_OUT); - mode = U16_REGISTER_READ(SD_C_SPDIF_MODE); - - switch(val & 0xF) - { - case 0: - mode &= 0xFFFD; - out = (val & 0xFEF7) | 0x20; - break; - case 1: - mode |= 2; - out = (out & 0xFFD7) | 0x100; - break; - case 2: - out &= 0xFED7; - break; - case 0xF: - out = (out & 0xFEDF) | 8; - break; - default: return; - } - - if(val & 0x80) - mode |= 0x8000; - else - mode &= 0x7FFF; - - switch(val & 0xF00) - { - case 0x800: - U16_REGISTER_WRITE(SD_C_SPDIF_MEDIA, 0x200); - mode |= 0x1800; - break; - case 0x400 : - U16_REGISTER_WRITE(SD_C_SPDIF_MEDIA, 0); - mode &= 0xE7FF; - break; - default: - U16_REGISTER_WRITE(SD_C_SPDIF_MEDIA, 0x200); - mode = (mode & 0xE7FF) | 0x800; - break; - } - - U16_REGISTER_WRITE(SD_C_SPDIF_OUT, out); - U16_REGISTER_WRITE(SD_C_SPDIF_MODE, mode); - - SpdifSettings = val; -} - -// Enable/disable bits in SD_CORE_ATTR -u8 CoreAttrShifts[4] = {7, 6, 14, 8}; - -void sceSdSetCoreAttr(u16 entry, u16 val) -{ - u16 core_attr = U16_REGISTER_READ(SD_CORE_ATTR(entry & 1)); - - switch(entry & ~1) - { - case SD_CORE_NOISE_CLK: // 0x8 - U16_REGISTER_WRITE(SD_CORE_ATTR(entry & 1), (core_attr-0x3F01) | ((val & 0x3F) << 8)); - break; - case SD_CORE_SPDIF_MODE: // 0xA - SetSpdifMode(val); // sub1 - break; - default: - { - u32 core = entry & 1; - entry = (entry >> 1)-1; - core_attr &= ~(1 << CoreAttrShifts[entry]); - core_attr |= (val & 1) << CoreAttrShifts[entry]; - U16_REGISTER_WRITE(SD_CORE_ATTR(core), core_attr); - } - break; - } -} - -u16 sceSdGetCoreAttr(u16 entry) -{ - switch(entry & ~1) - { - case SD_CORE_NOISE_CLK: - return (U16_REGISTER_READ(SD_CORE_ATTR(entry & 1)) >> 8) & 0x3F; - case SD_CORE_SPDIF_MODE: - return SpdifSettings; - default: - { - u32 core = entry & 1; - entry = (entry >> 1)-1; - return (U16_REGISTER_READ(SD_CORE_ATTR(core)) >> CoreAttrShifts[entry]) & 1; - } - } -} - - -sceSdTransIntrHandler sceSdSetTransIntrHandler(int chan, sceSdTransIntrHandler func, void *data) -{ - sceSdTransIntrHandler old_handler; - - old_handler = TransIntrHandlers[chan & 1]; - TransIntrHandlers[chan & 1] = func; - TransIntrData[chan & 1].data = data; - - return old_handler; -} - - - -int sceSdQuit() -{ - s32 ret; - - DmaStop(0); - DmaStop(1); - - DisableIntr(0x28, (int *)&ret); - DisableIntr(0x24, (int *)&ret); - DisableIntr(0x9, (int *)&ret); - ReleaseIntrHandler(0x28); - ReleaseIntrHandler(0x24); - ReleaseIntrHandler(0x9); - - return 0; -} - -void sceSdSetAddr(u16 reg, u32 val) -{ - volatile u16 *reg1; - u16 voice; - - reg1 = ParamRegList[(reg >> 8) & 0xFF] + ((reg & 1) << 9); - voice = reg & 0x3E; - - reg1 += ((voice << 1) + voice); - - U16_REGISTER_WRITE(reg1++, (val >> 17) & 0xFFFF); - - if((reg & 0xFF00) != 0x1D00) - { - U16_REGISTER_WRITE(reg1, (val >> 1) & 0xFFF8); - } -} - -u32 sceSdGetAddr(u16 reg) - -{ - volatile u16 *reg1; - u16 voice; - u32 retlo, rethi; - - reg1 = ParamRegList[(reg >> 8) & 0xFF] + ((reg & 1) << 9); - voice = reg & 0x3E; - reg1 += ((voice << 1) + voice); - rethi = U16_REGISTER_READ(reg1) << 17; - retlo = 0x1FFFF; - - reg &= 0xFF00; - - if(reg != 0x1D00) - { - retlo = U16_REGISTER_READ(reg1 + 1) << 1; - - if((reg == 0x2100) || (reg == 0x2200)) - { - u32 lo, hi; - - hi = U16_REGISTER_READ(reg1) << 17; - lo = U16_REGISTER_READ(reg1 + 1) << 1; - - if((rethi == hi) || (retlo != lo)) - { - retlo = lo; - rethi = hi; - } - } - } - - return rethi | retlo; -} - -SdIntrCallback sceSdSetTransCallback(s32 core, SdIntrCallback cb) -{ - SdIntrCallback old_cb; - - old_cb = TransIntrCallbacks[core & 1]; - TransIntrCallbacks[core & 1] = cb; - - return old_cb; -} - -SdIntrCallback sceSdSetIRQCallback(SdIntrCallback cb) -{ - SdIntrCallback old_cb; - - old_cb = Spu2IrqCallback; - Spu2IrqCallback = cb; - - return old_cb; -} diff --git a/iop/sound/libsd/src/imports.lst b/iop/sound/libsd/src/imports.lst index eef5f666623..489459be690 100644 --- a/iop/sound/libsd/src/imports.lst +++ b/iop/sound/libsd/src/imports.lst @@ -1,6 +1,3 @@ -sysclib_IMPORTS_start -I_memcpy -sysclib_IMPORTS_end intrman_IMPORTS_start I_RegisterIntrHandler @@ -9,6 +6,7 @@ I_EnableIntr I_DisableIntr I_CpuSuspendIntr I_CpuResumeIntr +I_QueryIntrContext intrman_IMPORTS_end loadcore_IMPORTS_start @@ -21,6 +19,18 @@ I_sceSifSetDma I_sceSifDmaStat sifman_IMPORTS_end -stdio_IMPORTS_start -I_printf -stdio_IMPORTS_end +sysclib_IMPORTS_start +I_bzero +I_memset +I_memcpy +sysclib_IMPORTS_end + +thevent_IMPORTS_start +I_CreateEventFlag +I_DeleteEventFlag +I_SetEventFlag +I_iSetEventFlag +I_ClearEventFlag +I_iClearEventFlag +I_WaitEventFlag +thevent_IMPORTS_end diff --git a/iop/sound/libsd/src/include/freesd.h b/iop/sound/libsd/src/include/freesd.h deleted file mode 100644 index 5ccaae96e93..00000000000 --- a/iop/sound/libsd/src/include/freesd.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __FREESD_H__ -#define __FREESD_H__ - -#include "libsd.h" - -typedef struct -{ - u32 mode; - void *data; -} IntrData; - -#endif diff --git a/iop/sound/libsd/src/irx_imports.h b/iop/sound/libsd/src/irx_imports.h index 92e8a8f0ce3..4db577b954c 100644 --- a/iop/sound/libsd/src/irx_imports.h +++ b/iop/sound/libsd/src/irx_imports.h @@ -3,7 +3,7 @@ # ____| | ____| | | |____| # | ___| |____ ___| ____| | \ PS2DEV Open Source Project. #----------------------------------------------------------------------- -# Copyright 2001-2009, ps2dev - http://www.ps2dev.org +# Copyright ps2dev - http://www.ps2dev.org # Licenced under Academic Free License version 2.0 # Review ps2sdk README & LICENSE files for further details. # @@ -19,7 +19,7 @@ #include #include #include -#include #include +#include #endif /* IOP_IRX_IMPORTS_H */ diff --git a/iop/sound/libsd/src/libsd.c b/iop/sound/libsd/src/libsd.c new file mode 100644 index 00000000000..ad11705094f --- /dev/null +++ b/iop/sound/libsd/src/libsd.c @@ -0,0 +1,2558 @@ +/* +# _____ ___ ____ ___ ____ +# ____| | ____| | | |____| +# | ___| |____ ___| ____| | \ PS2DEV Open Source Project. +#----------------------------------------------------------------------- +# Copyright ps2dev - http://www.ps2dev.org +# Licenced under Academic Free License version 2.0 +# Review ps2sdk README & LICENSE files for further details. +*/ + +/** + * @file + * Part of the IOP Sound Driver + */ + +#include + +#include +#include +#include +#include + +IRX_ID("Sound_Device_Library", 3, 3); +// Based on the module from SDK 3.1.0. + +#define SD_DMA_CS (1 << 9) // Continuous stream +#define SD_DMA_START (1 << 24) +#define SD_DMA_DIR_SPU2IOP 0 +#define SD_DMA_DIR_IOP2SPU 1 + +extern struct irx_export_table _exp_libsd; + +struct mode_data_struct +{ + u32 m_mode_flags; + u16 m_d_apf1_size; + u16 m_d_apf2_size; + u16 m_d_iir_vol; + u16 m_d_comb1_vol; + u16 m_d_comb2_vol; + u16 m_d_comb3_vol; + u16 m_d_comb4_vol; + u16 m_d_wall_vol; + u16 m_d_apf1_vol; + u16 m_d_apf2_vol; + u16 m_d_same_l_dst; + u16 m_d_same_r_dst; + u16 m_d_comb1_l_src; + u16 m_d_comb1_r_src; + u16 m_d_comb2_l_src; + u16 m_d_comb2_r_src; + u16 m_d_same_l_src; + u16 m_d_same_r_src; + u16 m_d_diff_l_dst; + u16 m_d_diff_r_dst; + u16 m_d_comb3_l_src; + u16 m_d_comb3_r_src; + u16 m_d_comb4_l_src; + u16 m_d_comb4_r_src; + u16 m_d_diff_l_src; + u16 m_d_diff_r_src; + u16 m_d_apf1_l_dst; + u16 m_d_apf1_r_dst; + u16 m_d_apf2_l_dst; + u16 m_d_apf2_r_dst; + u16 m_d_in_coef_l; + u16 m_d_in_coef_r; +}; + +typedef struct +{ + u32 m_mode; + void *m_data; +} IntrData; + +typedef struct BlockHandlerIntrData_ +{ + sceSdBlockTransHandler m_cb; + void *m_userdata; +} BlockHandlerIntrData_t; + +typedef struct CleanRegionBufferElement_ +{ + u32 *m_spuaddr; + u32 m_size; +} CleanRegionBufferElement_t; + +typedef struct CleanRegionBuffer_ +{ + CleanRegionBufferElement_t m_elements[97]; +} CleanRegionBuffer_t; + +typedef int (*SdCleanHandler)(int core); + +static int GetEEA(int core); +static void InitSpu2_Inner(void); +static void libsd_do_busyloop(int count); +static u32 DmaStartStop(int mainarg, void *vararg2, u32 vararg3); +static u32 VoiceTrans_Write_IOMode(const u16 *iopaddr, u32 size, int core); +static u32 BlockTransWriteFrom(u8 *iopaddr, u32 size, int core, int mode, u8 *startaddr); +static u32 BlockTransRead(u8 *iopaddr, u32 size, int core, u16 mode); +static void reset_vars(void); + +// clang-format off +static vu16 *const g_ParamRegList[] = +{ + (vu16 *)0xBF900000, + (vu16 *)0xBF900002, + (vu16 *)0xBF900004, + (vu16 *)0xBF900006, + (vu16 *)0xBF900008, + (vu16 *)0xBF90000A, + (vu16 *)0xBF90000C, + (vu16 *)0xBF90000E, + (vu16 *)0xBF900198, + (vu16 *)0xBF900760, + (vu16 *)0xBF900762, + (vu16 *)0xBF900764, + (vu16 *)0xBF900766, + (vu16 *)0xBF900768, + (vu16 *)0xBF90076A, + (vu16 *)0xBF90076C, + (vu16 *)0xBF90076E, + (vu16 *)0xBF900770, + (vu16 *)0xBF900772, + (vu16 *)0xBF900180, + (vu16 *)0xBF900184, + (vu16 *)0xBF9001A0, + (vu16 *)0xBF9001A4, + (vu16 *)0xBF900340, + (vu16 *)0xBF900188, + (vu16 *)0xBF90018C, + (vu16 *)0xBF900190, + (vu16 *)0xBF900194, + (vu16 *)0xBF9002E0, + (vu16 *)0xBF90033C, + (vu16 *)0xBF9001A8, + (vu16 *)0xBF90019C, + (vu16 *)0xBF9001C0, + (vu16 *)0xBF9001C4, + (vu16 *)0xBF9001C8, + (vu16 *)0xBF90019A, + (vu16 *)0xBF9001A8, + (vu16 *)0xBF9001AC, + // 1AE & 1B0 are both related to core attr & dma somehow + (vu16 *)0xBF9001AE, + (vu16 *)0xBF9001B0, + (vu16 *)0xBF900344, + NULL, + NULL, + NULL, +}; +// The values are more or less the same as on PSX (SPU) +static const u32 g_EffectSizes[] = +{ + 0x2, + 0x4d8, + 0x3e8, + 0x908, + 0xdfc, + 0x15bc, + 0x1ed8, + 0x3008, + 0x3008, + 0x780, +}; +static const struct mode_data_struct g_EffectParams[] = +{ + // SD_EFFECT_MODE_OFF + { + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x1, + 0x1, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x1, + 0x1, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + }, + // SD_EFFECT_MODE_ROOM + { + 0x0, + 0x7d, + 0x5b, + 0x6d80, + 0x54b8, + 0xbed0, + 0x0, + 0x0, + 0xba80, + 0x5800, + 0x5300, + 0x4d6, + 0x333, + 0x3f0, + 0x227, + 0x374, + 0x1ef, + 0x336, + 0x1b7, + 0x335, + 0x1b6, + 0x334, + 0x1b5, + 0x334, + 0x1b5, + 0x334, + 0x1b5, + 0x1b4, + 0x136, + 0xb8, + 0x5c, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_STUDIO_1 + { + 0x0, + 0x33, + 0x25, + 0x70f0, + 0x4fa8, + 0xbce0, + 0x4410, + 0xc0f0, + 0x9c00, + 0x5280, + 0x4ec0, + 0x3e4, + 0x31b, + 0x3a4, + 0x2af, + 0x372, + 0x266, + 0x31c, + 0x25d, + 0x25c, + 0x18e, + 0x22f, + 0x135, + 0x1d2, + 0xb7, + 0x18f, + 0xb5, + 0xb4, + 0x80, + 0x4c, + 0x26, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_STUDIO_2 + { + 0x0, + 0xb1, + 0x7f, + 0x70f0, + 0x4fa8, + 0xbce0, + 0x4510, + 0xbef0, + 0xb4c0, + 0x5280, + 0x4ec0, + 0x904, + 0x76b, + 0x824, + 0x65f, + 0x7a2, + 0x616, + 0x76c, + 0x5ed, + 0x5ec, + 0x42e, + 0x50f, + 0x305, + 0x462, + 0x2b7, + 0x42f, + 0x265, + 0x264, + 0x1b2, + 0x100, + 0x80, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_STUDIO_3 + { + 0x0, + 0xe3, + 0xa9, + 0x6f60, + 0x4fa8, + 0xbce0, + 0x4510, + 0xbef0, + 0xa680, + 0x5680, + 0x52c0, + 0xdfb, + 0xb58, + 0xd09, + 0xa3c, + 0xbd9, + 0x973, + 0xb59, + 0x8da, + 0x8d9, + 0x5e9, + 0x7ec, + 0x4b0, + 0x6ef, + 0x3d2, + 0x5ea, + 0x31d, + 0x31c, + 0x238, + 0x154, + 0xaa, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_HALL + { + 0x0, + 0x1a5, + 0x139, + 0x6000, + 0x5000, + 0x4c00, + 0xb800, + 0xbc00, + 0xc000, + 0x6000, + 0x5c00, + 0x15ba, + 0x11bb, + 0x14c2, + 0x10bd, + 0x11bc, + 0xdc1, + 0x11c0, + 0xdc3, + 0xdc0, + 0x9c1, + 0xbc4, + 0x7c1, + 0xa00, + 0x6cd, + 0x9c2, + 0x5c1, + 0x5c0, + 0x41a, + 0x274, + 0x13a, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_SPACE + { + 0x0, + 0x33d, + 0x231, + 0x7e00, + 0x5000, + 0xb400, + 0xb000, + 0x4c00, + 0xb000, + 0x6000, + 0x5400, + 0x1ed6, + 0x1a31, + 0x1d14, + 0x183b, + 0x1bc2, + 0x16b2, + 0x1a32, + 0x15ef, + 0x15ee, + 0x1055, + 0x1334, + 0xf2d, + 0x11f6, + 0xc5d, + 0x1056, + 0xae1, + 0xae0, + 0x7a2, + 0x464, + 0x232, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_ECHO + { + 0x0, + 0x3, + 0x3, + 0x7fff, + 0x7fff, + 0x0, + 0x0, + 0x0, + 0x8100, + 0x0, + 0x0, + 0x1ffd, + 0xffd, + 0x1009, + 0x9, + 0x0, + 0x0, + 0x1009, + 0x9, + 0x1fff, + 0x1fff, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1008, + 0x1004, + 0x8, + 0x4, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_DELAY + { + 0x0, + 0x3, + 0x3, + 0x7fff, + 0x7fff, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x1ffd, + 0xffd, + 0x1009, + 0x9, + 0x0, + 0x0, + 0x1009, + 0x9, + 0x1fff, + 0x1fff, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1ffe, + 0x1008, + 0x1004, + 0x8, + 0x4, + 0x8000, + 0x8000, + }, + // SD_EFFECT_MODE_CLEAR + { + 0x0, + 0x17, + 0x13, + 0x70f0, + 0x4fa8, + 0xbce0, + 0x4510, + 0xbef0, + 0x8500, + 0x5f80, + 0x54c0, + 0x371, + 0x2af, + 0x2e5, + 0x1df, + 0x2b0, + 0x1d7, + 0x358, + 0x26a, + 0x1d6, + 0x11e, + 0x12d, + 0xb1, + 0x11f, + 0x59, + 0x1a0, + 0xe3, + 0x58, + 0x40, + 0x28, + 0x14, + 0x8000, + 0x8000, + } +}; +static const u16 g_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, + 0x82fa, + 0x830a, + 0x8319, + 0x8328, + 0x8337, + 0x8346, + 0x8355, + 0x8364, + 0x8374, + 0x8383, + 0x8392, + 0x83a1, + 0x83b0, + 0x83c0, + 0x83cf, + 0x83de, + 0x83ed, + 0x83fd, + 0x840c, + 0x841b, + 0x842a, + 0x843a, + 0x8449, + 0x8458, + 0x8468, + 0x8477, + 0x8486, + 0x8495, + 0x84a5, + 0x84b4, + 0x84c3, + 0x84d3, + 0x84e2, + 0x84f1, + 0x8501, + 0x8510, + 0x8520, + 0x852f, + 0x853e, + 0x854e, + 0x855d, + 0x856d, + 0x857c, + 0x858b, + 0x859b, + 0x85aa, + 0x85ba, + 0x85c9, + 0x85d9, + 0x85e8, + 0x85f8, + 0x8607, + 0x8617, + 0x8626, + 0x8636, + 0x8645, + 0x8655, + 0x8664, + 0x8674, + 0x8683, + 0x8693, + 0x86a2, + 0x86b2, + 0x86c1, + 0x86d1, + 0x86e0, + 0x86f0, + 0x8700, + 0x870f, + 0x871f, + 0x872e, + 0x873e, + 0x874e, + 0x875d, + 0x876d, + 0x877d, + 0x878c, +}; +// Enable/disable bits in SD_CORE_ATTR +static const u16 g_CoreAttrShifts[] = +{ + 0x7, + 0x6, + 0xe, + 0x8, +}; +static const u16 g_VoiceDataInit[] = +{ + 0x700, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, +}; +// clang-format on + +// Unofficial: move to bss +static const u32 g_ClearEffectData[256] __attribute__((__aligned__(16))); +// Unofficial: move to bss +static int g_VoiceTransStatus[2]; +// Unofficial: move to bss +static int g_VoiceTransIoMode[2]; +// Unofficial: move to bss +static int g_SpdifSettings; +// Unofficial: move to bss +static sceSdEffectAttr g_EffectAttr[2]; +// Unofficial: move to bss +static int g_VoiceTransCompleteBool[2]; +// Unofficial: move to bss +static int g_VoiceTransCompleteEf[2]; +// Unofficial: move to bss +static int g_vars_inited; +// Unofficial: move to bss +static SdIntrCallback g_Spu2IrqCallback; +// Unofficial: move to bss +static sceSdSpu2IntrHandler g_Spu2IntrHandler; +// Unofficial: move to bss +static void *g_Spu2IntrHandlerData; +// Unofficial: move to bss +static sceSdTransIntrHandler g_TransIntrHandlers[2]; +// Unofficial: move to bss +static BlockHandlerIntrData_t g_BlockHandlerIntrData[2]; +// Unofficial: move to bss +static SdCleanHandler g_CleanHandlers[2]; +// Unofficial: move to bss +static IntrData g_TransIntrData[2]; +static u32 g_CleanRegionMax[2]; +static u32 g_CleanRegionCur[2]; +static CleanRegionBuffer_t g_CleanRegionBuffer[2]; +static u32 g_BlockTransBuff[2]; +static u8 *g_BlockTransAddr[2]; +static u32 g_BlockTransSize[2]; +static u32 g_BatchData __attribute__((__aligned__(16))); +static SdIntrCallback g_TransIntrCallbacks[2]; +static u32 g_EffectAddr[2]; + +int _start(int ac, char **av) +{ + int regres; + int state; + + (void)ac; + (void)av; + CpuSuspendIntr(&state); + regres = RegisterLibraryEntries(&_exp_libsd); + CpuResumeIntr(state); + if ( regres ) + return MODULE_NO_RESIDENT_END; + InitSpu2_Inner(); + reset_vars(); + return MODULE_RESIDENT_END; +} + +static void SetEffectRegisterPair(spu2_u16pair_t *pair, u32 val) +{ + val <<= 2; + // Unofficial: receive register pair instead of base+offset + pair->m_pair[0] = (val >> 16) & 0xFFFF; + pair->m_pair[1] = val; +} + +static void SetEffectData(int core, const struct mode_data_struct *mode_data) +{ + int mode_flags; + // Unofficial: use local instead of global variable for SPU2 MMIO + USE_SPU2_MMIO_HWPORT(); + + mode_flags = mode_data->m_mode_flags; + if ( !mode_flags ) + mode_flags = 0xFFFFFFFF; + if ( (mode_flags & 1) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_size, mode_data->m_d_apf1_size); + if ( (mode_flags & 2) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_size, mode_data->m_d_apf2_size); + if ( (mode_flags & 4) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_iir_vol = mode_data->m_d_iir_vol; + if ( (mode_flags & 8) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb1_vol = mode_data->m_d_comb1_vol; + if ( (mode_flags & 0x10) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb2_vol = mode_data->m_d_comb2_vol; + if ( (mode_flags & 0x20) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb3_vol = mode_data->m_d_comb3_vol; + if ( (mode_flags & 0x40) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb4_vol = mode_data->m_d_comb4_vol; + if ( (mode_flags & 0x80) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_wall_vol = mode_data->m_d_wall_vol; + if ( (mode_flags & 0x100) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_apf1_vol = mode_data->m_d_apf1_vol; + if ( (mode_flags & 0x200) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_apf2_vol = mode_data->m_d_apf2_vol; + if ( (mode_flags & 0x400) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_l_dst, mode_data->m_d_same_l_dst); + if ( (mode_flags & 0x800) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_r_dst, mode_data->m_d_same_r_dst); + if ( (mode_flags & 0x1000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb1_l_src, mode_data->m_d_comb1_l_src); + if ( (mode_flags & 0x2000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb1_r_src, mode_data->m_d_comb1_r_src); + if ( (mode_flags & 0x4000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb2_l_src, mode_data->m_d_comb2_l_src); + if ( (mode_flags & 0x8000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb2_r_src, mode_data->m_d_comb2_r_src); + if ( (mode_flags & 0x10000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_l_src, mode_data->m_d_same_l_src); + if ( (mode_flags & 0x20000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_same_r_src, mode_data->m_d_same_r_src); + if ( (mode_flags & 0x40000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_l_dst, mode_data->m_d_diff_l_dst); + if ( (mode_flags & 0x80000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_r_dst, mode_data->m_d_diff_r_dst); + if ( (mode_flags & 0x100000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb3_l_src, mode_data->m_d_comb3_l_src); + if ( (mode_flags & 0x200000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb3_r_src, mode_data->m_d_comb3_r_src); + if ( (mode_flags & 0x400000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb4_l_src, mode_data->m_d_comb4_l_src); + if ( (mode_flags & 0x800000) ) + SetEffectRegisterPair( + &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb4_r_src, mode_data->m_d_comb4_r_src); + if ( (mode_flags & 0x1000000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_l_src, mode_data->m_d_diff_l_src); + if ( (mode_flags & 0x2000000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_diff_r_src, mode_data->m_d_diff_r_src); + if ( (mode_flags & 0x4000000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_l_dst, mode_data->m_d_apf1_l_dst); + if ( (mode_flags & 0x8000000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_r_dst, mode_data->m_d_apf1_r_dst); + if ( (mode_flags & 0x10000000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_l_dst, mode_data->m_d_apf2_l_dst); + if ( (mode_flags & 0x20000000) ) + SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_r_dst, mode_data->m_d_apf2_r_dst); + if ( (mode_flags & 0x40000000) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_in_coef_l = mode_data->m_d_in_coef_l; + if ( (mode_flags & 0x80000000) ) + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_in_coef_r = mode_data->m_d_in_coef_r; +} + +int sceSdClearEffectWorkArea(int core, int channel, int effect_mode) +{ + u32 aligned_addr; + u32 effect_size; + u32 effect_addr; + int xferres; + SdIntrCallback callback_tmp; + sceSdTransIntrHandler handler_tmp; + + effect_mode &= 0xFF; + if ( effect_mode > SD_EFFECT_MODE_PIPE ) + return -100; + if ( !effect_mode ) + return 0; + // Unofficial: restrict channel + channel &= 1; + if ( DmaStartStop((channel << 4) | 4, 0, 0) ) + return -210; + if ( g_VoiceTransIoMode[channel] != 1 ) + return -201; + if ( QueryIntrContext() ) + return -202; + aligned_addr = 0; + effect_size = g_EffectSizes[effect_mode] << 3; + effect_addr = (GetEEA(core) - (effect_size - 1)) >> 1; + if ( (effect_size & 0x3F) ) + { + effect_size &= 0x3FFFFFF; + aligned_addr = (GetEEA(core) - (effect_size - 1)) >> 1; + } + // Disable intr_handlers by removing them + handler_tmp = g_TransIntrHandlers[channel]; + callback_tmp = g_TransIntrCallbacks[channel]; + g_TransIntrHandlers[channel] = 0; + g_TransIntrCallbacks[channel] = 0; + xferres = 0; + if ( aligned_addr ) + { + xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)(effect_addr << 1), 0x40); + if ( xferres >= 0 ) + xferres = sceSdVoiceTransStatus(channel, 1); + effect_addr = aligned_addr; + } + if ( xferres >= 0 ) + { + int i; + + for ( i = 0;; i += 1 ) + { + u32 size; + + size = (effect_size <= 0x400) ? effect_size : 0x400; + xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)((effect_addr + (i << 9)) << 1), size); + if ( xferres < 0 ) + break; + // Wait for completion + xferres = sceSdVoiceTransStatus(channel, 1); + if ( xferres < 0 ) + break; + if ( effect_size <= 0x400 ) + { + xferres = 0; + break; + } + effect_size -= 0x400; + } + } + // Enable intr_handlers by adding them again + g_TransIntrHandlers[channel] = handler_tmp; + g_TransIntrCallbacks[channel] = callback_tmp; + return xferres; +} + +static int CleanHandler(int core) +{ + // Unofficial: restrict core + core &= 1; + g_CleanRegionCur[core] += 1; + if ( (int)g_CleanRegionCur[core] >= (int)(g_CleanRegionMax[core] - 1) ) + g_CleanHandlers[core] = 0; + DmaStartStop((core << 4) | 2, g_CleanRegionBuffer[core].m_elements[g_CleanRegionCur[core]].m_spuaddr, 0); + DmaStartStop( + (core << 4) | 6, (u8 *)g_ClearEffectData, g_CleanRegionBuffer[core].m_elements[g_CleanRegionCur[core]].m_size); + return 0; +} + +int sceSdCleanEffectWorkArea(int core, int channel, int effect_mode) +{ + u32 effect_size; + u32 effect_addr; + int xferres; + int i; + + effect_mode &= 0xFF; + if ( effect_mode > SD_EFFECT_MODE_PIPE ) + return -100; + if ( !effect_mode ) + return 0; + // Unofficial: restrict channel + channel &= 1; + if ( DmaStartStop((channel << 4) | 4, 0, 0) ) + return -210; + if ( g_VoiceTransIoMode[channel] != 1 ) + return -201; + effect_size = g_EffectSizes[effect_mode] << 3; + effect_addr = GetEEA(core) - (effect_size - 1); + if ( (effect_size & 0x3F) ) + { + effect_size &= 0x3FFFFFF; + xferres = sceSdVoiceTrans(channel, 8, (u8 *)g_ClearEffectData, (u32 *)effect_addr, 0x40); + if ( xferres < 0 ) + return xferres; + effect_addr = GetEEA(core) - (effect_size - 1); + } + effect_addr += 0x100; + effect_size -= 0x400; + for ( i = 0;; i += 1 ) + { + g_CleanRegionBuffer[channel].m_elements[i].m_spuaddr = (u32 *)effect_addr; + g_CleanRegionBuffer[channel].m_elements[i].m_size = (effect_size <= 0x400) ? effect_size : 0x400; + if ( effect_size <= 0x400 ) + break; + effect_addr += 0x100; + effect_size -= 0x400; + } + g_CleanRegionMax[channel] = i + 1; + g_CleanHandlers[channel] = CleanHandler; + g_CleanRegionCur[channel] = 0; + xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)effect_addr, 0x400); + if ( xferres >= 0 ) + xferres = 0; + return xferres; +} + +void sceSdGetEffectAttr(int core, sceSdEffectAttr *attr) +{ + USE_SPU2_MMIO_HWPORT(); + + attr->core = core; + attr->mode = g_EffectAttr[core].mode; + attr->delay = g_EffectAttr[core].delay; + attr->feedback = g_EffectAttr[core].feedback; + attr->depth_L = spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll; + attr->depth_R = spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr; +} + +int sceSdSetEffectAttr(int core, const sceSdEffectAttr *attr) +{ + int clearram; + int channel; + int mode; + int effects_enabled; + int retval; + struct mode_data_struct mode_data; + int state; + int effect_mode; + USE_SPU2_MMIO_HWPORT(); + + mode_data.m_mode_flags = 0; + mode = attr->mode; + clearram = !!(mode & SD_EFFECT_MODE_CLEAR); + effect_mode = clearram ? g_EffectAttr[core].mode : 0; + channel = clearram && !!(mode & 0x200); + mode &= 0xFF; + // Check if valid mode + if ( mode > SD_EFFECT_MODE_PIPE ) + return -100; + g_EffectAttr[core].mode = mode; + g_EffectAddr[core] = GetEEA(core) - ((g_EffectSizes[mode] << 3) - 1); + // Unoffical: use memcpy from sysclib + memcpy(&mode_data, &g_EffectParams[mode], sizeof(mode_data)); + switch ( mode ) + { + case SD_EFFECT_MODE_ECHO: + g_EffectAttr[core].feedback = 0x80; + g_EffectAttr[core].delay = 0x80; + break; + case SD_EFFECT_MODE_DELAY: + g_EffectAttr[core].feedback = 0; + g_EffectAttr[core].delay = 0x80; + break; + default: + g_EffectAttr[core].feedback = 0; + g_EffectAttr[core].delay = 0; + break; + } + if ( mode >= SD_EFFECT_MODE_ECHO && mode <= SD_EFFECT_MODE_DELAY ) + { + int delay; + + delay = attr->delay; + g_EffectAttr[core].delay = delay; + g_EffectAttr[core].feedback = attr->feedback; + delay += 1; + delay &= 0xFFFF; + mode_data.m_d_same_l_dst = (s16)((u16)delay << 6) - (s16)mode_data.m_d_apf1_size; + delay <<= 5; + delay &= 0xFFFF; + mode_data.m_d_same_l_src = delay + mode_data.m_d_same_r_src; + mode_data.m_d_same_r_dst = delay - mode_data.m_d_apf2_size; + mode_data.m_d_comb1_l_src = delay + mode_data.m_d_comb1_r_src; + mode_data.m_d_apf1_l_dst = delay + mode_data.m_d_apf2_l_dst; + mode_data.m_d_apf1_r_dst = delay + mode_data.m_d_apf2_r_dst; + mode_data.m_d_wall_vol = 0x102 * g_EffectAttr[core].feedback; + } + // Disable effects + effects_enabled = (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1; + if ( effects_enabled ) + { + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_ENABLE_EFFECTS; + CpuResumeIntr(state); + } + // Clean up after last mode + retval = (effects_enabled && clearram) ? sceSdClearEffectWorkArea(core, channel, effect_mode) : 0; + if ( retval >= 0 ) + { + // Depth / Volume + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = attr->depth_L; + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = attr->depth_R; + SetEffectData(core, &mode_data); + // Set effect start addr (ESA) + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[0] = g_EffectAddr[core] >> 17; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[1] = g_EffectAddr[core] >> 1; + retval = clearram ? sceSdClearEffectWorkArea(core, channel, mode) : 0; + } + // Enable effects + if ( effects_enabled ) + { + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_ENABLE_EFFECTS; + CpuResumeIntr(state); + } + return retval; +} + +static int GetEEA(int core) +{ + USE_SPU2_MMIO_HWPORT(); + + return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_eea << 17) | 0x1FFFF; +} + +int sceSdSetEffectMode(int core, const sceSdEffectAttr *param) +{ + int clearram; + int channel; + u32 mode; + int effects_enabled; + struct mode_data_struct mode_data; + int state; + USE_SPU2_MMIO_HWPORT(); + + mode_data.m_mode_flags = 0; + mode = param->mode; + clearram = !!(mode & 0x100); + channel = clearram && !!(mode & 0x200); + mode &= 0xFF; + if ( mode > SD_EFFECT_MODE_PIPE ) + return -100; + g_EffectAttr[core].mode = mode; + g_EffectAttr[core].delay = 0; + g_EffectAttr[core].feedback = 0; + g_EffectAddr[core] = GetEEA(core) - ((g_EffectSizes[mode] << 3) - 1); + // Unoffical: don't use inlined memcpy + memcpy(&mode_data, &g_EffectParams[mode], sizeof(mode_data)); + effects_enabled = (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1; + if ( effects_enabled ) + { + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_ENABLE_EFFECTS; + CpuResumeIntr(state); + } + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = 0; + SetEffectData(core, &mode_data); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[0] = g_EffectAddr[core] >> 17; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[1] = g_EffectAddr[core] >> 1; + if ( effects_enabled ) + { + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_ENABLE_EFFECTS; + CpuResumeIntr(state); + } + return clearram ? sceSdCleanEffectWorkArea(core, channel, mode) : 0; +} + +int sceSdSetEffectModeParams(int core, const sceSdEffectAttr *attr) +{ + int mode; + struct mode_data_struct mode_data; + USE_SPU2_MMIO_HWPORT(); + + mode = attr->mode; + mode &= 0xFF; + if ( mode > SD_EFFECT_MODE_PIPE ) + return -100; + if ( g_EffectAttr[core].mode != mode ) + return -100; + if ( mode >= SD_EFFECT_MODE_ECHO && mode <= SD_EFFECT_MODE_DELAY ) + { + int delay; + + // Unoffical: don't use inlined memcpy + memcpy(&mode_data, &g_EffectParams[mode], sizeof(mode_data)); + mode_data.m_mode_flags = 0xC011C80; + delay = attr->delay; + g_EffectAttr[core].delay = delay; + g_EffectAttr[core].feedback = attr->feedback; + delay += 1; + delay &= 0xFFFF; + mode_data.m_d_same_l_dst = (s16)(((u16)delay << 6) - (s16)mode_data.m_d_apf1_size); + delay <<= 5; + delay &= 0xFFFF; + mode_data.m_d_same_l_src = delay + mode_data.m_d_same_r_src; + mode_data.m_d_same_r_dst = delay - mode_data.m_d_apf2_size; + mode_data.m_d_comb1_l_src = delay + mode_data.m_d_comb1_r_src; + mode_data.m_d_apf1_l_dst = delay + mode_data.m_d_apf2_l_dst; + mode_data.m_d_apf1_r_dst = delay + mode_data.m_d_apf2_r_dst; + mode_data.m_d_wall_vol = 0x102 * g_EffectAttr[core].feedback; + SetEffectData(core, &mode_data); + } + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = attr->depth_L; + spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = attr->depth_R; + return 0; +} + +static void InitSpu2_Inner(void) +{ + int state; + USE_IOP_MMIO_HWPORT(); + + iop_mmio_hwport->ssbus2.ind_4_address = 0xBF900000; + iop_mmio_hwport->ssbus2.ind_9_address = 0xBF900800; + CpuSuspendIntr(&state); + iop_mmio_hwport->dmac1.dpcr1 |= 0x80000; + iop_mmio_hwport->dmac2.dpcr2 |= 8; + CpuResumeIntr(state); + iop_mmio_hwport->ssbus1.ind_4_delay = 0x200B31E1; + iop_mmio_hwport->ssbus2.ind_9_delay = 0x200B31E1; +} + +static void InitSpu2(void) +{ + USE_SPU2_MMIO_HWPORT(); + + InitSpu2_Inner(); + spu2_mmio_hwport->m_u.m_e.m_spdif_mode = 0x0900; + spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200; + spu2_mmio_hwport->m_u.m_e.m_unknown7ca = 8; +} + +// Core / Volume Registers +static void InitCoreVolume(int flag) +{ + int i; + USE_SPU2_MMIO_HWPORT(); + + spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0xC032; + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr = + (flag ? SD_ENABLE_EFFECTS : 0) | (i ? SD_ENABLE_EX_INPUT : 0) | SD_MUTE | SD_SPU2_ON; + // Unofficial: rerolled + // HIgh is voices 0-15, Low is 16-23, representing voices 0..23 (24) + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixl.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixl.m_pair[1] = 0xFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixel.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixel.m_pair[1] = 0x00FF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixr.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixr.m_pair[1] = 0x00FF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixer.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixer.m_pair[1] = 0x00FF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_mmix = 0xFF0 + (i * 0xC); + } + if ( !flag ) + { + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_evoll = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_evolr = 0; + } + // Unofficial: rerolled + // Effect End Address, Upper part + for ( i = 0; i < 2; i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_eea = 14 + i; + } + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + // Core 1 External Input Volume. + // The external Input is Core 0's output. + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_avoll = i ? 0x7FFF : 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_avolr = i ? 0x7FFF : 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_bvoll = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_bvolr = 0; + } +} + +int sceSdVoiceTrans(s16 chan, u16 mode, u8 *iopaddr, u32 *spuaddr, u32 size) +{ + int core; + + core = chan & 1; + if ( !size ) + return -100; + if ( DmaStartStop((core << 4) | 4, 0, 0) ) + return -210; + if ( g_VoiceTransIoMode[core] != 1 ) + return -201; + switch ( mode & 3 ) + { + case SD_TRANS_READ: + g_TransIntrData[core].m_mode = core | 0x900; + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + g_VoiceTransStatus[core] = 0; + DmaStartStop((core << 4) | 2, spuaddr, 0); + if ( QueryIntrContext() ) + iClearEventFlag(g_VoiceTransCompleteEf[core], ~1); + else + ClearEventFlag(g_VoiceTransCompleteEf[core], ~1); + g_VoiceTransIoMode[core] = 0; + return DmaStartStop((core << 4) | 5, iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0)); + case SD_TRANS_WRITE: + g_TransIntrData[core].m_mode = core | 0x500; + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + DmaStartStop((core << 4) | 2, spuaddr, 0); + if ( QueryIntrContext() ) + iClearEventFlag(g_VoiceTransCompleteEf[core], ~1); + else + ClearEventFlag(g_VoiceTransCompleteEf[core], ~1); + g_VoiceTransIoMode[core] = 0; + if ( !(mode & SD_TRANS_MODE_IO) ) + { + g_VoiceTransStatus[core] = 0; + return DmaStartStop((core << 4) | 6, iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0)); + } + g_VoiceTransStatus[core] = 1; + return VoiceTrans_Write_IOMode((u16 *)iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0), core); + default: + return -100; + } +} + +u32 sceSdVoiceTransStatus(s16 channel, s16 flag) +{ + u32 efres; + int core; + + core = channel & 1; + if ( g_VoiceTransStatus[core] == 1 || g_VoiceTransIoMode[core] == 1 ) + return 1; + switch ( flag ) + { + case 0: + if ( g_VoiceTransCompleteBool[core] ) + { + g_VoiceTransCompleteBool[core] = 0; + g_VoiceTransIoMode[core] = 1; + } + break; + case 1: + if ( QueryIntrContext() ) + return -202; + WaitEventFlag(g_VoiceTransCompleteEf[core], 1, 0, &efres); + g_VoiceTransCompleteBool[core] = 0; + g_VoiceTransIoMode[core] = 1; + break; + default: + break; + } + return g_VoiceTransIoMode[core]; +} + +int sceSdStopTrans(int channel) +{ + int core; + + core = channel & 1; + g_TransIntrData[core].m_mode = core; + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + return DmaStartStop((core << 4) | 0xA, 0, 0); +} + +int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...) +{ + int core; + u32 started; + int transfer_dir; + int retres_1; + uiptr vararg_elm1; + uiptr vararg_elm2; + uiptr vararg_elm3; + va_list va2; + + va_start(va2, size); + vararg_elm1 = va_arg(va2, uiptr); + vararg_elm2 = va_arg(va2, uiptr); + vararg_elm3 = va_arg(va2, uiptr); + va_end(va2); + core = chan & 1; + started = DmaStartStop((core << 4) | 4, 0, 0); + transfer_dir = mode & 3; + switch ( transfer_dir ) + { + case SD_TRANS_READ: + if ( !size ) + return -100; + if ( started ) + return -210; + g_TransIntrData[core].m_mode = core | 0xA00; + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + if ( (mode & 0x80) ) + { + if ( !vararg_elm1 ) + { + g_TransIntrData[core].m_mode = core; + return -100; + } + g_BlockHandlerIntrData[core].m_cb = (void *)vararg_elm1; + g_BlockHandlerIntrData[core].m_userdata = (void *)vararg_elm2; + g_TransIntrData[core].m_mode |= 0x8000; + } + else if ( (mode & SD_TRANS_LOOP) ) + { + size >>= 1; + g_TransIntrData[core].m_mode |= SD_TRANS_LOOP << 8; + } + retres_1 = BlockTransRead(iopaddr, size, core, mode); + break; + case SD_TRANS_STOP: + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + g_TransIntrData[core].m_mode = core; + return DmaStartStop((core << 4) | 0xA, 0, 0); + case SD_TRANS_WRITE: + case SD_TRANS_WRITE_FROM: + if ( !size ) + return -100; + if ( started ) + return -210; + g_TransIntrData[core].m_mode = core | 0x600; + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + if ( (mode & 0x80) ) + { + if ( !vararg_elm2 ) + { + g_TransIntrData[core].m_mode = core; + return -100; + } + g_BlockHandlerIntrData[core].m_cb = (void *)vararg_elm2; + g_BlockHandlerIntrData[core].m_userdata = (void *)vararg_elm3; + g_TransIntrData[core].m_mode |= 0x8000; + } + else if ( (mode & SD_TRANS_LOOP) ) + { + size >>= 1; + g_TransIntrData[core].m_mode |= SD_TRANS_LOOP << 8; + } + retres_1 = + BlockTransWriteFrom(iopaddr, size, chan, mode, (transfer_dir == SD_TRANS_WRITE_FROM) ? (void *)vararg_elm1 : 0); + break; + default: + return -100; + } + if ( retres_1 < 0 ) + { + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + g_TransIntrData[core].m_mode = core; + } + return retres_1; +} + +u32 sceSdBlockTransStatus(s16 channel, s16 flag) +{ + int core; + // Unofficial: inline thunk + USE_IOP_MMIO_HWPORT(); + USE_SPU2_MMIO_HWPORT(); + + (void)flag; + core = channel & 1; + return (g_BlockTransBuff[core] << 24) + | (((spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas & 7) ? + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr : + 0) + & ~0xFF000000); +} + +static int InitSpdif() +{ + int i; + USE_SPU2_MMIO_HWPORT(); + + spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0; + libsd_do_busyloop(2); + spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0x8000; + libsd_do_busyloop(1); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0; + } + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_admas = 0; + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr = 0; + libsd_do_busyloop(1); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr = SD_SPU2_ON; + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0; + spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0; + } + for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_statx & 0x7FF) + && (spu2_mmio_hwport->m_u.m_m.m_core_regs[1].m_cregs.m_statx & 0x7FF) && i < 0xF00; + i += 1 ) + libsd_do_busyloop(1); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_koff.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_koff.m_pair[1] = 0xFF; + } + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_pmon.m_pair[0] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_pmon.m_pair[1] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_non.m_pair[0] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_non.m_pair[1] = 0; + } + return 0; +} + +static void SetDmaWrite(int chan) +{ + vu32 *dmachanptr; + USE_IOP_MMIO_HWPORT(); + + dmachanptr = chan ? &iop_mmio_hwport->ssbus2.ind_9_delay : &iop_mmio_hwport->ssbus1.ind_4_delay; + *dmachanptr &= ~0xF000000; +} + +static void SetDmaRead(int chan) +{ + vu32 *dmachanptr; + USE_IOP_MMIO_HWPORT(); + + dmachanptr = chan ? &iop_mmio_hwport->ssbus2.ind_9_delay : &iop_mmio_hwport->ssbus1.ind_4_delay; + *dmachanptr = (*dmachanptr & ~0xF000000) | 0x2000000; +} + +static void __attribute__((optimize("no-unroll-loops"))) libsd_do_busyloop_inner(void) +{ + int i; + int loopmul; + + loopmul = 13; + for ( i = 0; i < 120; i += 1 ) + { + loopmul *= 13; + __asm__ __volatile__("" : "+g"(loopmul) : :); + } +} + +static void libsd_do_busyloop(int count) +{ + int i; + + for ( i = 0; i < count; i += 1 ) + libsd_do_busyloop_inner(); +} + +static u32 DmaStartStop(int mainarg, void *vararg2, u32 vararg3) +{ + int core; + u32 tsa_tmp; + u32 vararg3_cal; + u32 blocktransbufitem; + int dma_addr; + int i; + int hichk; + int state; + USE_IOP_MMIO_HWPORT(); + USE_SPU2_MMIO_HWPORT(); + + // Unofficial: restrict core + core = (mainarg >> 4) & 1; + switch ( mainarg & 0xF ) + { + case 2: + tsa_tmp = ((u16)(uiptr)vararg2 >> 1) & ~7; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = tsa_tmp; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = (tsa_tmp >> 16) & 0xFFFF; + return 0; + case 4: + if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_DMA_IN_PROCESS) ) + return -1; + if ( ((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr & SD_DMA_START) ) + return -1; + if ( spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas ) + return -1; + return 0; + case 5: + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_DMA_READ; + CpuResumeIntr(state); + SetDmaRead(core); + vararg3_cal = (vararg3 >> 6) + (!!(vararg3 & 0x3F)); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)vararg2; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16; +#pragma GCC diagnostic pop + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = vararg3_cal; + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = + SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_SPU2IOP; + return vararg3_cal << 6; + case 6: + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr = + (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_WRITE; + CpuResumeIntr(state); + SetDmaWrite(core); + vararg3_cal = (vararg3 >> 6) + (!!(vararg3 & 0x3F)); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)vararg2; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16; +#pragma GCC diagnostic pop + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = vararg3_cal; + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = + SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_IOP2SPU; + return vararg3_cal << 6; + case 0xA: + blocktransbufitem = 0; + dma_addr = 0; + if ( ((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr & SD_DMA_START) ) + { + blocktransbufitem = g_BlockTransBuff[core]; + dma_addr = (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr; + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr &= ~SD_DMA_START; + if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) ) + { + for ( i = 0; !(spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & 0x80) && i < 0x1000000; i += 1 ) + { + } + } + } + if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) ) + { + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA; + CpuResumeIntr(state); + for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) && i < 0xF00; i += 1 ) + { + } + } + hichk = 0; + if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas & 7) ) + { + hichk = 1; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 0; + } + if ( QueryIntrContext() ) + iSetEventFlag(g_VoiceTransCompleteEf[core], 1); + else + SetEventFlag(g_VoiceTransCompleteEf[core], 1); + g_VoiceTransCompleteBool[core] = 0; + g_VoiceTransIoMode[core] = 1; + g_CleanHandlers[core] = 0; + return (dma_addr && hichk) ? ((dma_addr & ~0xFF000000) | (blocktransbufitem << 24)) : 0; + default: + return 0; + } +} + +static u32 VoiceTrans_Write_IOMode(const u16 *iopaddr, u32 size, int core) +{ + u32 size_tmp; + int count; + int i; + int state; + USE_SPU2_MMIO_HWPORT(); + + // Unofficial: restrict core + core &= 1; + for ( size_tmp = size; size_tmp; size_tmp -= count ) + { + count = (size_tmp <= 0x40) ? size_tmp : 0x40; + for ( i = 0; i < (count / 2); i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_xferdata = iopaddr[i]; + CpuSuspendIntr(&state); + // Set Transfer mode to IO + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr = + (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_IO; + CpuResumeIntr(state); + // Wait for transfer to complete; + for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & SD_IO_IN_PROCESS) && i < 0xF00; i += 1 ) + libsd_do_busyloop(1); + } + CpuSuspendIntr(&state); + // Reset DMA settings + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA; + CpuResumeIntr(state); + g_VoiceTransIoMode[core] = 1; + // Unofficial: return size + return size; +} + +static void do_finish_block_clean_xfer(int core) +{ + USE_SPU2_MMIO_HWPORT(); + + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 0; +} + +static int TransInterrupt(IntrData *intr) +{ + int dma_dir; + u32 mode; + int core; + int i; + void *dma_addr; + int dma_size; + USE_IOP_MMIO_HWPORT(); + USE_SPU2_MMIO_HWPORT(); + + mode = intr->m_mode; + switch ( mode & 0xC00 ) + { + case 0x400: + dma_dir = SD_DMA_DIR_IOP2SPU; + break; + case 0x800: + dma_dir = SD_DMA_DIR_SPU2IOP; + break; + default: + return 1; + } + core = mode & 1; + switch ( mode & 0x300 ) + { + // Voice Transfer + case 0x100: + // SD_C_STATX(core) + // If done elsewise, it doesn't work, havn't figured out why yet. + for ( i = 0; !(spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & 0x80) && i < 0x1000000; i += 1 ) + { + } + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA; + for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) && i < 0xF00; i += 1 ) + { + } + if ( dma_dir == SD_DMA_DIR_SPU2IOP ) + FlushDcache(); + if ( g_CleanHandlers[core] ) + g_CleanHandlers[core](core); + else + { + iSetEventFlag(g_VoiceTransCompleteEf[core], 1); + if ( g_TransIntrHandlers[core] ) + { + g_VoiceTransIoMode[core] = 1; + g_TransIntrHandlers[core](core, intr->m_data); + } + else if ( !g_TransIntrCallbacks[core] ) + g_VoiceTransCompleteBool[core] = 1; + else + { + g_VoiceTransIoMode[core] = 1; + g_TransIntrCallbacks[core](0); + } + } + break; + // Block Transfer + case 0x200: + if ( (mode & 0x8000) ) + { + if ( g_BlockHandlerIntrData[core].m_cb ) + { + g_BlockHandlerIntrData[core].m_cb(core, g_BlockHandlerIntrData[core].m_userdata, &dma_addr, &dma_size); + if ( dma_size > 0 ) + { + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = + (dma_size >> 6) + (dma_size - (dma_size & 0x3FFFFFF) > 0); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)dma_addr; + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = + dma_dir | SD_DMA_START | SD_DMA_CS; + } + else + { + do_finish_block_clean_xfer(core); + g_BlockHandlerIntrData[core].m_cb = 0; + g_BlockHandlerIntrData[core].m_userdata = 0; + } + } + else + do_finish_block_clean_xfer(core); + if ( dma_dir == SD_DMA_DIR_SPU2IOP ) + FlushDcache(); + } + else + { + if ( (mode & (SD_TRANS_LOOP << 8)) ) + { + // Switch buffers + g_BlockTransBuff[core] = 1 - g_BlockTransBuff[core]; + // Setup DMA & send + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = + (int)g_BlockTransSize[core] / 0x40 + ((int)g_BlockTransSize[core] % 0x40 > 0); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = + (uiptr)(g_BlockTransAddr[core] + g_BlockTransBuff[core] * g_BlockTransSize[core]); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = + dma_dir | SD_DMA_START | SD_DMA_CS; + } + else + do_finish_block_clean_xfer(core); + if ( dma_dir == SD_DMA_DIR_SPU2IOP ) + FlushDcache(); + if ( g_TransIntrHandlers[core] ) + g_TransIntrHandlers[core](core, intr->m_data); + else if ( g_TransIntrCallbacks[core] ) + g_TransIntrCallbacks[core](0); + } + break; + default: + break; + } + return 1; +} + +static u32 BlockTransWriteFrom(u8 *iopaddr, u32 size, int core, int mode, u8 *startaddr) +{ + u8 *startaddr_tmp; + int size_align; + int size_align_r6; + int state; + USE_IOP_MMIO_HWPORT(); + USE_SPU2_MMIO_HWPORT(); + + core &= 1; + startaddr_tmp = startaddr; + g_BlockTransAddr[core] = iopaddr; + g_BlockTransBuff[core] = 0; + g_BlockTransSize[core] = size; + if ( startaddr ) + { + size_align = size - (startaddr - iopaddr); + if ( (u32)(startaddr - iopaddr) >= size ) + { + u32 other_align; + + other_align = startaddr - iopaddr - size; + if ( !(mode & SD_TRANS_LOOP) || other_align >= size ) + return -100; + g_BlockTransBuff[core] += 1; + size_align = size - other_align; + } + if ( size_align % 0x400 > 0 ) + { + size_align = (size_align / 0x400 + 1) << 10; + startaddr_tmp = iopaddr + g_BlockTransBuff[core] * size + size - size_align; + } + } + else + { + startaddr_tmp = iopaddr; + size_align = size; + } + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA; + CpuResumeIntr(state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 1 << core; + SetDmaWrite(core); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)startaddr_tmp; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16; +#pragma GCC diagnostic pop + size_align_r6 = ((size_align < 0) ? (size_align + 63) : size_align) >> 6; + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = + size_align_r6 + (size_align - (size_align_r6 << 6) > 0); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = + SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_IOP2SPU; + return size; +} + +static u32 BlockTransRead(u8 *iopaddr, u32 size, int core, u16 mode) +{ + int state; + USE_IOP_MMIO_HWPORT(); + USE_SPU2_MMIO_HWPORT(); + + core &= 1; + g_BlockTransAddr[core] = iopaddr; + g_BlockTransBuff[core] = 0; + g_BlockTransSize[core] = size; + CpuSuspendIntr(&state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA; + CpuResumeIntr(state); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = ((mode & ~0xF0FF) << 1) + 0x400; + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_unk1ae = (mode & ~0xFFF) >> 11; + libsd_do_busyloop(3); + spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 4; + SetDmaRead(core); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)iopaddr; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16; +#pragma GCC diagnostic pop + ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = + (int)g_BlockTransSize[core] / 0x40 + ((int)g_BlockTransSize[core] % 0x40 > 0); + (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = SD_DMA_START | SD_DMA_CS; + return size; +} + +static int SifDmaBatch(void *ee_addr, void *iop_addr, int size) +{ + int dmat; + int i; + int dma_status; + SifDmaTransfer_t xferparam; + int state; + + xferparam.dest = ee_addr; + xferparam.src = iop_addr; + xferparam.size = size; + xferparam.attr = 0; + CpuSuspendIntr(&state); + dmat = sceSifSetDma(&xferparam, SIF_DMA_TO_EE); + CpuResumeIntr(state); + if ( !dmat ) + return -1; + for ( i = 0, dma_status = 0; i >= 0 && dma_status >= 0; i += 1 ) + { + CpuSuspendIntr(&state); + dma_status = sceSifDmaStat(dmat); + CpuResumeIntr(state); + } + return (i < 0) ? -1 : 0; +} + +int sceSdProcBatch(const sceSdBatch *batch, u32 *rets, u32 num) +{ + u32 cnt; + + for ( cnt = 0; cnt < num; cnt += 1 ) + { + u32 Param; + + Param = 0; + switch ( batch[cnt].func ) + { + case SD_BATCH_SETPARAM: + sceSdSetParam(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_SETSWITCH: + sceSdSetSwitch(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_SETADDR: + sceSdSetAddr(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_SETCORE: + sceSdSetCoreAttr(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_WRITEIOP: + *(u32 *)batch[cnt].value = batch[cnt].entry; + break; + case SD_BATCH_WRITEEE: + g_BatchData = batch[cnt].entry; + Param = SifDmaBatch((void *)batch[cnt].value, &g_BatchData, sizeof(g_BatchData)); + break; + case SD_BATCH_EERETURN: + Param = SifDmaBatch((void *)batch[cnt].value, rets, batch[cnt].entry); + break; + case SD_BATCH_GETPARAM: + Param = sceSdGetParam(batch[cnt].entry); + break; + case SD_BATCH_GETSWITCH: + Param = sceSdGetSwitch(batch[cnt].entry); + break; + case SD_BATCH_GETADDR: + Param = sceSdGetAddr(batch[cnt].entry); + break; + case SD_BATCH_GETCORE: + Param = sceSdGetCoreAttr(batch[cnt].entry); + break; + default: + return ~cnt; + } + if ( rets ) + rets[cnt] = Param; + } + return cnt; +} + +int sceSdProcBatchEx(const sceSdBatch *batch, u32 *rets, u32 num, u32 voice) +{ + u32 cnt; + int loop; + int i; + + loop = 0; + for ( cnt = 0; cnt < num; cnt += 1 ) + { + u32 Param; + + Param = 0; + switch ( batch[cnt].func ) + { + case SD_BATCH_SETPARAM: + if ( (batch[cnt].entry & 0x3E) == 0x3E ) + { + for ( i = 0; i < 24; i += 1 ) + { + if ( ((1 << i) & voice) ) + { + loop += 1; + sceSdSetParam((batch[cnt].entry & ~0x3E) | (i << 1), batch[cnt].value); + } + } + loop -= 1; + } + else + sceSdSetParam(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_SETSWITCH: + sceSdSetSwitch(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_SETADDR: + if ( (batch[cnt].entry & 0x7E) == 0x7E ) + { + for ( i = 0; i < 24; i += 1 ) + { + if ( ((1 << i) & voice) ) + { + loop += 1; + sceSdSetAddr((batch[cnt].entry & ~0x3E) | (i << 1), batch[cnt].value); + } + } + loop -= 1; + } + else + sceSdSetAddr(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_SETCORE: + sceSdSetCoreAttr(batch[cnt].entry, batch[cnt].value); + break; + case SD_BATCH_WRITEIOP: + *(u32 *)batch[cnt].value = batch[cnt].entry; + break; + case SD_BATCH_WRITEEE: + g_BatchData = batch[cnt].entry; + Param = SifDmaBatch((void *)batch[cnt].value, &g_BatchData, sizeof(g_BatchData)); + break; + case SD_BATCH_EERETURN: + Param = SifDmaBatch((void *)batch[cnt].value, rets, batch[cnt].entry); + break; + case SD_BATCH_GETPARAM: + if ( (batch[cnt].entry & 0x3E) == 0x3E ) + { + for ( i = 0; i < 24; i += 1 ) + { + if ( ((1 << i) & voice) ) + Param = sceSdGetParam((batch[cnt].entry & ~0x3E) | (i << 1)); + if ( rets ) + rets[loop] = Param; + loop += 1; + } + loop -= 1; + } + else + Param = sceSdGetParam(batch[cnt].entry); + break; + case SD_BATCH_GETSWITCH: + Param = sceSdGetSwitch(batch[cnt].entry); + break; + case SD_BATCH_GETADDR: + if ( (batch[cnt].entry & 0x7E) == 0x7E ) + { + for ( i = 0; i < 24; i += 1 ) + { + if ( ((1 << i) & voice) ) + { + Param = sceSdGetAddr((batch[cnt].entry & ~0x3E) | (i << 1)); + if ( rets ) + rets[loop] = Param; + loop += 1; + } + } + loop -= 1; + } + else + Param = sceSdGetAddr(batch[cnt].entry); + break; + case SD_BATCH_GETCORE: + Param = sceSdGetCoreAttr(batch[cnt].entry); + break; + default: + return ~cnt; + } + if ( rets ) + rets[loop] = Param; + loop += 1; + } + return loop; +} + +void sceSdSetParam(u16 entry, u16 value) +{ + // Determine the channel offset (entry & 0x80) + g_ParamRegList[((entry >> 8) & 0xFF)] + [((entry & 0x3E) << 2) + (((entry & 1) * (0x400 - 984 * (!!(entry & 0x80)))) >> 1)] = value; +} + +u16 sceSdGetParam(u16 entry) +{ + // Determine the channel offset (entry & 0x80) + return g_ParamRegList[((entry >> 8) & 0xFF)] + [((entry & 0x3E) << 2) + (((entry & 1) * (0x400 - 984 * (!!(entry & 0x80)))) >> 1)]; +} + +void sceSdSetSwitch(u16 entry, u32 value) +{ + vu16 *regptr; + + regptr = &g_ParamRegList[((entry >> 8) & 0xFF)][(entry & 1) << 9]; + regptr[0] = value; + regptr[1] = (value >> 16) & 0xFF; +} + +u32 sceSdGetSwitch(u16 entry) +{ + const vu16 *regptr; + + regptr = &g_ParamRegList[((entry >> 8) & 0xFF)][(entry & 1) << 9]; + return regptr[0] | (regptr[1] << 16); +} + +void sceSdSetAddr(u16 entry, u32 value) +{ + vu16 *reg1; + + reg1 = &g_ParamRegList[((entry >> 8) & 0xFF)][((entry & 1) << 9) + 3 * (entry & 0x3E)]; + reg1[0] = value >> 17; + if ( (entry & 0xFF00) != 0x1D00 ) + reg1[1] = (value >> 1) & ~7; +} + +u32 sceSdGetAddr(u16 entry) +{ + int retlo; + const vu16 *reg1; + int regmask; + int rethi; + + retlo = 0x1FFFF; + reg1 = &g_ParamRegList[((entry >> 8) & 0xFF)][((entry & 1) << 9) + 3 * (entry & 0x3E)]; + regmask = entry & 0xFF00; + rethi = reg1[0] << 17; + if ( regmask != 0x1D00 ) + { + retlo = reg1[1] << 1; + if ( regmask == 0x2100 || regmask == 0x2200 ) + { + rethi = reg1[0] << 17; + retlo = reg1[1] << 1; + } + } + return rethi | retlo; +} + +u16 sceSdNote2Pitch(u16 center_note, u16 center_fine, u16 note, s16 fine) +{ + int _fine; + s16 _note; + int _fine2; + int offset2; + int val2; + s16 val; + s16 offset1; + int retval; + + _fine = fine + center_fine; + _fine2 = _fine / 0x80; + _note = note + _fine2 - center_note; + offset2 = _fine % 0x80; + val2 = ((_note / 6) >> 1) - (_note < 0); + offset1 = _note - 12 * val2; + val = val2 - 2; + if ( (offset1 < 0) || (!offset1 && offset2 < 0) ) + { + offset1 += 12; + val -= 1; + } + if ( offset2 < 0 ) + { + offset2 += (_fine2 + 1) << 7; + offset1 -= 1; + offset1 += _fine2; + } + retval = (g_NotePitchTable[offset1] * g_NotePitchTable[offset2 + 12]) >> 16; + return (val < 0) ? (u32)(retval + (1 << (-val - 1))) >> -val : (u32)retval; +} + +u16 sceSdPitch2Note(u16 center_note, u16 center_fine, u16 pitch) +{ + int bit; + int i1; + s16 val; + int i2; + int i5; + + bit = 0; + pitch = (pitch > 0x3FFF) ? 0x3FFF : pitch; + for ( i1 = 0; i1 < 14; i1 += 1 ) + { + if ( ((pitch >> i1) & 1) ) + bit = i1; + } + val = pitch << (15 - bit); + for ( i2 = 11; val < g_NotePitchTable[i2] && i2 > 0; i2 -= 1 ) + { + } + if ( !g_NotePitchTable[i2] ) + __builtin_trap(); + val <<= 15; + val /= g_NotePitchTable[i2]; + for ( i5 = 127; val < g_NotePitchTable[i5 + 12] && i5 > 0; i5 -= 1 ) + { + } + return (((center_fine + i5 + 1) & 0x7E) + + ((i2 + center_note + 12 * (bit - 12) + ((u16)(center_fine + i5 + 1) >> 7)) << 8)) + & ~1; +} + +static int SetSpdifMode(int val) +{ + u16 spdif_out_new; + u16 spdif_mode_new; + USE_SPU2_MMIO_HWPORT(); + + spdif_out_new = spu2_mmio_hwport->m_u.m_e.m_spdif_out & ~0x1A8; + spdif_mode_new = spu2_mmio_hwport->m_u.m_e.m_spdif_mode & ~0xBF06; + switch ( val & 0xF ) + { + case 0: + spdif_out_new |= 0x20; + break; + case 1: + spdif_out_new |= 0x100; + spdif_mode_new |= 2; + break; + case 2: + break; + case 3: + spdif_out_new |= 0x100; + break; + default: + return -100; + } + spdif_mode_new |= (val & 0x80) ? 0x8000 : 0; + switch ( val & 0xF00 ) + { + case 0x400: + spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0; + spdif_mode_new |= 0x100; + break; + case 0x800: + spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200; + spdif_mode_new |= 0x1900; + break; + default: + spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200; + spdif_mode_new |= 0x900; + break; + } + spu2_mmio_hwport->m_u.m_e.m_spdif_out = spdif_out_new; + spu2_mmio_hwport->m_u.m_e.m_spdif_mode = spdif_mode_new; + g_SpdifSettings = val; + return 0; +} + +void sceSdSetCoreAttr(u16 entry, u16 value) +{ + u16 setting_tmp; + u16 param_tmp; + int state; + + switch ( entry & ~0xFFFF0001 ) + { + case SD_CORE_SPDIF_MODE: + SetSpdifMode(value); + break; + case SD_CORE_NOISE_CLK: + CpuSuspendIntr(&state); + param_tmp = (entry & 1) | 0x2300; + sceSdSetParam(param_tmp, (sceSdGetParam(param_tmp) & ~0x3F00) | ((value & 0x3F) << 8)); + CpuResumeIntr(state); + break; + default: + // Unofficial: inline the following + setting_tmp = g_CoreAttrShifts[((entry & 0xE) >> 1) - 1]; + CpuSuspendIntr(&state); + param_tmp = (entry & 1) | 0x2300; + sceSdSetParam(param_tmp, (sceSdGetParam(param_tmp) & ~(1 << setting_tmp)) | ((value & 1) << setting_tmp)); + CpuResumeIntr(state); + break; + } +} + +u16 sceSdGetCoreAttr(u16 entry) +{ + int core; + USE_SPU2_MMIO_HWPORT(); + + core = entry & 1; + switch ( entry & 0xE ) + { + case SD_CORE_EFFECT_ENABLE: + return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1; + case SD_CORE_IRQ_ENABLE: + return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 6) & 1; + case SD_CORE_MUTE_ENABLE: + return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 14) & 1; + case SD_CORE_NOISE_CLK: + return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 8) & 0x3F; + case SD_CORE_SPDIF_MODE: + return g_SpdifSettings & 0xFFFF; + default: + return 0; + } +} + +SdIntrCallback sceSdSetTransCallback(s32 core, SdIntrCallback cb) +{ + SdIntrCallback oldtmp; + + // Unofficial: restrict core + core &= 1; + oldtmp = g_TransIntrCallbacks[core]; + g_TransIntrCallbacks[core] = cb; + return oldtmp; +} + +sceSdTransIntrHandler sceSdSetTransIntrHandler(int channel, sceSdTransIntrHandler func, void *arg) +{ + sceSdTransIntrHandler oldtmp; + int core; + + // Unofficial: restrict core + core = channel & 1; + oldtmp = g_TransIntrHandlers[core]; + g_TransIntrHandlers[core] = func; + g_TransIntrData[core].m_data = arg; + return oldtmp; +} + +void *sceSdGetTransIntrHandlerArgument(int arg) +{ + return g_TransIntrData[arg].m_data; +} + +SdIntrCallback sceSdSetIRQCallback(SdIntrCallback cb) +{ + SdIntrCallback oldtmp; + + oldtmp = g_Spu2IrqCallback; + g_Spu2IrqCallback = cb; + return oldtmp; +} + +sceSdSpu2IntrHandler sceSdSetSpu2IntrHandler(sceSdSpu2IntrHandler func, void *arg) +{ + sceSdSpu2IntrHandler oldtmp; + + oldtmp = g_Spu2IntrHandler; + g_Spu2IntrHandler = func; + g_Spu2IntrHandlerData = arg; + return oldtmp; +} + +void *sceSdGetSpu2IntrHandlerArgument() +{ + return g_Spu2IntrHandlerData; +} + +static int Spu2Interrupt(void *data) +{ + int val; + USE_SPU2_MMIO_HWPORT(); + + (void)data; + if ( !g_Spu2IntrHandler && !g_Spu2IrqCallback ) + return 1; + while ( (val = (spu2_mmio_hwport->m_u.m_e.m_spdif_irqinfo & 0xC) >> 2) ) + { + int i; + + for ( i = 0; i < 2; i += 1 ) + if ( val & (1 << i) ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr &= ~0x40; + if ( g_Spu2IntrHandler ) + g_Spu2IntrHandler(val, g_Spu2IntrHandlerData); + else if ( g_Spu2IrqCallback ) + g_Spu2IrqCallback(0); + } + return 1; +} + +static int InitVoices(void) +{ + int i; + int j; + USE_SPU2_MMIO_HWPORT(); + + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr &= ~SD_CORE_DMA; + // Set Start Address of data to transfer. + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_tsa.m_pair[0] = 0x0000; + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_tsa.m_pair[1] = 0x5000 >> 1; + // Fill with data. + // First 16 bytes are reserved. + for ( i = 0; i < (int)(sizeof(g_VoiceDataInit) / sizeof(g_VoiceDataInit[0])); i += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_xferdata = g_VoiceDataInit[i]; + + // Set Transfer mode to IO + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr = + (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_IO; + // Wait for transfer to complete; + for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_statx & SD_IO_IN_PROCESS) && i <= 0x1000000; i += 1 ) + libsd_do_busyloop(1); + // Reset DMA settings + spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr &= ~SD_CORE_DMA; + // Unofficial: rerolled + // Init voices + for ( i = 0; i < 24; i += 1 ) + { + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_voll = 0; + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_volr = 0; + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_pitch = 0x3FFF; + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_adsr1 = 0; + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_adsr2 = 0; + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_address[i].m_ssa.m_pair[0] = 0; + // Top address of waveform data + for ( j = 0; j < 2; j += 1 ) + spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_address[i].m_ssa.m_pair[1] = 0x5000 >> 1; + } + // Unofficial: rerolled + // Set all voices to ON + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_kon.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_kon.m_pair[1] = 0xFF; + } + // There is no guarantee that voices will be turn on at once. + // So we wait to make sure. + libsd_do_busyloop(3); + // Unofficial: rerolled + // Set all voices to OFF + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_koff.m_pair[0] = 0xFFFF; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_koff.m_pair[1] = 0xFF; + } + // There is no guarantee that voices will be turn off at once. + // So we wait to make sure. + libsd_do_busyloop(3); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_endx.m_pair[1] = 0; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_endx.m_pair[0] = 0; + } + return 0; +} + +static int Reset(int flag) +{ + iop_event_t efparam; + int intrstate; + int i; + USE_SPU2_MMIO_HWPORT(); + + DisableIntr(IOP_IRQ_DMA_SPU, &intrstate); + DisableIntr(IOP_IRQ_DMA_SPU2, &intrstate); + DisableIntr(IOP_IRQ_SPU, &intrstate); + ReleaseIntrHandler(IOP_IRQ_DMA_SPU); + ReleaseIntrHandler(IOP_IRQ_DMA_SPU2); + ReleaseIntrHandler(IOP_IRQ_SPU); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + g_VoiceTransStatus[i] = 0; + g_VoiceTransIoMode[i] = 1; + g_VoiceTransCompleteBool[i] = 0; + g_TransIntrHandlers[i] = 0; + g_CleanHandlers[i] = 0; + g_TransIntrData[i].m_mode = i; + g_TransIntrData[i].m_data = 0; + g_BlockHandlerIntrData[i].m_cb = 0; + g_BlockHandlerIntrData[i].m_userdata = 0; + g_TransIntrCallbacks[i] = 0; + } + g_Spu2IntrHandler = 0; + g_Spu2IntrHandlerData = 0; + g_Spu2IrqCallback = 0; + if ( !(flag & 0xF) ) + { + bzero(g_EffectAttr, sizeof(g_EffectAttr)); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + g_EffectAddr[i] = 0x1DFFF0 + (0x20000 * i); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_esa.m_pair[0] = 0x000E + i; + spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_esa.m_pair[1] = 0xFFF8; + } + } + efparam.attr = EA_MULTI; + efparam.bits = 1; + efparam.option = 0; + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + { + if ( g_VoiceTransCompleteEf[i] <= 0 ) + g_VoiceTransCompleteEf[i] = CreateEventFlag(&efparam); + else + { + if ( QueryIntrContext() ) + iSetEventFlag(g_VoiceTransCompleteEf[i], 1); + else + SetEventFlag(g_VoiceTransCompleteEf[i], 1); + } + } + return (g_VoiceTransCompleteEf[0] <= 0 || g_VoiceTransCompleteEf[1] <= 0) ? -301 : 0; +} + +static void reset_vars(void) +{ + int i; + + g_vars_inited = 0; + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + g_VoiceTransCompleteEf[i] = 0; +} + +int sceSdInit(int flag) +{ + int resetres; + + InitSpu2(); + if ( !(flag & 0xF) ) + InitSpdif(); + resetres = Reset(flag); + InitVoices(); + InitCoreVolume(flag & 0xF); + EnableIntr(IOP_IRQ_DMA_SPU); + EnableIntr(IOP_IRQ_DMA_SPU2); + EnableIntr(IOP_IRQ_SPU); + RegisterIntrHandler(IOP_IRQ_DMA_SPU, 1, (int (*)(void *))TransInterrupt, &g_TransIntrData[0]); + RegisterIntrHandler(IOP_IRQ_DMA_SPU2, 1, (int (*)(void *))TransInterrupt, &g_TransIntrData[1]); + RegisterIntrHandler(IOP_IRQ_SPU, 1, (int (*)(void *))Spu2Interrupt, g_Spu2IntrHandlerData); + g_vars_inited = 1; + return resetres; +} + +int sceSdQuit() +{ + int intrstate; + int i; + + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + DmaStartStop((i << 4) | 0xA, 0, 0); + // Unofficial: rerolled + for ( i = 0; i < 2; i += 1 ) + if ( g_VoiceTransCompleteEf[i] > 0 ) + DeleteEventFlag(g_VoiceTransCompleteEf[i]); + DisableIntr(IOP_IRQ_DMA_SPU2, &intrstate); + DisableIntr(IOP_IRQ_DMA_SPU, &intrstate); + DisableIntr(IOP_IRQ_SPU, &intrstate); + ReleaseIntrHandler(IOP_IRQ_DMA_SPU2); + ReleaseIntrHandler(IOP_IRQ_DMA_SPU); + ReleaseIntrHandler(IOP_IRQ_SPU); + return 0; +} diff --git a/iop/sound/libsd/src/voice.c b/iop/sound/libsd/src/voice.c deleted file mode 100644 index 23ea28f3394..00000000000 --- a/iop/sound/libsd/src/voice.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2004 TyRaNiD - * Copyright (c) 2004,2007,2008 Lukasz Bruun - * - * See the file LICENSE included with this distribution for licensing terms. - */ - -/** - * @file - * Part of the IOP Sound Driver - */ - -#include "types.h" -#include "irx.h" -#include "sifman.h" -#include "freesd.h" -#include "spu2regs.h" - - -volatile u16 VoiceTransComplete[2]; -u32 VoiceTransStatus[2]; -u32 VoiceTransIoMode[2]; - -extern void SetDmaWrite(s32 chan); -extern void SetDmaRead(s32 chan); -extern IntrData TransIntrData[2]; -extern void DmaStop(u32 core); - -s32 VoiceTransDma(s16 chan, u16 mode, u8 *iop_addr, u32 *spu_addr, u32 size) -{ - u32 direction; - - if(U16_REGISTER_READ(SD_CORE_ATTR(chan)) & SD_DMA_IN_PROCESS) - return -1; - - if(U32_REGISTER_READ(SD_DMA_CHCR(chan)) & SD_DMA_START) - return -1; - - U16_REGISTER_WRITE(SD_A_TSA_HI(chan), (u32)spu_addr >> 17); - U16_REGISTER_WRITE(SD_A_TSA_LO(chan), (u32)spu_addr >> 1); - - if(mode == SD_TRANS_WRITE) - { - TransIntrData[chan].mode = chan; - direction = SD_DMA_DIR_IOP2SPU; - U16_REGISTER_WRITE(SD_CORE_ATTR(chan), (U16_REGISTER_READ(SD_CORE_ATTR(chan)) & ~SD_CORE_DMA) | SD_DMA_WRITE); - SetDmaWrite(chan); - } - else - { - if(mode == SD_TRANS_READ) - { - TransIntrData[chan].mode = (chan << 2) | 0x200; - direction = SD_DMA_DIR_SPU2IOP; - U16_REGISTER_WRITE(SD_CORE_ATTR(chan), (U16_REGISTER_READ(SD_CORE_ATTR(chan)) & ~SD_CORE_DMA) | SD_DMA_READ); - SetDmaRead(chan); - } - else - { - return -1; - } - } - - U32_REGISTER_WRITE(SD_DMA_ADDR(chan), (u32)iop_addr); - U32_REGISTER_WRITE(SD_DMA_MSIZE(chan), (((size+63)/64) << 16) | 0x10); - U32_REGISTER_WRITE(SD_DMA_CHCR(chan), SD_DMA_CS | SD_DMA_START | direction); - - return size; -} - -s32 VoiceTrans_Write_IOMode(u32 iopaddr, u32 spu_addr, s32 size, s16 chan) -{ - if(U16_REGISTER_READ(SD_CORE_ATTR(chan)) & SD_DMA_IN_PROCESS) - return -1; - - if(U32_REGISTER_READ(SD_DMA_CHCR(chan)) & SD_DMA_START) - return -1; - - U16_REGISTER_WRITE(SD_A_TSA_HI(chan), (u16)spu_addr >> 17); - U16_REGISTER_WRITE(SD_A_TSA_LO(chan), (u16)spu_addr >> 1); - - TransIntrData[chan].mode = chan; - - if(size) - { - s32 loop, count; - volatile u16* iop_mem = (volatile u16 *) iopaddr; - - while(size > 0) - { - volatile u16 *statx; - - if(size > 64) - count = 64; - else - count = size; - - if(count > 0) - { - for(loop = 0; loop < count; loop += 2) - U16_REGISTER_WRITE(SD_A_STD(chan), *iop_mem++); - } - - // Set Transfer mode to IO - U16_REGISTER_WRITE(SD_CORE_ATTR(chan), (U16_REGISTER_READ(SD_CORE_ATTR(chan)) & ~SD_CORE_DMA) | SD_DMA_IO); - - statx = U16_REGISTER(0x344 + (chan << 10)); - - // Wait for transfer to complete; - while(U16_REGISTER_READ(statx) & SD_IO_IN_PROCESS); - - size -= count; - } - } - - // Reset DMA settings - U16_REGISTER_WRITEAND(SD_CORE_ATTR(chan), ~SD_CORE_DMA); - - return 0; -} - -int sceSdVoiceTrans(s16 chan, u16 mode, u8 *iopaddr, u32 *spuaddr, u32 size) -{ - s32 res = size; - - chan &= 1; - - if(mode & SD_TRANS_MODE_IO) - VoiceTransIoMode[chan] = 1; - else - VoiceTransIoMode[chan] = 0; - - if(VoiceTransIoMode[chan] == 0) - { - res = VoiceTransDma(chan, mode & 3, iopaddr, spuaddr, size); - } - else - { - if((mode & 3) == SD_TRANS_WRITE) - { - res = VoiceTrans_Write_IOMode( (u32)iopaddr, (u32)spuaddr, size, chan); - } - } - - VoiceTransStatus[chan] = 0; - - return res; -} - -u32 sceSdVoiceTransStatus(s16 chan, s16 flag) -{ - chan &= 1; - flag &= 1; - - if((VoiceTransIoMode[chan] == 1) || (VoiceTransStatus[chan] == 1)) - return 1; - - if(flag) - { - while(!VoiceTransComplete[chan]); - VoiceTransStatus[chan] = 1; - VoiceTransComplete[chan] = 0; - - return 1; - } - else - { - if(VoiceTransComplete[chan] == 0) return 0; - VoiceTransStatus[chan] = 1; - VoiceTransComplete[chan] = 0; - } - - return 0; -}