16#include <irx_imports.h>
23IRX_ID(
"Sound_Device_Library", 3, 3);
26#define SD_DMA_CS (1 << 9)
27#define SD_DMA_START (1 << 24)
28#define SD_DMA_DIR_SPU2IOP 0
29#define SD_DMA_DIR_IOP2SPU 1
78 sceSdBlockTransHandler m_cb;
93typedef int (*SdCleanHandler)(
int core);
95static int GetEEA(
int core);
96static void InitSpu2_Inner(
void);
97static void libsd_do_busyloop(
int count);
98static u32 DmaStartStop(
int mainarg,
void *vararg2, u32 vararg3);
99static u32 VoiceTrans_Write_IOMode(
const u16 *iopaddr, u32 size,
int core);
100static u32 BlockTransWriteFrom(u8 *iopaddr, u32 size,
int core,
int mode, u8 *startaddr);
101static u32 BlockTransRead(u8 *iopaddr, u32 size,
int core, u16 mode);
102static void reset_vars(
void);
105static vu16 *
const g_ParamRegList[] =
154static const u32 g_EffectSizes[] =
530static const u16 g_NotePitchTable[] =
674static const u16 g_CoreAttrShifts[] =
681static const u16 g_VoiceDataInit[] =
695static const u32 g_ClearEffectData[256]
__attribute__((__aligned__(16)));
697static int g_VoiceTransStatus[2];
699static int g_VoiceTransIoMode[2];
701static int g_SpdifSettings;
705static int g_VoiceTransCompleteBool[2];
707static int g_VoiceTransCompleteEf[2];
709static int g_vars_inited;
711static SdIntrCallback g_Spu2IrqCallback;
713static sceSdSpu2IntrHandler g_Spu2IntrHandler;
715static void *g_Spu2IntrHandlerData;
717static sceSdTransIntrHandler g_TransIntrHandlers[2];
721static SdCleanHandler g_CleanHandlers[2];
724static u32 g_CleanRegionMax[2];
725static u32 g_CleanRegionCur[2];
727static u32 g_BlockTransBuff[2];
728static u8 *g_BlockTransAddr[2];
729static u32 g_BlockTransSize[2];
731static SdIntrCallback g_TransIntrCallbacks[2];
732static u32 g_EffectAddr[2];
734int _start(
int ac,
char **av)
742 regres = RegisterLibraryEntries(&_exp_libsd);
745 return MODULE_NO_RESIDENT_END;
748 return MODULE_RESIDENT_END;
755 pair->m_pair[0] = (val >> 16) & 0xFFFF;
756 pair->m_pair[1] = val;
759static void SetEffectData(
int core,
const struct mode_data_struct *mode_data)
763 USE_SPU2_MMIO_HWPORT();
765 mode_flags = mode_data->m_mode_flags;
767 mode_flags = 0xFFFFFFFF;
768 if ( (mode_flags & 1) )
769 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf1_size, mode_data->m_d_apf1_size);
770 if ( (mode_flags & 2) )
771 SetEffectRegisterPair(&spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_apf2_size, mode_data->m_d_apf2_size);
772 if ( (mode_flags & 4) )
773 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_iir_vol = mode_data->m_d_iir_vol;
774 if ( (mode_flags & 8) )
775 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb1_vol = mode_data->m_d_comb1_vol;
776 if ( (mode_flags & 0x10) )
777 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb2_vol = mode_data->m_d_comb2_vol;
778 if ( (mode_flags & 0x20) )
779 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb3_vol = mode_data->m_d_comb3_vol;
780 if ( (mode_flags & 0x40) )
781 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_comb4_vol = mode_data->m_d_comb4_vol;
782 if ( (mode_flags & 0x80) )
783 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_wall_vol = mode_data->m_d_wall_vol;
784 if ( (mode_flags & 0x100) )
785 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_apf1_vol = mode_data->m_d_apf1_vol;
786 if ( (mode_flags & 0x200) )
787 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_apf2_vol = mode_data->m_d_apf2_vol;
788 if ( (mode_flags & 0x400) )
789 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);
790 if ( (mode_flags & 0x800) )
791 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);
792 if ( (mode_flags & 0x1000) )
793 SetEffectRegisterPair(
794 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb1_l_src, mode_data->m_d_comb1_l_src);
795 if ( (mode_flags & 0x2000) )
796 SetEffectRegisterPair(
797 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb1_r_src, mode_data->m_d_comb1_r_src);
798 if ( (mode_flags & 0x4000) )
799 SetEffectRegisterPair(
800 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb2_l_src, mode_data->m_d_comb2_l_src);
801 if ( (mode_flags & 0x8000) )
802 SetEffectRegisterPair(
803 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb2_r_src, mode_data->m_d_comb2_r_src);
804 if ( (mode_flags & 0x10000) )
805 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);
806 if ( (mode_flags & 0x20000) )
807 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);
808 if ( (mode_flags & 0x40000) )
809 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);
810 if ( (mode_flags & 0x80000) )
811 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);
812 if ( (mode_flags & 0x100000) )
813 SetEffectRegisterPair(
814 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb3_l_src, mode_data->m_d_comb3_l_src);
815 if ( (mode_flags & 0x200000) )
816 SetEffectRegisterPair(
817 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb3_r_src, mode_data->m_d_comb3_r_src);
818 if ( (mode_flags & 0x400000) )
819 SetEffectRegisterPair(
820 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb4_l_src, mode_data->m_d_comb4_l_src);
821 if ( (mode_flags & 0x800000) )
822 SetEffectRegisterPair(
823 &spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_comb4_r_src, mode_data->m_d_comb4_r_src);
824 if ( (mode_flags & 0x1000000) )
825 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);
826 if ( (mode_flags & 0x2000000) )
827 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);
828 if ( (mode_flags & 0x4000000) )
829 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);
830 if ( (mode_flags & 0x8000000) )
831 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);
832 if ( (mode_flags & 0x10000000) )
833 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);
834 if ( (mode_flags & 0x20000000) )
835 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);
836 if ( (mode_flags & 0x40000000) )
837 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_in_coef_l = mode_data->m_d_in_coef_l;
838 if ( (mode_flags & 0x80000000) )
839 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_in_coef_r = mode_data->m_d_in_coef_r;
842int sceSdClearEffectWorkArea(
int core,
int channel,
int effect_mode)
848 SdIntrCallback callback_tmp;
849 sceSdTransIntrHandler handler_tmp;
852 if ( effect_mode > SD_EFFECT_MODE_PIPE )
858 if ( DmaStartStop((channel << 4) | 4, 0, 0) )
860 if ( g_VoiceTransIoMode[channel] != 1 )
865 effect_size = g_EffectSizes[effect_mode] << 3;
866 effect_addr = (GetEEA(core) - (effect_size - 1)) >> 1;
867 if ( (effect_size & 0x3F) )
869 effect_size &= 0x3FFFFFF;
870 aligned_addr = (GetEEA(core) - (effect_size - 1)) >> 1;
873 handler_tmp = g_TransIntrHandlers[channel];
874 callback_tmp = g_TransIntrCallbacks[channel];
875 g_TransIntrHandlers[channel] = 0;
876 g_TransIntrCallbacks[channel] = 0;
880 xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)(effect_addr << 1), 0x40);
882 xferres = sceSdVoiceTransStatus(channel, 1);
883 effect_addr = aligned_addr;
889 for ( i = 0;; i += 1 )
893 size = (effect_size <= 0x400) ? effect_size : 0x400;
894 xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)((effect_addr + (i << 9)) << 1), size);
898 xferres = sceSdVoiceTransStatus(channel, 1);
901 if ( effect_size <= 0x400 )
906 effect_size -= 0x400;
910 g_TransIntrHandlers[channel] = handler_tmp;
911 g_TransIntrCallbacks[channel] = callback_tmp;
915static int CleanHandler(
int core)
919 g_CleanRegionCur[core] += 1;
920 if ( (
int)g_CleanRegionCur[core] >= (
int)(g_CleanRegionMax[core] - 1) )
921 g_CleanHandlers[core] = 0;
922 DmaStartStop((core << 4) | 2, g_CleanRegionBuffer[core].m_elements[g_CleanRegionCur[core]].m_spuaddr, 0);
924 (core << 4) | 6, (u8 *)g_ClearEffectData, g_CleanRegionBuffer[core].m_elements[g_CleanRegionCur[core]].m_size);
928int sceSdCleanEffectWorkArea(
int core,
int channel,
int effect_mode)
936 if ( effect_mode > SD_EFFECT_MODE_PIPE )
942 if ( DmaStartStop((channel << 4) | 4, 0, 0) )
944 if ( g_VoiceTransIoMode[channel] != 1 )
946 effect_size = g_EffectSizes[effect_mode] << 3;
947 effect_addr = GetEEA(core) - (effect_size - 1);
948 if ( (effect_size & 0x3F) )
950 effect_size &= 0x3FFFFFF;
951 xferres = sceSdVoiceTrans(channel, 8, (u8 *)g_ClearEffectData, (u32 *)effect_addr, 0x40);
954 effect_addr = GetEEA(core) - (effect_size - 1);
956 effect_addr += 0x100;
957 effect_size -= 0x400;
958 for ( i = 0;; i += 1 )
960 g_CleanRegionBuffer[channel].m_elements[i].m_spuaddr = (u32 *)effect_addr;
961 g_CleanRegionBuffer[channel].m_elements[i].m_size = (effect_size <= 0x400) ? effect_size : 0x400;
962 if ( effect_size <= 0x400 )
964 effect_addr += 0x100;
965 effect_size -= 0x400;
967 g_CleanRegionMax[channel] = i + 1;
968 g_CleanHandlers[channel] = CleanHandler;
969 g_CleanRegionCur[channel] = 0;
970 xferres = sceSdVoiceTrans(channel, 0, (u8 *)g_ClearEffectData, (u32 *)effect_addr, 0x400);
978 USE_SPU2_MMIO_HWPORT();
981 attr->mode = g_EffectAttr[core].mode;
982 attr->delay = g_EffectAttr[core].delay;
983 attr->feedback = g_EffectAttr[core].feedback;
984 attr->depth_L = spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll;
985 attr->depth_R = spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr;
998 USE_SPU2_MMIO_HWPORT();
1000 mode_data.m_mode_flags = 0;
1002 clearram = !!(mode & SD_EFFECT_MODE_CLEAR);
1003 effect_mode = clearram ? g_EffectAttr[core].mode : 0;
1004 channel = clearram && !!(mode & 0x200);
1007 if ( mode > SD_EFFECT_MODE_PIPE )
1009 g_EffectAttr[core].mode = mode;
1010 g_EffectAddr[core] = GetEEA(core) - ((g_EffectSizes[mode] << 3) - 1);
1012 memcpy(&mode_data, &g_EffectParams[mode],
sizeof(mode_data));
1015 case SD_EFFECT_MODE_ECHO:
1016 g_EffectAttr[core].feedback = 0x80;
1017 g_EffectAttr[core].delay = 0x80;
1019 case SD_EFFECT_MODE_DELAY:
1020 g_EffectAttr[core].feedback = 0;
1021 g_EffectAttr[core].delay = 0x80;
1024 g_EffectAttr[core].feedback = 0;
1025 g_EffectAttr[core].delay = 0;
1028 if ( mode >= SD_EFFECT_MODE_ECHO && mode <= SD_EFFECT_MODE_DELAY )
1032 delay = attr->delay;
1033 g_EffectAttr[core].delay = delay;
1034 g_EffectAttr[core].feedback = attr->feedback;
1037 mode_data.m_d_same_l_dst = (s16)((u16)delay << 6) - (s16)mode_data.m_d_apf1_size;
1040 mode_data.m_d_same_l_src = delay + mode_data.m_d_same_r_src;
1041 mode_data.m_d_same_r_dst = delay - mode_data.m_d_apf2_size;
1042 mode_data.m_d_comb1_l_src = delay + mode_data.m_d_comb1_r_src;
1043 mode_data.m_d_apf1_l_dst = delay + mode_data.m_d_apf2_l_dst;
1044 mode_data.m_d_apf1_r_dst = delay + mode_data.m_d_apf2_r_dst;
1045 mode_data.m_d_wall_vol = 0x102 * g_EffectAttr[core].feedback;
1048 effects_enabled = (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1;
1049 if ( effects_enabled )
1052 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_ENABLE_EFFECTS;
1056 retval = (effects_enabled && clearram) ? sceSdClearEffectWorkArea(core, channel, effect_mode) : 0;
1060 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = attr->depth_L;
1061 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = attr->depth_R;
1062 SetEffectData(core, &mode_data);
1064 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[0] = g_EffectAddr[core] >> 17;
1065 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[1] = g_EffectAddr[core] >> 1;
1066 retval = clearram ? sceSdClearEffectWorkArea(core, channel, mode) : 0;
1069 if ( effects_enabled )
1072 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_ENABLE_EFFECTS;
1078static int GetEEA(
int core)
1080 USE_SPU2_MMIO_HWPORT();
1082 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_eea << 17) | 0x1FFFF;
1090 int effects_enabled;
1093 USE_SPU2_MMIO_HWPORT();
1095 mode_data.m_mode_flags = 0;
1097 clearram = !!(mode & 0x100);
1098 channel = clearram && !!(mode & 0x200);
1100 if ( mode > SD_EFFECT_MODE_PIPE )
1102 g_EffectAttr[core].mode = mode;
1103 g_EffectAttr[core].delay = 0;
1104 g_EffectAttr[core].feedback = 0;
1105 g_EffectAddr[core] = GetEEA(core) - ((g_EffectSizes[mode] << 3) - 1);
1107 memcpy(&mode_data, &g_EffectParams[mode],
sizeof(mode_data));
1108 effects_enabled = (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1;
1109 if ( effects_enabled )
1112 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_ENABLE_EFFECTS;
1115 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = 0;
1116 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = 0;
1117 SetEffectData(core, &mode_data);
1118 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[0] = g_EffectAddr[core] >> 17;
1119 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_esa.m_pair[1] = g_EffectAddr[core] >> 1;
1120 if ( effects_enabled )
1123 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_ENABLE_EFFECTS;
1126 return clearram ? sceSdCleanEffectWorkArea(core, channel, mode) : 0;
1133 USE_SPU2_MMIO_HWPORT();
1137 if ( mode > SD_EFFECT_MODE_PIPE )
1139 if ( g_EffectAttr[core].mode != mode )
1141 if ( mode >= SD_EFFECT_MODE_ECHO && mode <= SD_EFFECT_MODE_DELAY )
1146 memcpy(&mode_data, &g_EffectParams[mode],
sizeof(mode_data));
1147 mode_data.m_mode_flags = 0xC011C80;
1148 delay = attr->delay;
1149 g_EffectAttr[core].delay = delay;
1150 g_EffectAttr[core].feedback = attr->feedback;
1153 mode_data.m_d_same_l_dst = (s16)(((u16)delay << 6) - (s16)mode_data.m_d_apf1_size);
1156 mode_data.m_d_same_l_src = delay + mode_data.m_d_same_r_src;
1157 mode_data.m_d_same_r_dst = delay - mode_data.m_d_apf2_size;
1158 mode_data.m_d_comb1_l_src = delay + mode_data.m_d_comb1_r_src;
1159 mode_data.m_d_apf1_l_dst = delay + mode_data.m_d_apf2_l_dst;
1160 mode_data.m_d_apf1_r_dst = delay + mode_data.m_d_apf2_r_dst;
1161 mode_data.m_d_wall_vol = 0x102 * g_EffectAttr[core].feedback;
1162 SetEffectData(core, &mode_data);
1164 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evoll = attr->depth_L;
1165 spu2_mmio_hwport->m_u.m_e.m_different_regs[core].m_evolr = attr->depth_R;
1169static void InitSpu2_Inner(
void)
1172 USE_IOP_MMIO_HWPORT();
1174 iop_mmio_hwport->ssbus2.ind_4_address = 0xBF900000;
1175 iop_mmio_hwport->ssbus2.ind_9_address = 0xBF900800;
1177 iop_mmio_hwport->dmac1.dpcr1 |= 0x80000;
1178 iop_mmio_hwport->dmac2.dpcr2 |= 8;
1180 iop_mmio_hwport->ssbus1.ind_4_delay = 0x200B31E1;
1181 iop_mmio_hwport->ssbus2.ind_9_delay = 0x200B31E1;
1184static void InitSpu2(
void)
1186 USE_SPU2_MMIO_HWPORT();
1189 spu2_mmio_hwport->m_u.m_e.m_spdif_mode = 0x0900;
1190 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200;
1191 spu2_mmio_hwport->m_u.m_e.m_unknown7ca = 8;
1195static void InitCoreVolume(
int flag)
1198 USE_SPU2_MMIO_HWPORT();
1200 spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0xC032;
1202 for ( i = 0; i < 2; i += 1 )
1203 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr =
1204 (flag ? SD_ENABLE_EFFECTS : 0) | (i ? SD_ENABLE_EX_INPUT : 0) | SD_MUTE | SD_SPU2_ON;
1207 for ( i = 0; i < 2; i += 1 )
1209 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixl.m_pair[0] = 0xFFFF;
1210 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixl.m_pair[1] = 0xFF;
1211 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixel.m_pair[0] = 0xFFFF;
1212 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixel.m_pair[1] = 0x00FF;
1213 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixr.m_pair[0] = 0xFFFF;
1214 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixr.m_pair[1] = 0x00FF;
1215 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixer.m_pair[0] = 0xFFFF;
1216 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_vmixer.m_pair[1] = 0x00FF;
1217 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_mmix = 0xFF0 + (i * 0xC);
1222 for ( i = 0; i < 2; i += 1 )
1224 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0;
1225 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0;
1226 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_evoll = 0;
1227 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_evolr = 0;
1231 for ( i = 0; i < 2; i += 1 )
1232 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_eea = 14 + i;
1235 for ( i = 0; i < 2; i += 1 )
1239 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_avoll = i ? 0x7FFF : 0;
1240 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_avolr = i ? 0x7FFF : 0;
1241 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_bvoll = 0;
1242 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_bvolr = 0;
1246int sceSdVoiceTrans(s16 chan, u16 mode, u8 *iopaddr, u32 *spuaddr, u32 size)
1253 if ( DmaStartStop((core << 4) | 4, 0, 0) )
1255 if ( g_VoiceTransIoMode[core] != 1 )
1260 g_TransIntrData[core].m_mode = core | 0x900;
1261 g_BlockHandlerIntrData[core].m_cb = 0;
1262 g_BlockHandlerIntrData[core].m_userdata = 0;
1263 g_VoiceTransStatus[core] = 0;
1264 DmaStartStop((core << 4) | 2, spuaddr, 0);
1266 iClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1268 ClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1269 g_VoiceTransIoMode[core] = 0;
1270 return DmaStartStop((core << 4) | 5, iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0));
1271 case SD_TRANS_WRITE:
1272 g_TransIntrData[core].m_mode = core | 0x500;
1273 g_BlockHandlerIntrData[core].m_cb = 0;
1274 g_BlockHandlerIntrData[core].m_userdata = 0;
1275 DmaStartStop((core << 4) | 2, spuaddr, 0);
1277 iClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1279 ClearEventFlag(g_VoiceTransCompleteEf[core], ~1);
1280 g_VoiceTransIoMode[core] = 0;
1281 if ( !(mode & SD_TRANS_MODE_IO) )
1283 g_VoiceTransStatus[core] = 0;
1284 return DmaStartStop((core << 4) | 6, iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0));
1286 g_VoiceTransStatus[core] = 1;
1287 return VoiceTrans_Write_IOMode((u16 *)iopaddr, (size & 0x3FFFFFF) + ((size & 0x3F) ? 0x40 : 0), core);
1293u32 sceSdVoiceTransStatus(s16 channel, s16 flag)
1299 if ( g_VoiceTransStatus[core] == 1 || g_VoiceTransIoMode[core] == 1 )
1304 if ( g_VoiceTransCompleteBool[core] )
1306 g_VoiceTransCompleteBool[core] = 0;
1307 g_VoiceTransIoMode[core] = 1;
1313 WaitEventFlag(g_VoiceTransCompleteEf[core], 1, 0, &efres);
1314 g_VoiceTransCompleteBool[core] = 0;
1315 g_VoiceTransIoMode[core] = 1;
1320 return g_VoiceTransIoMode[core];
1323int sceSdStopTrans(
int channel)
1328 g_TransIntrData[core].m_mode = core;
1329 g_BlockHandlerIntrData[core].m_cb = 0;
1330 g_BlockHandlerIntrData[core].m_userdata = 0;
1331 return DmaStartStop((core << 4) | 0xA, 0, 0);
1334int sceSdBlockTrans(s16 chan, u16 mode, u8 *iopaddr, u32 size, ...)
1345 va_start(va2, size);
1346 vararg_elm1 = va_arg(va2, uiptr);
1347 vararg_elm2 = va_arg(va2, uiptr);
1348 vararg_elm3 = va_arg(va2, uiptr);
1351 started = DmaStartStop((core << 4) | 4, 0, 0);
1352 transfer_dir = mode & 3;
1353 switch ( transfer_dir )
1360 g_TransIntrData[core].m_mode = core | 0xA00;
1361 g_BlockHandlerIntrData[core].m_cb = 0;
1362 g_BlockHandlerIntrData[core].m_userdata = 0;
1363 if ( (mode & 0x80) )
1367 g_TransIntrData[core].m_mode = core;
1370 g_BlockHandlerIntrData[core].m_cb = (
void *)vararg_elm1;
1371 g_BlockHandlerIntrData[core].m_userdata = (
void *)vararg_elm2;
1372 g_TransIntrData[core].m_mode |= 0x8000;
1374 else if ( (mode & SD_TRANS_LOOP) )
1377 g_TransIntrData[core].m_mode |= SD_TRANS_LOOP << 8;
1379 retres_1 = BlockTransRead(iopaddr, size, core, mode);
1382 g_BlockHandlerIntrData[core].m_cb = 0;
1383 g_BlockHandlerIntrData[core].m_userdata = 0;
1384 g_TransIntrData[core].m_mode = core;
1385 return DmaStartStop((core << 4) | 0xA, 0, 0);
1386 case SD_TRANS_WRITE:
1387 case SD_TRANS_WRITE_FROM:
1392 g_TransIntrData[core].m_mode = core | 0x600;
1393 g_BlockHandlerIntrData[core].m_cb = 0;
1394 g_BlockHandlerIntrData[core].m_userdata = 0;
1395 if ( (mode & 0x80) )
1399 g_TransIntrData[core].m_mode = core;
1402 g_BlockHandlerIntrData[core].m_cb = (
void *)vararg_elm2;
1403 g_BlockHandlerIntrData[core].m_userdata = (
void *)vararg_elm3;
1404 g_TransIntrData[core].m_mode |= 0x8000;
1406 else if ( (mode & SD_TRANS_LOOP) )
1409 g_TransIntrData[core].m_mode |= SD_TRANS_LOOP << 8;
1412 BlockTransWriteFrom(iopaddr, size, chan, mode, (transfer_dir == SD_TRANS_WRITE_FROM) ? (
void *)vararg_elm1 : 0);
1419 g_BlockHandlerIntrData[core].m_cb = 0;
1420 g_BlockHandlerIntrData[core].m_userdata = 0;
1421 g_TransIntrData[core].m_mode = core;
1426u32 sceSdBlockTransStatus(s16 channel, s16 flag)
1430 USE_IOP_MMIO_HWPORT();
1431 USE_SPU2_MMIO_HWPORT();
1435 return (g_BlockTransBuff[core] << 24)
1436 | (((spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas & 7) ?
1437 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr :
1442static int InitSpdif()
1445 USE_SPU2_MMIO_HWPORT();
1447 spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0;
1448 libsd_do_busyloop(2);
1449 spu2_mmio_hwport->m_u.m_e.m_spdif_out = 0x8000;
1450 libsd_do_busyloop(1);
1452 for ( i = 0; i < 2; i += 1 )
1454 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0;
1455 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0;
1458 for ( i = 0; i < 2; i += 1 )
1459 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_admas = 0;
1461 for ( i = 0; i < 2; i += 1 )
1462 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr = 0;
1463 libsd_do_busyloop(1);
1465 for ( i = 0; i < 2; i += 1 )
1466 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr = SD_SPU2_ON;
1468 for ( i = 0; i < 2; i += 1 )
1470 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvoll = 0;
1471 spu2_mmio_hwport->m_u.m_e.m_different_regs[i].m_mvolr = 0;
1473 for ( i = 0; (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_statx & 0x7FF)
1474 && (spu2_mmio_hwport->m_u.m_m.m_core_regs[1].m_cregs.m_statx & 0x7FF) && i < 0xF00;
1476 libsd_do_busyloop(1);
1478 for ( i = 0; i < 2; i += 1 )
1480 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_koff.m_pair[0] = 0xFFFF;
1481 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_koff.m_pair[1] = 0xFF;
1484 for ( i = 0; i < 2; i += 1 )
1486 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_pmon.m_pair[0] = 0;
1487 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_pmon.m_pair[1] = 0;
1488 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_non.m_pair[0] = 0;
1489 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_non.m_pair[1] = 0;
1494static void SetDmaWrite(
int chan)
1497 USE_IOP_MMIO_HWPORT();
1499 dmachanptr = chan ? &iop_mmio_hwport->ssbus2.ind_9_delay : &iop_mmio_hwport->ssbus1.ind_4_delay;
1500 *dmachanptr &= ~0xF000000;
1503static void SetDmaRead(
int chan)
1506 USE_IOP_MMIO_HWPORT();
1508 dmachanptr = chan ? &iop_mmio_hwport->ssbus2.ind_9_delay : &iop_mmio_hwport->ssbus1.ind_4_delay;
1509 *dmachanptr = (*dmachanptr & ~0xF000000) | 0x2000000;
1512static void __attribute__((optimize(
"no-unroll-loops"))) libsd_do_busyloop_inner(
void)
1518 for ( i = 0; i < 120; i += 1 )
1521 __asm__ __volatile__(
"" :
"+g"(loopmul) : :);
1525static void libsd_do_busyloop(
int count)
1529 for ( i = 0; i <
count; i += 1 )
1530 libsd_do_busyloop_inner();
1533static u32 DmaStartStop(
int mainarg,
void *vararg2, u32 vararg3)
1538 u32 blocktransbufitem;
1543 USE_IOP_MMIO_HWPORT();
1544 USE_SPU2_MMIO_HWPORT();
1547 core = (mainarg >> 4) & 1;
1548 switch ( mainarg & 0xF )
1551 tsa_tmp = ((u16)(uiptr)vararg2 >> 1) & ~7;
1552 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = tsa_tmp;
1553 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = (tsa_tmp >> 16) & 0xFFFF;
1556 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_DMA_IN_PROCESS) )
1558 if ( ((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr & SD_DMA_START) )
1560 if ( spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas )
1565 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr |= SD_DMA_READ;
1568 vararg3_cal = (vararg3 >> 6) + (!!(vararg3 & 0x3F));
1569 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)vararg2;
1570#pragma GCC diagnostic push
1571#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1572 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1573#pragma GCC diagnostic pop
1574 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = vararg3_cal;
1575 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1576 SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_SPU2IOP;
1577 return vararg3_cal << 6;
1580 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr =
1581 (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_WRITE;
1584 vararg3_cal = (vararg3 >> 6) + (!!(vararg3 & 0x3F));
1585 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)vararg2;
1586#pragma GCC diagnostic push
1587#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1588 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1589#pragma GCC diagnostic pop
1590 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] = vararg3_cal;
1591 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1592 SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_IOP2SPU;
1593 return vararg3_cal << 6;
1595 blocktransbufitem = 0;
1597 if ( ((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr & SD_DMA_START) )
1599 blocktransbufitem = g_BlockTransBuff[core];
1600 dma_addr = (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr;
1601 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr &= ~SD_DMA_START;
1602 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) )
1604 for ( i = 0; !(spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & 0x80) && i < 0x1000000; i += 1 )
1609 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & SD_CORE_DMA) )
1612 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1614 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 )
1619 if ( (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas & 7) )
1622 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 0;
1625 iSetEventFlag(g_VoiceTransCompleteEf[core], 1);
1627 SetEventFlag(g_VoiceTransCompleteEf[core], 1);
1628 g_VoiceTransCompleteBool[core] = 0;
1629 g_VoiceTransIoMode[core] = 1;
1630 g_CleanHandlers[core] = 0;
1631 return (dma_addr && hichk) ? ((dma_addr & ~0xFF000000) | (blocktransbufitem << 24)) : 0;
1637static u32 VoiceTrans_Write_IOMode(
const u16 *iopaddr, u32 size,
int core)
1643 USE_SPU2_MMIO_HWPORT();
1647 for ( size_tmp = size; size_tmp; size_tmp -=
count )
1649 count = (size_tmp <= 0x40) ? size_tmp : 0x40;
1650 for ( i = 0; i < (
count / 2); i += 1 )
1651 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_xferdata = iopaddr[i];
1654 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr =
1655 (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_IO;
1658 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 )
1659 libsd_do_busyloop(1);
1663 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1665 g_VoiceTransIoMode[core] = 1;
1670static void do_finish_block_clean_xfer(
int core)
1672 USE_SPU2_MMIO_HWPORT();
1674 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1675 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 0;
1678static int TransInterrupt(
IntrData *intr)
1686 USE_IOP_MMIO_HWPORT();
1687 USE_SPU2_MMIO_HWPORT();
1689 mode = intr->m_mode;
1690 switch ( mode & 0xC00 )
1693 dma_dir = SD_DMA_DIR_IOP2SPU;
1696 dma_dir = SD_DMA_DIR_SPU2IOP;
1702 switch ( mode & 0x300 )
1708 for ( i = 0; !(spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_statx & 0x80) && i < 0x1000000; i += 1 )
1711 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1712 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 )
1715 if ( dma_dir == SD_DMA_DIR_SPU2IOP )
1717 if ( g_CleanHandlers[core] )
1718 g_CleanHandlers[core](core);
1721 iSetEventFlag(g_VoiceTransCompleteEf[core], 1);
1722 if ( g_TransIntrHandlers[core] )
1724 g_VoiceTransIoMode[core] = 1;
1725 g_TransIntrHandlers[core](core, intr->m_data);
1727 else if ( !g_TransIntrCallbacks[core] )
1728 g_VoiceTransCompleteBool[core] = 1;
1731 g_VoiceTransIoMode[core] = 1;
1732 g_TransIntrCallbacks[core](0);
1738 if ( (mode & 0x8000) )
1740 if ( g_BlockHandlerIntrData[core].m_cb )
1742 g_BlockHandlerIntrData[core].m_cb(core, g_BlockHandlerIntrData[core].m_userdata, &dma_addr, &dma_size);
1745 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1746 (dma_size >> 6) + (dma_size - (dma_size & 0x3FFFFFF) > 0);
1747 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)dma_addr;
1748 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1749 dma_dir | SD_DMA_START | SD_DMA_CS;
1753 do_finish_block_clean_xfer(core);
1754 g_BlockHandlerIntrData[core].m_cb = 0;
1755 g_BlockHandlerIntrData[core].m_userdata = 0;
1759 do_finish_block_clean_xfer(core);
1760 if ( dma_dir == SD_DMA_DIR_SPU2IOP )
1765 if ( (mode & (SD_TRANS_LOOP << 8)) )
1768 g_BlockTransBuff[core] = 1 - g_BlockTransBuff[core];
1770 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1771 (int)g_BlockTransSize[core] / 0x40 + ((int)g_BlockTransSize[core] % 0x40 > 0);
1772 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr =
1773 (uiptr)(g_BlockTransAddr[core] + g_BlockTransBuff[core] * g_BlockTransSize[core]);
1774 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1775 dma_dir | SD_DMA_START | SD_DMA_CS;
1778 do_finish_block_clean_xfer(core);
1779 if ( dma_dir == SD_DMA_DIR_SPU2IOP )
1781 if ( g_TransIntrHandlers[core] )
1782 g_TransIntrHandlers[core](core, intr->m_data);
1783 else if ( g_TransIntrCallbacks[core] )
1784 g_TransIntrCallbacks[core](0);
1793static u32 BlockTransWriteFrom(u8 *iopaddr, u32 size,
int core,
int mode, u8 *startaddr)
1799 USE_IOP_MMIO_HWPORT();
1800 USE_SPU2_MMIO_HWPORT();
1803 startaddr_tmp = startaddr;
1804 g_BlockTransAddr[core] = iopaddr;
1805 g_BlockTransBuff[core] = 0;
1806 g_BlockTransSize[core] = size;
1809 size_align = size - (startaddr - iopaddr);
1810 if ( (u32)(startaddr - iopaddr) >= size )
1814 other_align = startaddr - iopaddr - size;
1815 if ( !(mode & SD_TRANS_LOOP) || other_align >= size )
1817 g_BlockTransBuff[core] += 1;
1818 size_align = size - other_align;
1820 if ( size_align % 0x400 > 0 )
1822 size_align = (size_align / 0x400 + 1) << 10;
1823 startaddr_tmp = iopaddr + g_BlockTransBuff[core] * size + size - size_align;
1828 startaddr_tmp = iopaddr;
1832 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1834 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = 0;
1835 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = 0;
1836 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 1 << core;
1838 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)startaddr_tmp;
1839#pragma GCC diagnostic push
1840#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1841 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1842#pragma GCC diagnostic pop
1843 size_align_r6 = ((size_align < 0) ? (size_align + 63) : size_align) >> 6;
1844 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1845 size_align_r6 + (size_align - (size_align_r6 << 6) > 0);
1846 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr =
1847 SD_DMA_START | SD_DMA_CS | SD_DMA_DIR_IOP2SPU;
1851static u32 BlockTransRead(u8 *iopaddr, u32 size,
int core, u16 mode)
1854 USE_IOP_MMIO_HWPORT();
1855 USE_SPU2_MMIO_HWPORT();
1858 g_BlockTransAddr[core] = iopaddr;
1859 g_BlockTransBuff[core] = 0;
1860 g_BlockTransSize[core] = size;
1862 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr &= ~SD_CORE_DMA;
1864 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[0] = 0;
1865 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_tsa.m_pair[1] = ((mode & ~0xF0FF) << 1) + 0x400;
1866 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_unk1ae = (mode & ~0xFFF) >> 11;
1867 libsd_do_busyloop(3);
1868 spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_admas = 4;
1870 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->madr = (uiptr)iopaddr;
1871#pragma GCC diagnostic push
1872#pragma GCC diagnostic ignored "-Wstrict-aliasing"
1873 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[0] = 16;
1874#pragma GCC diagnostic pop
1875 ((vu16 *)&((core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->bcr))[1] =
1876 (int)g_BlockTransSize[core] / 0x40 + ((int)g_BlockTransSize[core] % 0x40 > 0);
1877 (core ? &iop_mmio_hwport->dmac2.newch[0] : &iop_mmio_hwport->dmac1.oldch[4])->chcr = SD_DMA_START | SD_DMA_CS;
1881static int SifDmaBatch(
void *ee_addr,
void *iop_addr,
int size)
1889 xferparam.dest = ee_addr;
1890 xferparam.src = iop_addr;
1891 xferparam.size = size;
1894 dmat = sceSifSetDma(&xferparam, SIF_DMA_TO_EE);
1898 for ( i = 0, dma_status = 0; i >= 0 && dma_status >= 0; i += 1 )
1901 dma_status = sceSifDmaStat(dmat);
1904 return (i < 0) ? -1 : 0;
1907int sceSdProcBatch(
const sceSdBatch *batch, u32 *rets, u32 num)
1911 for ( cnt = 0; cnt < num; cnt += 1 )
1916 switch ( batch[cnt].func )
1918 case SD_BATCH_SETPARAM:
1919 sceSdSetParam(batch[cnt].entry, batch[cnt].value);
1921 case SD_BATCH_SETSWITCH:
1922 sceSdSetSwitch(batch[cnt].entry, batch[cnt].value);
1924 case SD_BATCH_SETADDR:
1925 sceSdSetAddr(batch[cnt].entry, batch[cnt].value);
1927 case SD_BATCH_SETCORE:
1928 sceSdSetCoreAttr(batch[cnt].entry, batch[cnt].value);
1930 case SD_BATCH_WRITEIOP:
1931 *(u32 *)batch[cnt].value = batch[cnt].entry;
1933 case SD_BATCH_WRITEEE:
1934 g_BatchData = batch[cnt].entry;
1935 Param = SifDmaBatch((
void *)batch[cnt].value, &g_BatchData,
sizeof(g_BatchData));
1937 case SD_BATCH_EERETURN:
1938 Param = SifDmaBatch((
void *)batch[cnt].value, rets, batch[cnt].entry);
1940 case SD_BATCH_GETPARAM:
1941 Param = sceSdGetParam(batch[cnt].entry);
1943 case SD_BATCH_GETSWITCH:
1944 Param = sceSdGetSwitch(batch[cnt].entry);
1946 case SD_BATCH_GETADDR:
1947 Param = sceSdGetAddr(batch[cnt].entry);
1949 case SD_BATCH_GETCORE:
1950 Param = sceSdGetCoreAttr(batch[cnt].entry);
1961int sceSdProcBatchEx(
const sceSdBatch *batch, u32 *rets, u32 num, u32 voice)
1968 for ( cnt = 0; cnt < num; cnt += 1 )
1973 switch ( batch[cnt].func )
1975 case SD_BATCH_SETPARAM:
1976 if ( (batch[cnt].entry & 0x3E) == 0x3E )
1978 for ( i = 0; i < 24; i += 1 )
1980 if ( ((1 << i) & voice) )
1983 sceSdSetParam((batch[cnt].entry & ~0x3E) | (i << 1), batch[cnt].value);
1989 sceSdSetParam(batch[cnt].entry, batch[cnt].value);
1991 case SD_BATCH_SETSWITCH:
1992 sceSdSetSwitch(batch[cnt].entry, batch[cnt].value);
1994 case SD_BATCH_SETADDR:
1995 if ( (batch[cnt].entry & 0x7E) == 0x7E )
1997 for ( i = 0; i < 24; i += 1 )
1999 if ( ((1 << i) & voice) )
2002 sceSdSetAddr((batch[cnt].entry & ~0x3E) | (i << 1), batch[cnt].value);
2008 sceSdSetAddr(batch[cnt].entry, batch[cnt].value);
2010 case SD_BATCH_SETCORE:
2011 sceSdSetCoreAttr(batch[cnt].entry, batch[cnt].value);
2013 case SD_BATCH_WRITEIOP:
2014 *(u32 *)batch[cnt].value = batch[cnt].entry;
2016 case SD_BATCH_WRITEEE:
2017 g_BatchData = batch[cnt].entry;
2018 Param = SifDmaBatch((
void *)batch[cnt].value, &g_BatchData,
sizeof(g_BatchData));
2020 case SD_BATCH_EERETURN:
2021 Param = SifDmaBatch((
void *)batch[cnt].value, rets, batch[cnt].entry);
2023 case SD_BATCH_GETPARAM:
2024 if ( (batch[cnt].entry & 0x3E) == 0x3E )
2026 for ( i = 0; i < 24; i += 1 )
2028 if ( ((1 << i) & voice) )
2029 Param = sceSdGetParam((batch[cnt].entry & ~0x3E) | (i << 1));
2037 Param = sceSdGetParam(batch[cnt].entry);
2039 case SD_BATCH_GETSWITCH:
2040 Param = sceSdGetSwitch(batch[cnt].entry);
2042 case SD_BATCH_GETADDR:
2043 if ( (batch[cnt].entry & 0x7E) == 0x7E )
2045 for ( i = 0; i < 24; i += 1 )
2047 if ( ((1 << i) & voice) )
2049 Param = sceSdGetAddr((batch[cnt].entry & ~0x3E) | (i << 1));
2058 Param = sceSdGetAddr(batch[cnt].entry);
2060 case SD_BATCH_GETCORE:
2061 Param = sceSdGetCoreAttr(batch[cnt].entry);
2073void sceSdSetParam(u16 entry, u16 value)
2076 g_ParamRegList[((entry >> 8) & 0xFF)]
2077 [((entry & 0x3E) << 2) + (((entry & 1) * (0x400 - 984 * (!!(entry & 0x80)))) >> 1)] = value;
2080u16 sceSdGetParam(u16 entry)
2083 return g_ParamRegList[((entry >> 8) & 0xFF)]
2084 [((entry & 0x3E) << 2) + (((entry & 1) * (0x400 - 984 * (!!(entry & 0x80)))) >> 1)];
2087void sceSdSetSwitch(u16 entry, u32 value)
2091 regptr = &g_ParamRegList[((entry >> 8) & 0xFF)][(entry & 1) << 9];
2093 regptr[1] = (value >> 16) & 0xFF;
2096u32 sceSdGetSwitch(u16 entry)
2100 regptr = &g_ParamRegList[((entry >> 8) & 0xFF)][(entry & 1) << 9];
2101 return regptr[0] | (regptr[1] << 16);
2104void sceSdSetAddr(u16 entry, u32 value)
2108 reg1 = &g_ParamRegList[((entry >> 8) & 0xFF)][((entry & 1) << 9) + 3 * (entry & 0x3E)];
2109 reg1[0] = value >> 17;
2110 if ( (entry & 0xFF00) != 0x1D00 )
2111 reg1[1] = (value >> 1) & ~7;
2114u32 sceSdGetAddr(u16 entry)
2122 reg1 = &g_ParamRegList[((entry >> 8) & 0xFF)][((entry & 1) << 9) + 3 * (entry & 0x3E)];
2123 regmask = entry & 0xFF00;
2124 rethi = reg1[0] << 17;
2125 if ( regmask != 0x1D00 )
2127 retlo = reg1[1] << 1;
2128 if ( regmask == 0x2100 || regmask == 0x2200 )
2130 rethi = reg1[0] << 17;
2131 retlo = reg1[1] << 1;
2134 return rethi | retlo;
2137u16 sceSdNote2Pitch(u16 center_note, u16 center_fine, u16 note, s16 fine)
2148 _fine = fine + center_fine;
2149 _fine2 = _fine / 0x80;
2150 _note = note + _fine2 - center_note;
2151 offset2 = _fine % 0x80;
2152 val2 = ((_note / 6) >> 1) - (_note < 0);
2153 offset1 = _note - 12 * val2;
2155 if ( (offset1 < 0) || (!offset1 && offset2 < 0) )
2162 offset2 += (_fine2 + 1) << 7;
2166 retval = (g_NotePitchTable[offset1] * g_NotePitchTable[offset2 + 12]) >> 16;
2167 return (val < 0) ? (u32)(retval + (1 << (-val - 1))) >> -val : (u32)retval;
2170u16 sceSdPitch2Note(u16 center_note, u16 center_fine, u16 pitch)
2179 pitch = (pitch > 0x3FFF) ? 0x3FFF : pitch;
2180 for ( i1 = 0; i1 < 14; i1 += 1 )
2182 if ( ((pitch >> i1) & 1) )
2185 val = pitch << (15 - bit);
2186 for ( i2 = 11; val < g_NotePitchTable[i2] && i2 > 0; i2 -= 1 )
2189 if ( !g_NotePitchTable[i2] )
2192 val /= g_NotePitchTable[i2];
2193 for ( i5 = 127; val < g_NotePitchTable[i5 + 12] && i5 > 0; i5 -= 1 )
2196 return (((center_fine + i5 + 1) & 0x7E)
2197 + ((i2 + center_note + 12 * (bit - 12) + ((u16)(center_fine + i5 + 1) >> 7)) << 8))
2201static int SetSpdifMode(
int val)
2205 USE_SPU2_MMIO_HWPORT();
2207 spdif_out_new = spu2_mmio_hwport->m_u.m_e.m_spdif_out & ~0x1A8;
2208 spdif_mode_new = spu2_mmio_hwport->m_u.m_e.m_spdif_mode & ~0xBF06;
2209 switch ( val & 0xF )
2212 spdif_out_new |= 0x20;
2215 spdif_out_new |= 0x100;
2216 spdif_mode_new |= 2;
2221 spdif_out_new |= 0x100;
2226 spdif_mode_new |= (val & 0x80) ? 0x8000 : 0;
2227 switch ( val & 0xF00 )
2230 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0;
2231 spdif_mode_new |= 0x100;
2234 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200;
2235 spdif_mode_new |= 0x1900;
2238 spu2_mmio_hwport->m_u.m_e.m_spdif_media = 0x200;
2239 spdif_mode_new |= 0x900;
2242 spu2_mmio_hwport->m_u.m_e.m_spdif_out = spdif_out_new;
2243 spu2_mmio_hwport->m_u.m_e.m_spdif_mode = spdif_mode_new;
2244 g_SpdifSettings = val;
2248void sceSdSetCoreAttr(u16 entry, u16 value)
2254 switch ( entry & ~0xFFFF0001 )
2256 case SD_CORE_SPDIF_MODE:
2257 SetSpdifMode(value);
2259 case SD_CORE_NOISE_CLK:
2261 param_tmp = (entry & 1) | 0x2300;
2262 sceSdSetParam(param_tmp, (sceSdGetParam(param_tmp) & ~0x3F00) | ((value & 0x3F) << 8));
2267 setting_tmp = g_CoreAttrShifts[((entry & 0xE) >> 1) - 1];
2269 param_tmp = (entry & 1) | 0x2300;
2270 sceSdSetParam(param_tmp, (sceSdGetParam(param_tmp) & ~(1 << setting_tmp)) | ((value & 1) << setting_tmp));
2276u16 sceSdGetCoreAttr(u16 entry)
2279 USE_SPU2_MMIO_HWPORT();
2282 switch ( entry & 0xE )
2284 case SD_CORE_EFFECT_ENABLE:
2285 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 7) & 1;
2286 case SD_CORE_IRQ_ENABLE:
2287 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 6) & 1;
2288 case SD_CORE_MUTE_ENABLE:
2289 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 14) & 1;
2290 case SD_CORE_NOISE_CLK:
2291 return (spu2_mmio_hwport->m_u.m_m.m_core_regs[core].m_cregs.m_attr >> 8) & 0x3F;
2292 case SD_CORE_SPDIF_MODE:
2293 return g_SpdifSettings & 0xFFFF;
2299SdIntrCallback sceSdSetTransCallback(s32 core, SdIntrCallback cb)
2301 SdIntrCallback oldtmp;
2305 oldtmp = g_TransIntrCallbacks[core];
2306 g_TransIntrCallbacks[core] = cb;
2310sceSdTransIntrHandler sceSdSetTransIntrHandler(
int channel, sceSdTransIntrHandler func,
void *arg)
2312 sceSdTransIntrHandler oldtmp;
2317 oldtmp = g_TransIntrHandlers[core];
2318 g_TransIntrHandlers[core] = func;
2319 g_TransIntrData[core].m_data = arg;
2323void *sceSdGetTransIntrHandlerArgument(
int arg)
2325 return g_TransIntrData[arg].m_data;
2328SdIntrCallback sceSdSetIRQCallback(SdIntrCallback cb)
2330 SdIntrCallback oldtmp;
2332 oldtmp = g_Spu2IrqCallback;
2333 g_Spu2IrqCallback = cb;
2337sceSdSpu2IntrHandler sceSdSetSpu2IntrHandler(sceSdSpu2IntrHandler func,
void *arg)
2339 sceSdSpu2IntrHandler oldtmp;
2341 oldtmp = g_Spu2IntrHandler;
2342 g_Spu2IntrHandler = func;
2343 g_Spu2IntrHandlerData = arg;
2347void *sceSdGetSpu2IntrHandlerArgument()
2349 return g_Spu2IntrHandlerData;
2352static int Spu2Interrupt(
void *data)
2355 USE_SPU2_MMIO_HWPORT();
2358 if ( !g_Spu2IntrHandler && !g_Spu2IrqCallback )
2360 while ( (val = (spu2_mmio_hwport->m_u.m_e.m_spdif_irqinfo & 0xC) >> 2) )
2364 for ( i = 0; i < 2; i += 1 )
2365 if ( val & (1 << i) )
2366 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_attr &= ~0x40;
2367 if ( g_Spu2IntrHandler )
2368 g_Spu2IntrHandler(val, g_Spu2IntrHandlerData);
2369 else if ( g_Spu2IrqCallback )
2370 g_Spu2IrqCallback(0);
2375static int InitVoices(
void)
2379 USE_SPU2_MMIO_HWPORT();
2381 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr &= ~SD_CORE_DMA;
2383 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_tsa.m_pair[0] = 0x0000;
2384 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_tsa.m_pair[1] = 0x5000 >> 1;
2387 for ( i = 0; i < (int)(
sizeof(g_VoiceDataInit) /
sizeof(g_VoiceDataInit[0])); i += 1 )
2388 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_xferdata = g_VoiceDataInit[i];
2391 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr =
2392 (spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr & ~SD_CORE_DMA) | SD_DMA_IO;
2394 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 )
2395 libsd_do_busyloop(1);
2397 spu2_mmio_hwport->m_u.m_m.m_core_regs[0].m_cregs.m_attr &= ~SD_CORE_DMA;
2400 for ( i = 0; i < 24; i += 1 )
2402 for ( j = 0; j < 2; j += 1 )
2403 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_voll = 0;
2404 for ( j = 0; j < 2; j += 1 )
2405 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_volr = 0;
2406 for ( j = 0; j < 2; j += 1 )
2407 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_pitch = 0x3FFF;
2408 for ( j = 0; j < 2; j += 1 )
2409 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_adsr1 = 0;
2410 for ( j = 0; j < 2; j += 1 )
2411 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_params[i].m_adsr2 = 0;
2412 for ( j = 0; j < 2; j += 1 )
2413 spu2_mmio_hwport->m_u.m_m.m_core_regs[j ^ 1].m_cregs.m_voice_address[i].m_ssa.m_pair[0] = 0;
2415 for ( j = 0; j < 2; j += 1 )
2416 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;
2420 for ( i = 0; i < 2; i += 1 )
2422 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_kon.m_pair[0] = 0xFFFF;
2423 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_kon.m_pair[1] = 0xFF;
2427 libsd_do_busyloop(3);
2430 for ( i = 0; i < 2; i += 1 )
2432 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_koff.m_pair[0] = 0xFFFF;
2433 spu2_mmio_hwport->m_u.m_m.m_core_regs[i ^ 1].m_cregs.m_koff.m_pair[1] = 0xFF;
2437 libsd_do_busyloop(3);
2439 for ( i = 0; i < 2; i += 1 )
2441 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_endx.m_pair[1] = 0;
2442 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_endx.m_pair[0] = 0;
2447static int Reset(
int flag)
2452 USE_SPU2_MMIO_HWPORT();
2461 for ( i = 0; i < 2; i += 1 )
2463 g_VoiceTransStatus[i] = 0;
2464 g_VoiceTransIoMode[i] = 1;
2465 g_VoiceTransCompleteBool[i] = 0;
2466 g_TransIntrHandlers[i] = 0;
2467 g_CleanHandlers[i] = 0;
2468 g_TransIntrData[i].m_mode = i;
2469 g_TransIntrData[i].m_data = 0;
2470 g_BlockHandlerIntrData[i].m_cb = 0;
2471 g_BlockHandlerIntrData[i].m_userdata = 0;
2472 g_TransIntrCallbacks[i] = 0;
2474 g_Spu2IntrHandler = 0;
2475 g_Spu2IntrHandlerData = 0;
2476 g_Spu2IrqCallback = 0;
2477 if ( !(flag & 0xF) )
2479 bzero(g_EffectAttr,
sizeof(g_EffectAttr));
2481 for ( i = 0; i < 2; i += 1 )
2482 g_EffectAddr[i] = 0x1DFFF0 + (0x20000 * i);
2484 for ( i = 0; i < 2; i += 1 )
2486 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_esa.m_pair[0] = 0x000E + i;
2487 spu2_mmio_hwport->m_u.m_m.m_core_regs[i].m_cregs.m_esa.m_pair[1] = 0xFFF8;
2494 for ( i = 0; i < 2; i += 1 )
2496 if ( g_VoiceTransCompleteEf[i] <= 0 )
2497 g_VoiceTransCompleteEf[i] = CreateEventFlag(&efparam);
2501 iSetEventFlag(g_VoiceTransCompleteEf[i], 1);
2503 SetEventFlag(g_VoiceTransCompleteEf[i], 1);
2506 return (g_VoiceTransCompleteEf[0] <= 0 || g_VoiceTransCompleteEf[1] <= 0) ? -301 : 0;
2509static void reset_vars(
void)
2515 for ( i = 0; i < 2; i += 1 )
2516 g_VoiceTransCompleteEf[i] = 0;
2519int sceSdInit(
int flag)
2524 if ( !(flag & 0xF) )
2526 resetres = Reset(flag);
2528 InitCoreVolume(flag & 0xF);
2532 RegisterIntrHandler(IOP_IRQ_DMA_SPU, 1, (
int (*)(
void *))TransInterrupt, &g_TransIntrData[0]);
2533 RegisterIntrHandler(IOP_IRQ_DMA_SPU2, 1, (
int (*)(
void *))TransInterrupt, &g_TransIntrData[1]);
2534 RegisterIntrHandler(IOP_IRQ_SPU, 1, (
int (*)(
void *))Spu2Interrupt, g_Spu2IntrHandlerData);
2545 for ( i = 0; i < 2; i += 1 )
2546 DmaStartStop((i << 4) | 0xA, 0, 0);
2548 for ( i = 0; i < 2; i += 1 )
2549 if ( g_VoiceTransCompleteEf[i] > 0 )
2550 DeleteEventFlag(g_VoiceTransCompleteEf[i]);
int CpuResumeIntr(int state)
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
int ReleaseIntrHandler(int irq)
int QueryIntrContext(void)
int DisableIntr(int irq, int *res)
int CpuSuspendIntr(int *state)
u32 count
start sector of fragmented bd/file