From c643345c71c025452e89ced390a9543a2a5e7c5f Mon Sep 17 00:00:00 2001 From: jacky400 Date: Fri, 7 Dec 2012 12:45:16 +0800 Subject: [PATCH 01/34] Implement sceSasGetGrain and sceSasSetGrain --- Core/HLE/sceSas.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 66eab7c98b..2ef6bf1e0e 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -41,6 +41,8 @@ static const int PSP_SAS_ADSR_DECAY=2; static const int PSP_SAS_ADSR_SUSTAIN=4; static const int PSP_SAS_ADSR_RELEASE=8; +int grainSamples; + static const double f[5][2] = { { 0.0, 0.0 }, { 60.0 / 64.0, 0.0 }, @@ -461,6 +463,20 @@ void sceSasRevVON(u32 core, int param1, int param2) RETURN(0); } +u32 sceSasGetGrain(u32 core) +{ + DEBUG_LOG(HLE,"0=sceSasGetGrain(core=%08x)", core); + return grainSamples; +} + +u32 sceSasSetGrain(u32 core, int grain) +{ + DEBUG_LOG(HLE,"0=sceSasSetGrain(core=%08x, grain=%i)", core, grain); + grainSamples=grain; + return(0); +} + + void sceSasGetOutputMode(u32 core, int param1, int param2) { DEBUG_LOG(HLE,"UNIMPL 0=sceSasGetOutputMode(core=%08x, param1=%i, param2=%i)", core, param1, param2); @@ -493,8 +509,8 @@ const HLEFunction sceSasCore[] = {0x787d04d5, 0, "__sceSasSetPause"}, {0xa232cbe6, 0, "__sceSasSetTriangularWave"}, // (int sasCore, int voice, int unknown) {0xd5ebbbcd, 0, "__sceSasSetSteepWave"}, // (int sasCore, int voice, int unknown) // square wave? - {0xBD11B7C2, 0, "__sceSasGetGrain"}, - {0xd1e0a01e, 0, "__sceSasSetGrain"}, + {0xBD11B7C2, WrapU_U, "__sceSasGetGrain"}, + {0xd1e0a01e, WrapU_UI, "__sceSasSetGrain"}, {0xe175ef66, WrapV_UII, "__sceSasGetOutputmode"}, {0xe855bf76, 0, "__sceSasSetOutputmode"}, {0x07f58c24, 0, "__sceSasGetAllEnvelopeHeights"}, // (int sasCore, int heightAddr) 32-bit heights, 0-0x40000000 From b61a672449feeab645c8b829600be9a527da7cbc Mon Sep 17 00:00:00 2001 From: jacky400 Date: Fri, 7 Dec 2012 12:59:30 +0800 Subject: [PATCH 02/34] Add WrapU_UIC for sceSasSetPause --- Core/HLE/FunctionWrappers.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index a0561526f7..43bd31e6a1 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -103,6 +103,10 @@ template void WrapU_I() { RETURN(retval); } +template void WrapU_UIC() { + func(PARAM(0), PARAM(1), Memory::GetCharPointer(PARAM(2))); +} + template void WrapI_I() { int retval = func(PARAM(0)); RETURN(retval); From a24cc1dd9a33468e6962d4c908ed0d25cbe26665 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Fri, 7 Dec 2012 13:23:26 +0800 Subject: [PATCH 03/34] Implement sceSasSetPause --- Core/HLE/sceSas.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 2ef6bf1e0e..1da1cac099 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -156,6 +156,7 @@ struct Voice bool endFlag; bool PauseFlag; bool playing; + bool setPaused; VagDecoder vag; }; @@ -262,6 +263,17 @@ void sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) RETURN(0); } +u32 sceSasSetPause(u32 core, int voicebit, const char *pause) +{ + DEBUG_LOG(HLE,"0=sceSasSetPause(core=%08x, voicebit=%i, pause=%c)", core, voicebit, pause); + for (int i = 0; voicebit != 0; i++, voicebit >>= 1) { + if ((voicebit & 1) != 0) { + sas.voices[i].setPaused=pause; + } + } + return(0); +} + void sceSasSetVolume(u32 core, int voiceNum, int l, int r, int el, int er) { DEBUG_LOG(HLE,"UNIMPL 0=sceSasSetVolume(core=%08x, voicenum=%i, l=%i, r=%i, el=%i, er=%i", core, voiceNum, l, r, el, er); @@ -506,7 +518,7 @@ const HLEFunction sceSasCore[] = {0x33d4ab37, WrapV_UI, "__sceSasRevType"}, // (int sasCore, int type) {0x267a6dd2, WrapV_UII, "__sceSasRevParam"}, // (int sasCore, int delay, int feedback) {0x2c8e6ab3, WrapU_V, "__sceSasGetPauseFlag"}, // int sasCore - {0x787d04d5, 0, "__sceSasSetPause"}, + {0x787d04d5, WrapU_UIC, "__sceSasSetPause"}, {0xa232cbe6, 0, "__sceSasSetTriangularWave"}, // (int sasCore, int voice, int unknown) {0xd5ebbbcd, 0, "__sceSasSetSteepWave"}, // (int sasCore, int voice, int unknown) // square wave? {0xBD11B7C2, WrapU_U, "__sceSasGetGrain"}, From 17d32c2606284bee069c882861fc82b6d832c081 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Fri, 7 Dec 2012 20:41:51 +0800 Subject: [PATCH 04/34] Add 3 functions in sceVaudio --- Core/HLE/sceVaudio.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index 6ca72b69d0..d384a95c88 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -19,11 +19,29 @@ #include "sceVaudio.h" +void sceVaudioOutputBlockingFunction() +{ + WARN_LOG(HLE, "HACK sceVaudioOutputBlockingFunction(...)"); + RETURN(0); +} + +void sceVaudioChReserveFunction() +{ + WARN_LOG(HLE, "HACK sceVaudioChReserveFunction(...)"); + RETURN(0); +} + +void sceVaudioChReleaseFunction() +{ + WARN_LOG(HLE, "HACK sceVaudioChReleaseFunction(...)"); + RETURN(0); +} + const HLEFunction sceVaudio[] = { - {0x03b6807d, 0, "sceVaudio_0x03b6807d"}, - {0x67585dfd, 0, "sceVaudio_0x67585dfd"}, - {0x8986295e, 0, "sceVaudio_0x8986295e"}, + {0x03b6807d, sceVaudioOutputBlockingFunction, "sceVaudioOutputBlockingFunction"}, + {0x67585dfd, sceVaudioChReserveFunction, "sceVaudioChReserveFunction"}, + {0x8986295e, sceVaudioChReleaseFunction, "sceVaudioChReleaseFunction"}, }; void Register_sceVaudio() From 414f103211f3a095eb7c436ee81e667252cff5c0 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 11:36:07 +0800 Subject: [PATCH 05/34] Cleanup and new function in SasCore --- Core/HLE/sceSas.cpp | 84 +++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 1da1cac099..b0654f60dd 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -42,6 +42,14 @@ static const int PSP_SAS_ADSR_SUSTAIN=4; static const int PSP_SAS_ADSR_RELEASE=8; int grainSamples; +int output; +int waveformEffectType; +int waveformEffectDelay; +int waveformEffectFeedback ; +int waveformEffectLeftVol; +int waveformEffectRightVol; +bool waveformEffectIsDryOn; +bool waveformEffectIsWetOn; static const double f[5][2] = { { 0.0, 0.0 }, @@ -135,6 +143,7 @@ bool VagDecoder::Decode() struct Voice { u32 vagAddr; + u32 pcmAddr; int samplePos; int size; int loop; @@ -169,6 +178,7 @@ public: int grainSize; int maxVoices; int sampleRate; + int output; void mix(u32 outAddr); }; @@ -208,20 +218,21 @@ void SasInstance::mix(u32 outAddr) } } -u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 unknown, u32 sampleRate) +u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate) { DEBUG_LOG(HLE,"0=sceSasInit()"); memset(&sas, 0, sizeof(sas)); sas.grainSize = grainSize; sas.maxVoices = maxVoices; sas.sampleRate = sampleRate; + sas.output = outputMode; for (int i = 0; i < 32; i++) { sas.voices[i].playing = false; } return 0; } -u32 sceSasGetEndFlag() +u32 sceSasGetEndFlag(u32 core) { u32 endFlag = 0; for (int i = 0; i < sas.maxVoices; i++) { @@ -440,17 +451,20 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) void sceSasRevType(u32 core, int type) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevType(core=%08x, type=%i)", core, type); + DEBUG_LOG(HLE,"0=sceSasRevType(core=%08x, type=%i)", core, type); + waveformEffectType=type; RETURN(0); } -void sceSasRevParam(u32 core, int param1, int param2) +void sceSasRevParam(u32 core, int delay, int feedback) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevParam(core=%08x, param1=%i, param2=%i)", core, param1, param2); + DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback); + waveformEffectDelay = delay; + waveformEffectFeedback = feedback; RETURN(0); } -u32 sceSasGetPauseFlag() +u32 sceSasGetPauseFlag(u32 core) { u32 PauseFlag = 0; for (int i = 0; i < sas.maxVoices; i++) { @@ -461,17 +475,19 @@ u32 sceSasGetPauseFlag() return PauseFlag; } - - -void sceSasRevEVOL(u32 core, int param1, int param2) +void sceSasRevEVOL(u32 core, int lv, int rv) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevEVOL(core=%08x, param1=%i, param2=%i)", core, param1, param2); + DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, leftVolume=%i, rightVolume=%i)", core, lv, rv); + waveformEffectLeftVol = lv; + waveformEffectRightVol = rv; RETURN(0); } -void sceSasRevVON(u32 core, int param1, int param2) +void sceSasRevVON(u32 core, int dry, int wet) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevEVOL(core=%08x, param1=%i, param2=%i)", core, param1, param2); + DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, dry=%i, param2=%i)", core, dry, wet); + waveformEffectIsDryOn = (dry > 0); + waveformEffectIsWetOn = (wet > 0); RETURN(0); } @@ -489,19 +505,45 @@ u32 sceSasSetGrain(u32 core, int grain) } -void sceSasGetOutputMode(u32 core, int param1, int param2) +u32 sceSasGetOutputMode(u32 core) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasGetOutputMode(core=%08x, param1=%i, param2=%i)", core, param1, param2); - RETURN(0); + DEBUG_LOG(HLE,"0=sceSasGetOutputMode(core=%08x)", core); + RETURN output; } +u32 sceSasSetOutputMode(u32 core, u32 outputMode) +{ + DEBUG_LOG(HLE,"0=sceSasSetOutputMode(core=%08x, outputMode=%i)", core, outputMode); + output=outputMode; + return(0); +} + +u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) +{ + Memory::Memset(heightsAddr, 0 , sas.length * 4); + for (int i = 0; i < sas.length ; i++) { + int voiceHeight = sas.voices[i].height; + } + return 0; +} + +void sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop) +{ + DEBUG_LOG(HLE,"0=sceSasSetVoice(core=%08x, voicenum=%i, pcm=%08x, size=%i, loop=%i)",core, voiceNum, pcmAddr, size, loop); + Voice &v = sas.voices[voiceNum]; + v.pcmAddr = pcmAddr; + v.size = size; + v.loop = loop; + v.playing = true; + RETURN(0); +} const HLEFunction sceSasCore[] = { {0x42778a9f, WrapU_UUUUU, "__sceSasInit"}, // (SceUID * sasCore, int grain, int maxVoices, int outputMode, int sampleRate) {0xa3589d81, WrapV_U<_sceSasCore>, "__sceSasCore"}, {0x50a14dfc, WrapV_U<_sceSasCoreWithMix>, "__sceSasCoreWithMix"}, // Process and mix into buffer (int sasCore, int sasInOut, int leftVolume, int rightVolume) - {0x68a46b95, WrapU_V, "__sceSasGetEndFlag"}, // int sasCore + {0x68a46b95, WrapU_U, "__sceSasGetEndFlag"}, // int sasCore {0x440ca7d8, WrapV_UIIIII, "__sceSasSetVolume"}, {0xad84d37f, WrapV_UII, "__sceSasSetPitch"}, {0x99944089, WrapV_UIUII, "__sceSasSetVoice"}, // (int sasCore, int voice, int vagAddr, int size, int loopmode) @@ -517,16 +559,16 @@ const HLEFunction sceSasCore[] = {0xd5a229c9, WrapV_UII, "__sceSasRevEVOL"}, // (int sasCore, int leftVol, int rightVol) // effect volume {0x33d4ab37, WrapV_UI, "__sceSasRevType"}, // (int sasCore, int type) {0x267a6dd2, WrapV_UII, "__sceSasRevParam"}, // (int sasCore, int delay, int feedback) - {0x2c8e6ab3, WrapU_V, "__sceSasGetPauseFlag"}, // int sasCore + {0x2c8e6ab3, WrapU_U, "__sceSasGetPauseFlag"}, // int sasCore {0x787d04d5, WrapU_UIC, "__sceSasSetPause"}, {0xa232cbe6, 0, "__sceSasSetTriangularWave"}, // (int sasCore, int voice, int unknown) {0xd5ebbbcd, 0, "__sceSasSetSteepWave"}, // (int sasCore, int voice, int unknown) // square wave? {0xBD11B7C2, WrapU_U, "__sceSasGetGrain"}, {0xd1e0a01e, WrapU_UI, "__sceSasSetGrain"}, - {0xe175ef66, WrapV_UII, "__sceSasGetOutputmode"}, - {0xe855bf76, 0, "__sceSasSetOutputmode"}, - {0x07f58c24, 0, "__sceSasGetAllEnvelopeHeights"}, // (int sasCore, int heightAddr) 32-bit heights, 0-0x40000000 - {0xE1CD9561, 0, "__sceSasSetVoicePCM"}, + {0xe175ef66, WrapU_U, "__sceSasGetOutputmode"}, + {0xe855bf76, WrapU_UU, "__sceSasSetOutputmode"}, + {0x07f58c24, WrapU_UU, "__sceSasGetAllEnvelopeHeights"}, // (int sasCore, int heightAddr) 32-bit heights, 0-0x40000000 + {0xE1CD9561, WrapV_UIUII, "__sceSasSetVoicePCM"}, }; void Register_sceSasCore() From e7cb558cb94587afac84052b6622a31faadb4161 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 14:13:41 +0800 Subject: [PATCH 06/34] Update Core/HLE/sceSas.cpp --- Core/HLE/sceSas.cpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index b0654f60dd..46595534ee 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -48,8 +48,8 @@ int waveformEffectDelay; int waveformEffectFeedback ; int waveformEffectLeftVol; int waveformEffectRightVol; -bool waveformEffectIsDryOn; -bool waveformEffectIsWetOn; +int waveformEffectIsDryOn; +int waveformEffectIsWetOn; static const double f[5][2] = { { 0.0, 0.0 }, @@ -162,10 +162,9 @@ struct Voice int sustainLevel; int releaseType; int pitch; - bool endFlag; - bool PauseFlag; + int setPaused; + int height; bool playing; - bool setPaused; VagDecoder vag; }; @@ -178,7 +177,8 @@ public: int grainSize; int maxVoices; int sampleRate; - int output; + int outputMode; + int length; void mix(u32 outAddr); }; @@ -225,7 +225,7 @@ u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampl sas.grainSize = grainSize; sas.maxVoices = maxVoices; sas.sampleRate = sampleRate; - sas.output = outputMode; + sas.outputMode = outputMode; for (int i = 0; i < 32; i++) { sas.voices[i].playing = false; } @@ -274,7 +274,7 @@ void sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) RETURN(0); } -u32 sceSasSetPause(u32 core, int voicebit, const char *pause) +u32 sceSasSetPause(u32 core, int voicebit, int pause) { DEBUG_LOG(HLE,"0=sceSasSetPause(core=%08x, voicebit=%i, pause=%c)", core, voicebit, pause); for (int i = 0; voicebit != 0; i++, voicebit >>= 1) { @@ -282,7 +282,7 @@ u32 sceSasSetPause(u32 core, int voicebit, const char *pause) sas.voices[i].setPaused=pause; } } - return(0); + return 0; } void sceSasSetVolume(u32 core, int voiceNum, int l, int r, int el, int er) @@ -326,7 +326,7 @@ u32 sceSasSetNoise(u32 core, int voiceNum, int freq) DEBUG_LOG(HLE,"0=sceSasSetVoice(core=%08x, voiceNum=%i, freq=%i)", core, voiceNum, freq); Voice &v = sas.voices[voiceNum]; v.freq = freq; - return(0); + return 0; } u32 sceSasSetSL(u32 core, int voiceNum, int level) @@ -334,7 +334,7 @@ u32 sceSasSetSL(u32 core, int voiceNum, int level) DEBUG_LOG(HLE,"0=sceSasSetSL(core=%08x, voicenum=%i, level=%i)", core, voiceNum, level); Voice &v = sas.voices[voiceNum]; v.sustainLevel = level; - return(0); + return 0; } u32 sceSasSetADSR(u32 core, int voiceNum,int flag ,int a, int d, int s, int r) @@ -356,7 +356,7 @@ u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int if ((flag & 0x2) != 0) v.decayType = d; if ((flag & 0x4) != 0) v.sustainType = s; if ((flag & 0x8) != 0) v.releaseType = r; - return 0; + return 0 ; } // http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/sceSasCore.java @@ -501,21 +501,21 @@ u32 sceSasSetGrain(u32 core, int grain) { DEBUG_LOG(HLE,"0=sceSasSetGrain(core=%08x, grain=%i)", core, grain); grainSamples=grain; - return(0); + return 0; } u32 sceSasGetOutputMode(u32 core) { DEBUG_LOG(HLE,"0=sceSasGetOutputMode(core=%08x)", core); - RETURN output; + return output; } u32 sceSasSetOutputMode(u32 core, u32 outputMode) { DEBUG_LOG(HLE,"0=sceSasSetOutputMode(core=%08x, outputMode=%i)", core, outputMode); output=outputMode; - return(0); + return 0; } u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) @@ -560,13 +560,13 @@ const HLEFunction sceSasCore[] = {0x33d4ab37, WrapV_UI, "__sceSasRevType"}, // (int sasCore, int type) {0x267a6dd2, WrapV_UII, "__sceSasRevParam"}, // (int sasCore, int delay, int feedback) {0x2c8e6ab3, WrapU_U, "__sceSasGetPauseFlag"}, // int sasCore - {0x787d04d5, WrapU_UIC, "__sceSasSetPause"}, + {0x787d04d5, WrapU_UII, "__sceSasSetPause"}, {0xa232cbe6, 0, "__sceSasSetTriangularWave"}, // (int sasCore, int voice, int unknown) {0xd5ebbbcd, 0, "__sceSasSetSteepWave"}, // (int sasCore, int voice, int unknown) // square wave? {0xBD11B7C2, WrapU_U, "__sceSasGetGrain"}, {0xd1e0a01e, WrapU_UI, "__sceSasSetGrain"}, {0xe175ef66, WrapU_U, "__sceSasGetOutputmode"}, - {0xe855bf76, WrapU_UU, "__sceSasSetOutputmode"}, + {0xe855bf76, WrapU_UU, "__sceSasSetOutputmode"}, {0x07f58c24, WrapU_UU, "__sceSasGetAllEnvelopeHeights"}, // (int sasCore, int heightAddr) 32-bit heights, 0-0x40000000 {0xE1CD9561, WrapV_UIUII, "__sceSasSetVoicePCM"}, }; From 453182b7bc99e197fb7013e7d8cd654bdfe5c365 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 14:22:47 +0800 Subject: [PATCH 07/34] Update Core/HLE/FunctionWrappers.h --- Core/HLE/FunctionWrappers.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 43bd31e6a1..29d7fd3701 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -103,9 +103,7 @@ template void WrapU_I() { RETURN(retval); } -template void WrapU_UIC() { - func(PARAM(0), PARAM(1), Memory::GetCharPointer(PARAM(2))); -} + template void WrapI_I() { int retval = func(PARAM(0)); From 43a89fe4b7f9e04d93187f309b662ed491803ba2 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 15:33:19 +0800 Subject: [PATCH 08/34] Update Core/HLE/sceSas.cpp --- Core/HLE/sceSas.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 46595534ee..c0d66cf05c 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -244,7 +244,7 @@ u32 sceSasGetEndFlag(u32 core) } // Runs the mixer -void _sceSasCore(u32 outAddr) +void _sceSasCore(u32 core, u32 outAddr) { DEBUG_LOG(HLE,"0=sceSasCore(, %08x) (grain: %i samples)", outAddr, sas.grainSize); Memory::Memset(outAddr, 0, sas.grainSize * 2 * 2); @@ -253,7 +253,7 @@ void _sceSasCore(u32 outAddr) } // Another way of running the mixer, what was the difference again? -void _sceSasCoreWithMix(u32 outAddr) +void _sceSasCoreWithMix(u32 core, u32 outAddr) { DEBUG_LOG(HLE,"0=sceSasCoreWithMix(, %08x)", outAddr); sas.mix(outAddr); @@ -541,8 +541,8 @@ void sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop) const HLEFunction sceSasCore[] = { {0x42778a9f, WrapU_UUUUU, "__sceSasInit"}, // (SceUID * sasCore, int grain, int maxVoices, int outputMode, int sampleRate) - {0xa3589d81, WrapV_U<_sceSasCore>, "__sceSasCore"}, - {0x50a14dfc, WrapV_U<_sceSasCoreWithMix>, "__sceSasCoreWithMix"}, // Process and mix into buffer (int sasCore, int sasInOut, int leftVolume, int rightVolume) + {0xa3589d81, WrapV_UU<_sceSasCore>, "__sceSasCore"}, + {0x50a14dfc, WrapV_UU<_sceSasCoreWithMix>, "__sceSasCoreWithMix"}, // Process and mix into buffer (int sasCore, int sasInOut, int leftVolume, int rightVolume) {0x68a46b95, WrapU_U, "__sceSasGetEndFlag"}, // int sasCore {0x440ca7d8, WrapV_UIIIII, "__sceSasSetVolume"}, {0xad84d37f, WrapV_UII, "__sceSasSetPitch"}, From 0739fd23707bf4539cddf8aac48672e32d991d1f Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 15:43:31 +0800 Subject: [PATCH 09/34] Update Core/HLE/sceSas.cpp --- Core/HLE/sceSas.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index c0d66cf05c..17313749f1 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -520,11 +520,11 @@ u32 sceSasSetOutputMode(u32 core, u32 outputMode) u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) { - Memory::Memset(heightsAddr, 0 , sas.length * 4); - for (int i = 0; i < sas.length ; i++) { - int voiceHeight = sas.voices[i].height; - } - return 0; + Memory::Memset(heightsAddr, 0 , sas.length * 4); + for (int i = 0; i < sas.length ; i++) { + int voiceHeight = sas.voices[i].height; + } + return 0; } void sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop) From 86e21c248a4f84c0df8691d57f9dfc4db8e15840 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 15:53:11 +0800 Subject: [PATCH 10/34] Update Core/HLE/sceSas.cpp --- Core/HLE/sceSas.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 17313749f1..cf0706ccd3 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -276,7 +276,7 @@ void sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) u32 sceSasSetPause(u32 core, int voicebit, int pause) { - DEBUG_LOG(HLE,"0=sceSasSetPause(core=%08x, voicebit=%i, pause=%c)", core, voicebit, pause); + DEBUG_LOG(HLE,"0=sceSasSetPause(core=%08x, voicebit=%i, pause=%i)", core, voicebit, pause); for (int i = 0; voicebit != 0; i++, voicebit >>= 1) { if ((voicebit & 1) != 0) { sas.voices[i].setPaused=pause; @@ -485,7 +485,7 @@ void sceSasRevEVOL(u32 core, int lv, int rv) void sceSasRevVON(u32 core, int dry, int wet) { - DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, dry=%i, param2=%i)", core, dry, wet); + DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, dry=%i, wet=%i)", core, dry, wet); waveformEffectIsDryOn = (dry > 0); waveformEffectIsWetOn = (wet > 0); RETURN(0); @@ -520,6 +520,7 @@ u32 sceSasSetOutputMode(u32 core, u32 outputMode) u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) { + DEBUG_LOG(HLE,"0=sceSasGetAllEnvelopeHeights(core=%08x, heightsAddr=%i)", core, heightsAddr); Memory::Memset(heightsAddr, 0 , sas.length * 4); for (int i = 0; i < sas.length ; i++) { int voiceHeight = sas.voices[i].height; From 5231dc0dda0e2b718e2a3377012bc980460db21f Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 16:02:21 +0800 Subject: [PATCH 11/34] Update Core/HLE/sceSas.cpp --- Core/HLE/sceSas.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index cf0706ccd3..4ab6fc0876 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -287,7 +287,7 @@ u32 sceSasSetPause(u32 core, int voicebit, int pause) void sceSasSetVolume(u32 core, int voiceNum, int l, int r, int el, int er) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasSetVolume(core=%08x, voicenum=%i, l=%i, r=%i, el=%i, er=%i", core, voiceNum, l, r, el, er); + DEBUG_LOG(HLE,"0=sceSasSetVolume(core=%08x, voiceNum=%i, l=%i, r=%i, el=%i, er=%i", core, voiceNum, l, r, el, er); Voice &v = sas.voices[voiceNum]; v.volumeLeft = l; v.volumeRight = r; @@ -298,13 +298,13 @@ void sceSasSetPitch(u32 core, int voiceNum, int pitch) { Voice &v = sas.voices[voiceNum]; v.pitch = pitch; - DEBUG_LOG(HLE,"UNIMPL 0=sceSasSetPitch(core=%08x, voicenum=%i, pitch=%i)", core, voiceNum, pitch); + DEBUG_LOG(HLE,"0=sceSasSetPitch(core=%08x, voiceNum=%i, pitch=%i)", core, voiceNum, pitch); RETURN(0); } void sceSasSetKeyOn(u32 core, int voiceNum) { - DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voicenum=%i)", core, voiceNum); + DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voiceNum=%i)", core, voiceNum); Voice &v = sas.voices[voiceNum]; v.vag.Start(Memory::GetPointer(v.vagAddr)); v.playing = true; @@ -315,7 +315,7 @@ void sceSasSetKeyOn(u32 core, int voiceNum) // sceSasSetKeyOff can be used to start sounds, that just sound during the Release phase! void sceSasSetKeyOff(u32 core, int voiceNum) { - DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voicenum=%i)", core, voiceNum); + DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voiceNum=%i)", core, voiceNum); Voice &v = sas.voices[voiceNum]; v.playing = false; // not right! Should directly enter Release envelope stage instead! RETURN(0); @@ -331,7 +331,7 @@ u32 sceSasSetNoise(u32 core, int voiceNum, int freq) u32 sceSasSetSL(u32 core, int voiceNum, int level) { - DEBUG_LOG(HLE,"0=sceSasSetSL(core=%08x, voicenum=%i, level=%i)", core, voiceNum, level); + DEBUG_LOG(HLE,"0=sceSasSetSL(core=%08x, voiceNum=%i, level=%i)", core, voiceNum, level); Voice &v = sas.voices[voiceNum]; v.sustainLevel = level; return 0; @@ -458,7 +458,7 @@ void sceSasRevType(u32 core, int type) void sceSasRevParam(u32 core, int delay, int feedback) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback); + DEBUG_LOG(HLE,"0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback); waveformEffectDelay = delay; waveformEffectFeedback = feedback; RETURN(0); @@ -485,7 +485,7 @@ void sceSasRevEVOL(u32 core, int lv, int rv) void sceSasRevVON(u32 core, int dry, int wet) { - DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, dry=%i, wet=%i)", core, dry, wet); + DEBUG_LOG(HLE,"0=sceSasRevVON(core=%08x, dry=%i, wet=%i)", core, dry, wet); waveformEffectIsDryOn = (dry > 0); waveformEffectIsWetOn = (wet > 0); RETURN(0); @@ -530,7 +530,7 @@ u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) void sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop) { - DEBUG_LOG(HLE,"0=sceSasSetVoice(core=%08x, voicenum=%i, pcm=%08x, size=%i, loop=%i)",core, voiceNum, pcmAddr, size, loop); + DEBUG_LOG(HLE,"0=sceSasSetVoicePCM(core=%08x, voicenum=%i, pcmAddr=%08x, size=%i, loop=%i)",core, voiceNum, pcmAddr, size, loop); Voice &v = sas.voices[voiceNum]; v.pcmAddr = pcmAddr; v.size = size; From be167141dd5c701ed3d19d524257351da24cf4bf Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 16:05:11 +0800 Subject: [PATCH 12/34] Update Core/HLE/sceSas.cpp --- Core/HLE/sceSas.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 4ab6fc0876..ef75567d18 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -304,7 +304,7 @@ void sceSasSetPitch(u32 core, int voiceNum, int pitch) void sceSasSetKeyOn(u32 core, int voiceNum) { - DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voiceNum=%i)", core, voiceNum); + DEBUG_LOG(HLE,"0=sceSasSetKeyOn(core=%08x, voiceNum=%i)", core, voiceNum); Voice &v = sas.voices[voiceNum]; v.vag.Start(Memory::GetPointer(v.vagAddr)); v.playing = true; @@ -323,7 +323,7 @@ void sceSasSetKeyOff(u32 core, int voiceNum) u32 sceSasSetNoise(u32 core, int voiceNum, int freq) { - DEBUG_LOG(HLE,"0=sceSasSetVoice(core=%08x, voiceNum=%i, freq=%i)", core, voiceNum, freq); + DEBUG_LOG(HLE,"0=sceSasSetNoise(core=%08x, voiceNum=%i, freq=%i)", core, voiceNum, freq); Voice &v = sas.voices[voiceNum]; v.freq = freq; return 0; From b6b26e38f6fc24cb8315f60c55ba90f40b1211f8 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Fri, 7 Dec 2012 12:45:16 +0800 Subject: [PATCH 13/34] New functions for sceSas/sceVaudio .Massive checkup on all functions parameters and return value. --- Core/HLE/sceSas.cpp | 149 ++++++++++++++++++++++++++++++----------- Core/HLE/sceVaudio.cpp | 24 ++++++- 2 files changed, 131 insertions(+), 42 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 66eab7c98b..ef75567d18 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -41,6 +41,16 @@ static const int PSP_SAS_ADSR_DECAY=2; static const int PSP_SAS_ADSR_SUSTAIN=4; static const int PSP_SAS_ADSR_RELEASE=8; +int grainSamples; +int output; +int waveformEffectType; +int waveformEffectDelay; +int waveformEffectFeedback ; +int waveformEffectLeftVol; +int waveformEffectRightVol; +int waveformEffectIsDryOn; +int waveformEffectIsWetOn; + static const double f[5][2] = { { 0.0, 0.0 }, { 60.0 / 64.0, 0.0 }, @@ -133,6 +143,7 @@ bool VagDecoder::Decode() struct Voice { u32 vagAddr; + u32 pcmAddr; int samplePos; int size; int loop; @@ -151,8 +162,8 @@ struct Voice int sustainLevel; int releaseType; int pitch; - bool endFlag; - bool PauseFlag; + int setPaused; + int height; bool playing; VagDecoder vag; @@ -166,6 +177,8 @@ public: int grainSize; int maxVoices; int sampleRate; + int outputMode; + int length; void mix(u32 outAddr); }; @@ -205,20 +218,21 @@ void SasInstance::mix(u32 outAddr) } } -u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 unknown, u32 sampleRate) +u32 sceSasInit(u32 core, u32 grainSize, u32 maxVoices, u32 outputMode, u32 sampleRate) { DEBUG_LOG(HLE,"0=sceSasInit()"); memset(&sas, 0, sizeof(sas)); sas.grainSize = grainSize; sas.maxVoices = maxVoices; sas.sampleRate = sampleRate; + sas.outputMode = outputMode; for (int i = 0; i < 32; i++) { sas.voices[i].playing = false; } return 0; } -u32 sceSasGetEndFlag() +u32 sceSasGetEndFlag(u32 core) { u32 endFlag = 0; for (int i = 0; i < sas.maxVoices; i++) { @@ -230,7 +244,7 @@ u32 sceSasGetEndFlag() } // Runs the mixer -void _sceSasCore(u32 outAddr) +void _sceSasCore(u32 core, u32 outAddr) { DEBUG_LOG(HLE,"0=sceSasCore(, %08x) (grain: %i samples)", outAddr, sas.grainSize); Memory::Memset(outAddr, 0, sas.grainSize * 2 * 2); @@ -239,7 +253,7 @@ void _sceSasCore(u32 outAddr) } // Another way of running the mixer, what was the difference again? -void _sceSasCoreWithMix(u32 outAddr) +void _sceSasCoreWithMix(u32 core, u32 outAddr) { DEBUG_LOG(HLE,"0=sceSasCoreWithMix(, %08x)", outAddr); sas.mix(outAddr); @@ -260,9 +274,20 @@ void sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loop) RETURN(0); } +u32 sceSasSetPause(u32 core, int voicebit, int pause) +{ + DEBUG_LOG(HLE,"0=sceSasSetPause(core=%08x, voicebit=%i, pause=%i)", core, voicebit, pause); + for (int i = 0; voicebit != 0; i++, voicebit >>= 1) { + if ((voicebit & 1) != 0) { + sas.voices[i].setPaused=pause; + } + } + return 0; +} + void sceSasSetVolume(u32 core, int voiceNum, int l, int r, int el, int er) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasSetVolume(core=%08x, voicenum=%i, l=%i, r=%i, el=%i, er=%i", core, voiceNum, l, r, el, er); + DEBUG_LOG(HLE,"0=sceSasSetVolume(core=%08x, voiceNum=%i, l=%i, r=%i, el=%i, er=%i", core, voiceNum, l, r, el, er); Voice &v = sas.voices[voiceNum]; v.volumeLeft = l; v.volumeRight = r; @@ -273,13 +298,13 @@ void sceSasSetPitch(u32 core, int voiceNum, int pitch) { Voice &v = sas.voices[voiceNum]; v.pitch = pitch; - DEBUG_LOG(HLE,"UNIMPL 0=sceSasSetPitch(core=%08x, voicenum=%i, pitch=%i)", core, voiceNum, pitch); + DEBUG_LOG(HLE,"0=sceSasSetPitch(core=%08x, voiceNum=%i, pitch=%i)", core, voiceNum, pitch); RETURN(0); } void sceSasSetKeyOn(u32 core, int voiceNum) { - DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voicenum=%i)", core, voiceNum); + DEBUG_LOG(HLE,"0=sceSasSetKeyOn(core=%08x, voiceNum=%i)", core, voiceNum); Voice &v = sas.voices[voiceNum]; v.vag.Start(Memory::GetPointer(v.vagAddr)); v.playing = true; @@ -290,7 +315,7 @@ void sceSasSetKeyOn(u32 core, int voiceNum) // sceSasSetKeyOff can be used to start sounds, that just sound during the Release phase! void sceSasSetKeyOff(u32 core, int voiceNum) { - DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voicenum=%i)", core, voiceNum); + DEBUG_LOG(HLE,"0=sceSasSetKeyOff(core=%08x, voiceNum=%i)", core, voiceNum); Voice &v = sas.voices[voiceNum]; v.playing = false; // not right! Should directly enter Release envelope stage instead! RETURN(0); @@ -298,18 +323,18 @@ void sceSasSetKeyOff(u32 core, int voiceNum) u32 sceSasSetNoise(u32 core, int voiceNum, int freq) { - DEBUG_LOG(HLE,"0=sceSasSetVoice(core=%08x, voiceNum=%i, freq=%i)", core, voiceNum, freq); + DEBUG_LOG(HLE,"0=sceSasSetNoise(core=%08x, voiceNum=%i, freq=%i)", core, voiceNum, freq); Voice &v = sas.voices[voiceNum]; v.freq = freq; - return(0); + return 0; } u32 sceSasSetSL(u32 core, int voiceNum, int level) { - DEBUG_LOG(HLE,"0=sceSasSetSL(core=%08x, voicenum=%i, level=%i)", core, voiceNum, level); + DEBUG_LOG(HLE,"0=sceSasSetSL(core=%08x, voiceNum=%i, level=%i)", core, voiceNum, level); Voice &v = sas.voices[voiceNum]; v.sustainLevel = level; - return(0); + return 0; } u32 sceSasSetADSR(u32 core, int voiceNum,int flag ,int a, int d, int s, int r) @@ -331,7 +356,7 @@ u32 sceSasSetADSRMode(u32 core, int voiceNum,int flag ,int a, int d, int s, int if ((flag & 0x2) != 0) v.decayType = d; if ((flag & 0x4) != 0) v.sustainType = s; if ((flag & 0x8) != 0) v.releaseType = r; - return 0; + return 0 ; } // http://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/HLE/modules150/sceSasCore.java @@ -426,17 +451,20 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) void sceSasRevType(u32 core, int type) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevType(core=%08x, type=%i)", core, type); + DEBUG_LOG(HLE,"0=sceSasRevType(core=%08x, type=%i)", core, type); + waveformEffectType=type; RETURN(0); } -void sceSasRevParam(u32 core, int param1, int param2) +void sceSasRevParam(u32 core, int delay, int feedback) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevParam(core=%08x, param1=%i, param2=%i)", core, param1, param2); + DEBUG_LOG(HLE,"0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback); + waveformEffectDelay = delay; + waveformEffectFeedback = feedback; RETURN(0); } -u32 sceSasGetPauseFlag() +u32 sceSasGetPauseFlag(u32 core) { u32 PauseFlag = 0; for (int i = 0; i < sas.maxVoices; i++) { @@ -447,33 +475,76 @@ u32 sceSasGetPauseFlag() return PauseFlag; } - - -void sceSasRevEVOL(u32 core, int param1, int param2) +void sceSasRevEVOL(u32 core, int lv, int rv) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevEVOL(core=%08x, param1=%i, param2=%i)", core, param1, param2); + DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, leftVolume=%i, rightVolume=%i)", core, lv, rv); + waveformEffectLeftVol = lv; + waveformEffectRightVol = rv; RETURN(0); } -void sceSasRevVON(u32 core, int param1, int param2) +void sceSasRevVON(u32 core, int dry, int wet) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasRevEVOL(core=%08x, param1=%i, param2=%i)", core, param1, param2); + DEBUG_LOG(HLE,"0=sceSasRevVON(core=%08x, dry=%i, wet=%i)", core, dry, wet); + waveformEffectIsDryOn = (dry > 0); + waveformEffectIsWetOn = (wet > 0); RETURN(0); } -void sceSasGetOutputMode(u32 core, int param1, int param2) +u32 sceSasGetGrain(u32 core) { - DEBUG_LOG(HLE,"UNIMPL 0=sceSasGetOutputMode(core=%08x, param1=%i, param2=%i)", core, param1, param2); - RETURN(0); + DEBUG_LOG(HLE,"0=sceSasGetGrain(core=%08x)", core); + return grainSamples; } +u32 sceSasSetGrain(u32 core, int grain) +{ + DEBUG_LOG(HLE,"0=sceSasSetGrain(core=%08x, grain=%i)", core, grain); + grainSamples=grain; + return 0; +} + + +u32 sceSasGetOutputMode(u32 core) +{ + DEBUG_LOG(HLE,"0=sceSasGetOutputMode(core=%08x)", core); + return output; +} + +u32 sceSasSetOutputMode(u32 core, u32 outputMode) +{ + DEBUG_LOG(HLE,"0=sceSasSetOutputMode(core=%08x, outputMode=%i)", core, outputMode); + output=outputMode; + return 0; +} + +u32 sceSasGetAllEnvelopeHeights(u32 core, u32 heightsAddr) +{ + DEBUG_LOG(HLE,"0=sceSasGetAllEnvelopeHeights(core=%08x, heightsAddr=%i)", core, heightsAddr); + Memory::Memset(heightsAddr, 0 , sas.length * 4); + for (int i = 0; i < sas.length ; i++) { + int voiceHeight = sas.voices[i].height; + } + return 0; +} + +void sceSasSetVoicePCM(u32 core, int voiceNum, u32 pcmAddr, int size, int loop) +{ + DEBUG_LOG(HLE,"0=sceSasSetVoicePCM(core=%08x, voicenum=%i, pcmAddr=%08x, size=%i, loop=%i)",core, voiceNum, pcmAddr, size, loop); + Voice &v = sas.voices[voiceNum]; + v.pcmAddr = pcmAddr; + v.size = size; + v.loop = loop; + v.playing = true; + RETURN(0); +} const HLEFunction sceSasCore[] = { {0x42778a9f, WrapU_UUUUU, "__sceSasInit"}, // (SceUID * sasCore, int grain, int maxVoices, int outputMode, int sampleRate) - {0xa3589d81, WrapV_U<_sceSasCore>, "__sceSasCore"}, - {0x50a14dfc, WrapV_U<_sceSasCoreWithMix>, "__sceSasCoreWithMix"}, // Process and mix into buffer (int sasCore, int sasInOut, int leftVolume, int rightVolume) - {0x68a46b95, WrapU_V, "__sceSasGetEndFlag"}, // int sasCore + {0xa3589d81, WrapV_UU<_sceSasCore>, "__sceSasCore"}, + {0x50a14dfc, WrapV_UU<_sceSasCoreWithMix>, "__sceSasCoreWithMix"}, // Process and mix into buffer (int sasCore, int sasInOut, int leftVolume, int rightVolume) + {0x68a46b95, WrapU_U, "__sceSasGetEndFlag"}, // int sasCore {0x440ca7d8, WrapV_UIIIII, "__sceSasSetVolume"}, {0xad84d37f, WrapV_UII, "__sceSasSetPitch"}, {0x99944089, WrapV_UIUII, "__sceSasSetVoice"}, // (int sasCore, int voice, int vagAddr, int size, int loopmode) @@ -489,16 +560,16 @@ const HLEFunction sceSasCore[] = {0xd5a229c9, WrapV_UII, "__sceSasRevEVOL"}, // (int sasCore, int leftVol, int rightVol) // effect volume {0x33d4ab37, WrapV_UI, "__sceSasRevType"}, // (int sasCore, int type) {0x267a6dd2, WrapV_UII, "__sceSasRevParam"}, // (int sasCore, int delay, int feedback) - {0x2c8e6ab3, WrapU_V, "__sceSasGetPauseFlag"}, // int sasCore - {0x787d04d5, 0, "__sceSasSetPause"}, + {0x2c8e6ab3, WrapU_U, "__sceSasGetPauseFlag"}, // int sasCore + {0x787d04d5, WrapU_UII, "__sceSasSetPause"}, {0xa232cbe6, 0, "__sceSasSetTriangularWave"}, // (int sasCore, int voice, int unknown) {0xd5ebbbcd, 0, "__sceSasSetSteepWave"}, // (int sasCore, int voice, int unknown) // square wave? - {0xBD11B7C2, 0, "__sceSasGetGrain"}, - {0xd1e0a01e, 0, "__sceSasSetGrain"}, - {0xe175ef66, WrapV_UII, "__sceSasGetOutputmode"}, - {0xe855bf76, 0, "__sceSasSetOutputmode"}, - {0x07f58c24, 0, "__sceSasGetAllEnvelopeHeights"}, // (int sasCore, int heightAddr) 32-bit heights, 0-0x40000000 - {0xE1CD9561, 0, "__sceSasSetVoicePCM"}, + {0xBD11B7C2, WrapU_U, "__sceSasGetGrain"}, + {0xd1e0a01e, WrapU_UI, "__sceSasSetGrain"}, + {0xe175ef66, WrapU_U, "__sceSasGetOutputmode"}, + {0xe855bf76, WrapU_UU, "__sceSasSetOutputmode"}, + {0x07f58c24, WrapU_UU, "__sceSasGetAllEnvelopeHeights"}, // (int sasCore, int heightAddr) 32-bit heights, 0-0x40000000 + {0xE1CD9561, WrapV_UIUII, "__sceSasSetVoicePCM"}, }; void Register_sceSasCore() diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index 6ca72b69d0..d384a95c88 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -19,11 +19,29 @@ #include "sceVaudio.h" +void sceVaudioOutputBlockingFunction() +{ + WARN_LOG(HLE, "HACK sceVaudioOutputBlockingFunction(...)"); + RETURN(0); +} + +void sceVaudioChReserveFunction() +{ + WARN_LOG(HLE, "HACK sceVaudioChReserveFunction(...)"); + RETURN(0); +} + +void sceVaudioChReleaseFunction() +{ + WARN_LOG(HLE, "HACK sceVaudioChReleaseFunction(...)"); + RETURN(0); +} + const HLEFunction sceVaudio[] = { - {0x03b6807d, 0, "sceVaudio_0x03b6807d"}, - {0x67585dfd, 0, "sceVaudio_0x67585dfd"}, - {0x8986295e, 0, "sceVaudio_0x8986295e"}, + {0x03b6807d, sceVaudioOutputBlockingFunction, "sceVaudioOutputBlockingFunction"}, + {0x67585dfd, sceVaudioChReserveFunction, "sceVaudioChReserveFunction"}, + {0x8986295e, sceVaudioChReleaseFunction, "sceVaudioChReleaseFunction"}, }; void Register_sceVaudio() From eff0f8663f3369f8db61594736b9e2c6a80c8923 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 17:24:44 +0800 Subject: [PATCH 14/34] Change HACK to UNIMPL in sceAudio --- Core/HLE/sceVaudio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index d384a95c88..f1f2519f24 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -21,19 +21,19 @@ void sceVaudioOutputBlockingFunction() { - WARN_LOG(HLE, "HACK sceVaudioOutputBlockingFunction(...)"); + WARN_LOG(HLE, "UNIMPL sceVaudioOutputBlockingFunction(...)"); RETURN(0); } void sceVaudioChReserveFunction() { - WARN_LOG(HLE, "HACK sceVaudioChReserveFunction(...)"); + WARN_LOG(HLE, "UNIMPL sceVaudioChReserveFunction(...)"); RETURN(0); } void sceVaudioChReleaseFunction() { - WARN_LOG(HLE, "HACK sceVaudioChReleaseFunction(...)"); + WARN_LOG(HLE, "UNIMPL sceVaudioChReleaseFunction(...)"); RETURN(0); } From bfb0108959c021e5a2d90540746299b0de4232d0 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 17:26:04 +0800 Subject: [PATCH 15/34] Change HACK to UNIMPL in sceAudio --- Core/HLE/sceVaudio.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index d384a95c88..f1f2519f24 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -21,19 +21,19 @@ void sceVaudioOutputBlockingFunction() { - WARN_LOG(HLE, "HACK sceVaudioOutputBlockingFunction(...)"); + WARN_LOG(HLE, "UNIMPL sceVaudioOutputBlockingFunction(...)"); RETURN(0); } void sceVaudioChReserveFunction() { - WARN_LOG(HLE, "HACK sceVaudioChReserveFunction(...)"); + WARN_LOG(HLE, "UNIMPL sceVaudioChReserveFunction(...)"); RETURN(0); } void sceVaudioChReleaseFunction() { - WARN_LOG(HLE, "HACK sceVaudioChReleaseFunction(...)"); + WARN_LOG(HLE, "UNIMPL sceVaudioChReleaseFunction(...)"); RETURN(0); } From ba83f0041a0f669b56e96dfb1a9c9e9dfd4f9c67 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 17:29:53 +0800 Subject: [PATCH 16/34] Make struct WaveformEffect --- Core/HLE/sceSas.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index ef75567d18..11848edc82 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -43,6 +43,9 @@ static const int PSP_SAS_ADSR_RELEASE=8; int grainSamples; int output; + +struct WaveformEffect +{ int waveformEffectType; int waveformEffectDelay; int waveformEffectFeedback ; @@ -50,6 +53,7 @@ int waveformEffectLeftVol; int waveformEffectRightVol; int waveformEffectIsDryOn; int waveformEffectIsWetOn; +}; static const double f[5][2] = { { 0.0, 0.0 }, @@ -174,6 +178,7 @@ class SasInstance public: enum { NUM_VOICES = 32 }; Voice voices[NUM_VOICES]; + WaveformEffect waveformEffect; int grainSize; int maxVoices; int sampleRate; @@ -452,15 +457,15 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) void sceSasRevType(u32 core, int type) { DEBUG_LOG(HLE,"0=sceSasRevType(core=%08x, type=%i)", core, type); - waveformEffectType=type; + sas.waveformEffect.waveformEffectType=type; RETURN(0); } void sceSasRevParam(u32 core, int delay, int feedback) { DEBUG_LOG(HLE,"0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback); - waveformEffectDelay = delay; - waveformEffectFeedback = feedback; + sas.waveformEffect.waveformEffectDelay = delay; + sas.waveformEffect.waveformEffectFeedback = feedback; RETURN(0); } @@ -478,16 +483,16 @@ u32 sceSasGetPauseFlag(u32 core) void sceSasRevEVOL(u32 core, int lv, int rv) { DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, leftVolume=%i, rightVolume=%i)", core, lv, rv); - waveformEffectLeftVol = lv; - waveformEffectRightVol = rv; + sas.waveformEffect.waveformEffectLeftVol = lv; + sas.waveformEffect.waveformEffectRightVol = rv; RETURN(0); } void sceSasRevVON(u32 core, int dry, int wet) { DEBUG_LOG(HLE,"0=sceSasRevVON(core=%08x, dry=%i, wet=%i)", core, dry, wet); - waveformEffectIsDryOn = (dry > 0); - waveformEffectIsWetOn = (wet > 0); + sas.waveformEffect.waveformEffectIsDryOn = (dry > 0); + sas.waveformEffect.waveformEffectIsWetOn = (wet > 0); RETURN(0); } From 6cef08fd72f82e25bc7c421ccc34b57ec4991c81 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Sat, 8 Dec 2012 21:07:21 +0800 Subject: [PATCH 17/34] Remove prefix in struct WaveformEffect --- Core/HLE/sceSas.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Core/HLE/sceSas.cpp b/Core/HLE/sceSas.cpp index 11848edc82..96d864b80d 100644 --- a/Core/HLE/sceSas.cpp +++ b/Core/HLE/sceSas.cpp @@ -46,13 +46,13 @@ int output; struct WaveformEffect { -int waveformEffectType; -int waveformEffectDelay; -int waveformEffectFeedback ; -int waveformEffectLeftVol; -int waveformEffectRightVol; -int waveformEffectIsDryOn; -int waveformEffectIsWetOn; + int type; + int delay; + int feedback ; + int leftVol; + int rightVol; + int isDryOn; + int isWetOn; }; static const double f[5][2] = @@ -457,15 +457,15 @@ u32 sceSasGetEnvelopeHeight(u32 core, u32 voiceNum) void sceSasRevType(u32 core, int type) { DEBUG_LOG(HLE,"0=sceSasRevType(core=%08x, type=%i)", core, type); - sas.waveformEffect.waveformEffectType=type; + sas.waveformEffect.type=type; RETURN(0); } void sceSasRevParam(u32 core, int delay, int feedback) { DEBUG_LOG(HLE,"0=sceSasRevParam(core=%08x, delay=%i, feedback=%i)", core, delay, feedback); - sas.waveformEffect.waveformEffectDelay = delay; - sas.waveformEffect.waveformEffectFeedback = feedback; + sas.waveformEffect.delay = delay; + sas.waveformEffect.feedback = feedback; RETURN(0); } @@ -483,16 +483,16 @@ u32 sceSasGetPauseFlag(u32 core) void sceSasRevEVOL(u32 core, int lv, int rv) { DEBUG_LOG(HLE,"0=sceSasRevEVOL(core=%08x, leftVolume=%i, rightVolume=%i)", core, lv, rv); - sas.waveformEffect.waveformEffectLeftVol = lv; - sas.waveformEffect.waveformEffectRightVol = rv; + sas.waveformEffect.leftVol = lv; + sas.waveformEffect.rightVol = rv; RETURN(0); } void sceSasRevVON(u32 core, int dry, int wet) { DEBUG_LOG(HLE,"0=sceSasRevVON(core=%08x, dry=%i, wet=%i)", core, dry, wet); - sas.waveformEffect.waveformEffectIsDryOn = (dry > 0); - sas.waveformEffect.waveformEffectIsWetOn = (wet > 0); + sas.waveformEffect.isDryOn = (dry > 0); + sas.waveformEffect.isWetOn = (wet > 0); RETURN(0); } From f9b561ee42f0df883678d89e7126ba930cd3f984 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 7 Dec 2012 19:01:31 -0800 Subject: [PATCH 18/34] Implement priority unlocking for mutexes. --- Core/HLE/sceKernelMutex.cpp | 180 ++++++++++++++++++------------------ test.py | 5 +- 2 files changed, 93 insertions(+), 92 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 23232590ae..5c30aad005 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -161,6 +161,26 @@ void __KernelMutexEraseLock(Mutex *mutex) mutex->nm.lockThread = -1; } +std::vector::iterator __KernelMutexFindPriority(std::vector &waiting) +{ + _dbg_assert_msg_(HLE, !waiting.empty(), "__KernelMutexFindPriority: Trying to find best of no threads."); + + std::vector::iterator iter, end, best = waiting.end(); + u32 best_prio = 0xFFFFFFFF; + for (iter = waiting.begin(), end = waiting.end(); iter != end; ++iter) + { + u32 iter_prio = __KernelGetThreadPrio(*iter); + if (iter_prio < best_prio) + { + best = iter; + best_prio = iter_prio; + } + } + + _dbg_assert_msg_(HLE, best != waiting.end(), "__KernelMutexFindPriority: Returning invalid best thread."); + return best; +} + void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) { if (!mutexInitComplete) @@ -203,6 +223,33 @@ void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 opti RETURN(id); } +bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int result) +{ + SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + + // The waitID may be different after a timeout. + if (waitID != mutex->GetUID()) + return false; + + // If result is an error code, we're just letting it go. + if (result == 0) + { + int wVal = (int)__KernelGetWaitValue(threadID, error); + __KernelMutexAcquireLock(mutex, wVal, threadID); + } + + if (timeoutPtr != 0 && mutexWaitTimer != 0) + { + // Remove any event for this thread. + u64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); + Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); + } + + __KernelResumeThreadFromWait(threadID, result); + return true; +} + void sceKernelDeleteMutex(SceUID id) { DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id); @@ -213,24 +260,8 @@ void sceKernelDeleteMutex(SceUID id) bool wokeThreads = false; std::vector::iterator iter, end; for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter) - { - SceUID threadID = *iter; - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); - // The waitID may be different after a timeout. - if (waitID != id) - continue; + wokeThreads |= __KernelUnlockMutexForThread(mutex, *iter, error, SCE_KERNEL_ERROR_WAIT_DELETE); - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - if (timeoutPtr != 0 && mutexWaitTimer != 0) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE); - wokeThreads = true; - } if (mutex->nm.lockThread != -1) __KernelMutexEraseLock(mutex); mutex->waitingThreads.clear(); @@ -289,37 +320,17 @@ bool __KernelUnlockMutex(Mutex *mutex, u32 &error) { __KernelMutexEraseLock(mutex); - // TODO: PSP_MUTEX_ATTR_PRIORITY bool wokeThreads = false; - std::vector::iterator iter, end; -retry: - for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter) + std::vector::iterator iter; + while (!wokeThreads && !mutex->waitingThreads.empty()) { - SceUID threadID = *iter; - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); - // The waitID may be different after a timeout. - if (waitID != mutex->GetUID()) - { - mutex->waitingThreads.erase(iter); - goto retry; - } + if ((mutex->nm.attr & PSP_MUTEX_ATTR_PRIORITY) != 0) + iter = __KernelMutexFindPriority(mutex->waitingThreads); + else + iter = mutex->waitingThreads.begin(); - int wVal = (int)__KernelGetWaitValue(threadID, error); - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - - __KernelMutexAcquireLock(mutex, wVal, threadID); - - if (timeoutPtr != 0 && mutexWaitTimer != 0) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, 0); - wokeThreads = true; + wokeThreads |= __KernelUnlockMutexForThread(mutex, *iter, error, 0); mutex->waitingThreads.erase(iter); - break; } if (!wokeThreads) @@ -530,6 +541,33 @@ void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int ini RETURN(0); } +bool __KernelUnlockLwMutexForThread(LwMutex *mutex, NativeLwMutexWorkarea &workarea, SceUID threadID, u32 &error, int result) +{ + SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + + // The waitID may be different after a timeout. + if (waitID != mutex->GetUID()) + return false; + + // If result is an error code, we're just letting it go. + if (result == 0) + { + workarea.lockLevel = (int) __KernelGetWaitValue(threadID, error); + workarea.lockThread = threadID; + } + + if (timeoutPtr != 0 && lwMutexWaitTimer != 0) + { + // Remove any event for this thread. + u64 cyclesLeft = CoreTiming::UnscheduleEvent(lwMutexWaitTimer, threadID); + Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); + } + + __KernelResumeThreadFromWait(threadID, result); + return true; +} + void sceKernelDeleteLwMutex(u32 workareaPtr) { DEBUG_LOG(HLE,"sceKernelDeleteLwMutex(%08x)", workareaPtr); @@ -550,24 +588,7 @@ void sceKernelDeleteLwMutex(u32 workareaPtr) bool wokeThreads = false; std::vector::iterator iter, end; for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter) - { - SceUID threadID = *iter; - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); - // The waitID may be different after a timeout. - if (waitID != mutex->GetUID()) - continue; - - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - if (timeoutPtr != 0 && lwMutexWaitTimer != 0) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(lwMutexWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE); - wokeThreads = true; - } + wokeThreads |= __KernelUnlockLwMutexForThread(mutex, workarea, *iter, error, SCE_KERNEL_ERROR_WAIT_DELETE); mutex->waitingThreads.clear(); RETURN(kernelObjects.Destroy(workarea.uid)); @@ -641,38 +662,17 @@ bool __KernelUnlockLwMutex(NativeLwMutexWorkarea &workarea, u32 &error) return false; } - // TODO: PSP_MUTEX_ATTR_PRIORITY bool wokeThreads = false; - std::vector::iterator iter, end; -retry: - for (iter = mutex->waitingThreads.begin(), end = mutex->waitingThreads.end(); iter != end; ++iter) + std::vector::iterator iter; + while (!wokeThreads && !mutex->waitingThreads.empty()) { - SceUID threadID = *iter; - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); - // The waitID may be different after a timeout. - if (waitID != mutex->GetUID()) - { - mutex->waitingThreads.erase(iter); - goto retry; - } + if ((mutex->nm.attr & PSP_MUTEX_ATTR_PRIORITY) != 0) + iter = __KernelMutexFindPriority(mutex->waitingThreads); + else + iter = mutex->waitingThreads.begin(); - int wVal = (int)__KernelGetWaitValue(threadID, error); - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - - workarea.lockLevel = wVal; - workarea.lockThread = threadID; - - if (timeoutPtr != 0 && lwMutexWaitTimer != 0) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(lwMutexWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, 0); - wokeThreads = true; + wokeThreads |= __KernelUnlockLwMutexForThread(mutex, workarea, *iter, error, 0); mutex->waitingThreads.erase(iter); - break; } if (!wokeThreads) diff --git a/test.py b/test.py index e6b53b375f..e35edb93bc 100755 --- a/test.py +++ b/test.py @@ -60,13 +60,16 @@ tests_good = [ "threads/lwmutex/create/create", "threads/lwmutex/delete/delete", "threads/lwmutex/lock/lock", + "threads/lwmutex/priority/priority", "threads/lwmutex/try/try", "threads/lwmutex/try600/try600", "threads/lwmutex/unlock/unlock", "threads/mbx/mbx", + "threads/mutex/mutex", "threads/mutex/create/create", "threads/mutex/delete/delete", "threads/mutex/lock/lock", + "threads/mutex/priority/priority", "threads/mutex/try/try", "threads/mutex/unlock/unlock", "threads/semaphores/semaphores", @@ -89,8 +92,6 @@ tests_next = [ "threads/fpl/fpl", "threads/k0/k0", "threads/msgpipe/msgpipe", - "threads/mutex/mutex", - "threads/mutex/priority/priority", "threads/scheduling/scheduling", "threads/semaphores/priority/priority", "threads/threads/threads", From 1a77b22e3aafce192e2acfeac4e36351ff0e58d9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 7 Dec 2012 19:31:59 -0800 Subject: [PATCH 19/34] Implement priority signaling for semaphores. --- Core/HLE/sceKernelSemaphore.cpp | 118 ++++++++++++++++++-------------- test.py | 2 +- 2 files changed, 67 insertions(+), 53 deletions(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index b53e7d092f..4f2bf3f5af 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -70,39 +70,73 @@ void __KernelSemaInit() semaInitComplete = true; } +// Returns whether the thread should be removed. +bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &error, int result, bool &wokeThreads) +{ + SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + + // The waitID may be different after a timeout. + if (waitID != s->GetUID()) + return true; + + // If result is an error code, we're just letting it go. + if (result == 0) + { + int wVal = (int) __KernelGetWaitValue(threadID, error); + if (wVal > s->ns.currentCount) + return false; + + s->ns.currentCount -= wVal; + s->ns.numWaitThreads--; + } + + if (timeoutPtr != 0 && semaWaitTimer != 0) + { + // Remove any event for this thread. + u64 cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); + Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); + } + + __KernelResumeThreadFromWait(threadID, result); + wokeThreads = true; + return true; +} + // Resume all waiting threads (for delete / cancel.) // Returns true if it woke any threads. bool __KernelClearSemaThreads(Semaphore *s, int reason) { + u32 error; bool wokeThreads = false; - - // TODO: PSP_SEMA_ATTR_PRIORITY - std::vector::iterator iter; - for (iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter) - { - u32 error; - SceUID threadID = *iter; - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error); - // The waitID may be different after a timeout. - if (waitID != s->GetUID()) - continue; - - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - if (timeoutPtr != 0 && semaWaitTimer != 0) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, reason); - wokeThreads = true; - } + std::vector::iterator iter, end; + for (iter = s->waitingThreads.begin(), end = s->waitingThreads.end(); iter != end; ++iter) + __KernelUnlockSemaForThread(s, *iter, error, reason, wokeThreads); s->waitingThreads.clear(); return wokeThreads; } +std::vector::iterator __KernelSemaFindPriority(std::vector &waiting, std::vector::iterator begin) +{ + _dbg_assert_msg_(HLE, !waiting.empty(), "__KernelSemaFindPriority: Trying to find best of no threads."); + + std::vector::iterator iter, end, best = waiting.end(); + u32 best_prio = 0xFFFFFFFF; + for (iter = begin, end = waiting.end(); iter != end; ++iter) + { + u32 iter_prio = __KernelGetThreadPrio(*iter); + if (iter_prio < best_prio) + { + best = iter; + best_prio = iter_prio; + } + } + + _dbg_assert_msg_(HLE, best != waiting.end(), "__KernelSemaFindPriority: Returning invalid best thread."); + return best; +} + // int sceKernelCancelSema(SceUID id, int newCount, int *numWaitThreads); // void because it changes threads. void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) @@ -239,39 +273,19 @@ void sceKernelSignalSema(SceUID id, int signal) // We need to set the return value BEFORE processing other threads. RETURN(0); - // TODO: PSP_SEMA_ATTR_PRIORITY bool wokeThreads = false; - std::vector::iterator iter; + std::vector::iterator iter, end, best; retry: - for (iter = s->waitingThreads.begin(); iter != s->waitingThreads.end(); ++iter) + for (iter = s->waitingThreads.begin(), end = s->waitingThreads.end(); iter != end; ++iter) { - SceUID threadID = *iter; - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error); - // The waitID may be different after a timeout. - if (waitID != s->GetUID()) + if ((s->ns.attr & PSP_SEMA_ATTR_PRIORITY) != 0) + best = __KernelSemaFindPriority(s->waitingThreads, iter); + else + best = iter; + + if (__KernelUnlockSemaForThread(s, *best, error, 0, wokeThreads)) { - s->waitingThreads.erase(iter); - goto retry; - } - - int wVal = (int)__KernelGetWaitValue(threadID, error); - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - - if (wVal <= s->ns.currentCount) - { - s->ns.currentCount -= wVal; - s->ns.numWaitThreads--; - - if (timeoutPtr != 0 && semaWaitTimer != 0) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, 0); - s->waitingThreads.erase(iter); - wokeThreads = true; + s->waitingThreads.erase(best); goto retry; } } diff --git a/test.py b/test.py index e35edb93bc..81f815872f 100755 --- a/test.py +++ b/test.py @@ -77,6 +77,7 @@ tests_good = [ "threads/semaphores/create/create", "threads/semaphores/delete/delete", "threads/semaphores/poll/poll", + "threads/semaphores/priority/priority", "threads/semaphores/refer/refer", "threads/semaphores/signal/signal", "threads/semaphores/wait/wait", @@ -93,7 +94,6 @@ tests_next = [ "threads/k0/k0", "threads/msgpipe/msgpipe", "threads/scheduling/scheduling", - "threads/semaphores/priority/priority", "threads/threads/threads", "threads/vpl/vpl", "threads/vtimers/vtimer", From ee1a729157a9ae02a5fda22550c194baf553ae8f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 7 Dec 2012 22:18:40 -0800 Subject: [PATCH 20/34] Turns out *CB() fires even when it succeeds. --- Core/HLE/sceKernelMutex.cpp | 6 ++++++ Core/HLE/sceKernelSemaphore.cpp | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 5c30aad005..071ba408e0 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -430,6 +430,9 @@ void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) if (__KernelLockMutex(mutex, count, error)) { RETURN(0); + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) + __KernelExecutePendingMipsCalls(); } else if (error) RETURN(error); @@ -789,6 +792,9 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) { Memory::WriteStruct(workareaPtr, &workarea); RETURN(0); + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) + __KernelExecutePendingMipsCalls(); } else if (error) RETURN(error); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 4f2bf3f5af..c41d4fb9cb 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -353,7 +353,15 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba RETURN(0); if (s->ns.currentCount >= wantedCount) + { s->ns.currentCount -= wantedCount; + if (processCallbacks) + { + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) + __KernelExecutePendingMipsCalls(); + } + } else { s->ns.numWaitThreads++; From 3f43ab5bb5d80dde3c9c00da16c675726ddc24b9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 7 Dec 2012 22:25:42 -0800 Subject: [PATCH 21/34] Callbacks are always fired on their own thread. At least, as far as I can tell. It does make sense too. --- Core/HLE/sceKernelThread.cpp | 8 ++++---- Core/HLE/sceKernelThread.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 387bef79cf..76766827af 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1479,7 +1479,7 @@ void sceKernelNotifyCallback() u32 arg = PARAM(1); DEBUG_LOG(HLE,"sceKernelNotifyCallback(%i, %i)", cbId, arg); - __KernelNotifyCallback(THREAD_CALLBACK_USER_DEFINED, __KernelGetCurThread(), cbId, arg); + __KernelNotifyCallback(THREAD_CALLBACK_USER_DEFINED, cbId, arg); RETURN(0); } @@ -1924,7 +1924,7 @@ u32 __KernelUnregisterCallback(RegisteredCallbackType type, SceUID cbId) } } -void __KernelNotifyCallback(RegisteredCallbackType type, SceUID threadId, SceUID cbId, int notifyArg) +void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg) { u32 error; @@ -1937,7 +1937,7 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID threadId, SceUID cb->nc.notifyCount++; cb->nc.notifyArg = notifyArg; - Thread *t = kernelObjects.Get(threadId, error); + Thread *t = kernelObjects.Get(cb->nc.threadId, error); t->readyCallbacks[type].remove(cbId); t->readyCallbacks[type].push_back(cbId); } @@ -1949,7 +1949,7 @@ u32 __KernelNotifyCallbackType(RegisteredCallbackType type, SceUID cbId, int not Thread *t = *iter; for (std::set::iterator citer = t->registeredCallbacks[type].begin(); citer != t->registeredCallbacks[type].end(); citer++) { if (cbId == -1 || cbId == *citer) { - __KernelNotifyCallback(type, t->GetUID(), *citer, notifyArg); + __KernelNotifyCallback(type, *citer, notifyArg); } } } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 3782ccef33..de0ee52f3f 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -170,7 +170,7 @@ bool __KernelForceCallbacks(); class Thread; void __KernelSwitchContext(Thread *target, const char *reason); bool __KernelExecutePendingMipsCalls(); -void __KernelNotifyCallback(RegisteredCallbackType type, SceUID threadId, SceUID cbId, int notifyArg); +void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg); // A call into game code. These can be pending on a thread. // Similar to Callback-s (NOT CallbackInfos) in JPCSP. From 771cf3981172abfb543a684a8595bd533618c0bf Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 01:23:27 -0800 Subject: [PATCH 22/34] Don't reschedule in sceKernelCheckCallback(). --- Core/HLE/sceKernelThread.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 76766827af..25fa8161ee 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1891,8 +1891,6 @@ void sceKernelCheckCallback() { __KernelExecutePendingMipsCalls(); } else { RETURN(0); - DEBUG_LOG(HLE,"sceKernelCheckCallback() - no callbacks to process, simply rescheduling"); - __KernelReSchedule(false, "checkcallbackhack"); } } From 9cd47e210b8d71bffe751408d3f4f6473d23f790 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 11:23:20 -0800 Subject: [PATCH 23/34] Callbacks: Don't trust s0 to retain the call id. Patapon 2 at least was not during a call, preventing injection. Hardware doesn't have to deal with injection so not a problem. --- Core/HLE/sceKernelThread.cpp | 12 ++++++++++-- Core/HLE/sceKernelThread.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 25fa8161ee..70b36bb0a9 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -256,6 +256,7 @@ public: SceUID moduleId; bool isProcessingCallbacks; + u32 currentCallbackId; ThreadContext context; @@ -1593,7 +1594,7 @@ void Thread::setReturnValue(u32 retval) { if (this == currentThread) { if (g_inCbCount) { - int callId = currentMIPS->r[MIPS_REG_CALL_ID]; + int callId = this->currentCallbackId; MipsCall *call = mipsCalls.get(callId); if (call) { call->savedV0 = retval; @@ -1713,12 +1714,16 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId) call->savedV0 = currentMIPS->r[MIPS_REG_V0]; call->savedV1 = currentMIPS->r[MIPS_REG_V1]; call->savedIdRegister = currentMIPS->r[MIPS_REG_CALL_ID]; + call->savedId = currentThread->currentCallbackId; call->returnVoid = false; // Set up the new state currentMIPS->pc = call->entryPoint; currentMIPS->r[MIPS_REG_RA] = __KernelMipsCallReturnAddress(); + // We put this two places in case the game overwrites it. + // We may want it later to "inject" return values. currentMIPS->r[MIPS_REG_CALL_ID] = callId; + currentThread->currentCallbackId = callId; for (int i = 0; i < call->numArgs; i++) { currentMIPS->r[MIPS_REG_A0 + i] = call->args[i]; } @@ -1728,7 +1733,9 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId) void __KernelReturnFromMipsCall() { - int callId = currentMIPS->r[MIPS_REG_CALL_ID]; + int callId = currentThread->currentCallbackId; + if (currentMIPS->r[MIPS_REG_CALL_ID] != callId) + WARN_LOG(HLE, "__KernelReturnFromMipsCall(): s0 is %08x != %08x", currentMIPS->r[MIPS_REG_CALL_ID], callId); MipsCall *call = mipsCalls.pop(callId); @@ -1745,6 +1752,7 @@ void __KernelReturnFromMipsCall() currentMIPS->r[MIPS_REG_V0] = call->savedV0; currentMIPS->r[MIPS_REG_V1] = call->savedV1; currentMIPS->r[MIPS_REG_CALL_ID] = call->savedIdRegister; + currentThread->currentCallbackId = call->savedId; g_inCbCount--; diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index de0ee52f3f..2447874fec 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -188,6 +188,7 @@ struct MipsCall { u32 savedV1; bool returnVoid; const char *tag; + u32 savedId; }; enum ThreadStatus { From ff7e1d7be91fb1c28f3d416b20da8fa189bcb99b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 15:28:54 -0800 Subject: [PATCH 24/34] Fix running threads in processing callbacks state. ActionAfterMipsCall was setting it back when it saved it. --- Core/HLE/sceKernelThread.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 70b36bb0a9..ccbbfddc7f 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1664,6 +1664,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo after->waitType = thread->nt.waitType; after->waitId = thread->nt.waitID; after->waitInfo = thread->waitInfo; + after->isProcessingCallbacks = thread->isProcessingCallbacks; afterAction = after; @@ -1841,8 +1842,9 @@ void ActionAfterCallback::run() { // Check callbacks on the current thread only. // Returns true if any callbacks were processed on the current thread. -bool __KernelCheckThreadCallbacks(Thread *thread) { - if (!thread->isProcessingCallbacks) +bool __KernelCheckThreadCallbacks(Thread *thread, bool force) +{ + if (!thread->isProcessingCallbacks && !force) return false; for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++) { @@ -1865,7 +1867,7 @@ bool __KernelCheckCallbacks() { for (std::vector::iterator iter = threadqueue.begin(); iter != threadqueue.end(); iter++) { Thread *thread = *iter; - if (thread->isProcessingCallbacks && __KernelCheckThreadCallbacks(thread)) { + if (__KernelCheckThreadCallbacks(thread, false)) { processed = true; } } @@ -1877,13 +1879,7 @@ bool __KernelForceCallbacks() { Thread *curThread = __GetCurrentThread(); - // This thread can now process callbacks. - curThread->isProcessingCallbacks = true; - - bool callbacksProcessed = __KernelCheckThreadCallbacks(curThread); - - // Note - same thread as above - checking callbacks may switch threads. - curThread->isProcessingCallbacks = false; + bool callbacksProcessed = __KernelCheckThreadCallbacks(curThread, true); return callbacksProcessed; } From fda41752e8239aad189c6dc1140403fc1ce46728 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 18:40:20 -0800 Subject: [PATCH 25/34] Simplify the API for HLE funcs to do callbacks. __KernelWaitCurThread() already (ultimately) calls __KernelCheckCallbacks. --- Core/HLE/sceDisplay.cpp | 3 --- Core/HLE/sceKernelEventFlag.cpp | 1 - Core/HLE/sceKernelMutex.cpp | 10 ++-------- Core/HLE/sceKernelSemaphore.cpp | 8 +------- Core/HLE/sceKernelThread.cpp | 20 ++++++++++---------- Core/HLE/sceUmd.cpp | 5 +---- 6 files changed, 14 insertions(+), 33 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index f8a0609c6b..c1938e3f86 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -337,21 +337,18 @@ void sceDisplayWaitVblankCB() { DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); - __KernelCheckCallbacks(); } void sceDisplayWaitVblankStartCB() { DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()"); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); - __KernelCheckCallbacks(); } void sceDisplayWaitVblankStartMultiCB() { DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()"); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); - __KernelCheckCallbacks(); } void sceDisplayGetVcount() diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index bd8478ecdc..e2ae736575 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -232,7 +232,6 @@ void sceKernelWaitEventFlagCB(SceUID id, u32 bits, u32 wait, u32 outBitsPtr, u32 timeout = Memory::Read_U32(timeoutPtr); __KernelWaitCurThread(WAITTYPE_EVENTFLAG, id, 0, 0, true); // sets RETURN - __KernelCheckCallbacks(); } } else diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 071ba408e0..c9936f48a3 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -430,9 +430,7 @@ void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) if (__KernelLockMutex(mutex, count, error)) { RETURN(0); - bool callbacksProcessed = __KernelForceCallbacks(); - if (callbacksProcessed) - __KernelExecutePendingMipsCalls(); + __KernelForceCallbacks(); } else if (error) RETURN(error); @@ -441,7 +439,6 @@ void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) mutex->waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitMutex(mutex, timeoutPtr); __KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, true); - __KernelCheckCallbacks(); } } @@ -792,9 +789,7 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) { Memory::WriteStruct(workareaPtr, &workarea); RETURN(0); - bool callbacksProcessed = __KernelForceCallbacks(); - if (callbacksProcessed) - __KernelExecutePendingMipsCalls(); + __KernelForceCallbacks(); } else if (error) RETURN(error); @@ -806,7 +801,6 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) mutex->waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitLwMutex(mutex, timeoutPtr); __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, true); - __KernelCheckCallbacks(); } else RETURN(error); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index c41d4fb9cb..fccd3d0c6c 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -356,11 +356,7 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba { s->ns.currentCount -= wantedCount; if (processCallbacks) - { - bool callbacksProcessed = __KernelForceCallbacks(); - if (callbacksProcessed) - __KernelExecutePendingMipsCalls(); - } + __KernelForceCallbacks(); } else { @@ -368,8 +364,6 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba s->waitingThreads.push_back(__KernelGetCurThread()); __KernelSetSemaTimeout(s, timeoutPtr); __KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, timeoutPtr, processCallbacks); - if (processCallbacks) - __KernelCheckCallbacks(); } } else diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index ccbbfddc7f..0b05c6dc29 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -959,7 +959,6 @@ void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) if (startThread->nt.status != THREADSTATUS_DORMANT) { -printf("NOT DORMANT\n"); //Not dormant, WTF? RETURN(ERROR_KERNEL_THREAD_IS_NOT_DORMANT); return; @@ -1276,8 +1275,6 @@ void sceKernelDelayThreadCB() SceUID curThread = __KernelGetCurThread(); __KernelScheduleWakeup(curThread, usec); __KernelWaitCurThread(WAITTYPE_DELAY, curThread, 0, 0, true); - if (__KernelCheckCallbacks()) - __KernelExecutePendingMipsCalls(); } void sceKernelDelayThread() @@ -1364,7 +1361,6 @@ void sceKernelSleepThreadCB() DEBUG_LOG(HLE, "sceKernelSleepThreadCB()"); __KernelSleepThread(true); __KernelCheckCallbacks(); - __KernelExecutePendingMipsCalls(); } void sceKernelWaitThreadEnd() @@ -1758,8 +1754,7 @@ void __KernelReturnFromMipsCall() g_inCbCount--; // yeah! back in the real world, let's keep going. Should we process more callbacks? - __KernelCheckCallbacks(); - if (!__KernelExecutePendingMipsCalls()) + if (!__KernelCheckCallbacks()) { // We should definitely reschedule as we might still be asleep. - except if we came from checkcallbacks? __KernelReSchedule("return from callback"); @@ -1872,6 +1867,9 @@ bool __KernelCheckCallbacks() { } } // } while (processed && currentThread == __KernelGetCurThread()); + + if (processed) + return __KernelExecutePendingMipsCalls(); return processed; } @@ -1880,19 +1878,21 @@ bool __KernelForceCallbacks() Thread *curThread = __GetCurrentThread(); bool callbacksProcessed = __KernelCheckThreadCallbacks(curThread, true); + if (callbacksProcessed) + __KernelExecutePendingMipsCalls(); return callbacksProcessed; } -void sceKernelCheckCallback() { - Thread *curThread = __GetCurrentThread(); +void sceKernelCheckCallback() +{ + // Start with yes. + RETURN(1); bool callbacksProcessed = __KernelForceCallbacks(); if (callbacksProcessed) { - curThread->setReturnValue(1); ERROR_LOG(HLE,"sceKernelCheckCallback() - processed a callback."); - __KernelExecutePendingMipsCalls(); } else { RETURN(0); } diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 1a2e40afa8..8dda1dc6a5 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -268,9 +268,7 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout); - bool callbacksProcessed = __KernelForceCallbacks(); - if (callbacksProcessed) - __KernelExecutePendingMipsCalls(); + __KernelForceCallbacks(); } else { @@ -284,7 +282,6 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) __UmdWaitStat(timeout); __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true); - __KernelCheckCallbacks(); } } From 7044fafe84a6275fbd2f8a9d2724a245243332c4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 19:13:33 -0800 Subject: [PATCH 26/34] Always run callbacks when rescheduling. Not just when rescheduling because of a *CB() func. --- Core/HLE/sceKernelThread.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 0b05c6dc29..fb795321b5 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -754,20 +754,27 @@ Thread *__KernelNextThread() { void __KernelReSchedule(const char *reason) { - // cancel rescheduling when in interrupt or callback, otherwise everything will be fucked up - if (__IsInInterrupt() || __KernelInCallback()) - { - reason = "In Interrupt Or Callback"; - return; - } + // cancel rescheduling when in interrupt or callback, otherwise everything will be fucked up + if (__IsInInterrupt() || __KernelInCallback()) + { + reason = "In Interrupt Or Callback"; + return; + } - // Execute any pending events while we're doing scheduling. - CoreTiming::Advance(); - if (__IsInInterrupt() || __KernelInCallback()) - { - reason = "In Interrupt Or Callback"; - return; - } + // This may get us running a callback, don't reschedule out of it. + if (__KernelCheckCallbacks()) + { + reason = "Began interrupt or callback."; + return; + } + + // Execute any pending events while we're doing scheduling. + CoreTiming::Advance(); + if (__IsInInterrupt() || __KernelInCallback()) + { + reason = "In Interrupt Or Callback"; + return; + } retry: Thread *nextThread = __KernelNextThread(); @@ -793,7 +800,6 @@ void __KernelReSchedule(bool doCallbacks, const char *reason) { if (thread) thread->isProcessingCallbacks = doCallbacks; - __KernelCheckCallbacks(); } __KernelReSchedule(reason); if (doCallbacks && thread == currentThread) { From 92e519c24bedf9710fa9a80c7ee2bd5f6b0e9fbc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 20:09:20 -0800 Subject: [PATCH 27/34] Don't always reschedule after running callbacks. When not waiting, usually only local callbacks are called. Some functions are unique though. --- Core/HLE/sceKernelThread.cpp | 33 ++++++++++++++++++--------------- Core/HLE/sceKernelThread.h | 3 ++- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index fb795321b5..acb46f66bf 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -268,7 +268,7 @@ public: u32 stackBlock; }; -void __KernelExecuteMipsCallOnCurrentThread(int callId); +void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter); int g_inCbCount = 0; @@ -1626,7 +1626,7 @@ void __KernelSwitchContext(Thread *target, const char *reason) currentThread->nt.waitType = WAITTYPE_NONE; currentThread->nt.waitID = 0; - __KernelExecutePendingMipsCalls(); + __KernelExecutePendingMipsCalls(true); } void __KernelChangeThreadState(Thread *thread, ThreadStatus newStatus) { @@ -1657,7 +1657,8 @@ bool __CanExecuteCallbackNow(Thread *thread) { return g_inCbCount == 0; } -void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bool returnVoid, std::vector args) { +void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bool returnVoid, std::vector args, bool reschedAfter) +{ if (thread) { ActionAfterMipsCall *after = new ActionAfterMipsCall(); after->chainedAction = afterAction; @@ -1692,7 +1693,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo if (__CanExecuteCallbackNow(thread)) { thread = currentThread; __KernelChangeThreadState(thread, THREADSTATUS_RUNNING); - __KernelExecuteMipsCallOnCurrentThread(callId); + __KernelExecuteMipsCallOnCurrentThread(callId, reschedAfter); called = true; } } @@ -1703,7 +1704,7 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, bo } } -void __KernelExecuteMipsCallOnCurrentThread(int callId) +void __KernelExecuteMipsCallOnCurrentThread(int callId, bool reschedAfter) { if (g_inCbCount > 0) { WARN_LOG(HLE, "__KernelExecuteMipsCallOnCurrentThread: Already in a callback!"); @@ -1719,6 +1720,7 @@ void __KernelExecuteMipsCallOnCurrentThread(int callId) call->savedIdRegister = currentMIPS->r[MIPS_REG_CALL_ID]; call->savedId = currentThread->currentCallbackId; call->returnVoid = false; + call->reschedAfter = reschedAfter; // Set up the new state currentMIPS->pc = call->entryPoint; @@ -1760,14 +1762,15 @@ void __KernelReturnFromMipsCall() g_inCbCount--; // yeah! back in the real world, let's keep going. Should we process more callbacks? - if (!__KernelCheckCallbacks()) + if (!__KernelExecutePendingMipsCalls(call->reschedAfter)) { - // We should definitely reschedule as we might still be asleep. - except if we came from checkcallbacks? - __KernelReSchedule("return from callback"); + // Sometimes, we want to stay on the thread. + if (call->reschedAfter) + __KernelReSchedule("return from callback"); } } -bool __KernelExecutePendingMipsCalls() +bool __KernelExecutePendingMipsCalls(bool reschedAfter) { Thread *thread = __GetCurrentThread(); @@ -1781,7 +1784,7 @@ bool __KernelExecutePendingMipsCalls() // Pop off the first pending mips call int callId = thread->pendingMipsCalls.front(); thread->pendingMipsCalls.pop_front(); - __KernelExecuteMipsCallOnCurrentThread(callId); + __KernelExecuteMipsCallOnCurrentThread(callId, reschedAfter); return true; } return false; @@ -1797,7 +1800,7 @@ public: }; // Executes the callback, when it next is context switched to. -void __KernelRunCallbackOnThread(SceUID cbId, Thread *thread) +void __KernelRunCallbackOnThread(SceUID cbId, Thread *thread, bool reschedAfter) { u32 error; Callback *cb = kernelObjects.Get(cbId, error); @@ -1821,7 +1824,7 @@ void __KernelRunCallbackOnThread(SceUID cbId, Thread *thread) cb->nc.notifyArg = 0; Action *action = new ActionAfterCallback(cbId); - __KernelCallAddress(thread, cb->nc.entrypoint, action, false, args); + __KernelCallAddress(thread, cb->nc.entrypoint, action, false, args, reschedAfter); } void ActionAfterCallback::run() { @@ -1852,7 +1855,7 @@ bool __KernelCheckThreadCallbacks(Thread *thread, bool force) if (thread->readyCallbacks[i].size()) { SceUID readyCallback = thread->readyCallbacks[i].front(); thread->readyCallbacks[i].pop_front(); - __KernelRunCallbackOnThread(readyCallback, thread); // makes pending + __KernelRunCallbackOnThread(readyCallback, thread, !force); // makes pending return true; } } @@ -1875,7 +1878,7 @@ bool __KernelCheckCallbacks() { // } while (processed && currentThread == __KernelGetCurThread()); if (processed) - return __KernelExecutePendingMipsCalls(); + return __KernelExecutePendingMipsCalls(true); return processed; } @@ -1885,7 +1888,7 @@ bool __KernelForceCallbacks() bool callbacksProcessed = __KernelCheckThreadCallbacks(curThread, true); if (callbacksProcessed) - __KernelExecutePendingMipsCalls(); + __KernelExecutePendingMipsCalls(false); return callbacksProcessed; } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 2447874fec..1770c62130 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -169,7 +169,7 @@ bool __KernelCheckCallbacks(); bool __KernelForceCallbacks(); class Thread; void __KernelSwitchContext(Thread *target, const char *reason); -bool __KernelExecutePendingMipsCalls(); +bool __KernelExecutePendingMipsCalls(bool reschedAfter); void __KernelNotifyCallback(RegisteredCallbackType type, SceUID cbId, int notifyArg); // A call into game code. These can be pending on a thread. @@ -189,6 +189,7 @@ struct MipsCall { bool returnVoid; const char *tag; u32 savedId; + bool reschedAfter; }; enum ThreadStatus { From 000884fadb479731de9ca41fb984e253513ec43b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 20:11:34 -0800 Subject: [PATCH 28/34] Reschedule in sceUmdWaitDriveStatCB(). __KernelForceCallbacks() used to be it shouldn't. --- Core/HLE/sceUmd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 8dda1dc6a5..f960edd72b 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -283,6 +283,8 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) __UmdWaitStat(timeout); __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true); } + else if (driveCBId != -1) + __KernelReSchedule("umd stat waited"); } void sceUmdCancelWaitDriveStat() From 5e8aa4c0719fc2767df568057dba21811845cee7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 8 Dec 2012 22:39:36 -0800 Subject: [PATCH 29/34] Implement deferred rescheduling/callbacks. This way most HLE functions can be wrapped normally. Hurray, sanity. --- Core/HLE/HLE.cpp | 55 +++++++++++++++++++++++++++++++++ Core/HLE/HLE.h | 8 +++++ Core/HLE/sceKernelMutex.cpp | 12 +++---- Core/HLE/sceKernelSemaphore.cpp | 10 +++--- Core/HLE/sceKernelThread.cpp | 25 +++++++-------- Core/HLE/sceUmd.cpp | 8 ++--- 6 files changed, 90 insertions(+), 28 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index 5313b5a1f2..eebc8bc888 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -25,10 +25,27 @@ #include "sceIo.h" #include "sceAudio.h" #include "sceKernelMemory.h" +#include "sceKernelThread.h" #include "../MIPS/MIPSCodeUtils.h" static std::vector moduleDB; static std::vector unresolvedSyscalls; +static int hleAfterSyscall; +static const char *hleAfterSyscallReschedReason; + +enum +{ + // Do nothing after the syscall. + HLE_AFTER_NOTHING = 0x00, + // Reschedule immediately after the syscall. + HLE_AFTER_RESCHED = 0x01, + // Call current thread's callbacks after the syscall. + HLE_AFTER_CURRENT_CALLBACKS = 0x02, + // Check all threads' callbacks after the syscall. + HLE_AFTER_ALL_CALLBACKS = 0x04, + // Reschedule and process current thread's callbacks after the syscall. + HLE_AFTER_RESCHED_CALLBACKS = 0x08, +}; void HLEInit() { @@ -177,6 +194,30 @@ const char *GetFuncName(int moduleIndex, int func) return "[unknown]"; } +void hleCheckAllCallbacks() +{ + hleAfterSyscall |= HLE_AFTER_ALL_CALLBACKS; +} + +void hleCheckCurrentCallbacks() +{ + hleAfterSyscall |= HLE_AFTER_CURRENT_CALLBACKS; +} + +void hleReSchedule(const char *reason) +{ + _dbg_assert_msg_(HLE, reason != 0, "hleReSchedule: Expecting a valid reason."); + + hleAfterSyscall |= HLE_AFTER_RESCHED; + hleAfterSyscallReschedReason = reason; +} + +void hleReSchedule(bool callbacks, const char *reason) +{ + hleReSchedule(reason); + hleAfterSyscall |= HLE_AFTER_RESCHED_CALLBACKS; +} + void CallSyscall(u32 op) { u32 callno = (op >> 6) & 0xFFFFF; //20 bits @@ -191,7 +232,21 @@ void CallSyscall(u32 op) HLEFunc func = moduleDB[modulenum].funcTable[funcnum].func; if (func) { + hleAfterSyscall = HLE_AFTER_NOTHING; + hleAfterSyscallReschedReason = 0; + func(); + + if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) + __KernelForceCallbacks(); + + // Rescheduling will also do HLE_AFTER_ALL_CALLBACKS. + if ((hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) != 0) + __KernelReSchedule(true, hleAfterSyscallReschedReason); + else if ((hleAfterSyscall & HLE_AFTER_RESCHED) != 0) + __KernelReSchedule(hleAfterSyscallReschedReason); + else if ((hleAfterSyscall & HLE_AFTER_ALL_CALLBACKS) != 0) + __KernelCheckCallbacks(); } else { diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index 9305057b61..83633b134f 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -73,6 +73,14 @@ int GetModuleIndex(const char *modulename); void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable); +// Run the current thread's callbacks after the syscall finishes. +void hleCheckCurrentCallbacks(); +// Check and potentially run all thread's callbacks after the syscall finishes. +void hleCheckAllCallbacks(); +// Reschedule after the syscall finishes. +void hleReSchedule(const char *reason); +// Reschedule and go into a callback processing state after the syscall finishes. +void hleReSchedule(bool callbacks, const char *reason); void HLEInit(); void HLEShutdown(); diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index c9936f48a3..bae59ab945 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -269,7 +269,7 @@ void sceKernelDeleteMutex(SceUID id) RETURN(kernelObjects.Destroy(id)); if (wokeThreads) - __KernelReSchedule("mutex deleted"); + hleReSchedule("mutex deleted"); } else RETURN(error); @@ -430,7 +430,7 @@ void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) if (__KernelLockMutex(mutex, count, error)) { RETURN(0); - __KernelForceCallbacks(); + hleCheckCurrentCallbacks(); } else if (error) RETURN(error); @@ -490,7 +490,7 @@ void sceKernelUnlockMutex(SceUID id, int count) if (mutex->nm.lockLevel == 0) { if (__KernelUnlockMutex(mutex, error)) - __KernelReSchedule("mutex unlocked"); + hleReSchedule("mutex unlocked"); } } @@ -596,7 +596,7 @@ void sceKernelDeleteLwMutex(u32 workareaPtr) Memory::WriteStruct(workareaPtr, &workarea); if (wokeThreads) - __KernelReSchedule("lwmutex deleted"); + hleReSchedule("lwmutex deleted"); } else RETURN(error); @@ -789,7 +789,7 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) { Memory::WriteStruct(workareaPtr, &workarea); RETURN(0); - __KernelForceCallbacks(); + hleCheckCurrentCallbacks(); } else if (error) RETURN(error); @@ -838,7 +838,7 @@ void sceKernelUnlockLwMutex(u32 workareaPtr, int count) if (workarea.lockLevel == 0) { if (__KernelUnlockLwMutex(workarea, error)) - __KernelReSchedule("lwmutex unlocked"); + hleReSchedule("lwmutex unlocked"); Memory::WriteStruct(workareaPtr, &workarea); } else diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index fccd3d0c6c..1edaee93bf 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -168,7 +168,7 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) RETURN(0); if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL)) - __KernelReSchedule("semaphore canceled"); + hleReSchedule("semaphore canceled"); } else { @@ -224,7 +224,7 @@ void sceKernelDeleteSema(SceUID id) RETURN(kernelObjects.Destroy(id)); if (wokeThreads) - __KernelReSchedule("semaphore deleted"); + hleReSchedule("semaphore deleted"); } else { @@ -291,12 +291,12 @@ retry: } if (wokeThreads) - __KernelReSchedule("semaphore signaled"); + hleReSchedule("semaphore signaled"); } else { ERROR_LOG(HLE, "sceKernelSignalSema : Trying to signal invalid semaphore %i", id); - RETURN(error;) + RETURN(error); } } @@ -356,7 +356,7 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba { s->ns.currentCount -= wantedCount; if (processCallbacks) - __KernelForceCallbacks(); + hleCheckCurrentCallbacks(); } else { diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index acb46f66bf..7dc3683825 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -397,7 +397,7 @@ void __KernelIdle() // In Advance, we might trigger an interrupt such as vblank. // If we end up in an interrupt, we don't want to reschedule. // However, we have to reschedule... damn. - __KernelReSchedule("idle"); + hleReSchedule("idle"); } void __KernelThreadingShutdown() @@ -618,10 +618,9 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, int retval) } } -// DANGEROUS // Only run when you can safely accept a context switch // Triggers a waitable event, that is, it wakes up all threads that waits for it -// If any changes were made, it will context switch +// If any changes were made, it will context switch after the syscall bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, bool dontSwitch) { bool doneAnything = false; @@ -649,7 +648,7 @@ bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, bool // TODO: time waster char temp[256]; sprintf(temp, "resumed from wait %s", waitTypeStrings[(int)type]); - __KernelReSchedule(temp); + hleReSchedule(temp); } } return true; @@ -681,7 +680,7 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time char temp[256]; sprintf(temp, "started wait %s", waitTypeStrings[(int)type]); - __KernelReSchedule(processCallbacks, temp); + hleReSchedule(processCallbacks, temp); // TODO: Remove thread from Ready queue? } @@ -998,7 +997,7 @@ void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) } RETURN(0); - __KernelReSchedule("thread started"); + hleReSchedule("thread started"); } else { @@ -1058,7 +1057,7 @@ void __KernelReturnFromThread() // Find threads that waited for me // Wake them if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - __KernelReSchedule("return from thread"); + hleReSchedule("return from thread"); // The stack will be deallocated when the thread is deleted. } @@ -1073,7 +1072,7 @@ void sceKernelExitThread() //Find threads that waited for me // Wake them if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - __KernelReSchedule("exited thread"); + hleReSchedule("exited thread"); // The stack will be deallocated when the thread is deleted. } @@ -1088,7 +1087,7 @@ void _sceKernelExitThread() //Find threads that waited for this one // Wake them if (!__KernelTriggerWait(WAITTYPE_THREADEND, __KernelGetCurThread())) - __KernelReSchedule("exit-deleted thread"); + hleReSchedule("exit-deleted thread"); // The stack will be deallocated when the thread is deleted. } @@ -1140,7 +1139,7 @@ u32 sceKernelResumeDispatchThread(u32 suspended) void sceKernelRotateThreadReadyQueue() { DEBUG_LOG(HLE,"sceKernelRotateThreadReadyQueue : rescheduling"); - __KernelReSchedule("rotatethreadreadyqueue"); + hleReSchedule("rotatethreadreadyqueue"); } void sceKernelDeleteThread() @@ -1164,7 +1163,7 @@ void sceKernelDeleteThread() //TODO: should we really reschedule here? //if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadHandle)) - // __KernelReSchedule("thread deleted"); + // hleReSchedule("thread deleted"); } } else @@ -1185,7 +1184,7 @@ void sceKernelTerminateDeleteThread() //TODO: should we really reschedule here? if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadno)) - __KernelReSchedule("termdeletethread"); + hleReSchedule("termdeletethread"); } else { @@ -1766,7 +1765,7 @@ void __KernelReturnFromMipsCall() { // Sometimes, we want to stay on the thread. if (call->reschedAfter) - __KernelReSchedule("return from callback"); + hleReSchedule("return from callback"); } } diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index f960edd72b..7868cb3fa1 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -132,7 +132,7 @@ void sceUmdActivate(u32 unknown, const char *name) RETURN(0); if (changed) - __KernelReSchedule("umd activated"); + hleReSchedule("umd activated"); } void sceUmdDeactivate(u32 unknown, const char *name) @@ -161,7 +161,7 @@ void sceUmdDeactivate(u32 unknown, const char *name) RETURN(0); if (changed) - __KernelReSchedule("umd deactivated"); + hleReSchedule("umd deactivated"); } u32 sceUmdRegisterUMDCallBack(u32 cbId) @@ -268,7 +268,7 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout); - __KernelForceCallbacks(); + hleCheckCurrentCallbacks(); } else { @@ -284,7 +284,7 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true); } else if (driveCBId != -1) - __KernelReSchedule("umd stat waited"); + hleReSchedule("umd stat waited"); } void sceUmdCancelWaitDriveStat() From 3d57a4c8381f9358329b114bcdcdd18fdfd7f56e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Dec 2012 00:09:25 -0800 Subject: [PATCH 30/34] Cleanup some wrappers now that rescheds defer. --- Core/HLE/FunctionWrappers.h | 32 +++++ Core/HLE/sceKernel.cpp | 32 ++--- Core/HLE/sceKernelInterrupt.cpp | 10 +- Core/HLE/sceKernelMutex.cpp | 215 ++++++++++++++------------------ Core/HLE/sceKernelMutex.h | 26 ++-- Core/HLE/sceKernelSemaphore.cpp | 115 +++++++---------- Core/HLE/sceKernelSemaphore.h | 16 +-- Core/HLE/sceUmd.cpp | 32 +++-- 8 files changed, 229 insertions(+), 249 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 29d7fd3701..abb7de402b 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -83,6 +83,11 @@ template void WrapI_U() { RETURN(retval); } +template void WrapI_UI() { + int retval = func(PARAM(0), PARAM(1)); + RETURN(retval); +} + template void WrapU_IUI() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2)); RETURN(retval); @@ -130,6 +135,11 @@ template void WrapV_UC() { func(PARAM(0), Memory::GetCharPointer(PARAM(1))); } +template void WrapI_UC() { + int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1))); + RETURN(retval); +} + template void WrapU_UIIIIII() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6)); RETURN(retval); @@ -264,6 +274,11 @@ template void WrapV_UIU() { func(PARAM(0), PARAM(1), PARAM(2)); } +template void WrapI_UIU() { + int retval = func(PARAM(0), PARAM(1), PARAM(2)); + RETURN(retval); +} + template void WrapV_IUUUU() { func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); } @@ -280,16 +295,33 @@ template void WrapV_CUIU() { func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); } +template void WrapI_CUIU() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3)); + RETURN(retval); +} + template void WrapV_UCUIU() { func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), PARAM(3), PARAM(4)); } +template void WrapI_UCUIU() { + int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), + PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapV_CUIIU() { func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), PARAM(3), PARAM(4)); } +template void WrapI_CUIIU() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), + PARAM(3), PARAM(4)); + RETURN(retval); +} + template void WrapU_UUUU() { u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3)); RETURN(retval); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 3544c9a171..7872b18f39 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -332,23 +332,23 @@ const HLEFunction ThreadManForUser[] = {0xCD203292,&WrapU_V, "sceKernelCancelEventFlag"}, {0xA66B0120,&WrapU_IU, "sceKernelReferEventFlagStatus"}, - {0x8FFDF9A2,&WrapV_IIU, "sceKernelCancelSema"}, - {0xD6DA4BA1,&WrapV_CUIIU, "sceKernelCreateSema"}, - {0x28b6489c,&WrapV_I, "sceKernelDeleteSema"}, - {0x58b1f937,&WrapV_II, "sceKernelPollSema"}, - {0xBC6FEBC5,&WrapV_IU, "sceKernelReferSemaStatus"}, - {0x3F53E640,&WrapV_II, "sceKernelSignalSema"}, - {0x4E3A1105,&WrapV_IIU, "sceKernelWaitSema"}, - {0x6d212bac,&WrapV_IIU, "sceKernelWaitSemaCB"}, + {0x8FFDF9A2,&WrapI_IIU, "sceKernelCancelSema"}, + {0xD6DA4BA1,&WrapI_CUIIU, "sceKernelCreateSema"}, + {0x28b6489c,&WrapI_I, "sceKernelDeleteSema"}, + {0x58b1f937,&WrapI_II, "sceKernelPollSema"}, + {0xBC6FEBC5,&WrapI_IU, "sceKernelReferSemaStatus"}, + {0x3F53E640,&WrapI_II, "sceKernelSignalSema"}, + {0x4E3A1105,&WrapI_IIU, "sceKernelWaitSema"}, + {0x6d212bac,&WrapI_IIU, "sceKernelWaitSemaCB"}, - {0x60107536,&WrapV_U, "sceKernelDeleteLwMutex"}, - {0x19CFF145,&WrapV_UCUIU, "sceKernelCreateLwMutex"}, - {0xf8170fbe,&WrapV_I, "sceKernelDeleteMutex"}, - {0xB011B11F,&WrapV_IIU, "sceKernelLockMutex"}, - {0x5bf4dd27,&WrapV_IIU, "sceKernelLockMutexCB"}, - {0x6b30100f,&WrapV_II, "sceKernelUnlockMutex"}, - {0xb7d098c6,&WrapV_CUIU, "sceKernelCreateMutex"}, - {0x0DDCD2C9,&WrapV_II, "sceKernelTryLockMutex"}, + {0x60107536,&WrapI_U, "sceKernelDeleteLwMutex"}, + {0x19CFF145,&WrapI_UCUIU, "sceKernelCreateLwMutex"}, + {0xf8170fbe,&WrapI_I, "sceKernelDeleteMutex"}, + {0xB011B11F,&WrapI_IIU, "sceKernelLockMutex"}, + {0x5bf4dd27,&WrapI_IIU, "sceKernelLockMutexCB"}, + {0x6b30100f,&WrapI_II, "sceKernelUnlockMutex"}, + {0xb7d098c6,&WrapI_CUIU, "sceKernelCreateMutex"}, + {0x0DDCD2C9,&WrapI_II, "sceKernelTryLockMutex"}, // NOTE: LockLwMutex and UnlockLwMutex are in Kernel_Library, see sceKernelInterrupt.cpp. {0xFCCFAD26,sceKernelCancelWakeupThread,"sceKernelCancelWakeupThread"}, diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index e23207bff2..bf298e4d40 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -439,11 +439,11 @@ const HLEFunction Kernel_Library[] = {0x47a0b729,sceKernelIsCpuIntrSuspended, "sceKernelIsCpuIntrSuspended"}, //flags {0xb55249d2,sceKernelIsCpuIntrEnable, "sceKernelIsCpuIntrEnable"}, {0xa089eca4,sceKernelMemset, "sceKernelMemset"}, - {0xDC692EE3,&WrapV_UI, "sceKernelTryLockLwMutex"}, - {0x37431849,&WrapV_UI, "sceKernelTryLockLwMutex_600"}, - {0xbea46419,&WrapV_UIU, "sceKernelLockLwMutex"}, - {0x1FC64E09,&WrapV_UIU, "sceKernelLockLwMutexCB"}, - {0x15b6446b,&WrapV_UI, "sceKernelUnlockLwMutex"}, + {0xDC692EE3,&WrapI_UI, "sceKernelTryLockLwMutex"}, + {0x37431849,&WrapI_UI, "sceKernelTryLockLwMutex_600"}, + {0xbea46419,&WrapI_UIU, "sceKernelLockLwMutex"}, + {0x1FC64E09,&WrapI_UIU, "sceKernelLockLwMutexCB"}, + {0x15b6446b,&WrapI_UI, "sceKernelUnlockLwMutex"}, {0x293b45b8,sceKernelGetThreadId, "sceKernelGetThreadId"}, {0x1839852A,&WrapU_UUU,"sce_paf_private_memcpy"}, }; diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index bae59ab945..337d41e427 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -181,26 +181,19 @@ std::vector::iterator __KernelMutexFindPriority(std::vector &wai return best; } -void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) +int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) { if (!mutexInitComplete) __KernelMutexInit(); - u32 error = 0; if (!name) - error = SCE_KERNEL_ERROR_ERROR; - else if (initialCount < 0) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if ((attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && initialCount > 1) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + return SCE_KERNEL_ERROR_ERROR; + if (initialCount < 0) + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + if ((attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && initialCount > 1) + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - if (error) - { - RETURN(error); - return; - } - - DEBUG_LOG(HLE,"sceKernelCreateMutex(%s, %08x, %d, %08x)", name, attr, initialCount, optionsPtr); + DEBUG_LOG(HLE, "sceKernelCreateMutex(%s, %08x, %d, %08x)", name, attr, initialCount, optionsPtr); Mutex *mutex = new Mutex(); SceUID id = kernelObjects.Create(mutex); @@ -218,9 +211,9 @@ void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 opti __KernelMutexAcquireLock(mutex, initialCount); if (optionsPtr != 0) - WARN_LOG(HLE,"sceKernelCreateMutex(%s) unsupported options parameter.", name); + WARN_LOG(HLE, "sceKernelCreateMutex(%s) unsupported options parameter.", name); - RETURN(id); + return id; } bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int result) @@ -250,7 +243,7 @@ bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int return true; } -void sceKernelDeleteMutex(SceUID id) +int sceKernelDeleteMutex(SceUID id) { DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id); u32 error; @@ -266,13 +259,13 @@ void sceKernelDeleteMutex(SceUID id) __KernelMutexEraseLock(mutex); mutex->waitingThreads.clear(); - RETURN(kernelObjects.Destroy(id)); - if (wokeThreads) hleReSchedule("mutex deleted"); + + return kernelObjects.Destroy(id); } else - RETURN(error); + return error; } bool __KernelLockMutex(Mutex *mutex, int count, u32 &error) @@ -356,10 +349,10 @@ void __KernelMutexThreadEnd(SceUID threadID) u32 error; // If it was waiting on the mutex, it should finish now. - SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); - if (mutexID) + SceUID waitingMutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); + if (waitingMutexID) { - Mutex *mutex = kernelObjects.Get(mutexID, error); + Mutex *mutex = kernelObjects.Get(waitingMutexID, error); if (mutex) mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end()); } @@ -398,122 +391,109 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr) } // int sceKernelLockMutex(SceUID id, int count, int *timeout) -// void because it changes threads. -void sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) +int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr) { - DEBUG_LOG(HLE,"sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelLockMutex(%i, %i, %08x)", id, count, timeoutPtr); u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) - { - RETURN(0); - } + return 0; else if (error) - RETURN(error); + return error; else { mutex->waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitMutex(mutex, timeoutPtr); __KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, false); + + // Return value will be overwritten by wait. + return 0; } } // int sceKernelLockMutexCB(SceUID id, int count, int *timeout) -// void because it changes threads. -void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) +int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) { - DEBUG_LOG(HLE,"sceKernelLockMutexCB(%i, %i, %08x)", id, count, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelLockMutexCB(%i, %i, %08x)", id, count, timeoutPtr); u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) { - RETURN(0); hleCheckCurrentCallbacks(); + return 0; } else if (error) - RETURN(error); + return error; else { mutex->waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitMutex(mutex, timeoutPtr); __KernelWaitCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr, true); + + // Return value will be overwritten by wait. + return 0; } } // int sceKernelTryLockMutex(SceUID id, int count) -// void because it changes threads. -void sceKernelTryLockMutex(SceUID id, int count) +int sceKernelTryLockMutex(SceUID id, int count) { - DEBUG_LOG(HLE,"sceKernelTryLockMutex(%i, %i)", id, count); + DEBUG_LOG(HLE, "sceKernelTryLockMutex(%i, %i)", id, count); u32 error; Mutex *mutex = kernelObjects.Get(id, error); if (__KernelLockMutex(mutex, count, error)) - RETURN(0); + return 0; else if (error) - RETURN(error); + return error; else - RETURN(PSP_MUTEX_ERROR_TRYLOCK_FAILED); + return PSP_MUTEX_ERROR_TRYLOCK_FAILED; } // int sceKernelUnlockMutex(SceUID id, int count) -// void because it changes threads. -void sceKernelUnlockMutex(SceUID id, int count) +int sceKernelUnlockMutex(SceUID id, int count) { - DEBUG_LOG(HLE,"sceKernelUnlockMutex(%i, %i)", id, count); + DEBUG_LOG(HLE, "sceKernelUnlockMutex(%i, %i)", id, count); u32 error; Mutex *mutex = kernelObjects.Get(id, error); - if (!error) - { - if (count <= 0) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if ((mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && count > 1) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if (mutex->nm.lockLevel == 0 || mutex->nm.lockThread != __KernelGetCurThread()) - error = PSP_MUTEX_ERROR_NOT_LOCKED; - else if (mutex->nm.lockLevel < count) - error = PSP_MUTEX_ERROR_UNLOCK_UNDERFLOW; - } - if (error) - { - RETURN(error); - return; - } + return error; + if (count <= 0) + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + if ((mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && count > 1) + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + if (mutex->nm.lockLevel == 0 || mutex->nm.lockThread != __KernelGetCurThread()) + return PSP_MUTEX_ERROR_NOT_LOCKED; + if (mutex->nm.lockLevel < count) + return PSP_MUTEX_ERROR_UNLOCK_UNDERFLOW; mutex->nm.lockLevel -= count; - RETURN(0); if (mutex->nm.lockLevel == 0) { if (__KernelUnlockMutex(mutex, error)) hleReSchedule("mutex unlocked"); } + + return 0; } -void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr) +int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr) { if (!mutexInitComplete) __KernelMutexInit(); - DEBUG_LOG(HLE,"sceKernelCreateLwMutex(%08x, %s, %08x, %d, %08x)", workareaPtr, name, attr, initialCount, optionsPtr); + DEBUG_LOG(HLE, "sceKernelCreateLwMutex(%08x, %s, %08x, %d, %08x)", workareaPtr, name, attr, initialCount, optionsPtr); - u32 error = 0; if (!name) - error = SCE_KERNEL_ERROR_ERROR; + return SCE_KERNEL_ERROR_ERROR; else if (initialCount < 0) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; else if ((attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && initialCount > 1) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - - if (error) - { - RETURN(error); - return; - } + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; LwMutex *mutex = new LwMutex(); SceUID id = kernelObjects.Create(mutex); @@ -536,9 +516,9 @@ void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int ini Memory::WriteStruct(workareaPtr, &workarea); if (optionsPtr != 0) - WARN_LOG(HLE,"sceKernelCreateLwMutex(%s) unsupported options parameter.", name); + WARN_LOG(HLE, "sceKernelCreateLwMutex(%s) unsupported options parameter.", name); - RETURN(0); + return 0; } bool __KernelUnlockLwMutexForThread(LwMutex *mutex, NativeLwMutexWorkarea &workarea, SceUID threadID, u32 &error, int result) @@ -568,15 +548,12 @@ bool __KernelUnlockLwMutexForThread(LwMutex *mutex, NativeLwMutexWorkarea &worka return true; } -void sceKernelDeleteLwMutex(u32 workareaPtr) +int sceKernelDeleteLwMutex(u32 workareaPtr) { - DEBUG_LOG(HLE,"sceKernelDeleteLwMutex(%08x)", workareaPtr); + DEBUG_LOG(HLE, "sceKernelDeleteLwMutex(%08x)", workareaPtr); if (!workareaPtr || !Memory::IsValidAddress(workareaPtr)) - { - RETURN(SCE_KERNEL_ERROR_ILLEGAL_ADDR); - return; - } + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); @@ -591,15 +568,16 @@ void sceKernelDeleteLwMutex(u32 workareaPtr) wokeThreads |= __KernelUnlockLwMutexForThread(mutex, workarea, *iter, error, SCE_KERNEL_ERROR_WAIT_DELETE); mutex->waitingThreads.clear(); - RETURN(kernelObjects.Destroy(workarea.uid)); workarea.clear(); Memory::WriteStruct(workareaPtr, &workarea); if (wokeThreads) hleReSchedule("lwmutex deleted"); + + return kernelObjects.Destroy(mutex->GetUID()); } else - RETURN(error); + return error; } bool __KernelLockLwMutex(NativeLwMutexWorkarea &workarea, int count, u32 &error) @@ -710,9 +688,9 @@ void __KernelWaitLwMutex(LwMutex *mutex, u32 timeoutPtr) CoreTiming::ScheduleEvent(usToCycles(micro), lwMutexWaitTimer, __KernelGetCurThread()); } -void sceKernelTryLockLwMutex(u32 workareaPtr, int count) +int sceKernelTryLockLwMutex(u32 workareaPtr, int count) { - DEBUG_LOG(HLE,"sceKernelTryLockLwMutex(%08x, %i)", workareaPtr, count); + DEBUG_LOG(HLE, "sceKernelTryLockLwMutex(%08x, %i)", workareaPtr, count); NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); @@ -721,17 +699,18 @@ void sceKernelTryLockLwMutex(u32 workareaPtr, int count) if (__KernelLockLwMutex(workarea, count, error)) { Memory::WriteStruct(workareaPtr, &workarea); - RETURN(0); + return 0; } + // Unlike sceKernelTryLockLwMutex_600, this always returns the same error. else if (error) - RETURN(PSP_MUTEX_ERROR_TRYLOCK_FAILED); + return PSP_MUTEX_ERROR_TRYLOCK_FAILED; else - RETURN(PSP_MUTEX_ERROR_TRYLOCK_FAILED); + return PSP_MUTEX_ERROR_TRYLOCK_FAILED; } -void sceKernelTryLockLwMutex_600(u32 workareaPtr, int count) +int sceKernelTryLockLwMutex_600(u32 workareaPtr, int count) { - DEBUG_LOG(HLE,"sceKernelTryLockLwMutex_600(%08x, %i)", workareaPtr, count); + DEBUG_LOG(HLE, "sceKernelTryLockLwMutex_600(%08x, %i)", workareaPtr, count); NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); @@ -740,17 +719,17 @@ void sceKernelTryLockLwMutex_600(u32 workareaPtr, int count) if (__KernelLockLwMutex(workarea, count, error)) { Memory::WriteStruct(workareaPtr, &workarea); - RETURN(0); + return 0; } else if (error) - RETURN(error); + return error; else - RETURN(PSP_LWMUTEX_ERROR_TRYLOCK_FAILED); + return PSP_LWMUTEX_ERROR_TRYLOCK_FAILED; } -void sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) +int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) { - DEBUG_LOG(HLE,"sceKernelLockLwMutex(%08x, %i, %08x)", workareaPtr, count, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelLockLwMutex(%08x, %i, %08x)", workareaPtr, count, timeoutPtr); NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); @@ -759,10 +738,10 @@ void sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) if (__KernelLockLwMutex(workarea, count, error)) { Memory::WriteStruct(workareaPtr, &workarea); - RETURN(0); + return 0; } else if (error) - RETURN(error); + return error; else { LwMutex *mutex = kernelObjects.Get(workarea.uid, error); @@ -771,15 +750,18 @@ void sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) mutex->waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitLwMutex(mutex, timeoutPtr); __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, false); + + // Return value will be overwritten by wait. + return 0; } else - RETURN(error); + return error; } } -void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) +int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) { - DEBUG_LOG(HLE,"sceKernelLockLwMutexCB(%08x, %i, %08x)", workareaPtr, count, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelLockLwMutexCB(%08x, %i, %08x)", workareaPtr, count, timeoutPtr); NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); @@ -788,11 +770,11 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) if (__KernelLockLwMutex(workarea, count, error)) { Memory::WriteStruct(workareaPtr, &workarea); - RETURN(0); hleCheckCurrentCallbacks(); + return 0; } else if (error) - RETURN(error); + return error; else { LwMutex *mutex = kernelObjects.Get(workarea.uid, error); @@ -801,42 +783,38 @@ void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) mutex->waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitLwMutex(mutex, timeoutPtr); __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, true); + + // Return value will be overwritten by wait. + return 0; } else - RETURN(error); + return error; } } -void sceKernelUnlockLwMutex(u32 workareaPtr, int count) +int sceKernelUnlockLwMutex(u32 workareaPtr, int count) { - DEBUG_LOG(HLE,"sceKernelUnlockLwMutex(%08x, %i)", workareaPtr, count); + DEBUG_LOG(HLE, "sceKernelUnlockLwMutex(%08x, %i)", workareaPtr, count); NativeLwMutexWorkarea workarea; Memory::ReadStruct(workareaPtr, &workarea); - u32 error = 0; if (workarea.uid == -1) - error = PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; + return PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; else if (count <= 0) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; else if ((workarea.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && count > 1) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; else if (workarea.lockLevel == 0 || workarea.lockThread != __KernelGetCurThread()) - error = PSP_LWMUTEX_ERROR_NOT_LOCKED; + return PSP_LWMUTEX_ERROR_NOT_LOCKED; else if (workarea.lockLevel < count) - error = PSP_LWMUTEX_ERROR_UNLOCK_UNDERFLOW; - - if (error) - { - RETURN(error); - return; - } + return PSP_LWMUTEX_ERROR_UNLOCK_UNDERFLOW; workarea.lockLevel -= count; - RETURN(0); if (workarea.lockLevel == 0) { + u32 error; if (__KernelUnlockLwMutex(workarea, error)) hleReSchedule("lwmutex unlocked"); Memory::WriteStruct(workareaPtr, &workarea); @@ -844,4 +822,5 @@ void sceKernelUnlockLwMutex(u32 workareaPtr, int count) else Memory::WriteStruct(workareaPtr, &workarea); + return 0; } \ No newline at end of file diff --git a/Core/HLE/sceKernelMutex.h b/Core/HLE/sceKernelMutex.h index bb89691fb7..8d7c09e9f2 100644 --- a/Core/HLE/sceKernelMutex.h +++ b/Core/HLE/sceKernelMutex.h @@ -17,20 +17,20 @@ #pragma once -void sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr); -void sceKernelDeleteMutex(SceUID id); -void sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr); -void sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr); -void sceKernelTryLockMutex(SceUID id, int count); -void sceKernelUnlockMutex(SceUID id, int count); +int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr); +int sceKernelDeleteMutex(SceUID id); +int sceKernelLockMutex(SceUID id, int count, u32 timeoutPtr); +int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr); +int sceKernelTryLockMutex(SceUID id, int count); +int sceKernelUnlockMutex(SceUID id, int count); -void sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr); -void sceKernelDeleteLwMutex(u32 workareaPtr); -void sceKernelTryLockLwMutex(u32 workareaPtr, int count); -void sceKernelTryLockLwMutex_600(u32 workareaPtr, int count); -void sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr); -void sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr); -void sceKernelUnlockLwMutex(u32 workareaPtr, int count); +int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int initialCount, u32 optionsPtr); +int sceKernelDeleteLwMutex(u32 workareaPtr); +int sceKernelTryLockLwMutex(u32 workareaPtr, int count); +int sceKernelTryLockLwMutex_600(u32 workareaPtr, int count); +int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr); +int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr); +int sceKernelUnlockLwMutex(u32 workareaPtr, int count); void __KernelMutexTimeout(u64 userdata, int cyclesLate); void __KernelLwMutexTimeout(u64 userdata, int cyclesLate); diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 1edaee93bf..c4b103f007 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -138,25 +138,19 @@ std::vector::iterator __KernelSemaFindPriority(std::vector &wait } // int sceKernelCancelSema(SceUID id, int newCount, int *numWaitThreads); -// void because it changes threads. -void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) +int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) { - DEBUG_LOG(HLE,"sceKernelCancelSema(%i)", id); + DEBUG_LOG(HLE, "sceKernelCancelSema(%i)", id); u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { if (newCount > s->ns.maxCount) - { - RETURN(SCE_KERNEL_ERROR_ILLEGAL_COUNT); - return; - } + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; if (numWaitThreadsPtr) - { Memory::Write_U32(s->ns.numWaitThreads, numWaitThreadsPtr); - } if (newCount < 0) s->ns.currentCount = s->ns.initCount; @@ -164,31 +158,26 @@ void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr) s->ns.currentCount = newCount; s->ns.numWaitThreads = 0; - // We need to set the return value BEFORE rescheduling threads. - RETURN(0); - if (__KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_CANCEL)) hleReSchedule("semaphore canceled"); + + return 0; } else { ERROR_LOG(HLE, "sceKernelCancelSema : Trying to cancel invalid semaphore %i", id); - RETURN(error); + return error; } } //SceUID sceKernelCreateSema(const char *name, SceUInt attr, int initVal, int maxVal, SceKernelSemaOptParam *option); -// void because it changes threads. -void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) +int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr) { if (!semaInitComplete) __KernelSemaInit(); if (!name) - { - RETURN(SCE_KERNEL_ERROR_ERROR); - return; - } + return SCE_KERNEL_ERROR_ERROR; Semaphore *s = new Semaphore; SceUID id = kernelObjects.Create(s); @@ -202,76 +191,67 @@ void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u3 s->ns.maxCount = maxVal; s->ns.numWaitThreads = 0; - DEBUG_LOG(HLE,"%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, optionPtr); + DEBUG_LOG(HLE, "%i=sceKernelCreateSema(%s, %08x, %i, %i, %08x)", id, s->ns.name, s->ns.attr, s->ns.initCount, s->ns.maxCount, optionPtr); if (optionPtr != 0) - WARN_LOG(HLE,"sceKernelCreateSema(%s) unsupported options parameter.", name); + WARN_LOG(HLE, "sceKernelCreateSema(%s) unsupported options parameter.", name); - RETURN(id); + return id; } //int sceKernelDeleteSema(SceUID semaid); -// void because it changes threads. -void sceKernelDeleteSema(SceUID id) +int sceKernelDeleteSema(SceUID id) { - DEBUG_LOG(HLE,"sceKernelDeleteSema(%i)", id); + DEBUG_LOG(HLE, "sceKernelDeleteSema(%i)", id); u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { bool wokeThreads = __KernelClearSemaThreads(s, SCE_KERNEL_ERROR_WAIT_DELETE); - RETURN(kernelObjects.Destroy(id)); - if (wokeThreads) hleReSchedule("semaphore deleted"); + + return kernelObjects.Destroy(id); } else { ERROR_LOG(HLE, "sceKernelDeleteSema : Trying to delete invalid semaphore %i", id); - RETURN(error); + return error; } } //int sceKernelDeleteSema(SceUID semaid, SceKernelSemaInfo *info); -// void because it changes threads. -void sceKernelReferSemaStatus(SceUID id, u32 infoPtr) +int sceKernelReferSemaStatus(SceUID id, u32 infoPtr) { u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { - DEBUG_LOG(HLE,"sceKernelReferSemaStatus(%i, %08x)", id, infoPtr); + DEBUG_LOG(HLE, "sceKernelReferSemaStatus(%i, %08x)", id, infoPtr); Memory::WriteStruct(infoPtr, &s->ns); - RETURN(0); + return 0; } else { - ERROR_LOG(HLE,"Error %08x", error); - RETURN(error); + ERROR_LOG(HLE, "sceKernelReferSemaStatus: error %08x", error); + return error; } } //int sceKernelSignalSema(SceUID semaid, int signal); -// void because it changes threads. -void sceKernelSignalSema(SceUID id, int signal) +int sceKernelSignalSema(SceUID id, int signal) { u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { if (s->ns.currentCount + signal - s->ns.numWaitThreads > s->ns.maxCount) - { - RETURN(SCE_KERNEL_ERROR_SEMA_OVF); - return; - } + return SCE_KERNEL_ERROR_SEMA_OVF; int oldval = s->ns.currentCount; s->ns.currentCount += signal; - DEBUG_LOG(HLE,"sceKernelSignalSema(%i, %i) (old: %i, new: %i)", id, signal, oldval, s->ns.currentCount); - - // We need to set the return value BEFORE processing other threads. - RETURN(0); + DEBUG_LOG(HLE, "sceKernelSignalSema(%i, %i) (old: %i, new: %i)", id, signal, oldval, s->ns.currentCount); bool wokeThreads = false; std::vector::iterator iter, end, best; @@ -292,11 +272,13 @@ retry: if (wokeThreads) hleReSchedule("semaphore signaled"); + + return 0; } else { ERROR_LOG(HLE, "sceKernelSignalSema : Trying to signal invalid semaphore %i", id); - RETURN(error); + return error; } } @@ -337,20 +319,14 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) CoreTiming::ScheduleEvent(usToCycles(micro), semaWaitTimer, __KernelGetCurThread()); } -void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks) +int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *badSemaMessage, bool processCallbacks) { u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { if (wantedCount > s->ns.maxCount || wantedCount <= 0) - { - RETURN(SCE_KERNEL_ERROR_ILLEGAL_COUNT); - return; - } - - // We need to set the return value BEFORE processing callbacks / etc. - RETURN(0); + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; if (s->ns.currentCount >= wantedCount) { @@ -365,42 +341,39 @@ void __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *ba __KernelSetSemaTimeout(s, timeoutPtr); __KernelWaitCurThread(WAITTYPE_SEMA, id, wantedCount, timeoutPtr, processCallbacks); } + + return 0; } else { ERROR_LOG(HLE, badSemaMessage, id); - RETURN(error); + return error; } } //int sceKernelWaitSema(SceUID semaid, int signal, SceUInt *timeout); -// void because it changes threads. -void sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr) +int sceKernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr) { - DEBUG_LOG(HLE,"sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelWaitSema(%i, %i, %i)", id, wantedCount, timeoutPtr); - __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false); + return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSema: Trying to wait for invalid semaphore %i", false); } //int sceKernelWaitSemaCB(SceUID semaid, int signal, SceUInt *timeout); -// void because it changes threads. -void sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr) +int sceKernelWaitSemaCB(SceUID id, int wantedCount, u32 timeoutPtr) { - DEBUG_LOG(HLE,"sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr); + DEBUG_LOG(HLE, "sceKernelWaitSemaCB(%i, %i, %i)", id, wantedCount, timeoutPtr); - __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSemaCB: Trying to wait for invalid semaphore %i", true); + return __KernelWaitSema(id, wantedCount, timeoutPtr, "sceKernelWaitSemaCB: Trying to wait for invalid semaphore %i", true); } // Should be same as WaitSema but without the wait, instead returning SCE_KERNEL_ERROR_SEMA_ZERO -void sceKernelPollSema(SceUID id, int wantedCount) +int sceKernelPollSema(SceUID id, int wantedCount) { - DEBUG_LOG(HLE,"sceKernelPollSema(%i, %i)", id, wantedCount); + DEBUG_LOG(HLE, "sceKernelPollSema(%i, %i)", id, wantedCount); if (wantedCount <= 0) - { - RETURN(SCE_KERNEL_ERROR_ILLEGAL_COUNT); - return; - } + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; u32 error; Semaphore *s = kernelObjects.Get(id, error); @@ -409,15 +382,15 @@ void sceKernelPollSema(SceUID id, int wantedCount) if (s->ns.currentCount >= wantedCount) { s->ns.currentCount -= wantedCount; - RETURN(0); + return 0; } else - RETURN(SCE_KERNEL_ERROR_SEMA_ZERO); + return SCE_KERNEL_ERROR_SEMA_ZERO; } else { ERROR_LOG(HLE, "sceKernelPollSema: Trying to poll invalid semaphore %i", id); - RETURN(error); + return error; } } diff --git a/Core/HLE/sceKernelSemaphore.h b/Core/HLE/sceKernelSemaphore.h index e6628fec9d..32150c6307 100644 --- a/Core/HLE/sceKernelSemaphore.h +++ b/Core/HLE/sceKernelSemaphore.h @@ -17,13 +17,13 @@ #pragma once -void sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr); -void sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr); -void sceKernelDeleteSema(SceUID id); -void sceKernelPollSema(SceUID id, int wantedCount); -void sceKernelReferSemaStatus(SceUID id, u32 infoPtr); -void sceKernelSignalSema(SceUID id, int signal); -void sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr); -void sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr); +int sceKernelCancelSema(SceUID id, int newCount, u32 numWaitThreadsPtr); +int sceKernelCreateSema(const char* name, u32 attr, int initVal, int maxVal, u32 optionPtr); +int sceKernelDeleteSema(SceUID id); +int sceKernelPollSema(SceUID id, int wantedCount); +int sceKernelReferSemaStatus(SceUID id, u32 infoPtr); +int sceKernelSignalSema(SceUID id, int signal); +int sceKernelWaitSema(SceUID semaid, int signal, u32 timeoutPtr); +int sceKernelWaitSemaCB(SceUID semaid, int signal, u32 timeoutPtr); void __KernelSemaTimeout(u64 userdata, int cycleslate); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 7868cb3fa1..4ab88c44bc 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -107,13 +107,10 @@ u32 sceUmdGetDiscInfo(u32 infoAddr) return PSP_ERROR_UMD_INVALID_PARAM; } -void sceUmdActivate(u32 unknown, const char *name) +int sceUmdActivate(u32 unknown, const char *name) { if (unknown < 1 || unknown > 2) - { - RETURN(PSP_ERROR_UMD_INVALID_PARAM); - return; - } + return PSP_ERROR_UMD_INVALID_PARAM; bool changed = umdActivated == 0; __KernelUmdActivate(); @@ -129,20 +126,18 @@ void sceUmdActivate(u32 unknown, const char *name) u32 notifyArg = UMD_PRESENT | UMD_READABLE; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - RETURN(0); if (changed) hleReSchedule("umd activated"); + + return 0; } -void sceUmdDeactivate(u32 unknown, const char *name) +int sceUmdDeactivate(u32 unknown, const char *name) { // Why 18? No idea. if (unknown < 0 || unknown > 18) - { - RETURN(PSP_ERROR_UMD_INVALID_PARAM); - return; - } + return PSP_ERROR_UMD_INVALID_PARAM; bool changed = umdActivated != 0; __KernelUmdDeactivate(); @@ -158,10 +153,11 @@ void sceUmdDeactivate(u32 unknown, const char *name) u32 notifyArg = UMD_PRESENT | UMD_READY; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - RETURN(0); if (changed) hleReSchedule("umd deactivated"); + + return 0; } u32 sceUmdRegisterUMDCallBack(u32 cbId) @@ -260,10 +256,8 @@ void sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) } -void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) +int sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - RETURN(0); - if (driveCBId != -1) { DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout); @@ -285,6 +279,8 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) } else if (driveCBId != -1) hleReSchedule("umd stat waited"); + + return 0; } void sceUmdCancelWaitDriveStat() @@ -306,13 +302,13 @@ u32 sceUmdGetErrorStat() const HLEFunction sceUmdUser[] = { - {0xC6183D47,WrapV_UC,"sceUmdActivate"}, + {0xC6183D47,WrapI_UC,"sceUmdActivate"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, - {0xE83742BA,WrapV_UC,"sceUmdDeactivate"}, + {0xE83742BA,WrapI_UC,"sceUmdDeactivate"}, {0x8EF08FCE,WrapV_U,"sceUmdWaitDriveStat"}, {0x56202973,WrapV_UU,"sceUmdWaitDriveStatWithTimer"}, - {0x4A9E5E29,WrapV_UU,"sceUmdWaitDriveStatCB"}, + {0x4A9E5E29,WrapI_UU,"sceUmdWaitDriveStatCB"}, {0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x20628E6F,&WrapU_V,"sceUmdGetErrorStat"}, From f145bafc7abf42793e3f38fb644e8763d886d968 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Dec 2012 00:29:10 -0800 Subject: [PATCH 31/34] Wrap a few of the sceKernel*Thread funcs. --- Core/HLE/FunctionWrappers.h | 6 +++ Core/HLE/sceKernel.cpp | 10 ++--- Core/HLE/sceKernelThread.cpp | 73 +++++++++++++++--------------------- Core/HLE/sceKernelThread.h | 10 ++--- 4 files changed, 47 insertions(+), 52 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index abb7de402b..bc7f1ed1b2 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -232,6 +232,12 @@ template void WrapI_CUUU() { RETURN(retval); } +template void WrapI_CUUIUU() { + int retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1), PARAM(2), + PARAM(3), PARAM(4), PARAM(5)); + RETURN(retval); +} + template void WrapU_CU() { u32 retval = func(Memory::GetCharPointer(PARAM(0)), PARAM(1)); RETURN((u32) retval); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 7872b18f39..c86a6d6d70 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -354,8 +354,8 @@ const HLEFunction ThreadManForUser[] = {0xFCCFAD26,sceKernelCancelWakeupThread,"sceKernelCancelWakeupThread"}, {0xea748e31,sceKernelChangeCurrentThreadAttr,"sceKernelChangeCurrentThreadAttr"}, {0x71bc9871,sceKernelChangeThreadPriority,"sceKernelChangeThreadPriority"}, - {0x446D8DE6,sceKernelCreateThread,"sceKernelCreateThread"}, - {0x9fa03cd3,sceKernelDeleteThread,"sceKernelDeleteThread"}, + {0x446D8DE6,WrapI_CUUIUU,"sceKernelCreateThread"}, + {0x9fa03cd3,WrapI_I,"sceKernelDeleteThread"}, {0xBD123D9E,0,"sceKernelDelaySysClockThread"}, {0x1181E963,0,"sceKernelDelaySysClockThreadCB"}, {0xceadeb47,sceKernelDelayThread,"sceKernelDelayThread"}, @@ -375,10 +375,10 @@ const HLEFunction ThreadManForUser[] = {0x912354a7,sceKernelRotateThreadReadyQueue,"sceKernelRotateThreadReadyQueue"}, {0x9ACE131E,sceKernelSleepThread,"sceKernelSleepThread"}, {0x82826f70,sceKernelSleepThreadCB,"sceKernelSleepThreadCB"}, - {0xF475845D,&WrapV_IUU,"sceKernelStartThread"}, + {0xF475845D,&WrapI_IUU,"sceKernelStartThread"}, {0x9944f31f,sceKernelSuspendThread,"sceKernelSuspendThread"}, - {0x616403ba,WrapV_U,"sceKernelTerminateThread"}, - {0x383f7bcc,sceKernelTerminateDeleteThread,"sceKernelTerminateDeleteThread"}, + {0x616403ba,WrapI_U,"sceKernelTerminateThread"}, + {0x383f7bcc,WrapI_I,"sceKernelTerminateDeleteThread"}, {0x840E8133,sceKernelWaitThreadEndCB,"sceKernelWaitThreadEndCB"}, {0xd13bde95,sceKernelCheckThreadStack,"sceKernelCheckThreadStack"}, diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 7dc3683825..1f5d969f05 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -929,26 +929,19 @@ void __KernelSetupRootThread(SceUID moduleID, int args, const char *argp, int pr } -void sceKernelCreateThread() +int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr) { - u32 nameAddr = PARAM(0); - const char *threadName = Memory::GetCharPointer(nameAddr); - u32 entry = PARAM(1); - u32 prio = PARAM(2); - int stacksize = PARAM(3); - u32 attr = PARAM(4); - //ignore PARAM(5) - SceUID id; __KernelCreateThread(id, curModule, threadName, entry, prio, stacksize, attr); - INFO_LOG(HLE,"%i = sceKernelCreateThread(name=\"%s\", entry= %08x, stacksize=%i )", id, threadName, entry, stacksize); - RETURN(id); + INFO_LOG(HLE, "%i = sceKernelCreateThread(name=\"%s\", entry=%08x, prio=%x, stacksize=%i)", id, threadName, entry, prio, stacksize); + if (optionAddr != 0) + WARN_LOG(HLE, "sceKernelCreateThread: unsupported options parameter.", threadName); + return id; } // int sceKernelStartThread(SceUID threadToStartID, SceSize argSize, void *argBlock) -// void because it reschedules. -void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) +int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) { if (threadToStartID != currentThread->GetUID()) { @@ -958,15 +951,13 @@ void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) { ERROR_LOG(HLE,"%08x=sceKernelStartThread(thread=%i, argSize=%i, argPtr= %08x): thread does not exist!", error,threadToStartID,argSize,argBlockPtr) - RETURN(error); - return; + return error; } if (startThread->nt.status != THREADSTATUS_DORMANT) { //Not dormant, WTF? - RETURN(ERROR_KERNEL_THREAD_IS_NOT_DORMANT); - return; + return ERROR_KERNEL_THREAD_IS_NOT_DORMANT; } INFO_LOG(HLE,"sceKernelStartThread(thread=%i, argSize=%i, argPtr= %08x )", @@ -995,14 +986,14 @@ void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr) if (!argBlockPtr && argSize > 0) { WARN_LOG(HLE,"sceKernelStartThread : had NULL arg"); } - RETURN(0); hleReSchedule("thread started"); + return 0; } else { ERROR_LOG(HLE,"thread %i trying to start itself", threadToStartID); - RETURN(-1); + return -1; } } @@ -1142,63 +1133,60 @@ void sceKernelRotateThreadReadyQueue() hleReSchedule("rotatethreadreadyqueue"); } -void sceKernelDeleteThread() +int sceKernelDeleteThread(int threadHandle) { - int threadHandle = PARAM(0); if (threadHandle != currentThread->GetUID()) { //TODO: remove from threadqueue! DEBUG_LOG(HLE,"sceKernelDeleteThread(%i)",threadHandle); - u32 error; - Thread *t = kernelObjects.Get(threadHandle, error); - if (t) - { - __KernelRemoveFromThreadQueue(t); - __KernelFireThreadEnd(t); + u32 error; + Thread *t = kernelObjects.Get(threadHandle, error); + if (t) + { + __KernelRemoveFromThreadQueue(t); + __KernelFireThreadEnd(t); - RETURN(kernelObjects.Destroy(threadHandle)); + __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle); - __KernelTriggerWait(WAITTYPE_THREADEND, threadHandle); - - //TODO: should we really reschedule here? - //if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadHandle)) - // hleReSchedule("thread deleted"); - } + //TODO: should we really reschedule here? + //if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadHandle)) + // hleReSchedule("thread deleted"); + return kernelObjects.Destroy(threadHandle); + } } else { ERROR_LOG(HLE, "Thread \"%s\" tries to delete itself! :(",currentThread->GetName()); - RETURN(-1); + return -1; } } -void sceKernelTerminateDeleteThread() +int sceKernelTerminateDeleteThread(int threadno) { - int threadno = PARAM(0); if (threadno != currentThread->GetUID()) { //TODO: remove from threadqueue! INFO_LOG(HLE, "sceKernelTerminateDeleteThread(%i)", threadno); - RETURN(0); //kernelObjects.Destroy(threadno)); //TODO: should we really reschedule here? if (!__KernelTriggerWait(WAITTYPE_THREADEND, threadno)) hleReSchedule("termdeletethread"); + + return 0; //kernelObjects.Destroy(threadno)); } else { ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", currentThread->GetName()); - RETURN(-1); + return -1; } } -void sceKernelTerminateThread(u32 threadID) +int sceKernelTerminateThread(u32 threadID) { if (threadID != currentThread->GetUID()) { INFO_LOG(HLE, "sceKernelTerminateThread(%i)", threadID); - RETURN(0); u32 error; Thread *t = kernelObjects.Get(threadID, error); @@ -1209,11 +1197,12 @@ void sceKernelTerminateThread(u32 threadID) __KernelTriggerWait(WAITTYPE_THREADEND, threadID); } // TODO: Return an error if it doesn't exist? + return 0; } else { ERROR_LOG(HLE, "Thread \"%s\" trying to delete itself! :(", currentThread->GetName()); - RETURN(-1); + return -1; } } diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 1770c62130..30998ea4ad 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -26,16 +26,16 @@ void sceKernelChangeThreadPriority(); -void sceKernelCreateThread(); +int sceKernelCreateThread(const char *threadName, u32 entry, u32 prio, int stacksize, u32 attr, u32 optionAddr); void sceKernelDelayThread(); void sceKernelDelayThreadCB(); -void sceKernelDeleteThread(); +int sceKernelDeleteThread(int threadHandle); void sceKernelExitDeleteThread(); void sceKernelExitThread(); void _sceKernelExitThread(); void sceKernelGetThreadId(); void sceKernelGetThreadCurrentPriority(); -void sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr); +int sceKernelStartThread(SceUID threadToStartID, u32 argSize, u32 argBlockPtr); u32 sceKernelSuspendDispatchThread(); u32 sceKernelResumeDispatchThread(u32 suspended); void sceKernelWaitThreadEnd(); @@ -47,8 +47,8 @@ void sceKernelSuspendThread(); void sceKernelResumeThread(); void sceKernelWakeupThread(); void sceKernelCancelWakeupThread(); -void sceKernelTerminateDeleteThread(); -void sceKernelTerminateThread(u32 threadID); +int sceKernelTerminateDeleteThread(int threadno); +int sceKernelTerminateThread(u32 threadID); void sceKernelWaitThreadEndCB(); void sceKernelGetThreadExitStatus(); void sceKernelGetThreadmanIdType(); From b6a7b0498184ac4a65942cf2f287a627b618e1ad Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 9 Dec 2012 01:16:19 -0800 Subject: [PATCH 32/34] Cleanup deferred rescheduling in case it's tight. Probably doesn't matter anyway. But this reads cleaner I think. --- Core/HLE/HLE.cpp | 42 ++++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index eebc8bc888..0c2e9ad829 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -28,11 +28,6 @@ #include "sceKernelThread.h" #include "../MIPS/MIPSCodeUtils.h" -static std::vector moduleDB; -static std::vector unresolvedSyscalls; -static int hleAfterSyscall; -static const char *hleAfterSyscallReschedReason; - enum { // Do nothing after the syscall. @@ -47,6 +42,11 @@ enum HLE_AFTER_RESCHED_CALLBACKS = 0x08, }; +static std::vector moduleDB; +static std::vector unresolvedSyscalls; +static int hleAfterSyscall = HLE_AFTER_NOTHING; +static const char *hleAfterSyscallReschedReason = NULL; + void HLEInit() { RegisterAllModules(); @@ -218,6 +218,23 @@ void hleReSchedule(bool callbacks, const char *reason) hleAfterSyscall |= HLE_AFTER_RESCHED_CALLBACKS; } +inline void hleFinishSyscall() +{ + if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) + __KernelForceCallbacks(); + + // Rescheduling will also do HLE_AFTER_ALL_CALLBACKS. + if ((hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) != 0) + __KernelReSchedule(true, hleAfterSyscallReschedReason); + else if ((hleAfterSyscall & HLE_AFTER_RESCHED) != 0) + __KernelReSchedule(hleAfterSyscallReschedReason); + else if ((hleAfterSyscall & HLE_AFTER_ALL_CALLBACKS) != 0) + __KernelCheckCallbacks(); + + hleAfterSyscall = HLE_AFTER_NOTHING; + hleAfterSyscallReschedReason = NULL; +} + void CallSyscall(u32 op) { u32 callno = (op >> 6) & 0xFFFFF; //20 bits @@ -232,21 +249,10 @@ void CallSyscall(u32 op) HLEFunc func = moduleDB[modulenum].funcTable[funcnum].func; if (func) { - hleAfterSyscall = HLE_AFTER_NOTHING; - hleAfterSyscallReschedReason = 0; - func(); - if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0) - __KernelForceCallbacks(); - - // Rescheduling will also do HLE_AFTER_ALL_CALLBACKS. - if ((hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) != 0) - __KernelReSchedule(true, hleAfterSyscallReschedReason); - else if ((hleAfterSyscall & HLE_AFTER_RESCHED) != 0) - __KernelReSchedule(hleAfterSyscallReschedReason); - else if ((hleAfterSyscall & HLE_AFTER_ALL_CALLBACKS) != 0) - __KernelCheckCallbacks(); + if (hleAfterSyscall != HLE_AFTER_NOTHING) + hleFinishSyscall(); } else { From 5e3590d94e38d447246f1d5ac6359596111f94af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 9 Dec 2012 19:41:19 +0700 Subject: [PATCH 33/34] Remove some RETURN, cleanup --- Core/HLE/sceAudio.cpp | 217 ++++++++++++++++++----------------------- Core/HLE/scePower.cpp | 136 ++++++++++---------------- Core/HLE/sceVaudio.cpp | 35 +++---- pspautotests | 2 +- 4 files changed, 161 insertions(+), 229 deletions(-) diff --git a/Core/HLE/sceAudio.cpp b/Core/HLE/sceAudio.cpp index 35f76a04e1..be2cc3652f 100644 --- a/Core/HLE/sceAudio.cpp +++ b/Core/HLE/sceAudio.cpp @@ -6,7 +6,7 @@ // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. @@ -36,74 +36,48 @@ AudioChannel chans[8]; // Not sure about the range of volume, I often see 0x800 so that might be either // max or 50%? -void sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr) -{ - if (samplePtr == 0) - { +u32 sceAudioOutputBlocking(u32 chan, u32 vol, u32 samplePtr) { + if (samplePtr == 0) { ERROR_LOG(HLE, "sceAudioOutputBlocking - Sample pointer null"); - RETURN(0); + return 0; } - if (chan < 0 || chan >= MAX_CHANNEL) - { + if (chan < 0 || chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutputBlocking() - BAD CHANNEL"); - RETURN(SCE_ERROR_AUDIO_INVALID_CHANNEL); - } - else if (!chans[chan].reserved) - { + return SCE_ERROR_AUDIO_INVALID_CHANNEL; + } else if (!chans[chan].reserved) { ERROR_LOG(HLE,"sceAudioOutputBlocking() - channel not reserved"); - RETURN(SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED); - } - else - { + return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; + } else { DEBUG_LOG(HLE, "sceAudioOutputBlocking(%d, %d, %08x )",chan,vol,samplePtr); chans[chan].leftVolume = vol; chans[chan].rightVolume = vol; chans[chan].sampleAddress = samplePtr; - RETURN(0); - int retval = __AudioEnqueue(chans[chan], chan, true); - if (retval != 0) { - // There was an error and didn't block (block always returns 0 here). Fine to RETURN. - RETURN(retval); - } + return __AudioEnqueue(chans[chan], chan, true); } } -void sceAudioOutputPannedBlocking(u32 chan, u32 volume1, u32 volume2, u32 samplePtr) -{ - if (samplePtr == 0) - { - ERROR_LOG(HLE, "sceAudioOutputPannedBlocking - Sample pointer null"); - RETURN(0); - } - else if (chan < 0 || chan >= MAX_CHANNEL) - { +u32 sceAudioOutputPannedBlocking(u32 chan, u32 volume1, u32 volume2, u32 samplePtr) { + if (samplePtr == 0) { + ERROR_LOG(HLE, "sceAudioOutputPannedBlocking - Sample pointer null"); + return 0; + } else if (chan < 0 || chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutputPannedBlocking() - BAD CHANNEL"); - RETURN(SCE_ERROR_AUDIO_INVALID_CHANNEL); - } - else if (!chans[chan].reserved) - { + return SCE_ERROR_AUDIO_INVALID_CHANNEL; + } else if (!chans[chan].reserved) { ERROR_LOG(HLE,"sceAudioOutputPannedBlocking() - CHANNEL NOT RESERVED"); - RETURN(SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED); - } - else - { - DEBUG_LOG(HLE, "sceAudioOutputPannedBlocking(%d,%d,%d, %08x )", chan, volume1, volume2, samplePtr); + return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; + } else { + DEBUG_LOG(HLE, "sceAudioOutputPannedBlocking(%d,%d,%d, %08x )", chan, volume1, volume2, samplePtr); chans[chan].leftVolume = volume1; chans[chan].rightVolume = volume2; chans[chan].sampleAddress = samplePtr; - RETURN(0); - int retval = __AudioEnqueue(chans[chan], chan, true); - if (retval != 0) { - // There was an error and didn't block (block always returns 0 here). Fine to RETURN. - RETURN(retval); - } + return __AudioEnqueue(chans[chan], chan, true); } } u32 sceAudioOutput(u32 chan, u32 vol, u32 samplePtr) { - if (chan < 0 || chan >= MAX_CHANNEL) - { + if (chan < 0 || chan >= MAX_CHANNEL) { ERROR_LOG(HLE,"sceAudioOutput() - BAD CHANNEL"); return SCE_ERROR_AUDIO_INVALID_CHANNEL; } @@ -175,7 +149,7 @@ int sceAudioGetChannelRestLength(u32 chan) static int GetFreeChannel() { for (int i = 0; i < MAX_CHANNEL; i++) - { + { if (!chans[i].reserved) { return i; @@ -240,64 +214,64 @@ u32 sceAudioChRelease(u32 chan) u32 sceAudioSetChannelDataLen(u32 chan, u32 len) { - if (chan < 0 || chan >= MAX_CHANNEL) - { - ERROR_LOG(HLE,"sceAudioSetChannelDataLen(%i, %i) - BAD CHANNEL", chan, len); - return SCE_ERROR_AUDIO_INVALID_CHANNEL; - } - else if (!chans[chan].reserved) - { - ERROR_LOG(HLE,"sceAudioSetChannelDataLen(%i, %i) - channel not reserved", chan, len); - return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; - } - else - { - DEBUG_LOG(HLE, "sceAudioSetChannelDataLen(%i, %i)", chan, len); + if (chan < 0 || chan >= MAX_CHANNEL) + { + ERROR_LOG(HLE,"sceAudioSetChannelDataLen(%i, %i) - BAD CHANNEL", chan, len); + return SCE_ERROR_AUDIO_INVALID_CHANNEL; + } + else if (!chans[chan].reserved) + { + ERROR_LOG(HLE,"sceAudioSetChannelDataLen(%i, %i) - channel not reserved", chan, len); + return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; + } + else + { + DEBUG_LOG(HLE, "sceAudioSetChannelDataLen(%i, %i)", chan, len); //chans[chan].dataLen = len; chans[chan].sampleCount = len; - return 0; - } + return 0; + } } u32 sceAudioChangeChannelConfig(u32 chan, u32 format) { - if (chan < 0 || chan >= MAX_CHANNEL) - { - ERROR_LOG(HLE,"sceAudioChangeChannelConfig(%i, %i) - invalid channel number", chan, format); - return SCE_ERROR_AUDIO_INVALID_CHANNEL; - } - else if (!chans[chan].reserved) - { - ERROR_LOG(HLE,"sceAudioChangeChannelConfig(%i, %i) - channel not reserved", chan, format); - return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; - } - else - { - DEBUG_LOG(HLE, "sceAudioChangeChannelConfig(%i, %i)", chan, format); - chans[chan].format = format; - return 0; - } + if (chan < 0 || chan >= MAX_CHANNEL) + { + ERROR_LOG(HLE,"sceAudioChangeChannelConfig(%i, %i) - invalid channel number", chan, format); + return SCE_ERROR_AUDIO_INVALID_CHANNEL; + } + else if (!chans[chan].reserved) + { + ERROR_LOG(HLE,"sceAudioChangeChannelConfig(%i, %i) - channel not reserved", chan, format); + return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; + } + else + { + DEBUG_LOG(HLE, "sceAudioChangeChannelConfig(%i, %i)", chan, format); + chans[chan].format = format; + return 0; + } } u32 sceAudioChangeChannelVolume(u32 chan, u32 lvolume, u32 rvolume) { - if (chan < 0 || chan >= MAX_CHANNEL) - { - ERROR_LOG(HLE,"sceAudioChangeChannelVolume(%i, %i, %i) - invalid channel number", chan, lvolume, rvolume); - return SCE_ERROR_AUDIO_INVALID_CHANNEL; - } - else if (!chans[chan].reserved) - { - ERROR_LOG(HLE,"sceAudioChangeChannelVolume(%i, %i, %i) - channel not reserved", chan, lvolume, rvolume); - return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; - } - else - { - DEBUG_LOG(HLE, "sceAudioChangeChannelVolume(%i, %i, %i)", chan, lvolume, rvolume); - chans[chan].leftVolume = lvolume; - chans[chan].rightVolume = rvolume; - return 0; - } + if (chan < 0 || chan >= MAX_CHANNEL) + { + ERROR_LOG(HLE,"sceAudioChangeChannelVolume(%i, %i, %i) - invalid channel number", chan, lvolume, rvolume); + return SCE_ERROR_AUDIO_INVALID_CHANNEL; + } + else if (!chans[chan].reserved) + { + ERROR_LOG(HLE,"sceAudioChangeChannelVolume(%i, %i, %i) - channel not reserved", chan, lvolume, rvolume); + return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED; + } + else + { + DEBUG_LOG(HLE, "sceAudioChangeChannelVolume(%i, %i, %i)", chan, lvolume, rvolume); + chans[chan].leftVolume = lvolume; + chans[chan].rightVolume = rvolume; + return 0; + } } u32 sceAudioInit() @@ -321,16 +295,13 @@ u32 sceAudioOutput2Reserve(u32 sampleCount) return 0; } -void sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr) +u32 sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr) { DEBUG_LOG(HLE,"FAKE sceAudioOutput2OutputBlocking(%i, %08x)", vol, dataPtr); chans[0].leftVolume = vol; chans[0].rightVolume = vol; chans[0].sampleAddress = dataPtr; - RETURN(0); - u32 retval = __AudioEnqueue(chans[0], 0, true); - if (retval < 0) - RETURN(retval); + return __AudioEnqueue(chans[0], 0, true); } u32 sceAudioOutput2ChangeLength(u32 sampleCount) @@ -342,7 +313,7 @@ u32 sceAudioOutput2ChangeLength(u32 sampleCount) u32 sceAudioOutput2GetRestSample() { - WARN_LOG(HLE,"UNTESTED sceAudioOutput2GetRestSample()"); + WARN_LOG(HLE,"UNTESTED sceAudioOutput2GetRestSample()"); return chans[0].sampleQueue.size() * 2; } @@ -368,30 +339,30 @@ const HLEFunction sceAudio[] = { // Newer simplified single channel audio output. Presumably for games that use Atrac3 // directly from Sas instead of playing it on a separate audio channel. - {0x01562ba3, WrapU_U, "sceAudioOutput2Reserve"}, - {0x2d53f36e, WrapV_UU, "sceAudioOutput2OutputBlocking"}, - {0x63f2889c, WrapU_U, "sceAudioOutput2ChangeLength"}, - {0x647cef33, WrapU_V, "sceAudioOutput2GetRestSample"}, - {0x43196845, WrapU_V, "sceAudioOutput2Release"}, + {0x01562ba3, WrapU_U, "sceAudioOutput2Reserve"}, + {0x2d53f36e, WrapU_UU, "sceAudioOutput2OutputBlocking"}, + {0x63f2889c, WrapU_U, "sceAudioOutput2ChangeLength"}, + {0x647cef33, WrapU_V, "sceAudioOutput2GetRestSample"}, + {0x43196845, WrapU_V, "sceAudioOutput2Release"}, {0x80F1F7E0, WrapU_V, "sceAudioInit"}, {0x210567F7, WrapU_V, "sceAudioEnd"}, - {0xA2BEAA6C, WrapU_U, "sceAudioSetFrequency"}, + {0xA2BEAA6C, WrapU_U, "sceAudioSetFrequency"}, {0x927AC32B, 0, "sceAudioSetVolumeOffset"}, // The oldest and standard audio interface. Supports 8 channels, most games use 1-2. - {0x8c1009b2, WrapU_UUU, "sceAudioOutput"}, - {0x136CAF51, WrapV_UUU, "sceAudioOutputBlocking"}, - {0xE2D56B2D, WrapU_UUUU, "sceAudioOutputPanned"}, - {0x13F592BC, WrapV_UUUU, "sceAudioOutputPannedBlocking"}, //(u32, u32, u32, void *)Output sound, blocking - {0x5EC81C55, WrapU_UUU, "sceAudioChReserve"}, //(u32, u32 samplecount, u32) Initialize channel and allocate buffer long, long samplecount, long);//init buffer? returns handle, minus if error - {0x6FC46853, WrapU_U, "sceAudioChRelease"}, //(long handle)Terminate channel and deallocate buffer //free buffer? - {0xE9D97901, WrapI_U, "sceAudioGetChannelRestLen"}, - {0xB011922F, WrapI_U, "sceAudioGetChannelRestLength"}, // Is there a difference between this and sceAudioGetChannelRestLen? + {0x8c1009b2, WrapU_UUU, "sceAudioOutput"}, + {0x136CAF51, WrapU_UUU, "sceAudioOutputBlocking"}, + {0xE2D56B2D, WrapU_UUUU, "sceAudioOutputPanned"}, + {0x13F592BC, WrapU_UUUU, "sceAudioOutputPannedBlocking"}, //(u32, u32, u32, void *)Output sound, blocking + {0x5EC81C55, WrapU_UUU, "sceAudioChReserve"}, //(u32, u32 samplecount, u32) Initialize channel and allocate buffer long, long samplecount, long);//init buffer? returns handle, minus if error + {0x6FC46853, WrapU_U, "sceAudioChRelease"}, //(long handle)Terminate channel and deallocate buffer //free buffer? + {0xE9D97901, WrapI_U, "sceAudioGetChannelRestLen"}, + {0xB011922F, WrapI_U, "sceAudioGetChannelRestLength"}, // Is there a difference between this and sceAudioGetChannelRestLen? {0xCB2E439E, WrapU_UU, "sceAudioSetChannelDataLen"}, //(u32, u32) - {0x95FD0C2D, WrapU_UU, "sceAudioChangeChannelConfig"}, - {0xB7E1D8E7, WrapU_UUU, "sceAudioChangeChannelVolume"}, + {0x95FD0C2D, WrapU_UU, "sceAudioChangeChannelConfig"}, + {0xB7E1D8E7, WrapU_UUU, "sceAudioChangeChannelVolume"}, // I guess these are like the others but do sample rate conversion? {0x38553111, 0, "sceAudioSRCChReserve"}, @@ -405,9 +376,9 @@ const HLEFunction sceAudio[] = // Microphone interface {0x7de61688, 0, "sceAudioInputInit"}, {0xE926D3FB, 0, "sceAudioInputInitEx"}, - {0x6d4bec68, 0, "sceAudioInput"}, - {0x086e5895, 0, "sceAudioInputBlocking"}, - {0xa708c6a6, 0, "sceAudioGetInputLength"}, + {0x6d4bec68, 0, "sceAudioInput"}, + {0x086e5895, 0, "sceAudioInputBlocking"}, + {0xa708c6a6, 0, "sceAudioGetInputLength"}, {0xA633048E, 0, "sceAudioPollInputEnd"}, {0x87b2e651, 0, "sceAudioWaitInputEnd"}, }; @@ -416,5 +387,5 @@ const HLEFunction sceAudio[] = void Register_sceAudio() { - RegisterModule("sceAudio", ARRAY_SIZE(sceAudio), sceAudio); + RegisterModule("sceAudio", ARRAY_SIZE(sceAudio), sceAudio); } diff --git a/Core/HLE/scePower.cpp b/Core/HLE/scePower.cpp index d4c49b0f27..bfe1943bc1 100644 --- a/Core/HLE/scePower.cpp +++ b/Core/HLE/scePower.cpp @@ -34,133 +34,102 @@ void __PowerInit() { memset(powerCbSlots, 0, sizeof(powerCbSlots)); } -int scePowerGetBatteryLifePercent() -{ +int scePowerGetBatteryLifePercent() { DEBUG_LOG(HLE, "100=scePowerGetBatteryLifePercent"); return 100; } -int scePowerIsPowerOnline() -{ +int scePowerIsPowerOnline() { DEBUG_LOG(HLE, "1=scePowerIsPowerOnline"); return 1; } -int scePowerIsBatteryExist() -{ +int scePowerIsBatteryExist() { DEBUG_LOG(HLE, "1=scePowerIsBatteryExist"); return 1; } -int scePowerIsBatteryCharging() -{ +int scePowerIsBatteryCharging() { DEBUG_LOG(HLE, "0=scePowerIsBatteryCharging"); return 0; } -int scePowerGetBatteryChargingStatus() -{ +int scePowerGetBatteryChargingStatus() { DEBUG_LOG(HLE, "0=scePowerGetBatteryChargingStatus"); return 0; } -int scePowerIsLowBattery() -{ +int scePowerIsLowBattery() { DEBUG_LOG(HLE, "0=scePowerIsLowBattery"); return 0; } -int scePowerRegisterCallback(int slot, int cbId) -{ +int scePowerRegisterCallback(int slot, int cbId) { DEBUG_LOG(HLE,"0=scePowerRegisterCallback(%i, %i)", slot, cbId); int foundSlot = -1; - if (slot == POWER_CB_AUTO) // -1 signifies auto select of bank - { - for(int i=0; i < numberOfCBPowerSlots; i++) - { - if ((powerCbSlots[i]==0) && (foundSlot == POWER_CB_AUTO)) // found an empty slot - { + if (slot == POWER_CB_AUTO) { // -1 signifies auto select of bank + for (int i=0; i < numberOfCBPowerSlots; i++) { + if ((powerCbSlots[i]==0) && (foundSlot == POWER_CB_AUTO)) { // found an empty slot powerCbSlots[i] = cbId; foundSlot = i; } } - } - else - { - if (powerCbSlots[slot] == 0) - { + } else { + if (powerCbSlots[slot] == 0) { powerCbSlots[slot] = cbId; foundSlot = 0; - } - else - { + } else { // slot already in use! foundSlot = POWER_CB_AUTO; } } - if (foundSlot>=0) - { + if (foundSlot>=0) { __KernelRegisterCallback(THREAD_CALLBACK_POWER, cbId); - - // Immediately notify - RETURN(0); - - __KernelNotifyCallbackType(THREAD_CALLBACK_POWER, cbId, 0x185); // TODO: I have no idea what the 0x185 is from the flags, but its needed for the test to pass. Need another example of it being called + __KernelNotifyCallbackType(THREAD_CALLBACK_POWER, cbId, 0x185); // TODO: I have no idea what the 0x185 is from the flags, but its needed for the test to pass. Need another example of it being called } return foundSlot; } -int scePowerUnregisterCallback(int slotId) -{ - if (slotId < 0 || slotId >= numberOfCBPowerSlots) - { +int scePowerUnregisterCallback(int slotId) { + if (slotId < 0 || slotId >= numberOfCBPowerSlots) { return -1; } - if (powerCbSlots[slotId] != 0) - { + if (powerCbSlots[slotId] != 0) { int cbId = powerCbSlots[slotId]; DEBUG_LOG(HLE,"0=scePowerUnregisterCallback(%i) (cbid = %i)", slotId, cbId); __KernelUnregisterCallback(THREAD_CALLBACK_POWER, cbId); powerCbSlots[slotId] = 0; - } - else - { + } else { return 0x80000025; // TODO: docs say a value less than 0, test checks for this specifically. why?? } return 0; } -int sceKernelPowerLock(int lockType) -{ +int sceKernelPowerLock(int lockType) { DEBUG_LOG(HLE,"0=sceKernelPowerLock(%i)", lockType); return 0; } -int sceKernelPowerUnlock(int lockType) -{ + +int sceKernelPowerUnlock(int lockType) { DEBUG_LOG(HLE,"0=sceKernelPowerUnlock(%i)", lockType); return 0; } -int sceKernelPowerTick(int flag) -{ + +int sceKernelPowerTick(int flag) { DEBUG_LOG(HLE,"UNIMPL 0=sceKernelPowerTick(%i)", flag); return 0; } #define ERROR_POWER_VMEM_IN_USE 0x802b0200 -int sceKernelVolatileMemTryLock(int type, int paddr, int psize) -{ - - if (!volatileMemLocked) - { +int sceKernelVolatileMemTryLock(int type, int paddr, int psize) { + if (!volatileMemLocked) { INFO_LOG(HLE,"sceKernelVolatileMemTryLock(%i, %08x, %i) - success", type, paddr, psize); volatileMemLocked = true; - } - else - { + } else { ERROR_LOG(HLE, "sceKernelVolatileMemTryLock(%i, %08x, %i) - already locked!", type, paddr, psize); return ERROR_POWER_VMEM_IN_USE; } @@ -174,47 +143,45 @@ int sceKernelVolatileMemTryLock(int type, int paddr, int psize) return 0; } -int sceKernelVolatileMemUnlock(int type) -{ - INFO_LOG(HLE,"sceKernelVolatileMemUnlock(%i)", type); - // TODO: sanity check - volatileMemLocked = false; +int sceKernelVolatileMemUnlock(int type) { + if (volatileMemLocked) { + INFO_LOG(HLE,"sceKernelVolatileMemUnlock(%i)", type); + volatileMemLocked = false; + } else { + ERROR_LOG(HLE, "sceKernelVolatileMemUnlock(%i) FAILED - not locked", type); + } return 0; } -int sceKernelVolatileMemLock(int type, int paddr, int psize) -{ +int sceKernelVolatileMemLock(int type, int paddr, int psize) { return sceKernelVolatileMemTryLock(type, paddr, psize); } -void scePowerSetClockFrequency(u32 cpufreq, u32 busfreq, u32 gpufreq) -{ +void scePowerSetClockFrequency(u32 cpufreq, u32 busfreq, u32 gpufreq) { CoreTiming::SetClockFrequencyMHz(cpufreq); - INFO_LOG(HLE,"scePowerSetClockFrequency(%i,%i,%i)", cpufreq, busfreq, gpufreq); } -void scePowerGetCpuClockFrequencyInt() { +u32 scePowerGetCpuClockFrequencyInt() { int freq = CoreTiming::GetClockFrequencyMHz(); INFO_LOG(HLE,"%i=scePowerGetCpuClockFrequencyInt()", freq); - RETURN(freq); + return freq; } -void scePowerGetPllClockFrequencyInt() { +u32 scePowerGetPllClockFrequencyInt() { int freq = CoreTiming::GetClockFrequencyMHz() / 2; INFO_LOG(HLE,"%i=scePowerGetPllClockFrequencyInt()", freq); - RETURN(freq); + return freq; } -void scePowerGetBusClockFrequencyInt() { +u32 scePowerGetBusClockFrequencyInt() { int freq = CoreTiming::GetClockFrequencyMHz() / 2; INFO_LOG(HLE,"%i=scePowerGetBusClockFrequencyInt()", freq); - RETURN(freq); + return freq; } -static const HLEFunction scePower[] = -{ +static const HLEFunction scePower[] = { {0x04B7766E,&WrapI_II,"scePowerRegisterCallback"}, {0x2B51FE2F,0,"scePower_2B51FE2F"}, {0x442BFBAC,0,"scePowerGetBacklightMaximum"}, @@ -249,27 +216,26 @@ static const HLEFunction scePower[] = {0xAC32C9CC,0,"scePowerRequestSuspend"}, {0x2875994B,0,"scePower_2875994B"}, {0x0074EF9B,0,"scePowerGetResumeCount"}, - {0xDFA8BAF8,&WrapI_I,"scePowerUnregisterCallback"}, - {0xDB9D28DD,&WrapI_I,"scePowerUnregitserCallback"}, //haha + {0xDFA8BAF8,WrapI_I,"scePowerUnregisterCallback"}, + {0xDB9D28DD,WrapI_I,"scePowerUnregitserCallback"}, //haha {0x843FBF43,0,"scePowerSetCpuClockFrequency"}, {0xB8D7B3FB,0,"scePowerSetBusClockFrequency"}, {0xFEE03A2F,0,"scePowerGetCpuClockFrequency"}, {0x478FE6F5,0,"scePowerGetBusClockFrequency"}, - {0xFDB5BFE9,scePowerGetCpuClockFrequencyInt,"scePowerGetCpuClockFrequencyInt"}, - {0xBD681969,scePowerGetBusClockFrequencyInt,"scePowerGetBusClockFrequencyInt"}, + {0xFDB5BFE9,WrapU_V,"scePowerGetCpuClockFrequencyInt"}, + {0xBD681969,WrapU_V,"scePowerGetBusClockFrequencyInt"}, {0xB1A52C83,0,"scePowerGetCpuClockFrequencyFloat"}, {0x9BADB3EB,0,"scePowerGetBusClockFrequencyFloat"}, - {0x737486F2,&WrapV_UUU,"scePowerSetClockFrequency"}, - {0x34f9c463,scePowerGetPllClockFrequencyInt,"scePowerGetPllClockFrequencyInt"}, + {0x737486F2,WrapV_UUU,"scePowerSetClockFrequency"}, + {0x34f9c463,WrapU_V,"scePowerGetPllClockFrequencyInt"}, {0xea382a27,0,"scePowerGetPllClockFrequencyFloat"}, - {0xebd177d6,&WrapV_UUU,"scePower_driver_EBD177D6"}, //TODO: used in a few places, jpcsp says is the same as scePowerSetClockFrequency + {0xebd177d6,WrapV_UUU,"scePower_driver_EBD177D6"}, //TODO: used in a few places, jpcsp says is the same as scePowerSetClockFrequency {0x469989ad,0,"scePower_469989ad"}, {0xa85880d0,0,"scePower_a85880d0"}, }; //890129c in tyshooter looks bogus -const HLEFunction sceSuspendForUser[] = -{ +const HLEFunction sceSuspendForUser[] = { {0xEADB1BD7,&WrapI_I,"sceKernelPowerLock"}, //(int param) set param to 0 {0x3AEE7261,&WrapI_I,"sceKernelPowerUnlock"},//(int param) set param to 0 {0x090ccb3f,&WrapI_I,"sceKernelPowerTick"}, diff --git a/Core/HLE/sceVaudio.cpp b/Core/HLE/sceVaudio.cpp index f1f2519f24..8b7168e631 100644 --- a/Core/HLE/sceVaudio.cpp +++ b/Core/HLE/sceVaudio.cpp @@ -16,35 +16,30 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "HLE.h" - +#include "FunctionWrappers.h" #include "sceVaudio.h" -void sceVaudioOutputBlockingFunction() -{ - WARN_LOG(HLE, "UNIMPL sceVaudioOutputBlockingFunction(...)"); - RETURN(0); +u32 sceVaudioOutputBlocking() { + ERROR_LOG(HLE, "UNIMPL sceVaudioOutputBlocking(...)"); + return 0; } -void sceVaudioChReserveFunction() -{ - WARN_LOG(HLE, "UNIMPL sceVaudioChReserveFunction(...)"); - RETURN(0); +u32 sceVaudioChReserve() { + ERROR_LOG(HLE, "UNIMPL sceVaudioChReserve(...)"); + return 0; } -void sceVaudioChReleaseFunction() -{ - WARN_LOG(HLE, "UNIMPL sceVaudioChReleaseFunction(...)"); - RETURN(0); +u32 sceVaudioChRelease() { + ERROR_LOG(HLE, "UNIMPL sceVaudioChRelease(...)"); + return 0; } -const HLEFunction sceVaudio[] = -{ - {0x03b6807d, sceVaudioOutputBlockingFunction, "sceVaudioOutputBlockingFunction"}, - {0x67585dfd, sceVaudioChReserveFunction, "sceVaudioChReserveFunction"}, - {0x8986295e, sceVaudioChReleaseFunction, "sceVaudioChReleaseFunction"}, +const HLEFunction sceVaudio[] = { + {0x03b6807d, WrapU_V, "sceVaudioOutputBlockingFunction"}, + {0x67585dfd, WrapU_V, "sceVaudioChReserveFunction"}, + {0x8986295e, WrapU_V, "sceVaudioChReleaseFunction"}, }; -void Register_sceVaudio() -{ +void Register_sceVaudio() { RegisterModule("sceVaudio",ARRAY_SIZE(sceVaudio), sceVaudio ); } diff --git a/pspautotests b/pspautotests index 099ac403dd..e9b4496e32 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 099ac403ddb436f94e7b2227e5c491027641e556 +Subproject commit e9b4496e32bb592dfff14b93abf284ff20783d3c From 454a6000c5e90e4a890be6add0a71ca48ccf5979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 9 Dec 2012 19:58:35 +0700 Subject: [PATCH 34/34] Let's try different audio buffer sizes --- Core/HLE/__sceAudio.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 380f0ba778..c163efdfc4 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -46,8 +46,8 @@ const int audioIntervalUs = (int)(1000000ULL * hwBlockSize / hwSampleRate); const int audioHostIntervalUs = (int)(1000000ULL * hostAttemptBlockSize / hwSampleRate); // High and low watermarks, basically. -const int chanQueueMaxSizeFactor = 2; -const int chanQueueMinSizeFactor = 1; +const int chanQueueMaxSizeFactor = 4; +const int chanQueueMinSizeFactor = 2; FixedSizeQueue outAudioQueue;