From f3e23f2672e6f006d3f225e83cf3a3bf3bf22b7c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 16:40:13 -0800 Subject: [PATCH 01/11] Add some asserts for activating UMDs. --- Core/HLE/sceUmd.cpp | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 81929ca7e6..637f34ef26 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -20,6 +20,8 @@ #include "sceUmd.h" #include "sceKernelThread.h" +const int PSP_ERROR_UMD_INVALID_PORT = 0x80010016; + #define UMD_NOT_PRESENT 0x01 #define UMD_PRESENT 0x02 #define UMD_CHANGED 0x04 @@ -76,11 +78,11 @@ void __KernelUmdDeactivate() //int sceUmdCheckMedium(int a); -void sceUmdCheckMedium() +int sceUmdCheckMedium() { DEBUG_LOG(HLE,"1=sceUmdCheckMedium(?)"); //ignore PARAM(0) - RETURN(1); //non-zero: disc in drive + return 1; //non-zero: disc in drive } void sceUmdGetDiscInfo() @@ -98,9 +100,21 @@ void sceUmdGetDiscInfo() u32 sceUmdActivate(u32 unknown, const char *name) { + if (unknown < 1 || unknown > 2) + return PSP_ERROR_UMD_INVALID_PORT; + u32 retVal = 0; __KernelUmdActivate(); - DEBUG_LOG(HLE,"%i=sceUmdActivate(%08x, %s)", retVal, unknown, name); + + if (unknown == 1) + { + DEBUG_LOG(HLE, "%i=sceUmdActivate(%d, %s)", retVal, unknown, name); + } + else + { + ERROR_LOG(HLE, "UNTESTED %i=sceUmdActivate(%d, %s)", retVal, unknown, name); + } + u32 notifyArg = UMD_PRESENT | UMD_READABLE; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); return retVal; @@ -108,7 +122,19 @@ u32 sceUmdActivate(u32 unknown, const char *name) u32 sceUmdDeactivate(u32 unknown, const char *name) { - DEBUG_LOG(HLE,"sceUmdDeactivate()"); + // Why 18? No idea. + if (unknown < 0 || unknown > 18) + return PSP_ERROR_UMD_INVALID_PORT; + + if (unknown == 1) + { + DEBUG_LOG(HLE, "0=sceUmdDeactivate(%d, %s)", unknown, name); + } + else + { + ERROR_LOG(HLE, "UNTESTED 0=sceUmdDeactivate(%d, %s)", unknown, name); + } + u8 triggerCallback = umdActivated; __KernelUmdDeactivate(); @@ -210,7 +236,7 @@ const HLEFunction sceUmdUser[] = { {0xC6183D47,&WrapU_UC,"sceUmdActivate"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, - {0x46EBB729,sceUmdCheckMedium,"sceUmdCheckMedium"}, + {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, {0xE83742BA,&WrapU_UC,"sceUmdDeactivate"}, {0x8EF08FCE,sceUmdWaitDriveStat,"sceUmdWaitDriveStat"}, {0x56202973,sceUmdWaitDriveStatWithTimer,"sceUmdWaitDriveStatWithTimer"}, From c00f3dcdd852dc3265e6a75cc91953686a75235a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 17:09:03 -0800 Subject: [PATCH 02/11] Implement sceUmdCancelWaitDriveStat(). --- Core/HLE/sceKernelThread.cpp | 14 +++++++++++++- Core/HLE/sceKernelThread.h | 1 + Core/HLE/sceUmd.cpp | 5 +++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 3d15e657b9..03a0e28f93 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -608,7 +608,7 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, int retval) // 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 -bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) +bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, bool dontSwitch) { bool doneAnything = false; @@ -621,6 +621,8 @@ bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) { // This thread was waiting for the triggered object. __KernelResumeThreadFromWait(t); + if (useRetVal) + t->setReturnValue(retVal); doneAnything = true; } } @@ -639,6 +641,16 @@ bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) return true; } +bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) +{ + return __KernelTriggerWait(type, id, false, 0, dontSwitch); +} + +bool __KernelTriggerWait(WaitType type, int id, int retVal, bool dontSwitch) +{ + return __KernelTriggerWait(type, id, true, retVal, dontSwitch); +} + // makes the current thread wait for an event void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr, bool processCallbacks) { diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 4e80b2afaf..f9093c0a9a 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -104,6 +104,7 @@ void __KernelLoadContext(ThreadContext *ctx); // TODO: Replace this with __KernelResumeThread over time as it's misguided. bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch = false); +bool __KernelTriggerWait(WaitType type, int id, int retVal, bool dontSwitch); u32 __KernelResumeThreadFromWait(SceUID threadID); // can return an error value u32 __KernelResumeThreadFromWait(SceUID threadID, int retval); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 637f34ef26..e7ff30faac 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -220,9 +220,10 @@ void sceUmdWaitDriveStatCB() void sceUmdCancelWaitDriveStat() { - u32 stat = PARAM(0); - ERROR_LOG(HLE,"UNIMPL 0=sceUmdCancelWaitDriveStat(stat = %08x)", stat); + DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()"); RETURN(0); + + __KernelTriggerWait(WAITTYPE_UMD, 0, SCE_KERNEL_ERROR_WAIT_CANCEL, false); } u32 sceUmdGetErrorStat() From 4abcb6a8acdfcad29084da723f77e92ae8270c1b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 18:43:45 -0800 Subject: [PATCH 03/11] Fix sceUmdWaitDriveStatCB() so it fires right away. This makes Crisis Core actually show loading again. --- Core/HLE/sceKernelThread.cpp | 11 ++++++++- Core/HLE/sceKernelThread.h | 1 + Core/HLE/sceUmd.cpp | 46 ++++++++++++++++++++---------------- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 03a0e28f93..509fd6e12f 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1811,7 +1811,8 @@ bool __KernelCheckCallbacks() { return processed; } -void sceKernelCheckCallback() { +bool __KernelForceCallbacks() +{ Thread *curThread = __GetCurrentThread(); // This thread can now process callbacks. @@ -1822,6 +1823,14 @@ void sceKernelCheckCallback() { // Note - same thread as above - checking callbacks may switch threads. curThread->isProcessingCallbacks = false; + return callbacksProcessed; +} + +void sceKernelCheckCallback() { + Thread *curThread = __GetCurrentThread(); + + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) { curThread->setReturnValue(1); ERROR_LOG(HLE,"sceKernelCheckCallback() - processed a callback."); diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index f9093c0a9a..36ec19c244 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -164,6 +164,7 @@ bool __KernelInCallback(); // Should be called by (nearly) all ...CB functions. bool __KernelCheckCallbacks(); +bool __KernelForceCallbacks(); class Thread; void __KernelSwitchContext(Thread *target, const char *reason); bool __KernelExecutePendingMipsCalls(); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index e7ff30faac..8624f3795b 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -181,41 +181,45 @@ u32 sceUmdGetDriveStat() * @return < 0 on error * */ -void sceUmdWaitDriveStat() +void sceUmdWaitDriveStat(u32 stat) { - u32 stat = PARAM(0); - DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat); - if ((stat & __KernelUmdGetState()) != stat) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat); RETURN(0); + + if ((stat & __KernelUmdGetState()) == 0) + __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); } -void sceUmdWaitDriveStatWithTimer() +void sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { - u32 stat = PARAM(0); - u32 timeout = PARAM(1); - DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x)", stat); - if ((stat & __KernelUmdGetState()) != stat) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %08x)", stat, timeout); RETURN(0); + + // TODO: timeout? + if ((stat & __KernelUmdGetState()) == 0) + __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); } -void sceUmdWaitDriveStatCB() +void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - u32 stat = PARAM(0); - DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x)", stat); - // Immediately notify - RETURN(0); + ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %08x)", stat, timeout); + RETURN(0); + + // TODO: wait and timeout? + if (driveCBId != -1) { - __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, driveCBId, __KernelUmdGetState()&stat); + // TODO: This is probably the unknown parameter from sceUmdActivate()? + __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, 1, __KernelUmdGetState()); + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) + __KernelExecutePendingMipsCalls(); } else { ERROR_LOG(HLE, "HACK 0=sceUmdWaitDriveStatCB(stat = %08x) attempting to call unset callback", stat); } - RETURN(0); } void sceUmdCancelWaitDriveStat() @@ -239,9 +243,9 @@ const HLEFunction sceUmdUser[] = {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, {0xE83742BA,&WrapU_UC,"sceUmdDeactivate"}, - {0x8EF08FCE,sceUmdWaitDriveStat,"sceUmdWaitDriveStat"}, - {0x56202973,sceUmdWaitDriveStatWithTimer,"sceUmdWaitDriveStatWithTimer"}, - {0x4A9E5E29,sceUmdWaitDriveStatCB,"sceUmdWaitDriveStatCB"}, + {0x8EF08FCE,WrapV_U,"sceUmdWaitDriveStat"}, + {0x56202973,WrapV_UU,"sceUmdWaitDriveStatWithTimer"}, + {0x4A9E5E29,WrapV_UU,"sceUmdWaitDriveStatCB"}, {0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x20628E6F,&WrapU_V,"sceUmdGetErrorStat"}, From 1142ad3ec6250224f15271e0424afff1b36c6919 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 22:05:35 -0800 Subject: [PATCH 04/11] sceUmdDeactivate() seems to always schedule a cb. --- Core/HLE/sceUmd.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 8624f3795b..4a1c579886 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -126,6 +126,8 @@ u32 sceUmdDeactivate(u32 unknown, const char *name) if (unknown < 0 || unknown > 18) return PSP_ERROR_UMD_INVALID_PORT; + __KernelUmdDeactivate(); + if (unknown == 1) { DEBUG_LOG(HLE, "0=sceUmdDeactivate(%d, %s)", unknown, name); @@ -135,13 +137,8 @@ u32 sceUmdDeactivate(u32 unknown, const char *name) ERROR_LOG(HLE, "UNTESTED 0=sceUmdDeactivate(%d, %s)", unknown, name); } - u8 triggerCallback = umdActivated; - __KernelUmdDeactivate(); - - if (triggerCallback) { - u32 notifyArg = UMD_PRESENT | UMD_READY; - __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - } + u32 notifyArg = UMD_PRESENT | UMD_READY; + __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); return 0; } From eaaedc7adc877461e0e6b5c7e616caa10a4fe313 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 22:10:33 -0800 Subject: [PATCH 05/11] This notify isn't needed and was broken anyway. --- Core/HLE/sceUmd.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 4a1c579886..6fdc1f51ca 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -207,8 +207,6 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) if (driveCBId != -1) { - // TODO: This is probably the unknown parameter from sceUmdActivate()? - __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, 1, __KernelUmdGetState()); bool callbacksProcessed = __KernelForceCallbacks(); if (callbacksProcessed) __KernelExecutePendingMipsCalls(); From 16c29a52a8f02d389563b52e01ae31de5a99ab39 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 22:13:58 -0800 Subject: [PATCH 06/11] Improve debugging for bad callback ids. --- Core/HLE/sceKernelThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 509fd6e12f..fb623ef17e 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1877,7 +1877,7 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID threadId, SceUID Callback *cb = kernelObjects.Get(cbId, error); if (!cb) { // Yeah, we're screwed, this shouldn't happen. - ERROR_LOG(HLE, "__KernelNotifyCallback - invalid callback 0"); + ERROR_LOG(HLE, "__KernelNotifyCallback - invalid callback %08x", cbId); return; } cb->nc.notifyCount++; From 00ca9d8dc7dba6e8fbd8d46c2d817fd9230b1811 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 23:05:03 -0800 Subject: [PATCH 07/11] Make the UMD wait funcs actually wait. --- Core/HLE/sceKernelMutex.cpp | 11 +++++-- Core/HLE/sceUmd.cpp | 60 ++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index bf024fbd44..647650b027 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -374,8 +374,15 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr) if (timeoutPtr == 0 || mutexWaitTimer == 0) return; - // This should call __KernelMutexTimeout() later, unless we cancel it. int micro = (int) Memory::Read_U32(timeoutPtr); + + // This happens to be how the hardware seems to time things. + if (micro <= 3) + micro = 15; + else if (micro <= 249) + micro = 250; + + // This should call __KernelMutexTimeout() later, unless we cancel it. CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread()); } @@ -701,7 +708,7 @@ void __KernelWaitLwMutex(LwMutex *mutex, u32 timeoutPtr) else if (micro <= 249) micro = 250; - // This should call __KernelMutexTimeout() later, unless we cancel it. + // This should call __KernelLwMutexTimeout() later, unless we cancel it. CoreTiming::ScheduleEvent(usToCycles(micro), lwMutexWaitTimer, __KernelGetCurThread()); } diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 6fdc1f51ca..9c13c7d464 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -17,6 +17,7 @@ #include "HLE.h" #include "../MIPS/MIPS.h" +#include "../../Core/CoreTiming.h" #include "sceUmd.h" #include "sceKernelThread.h" @@ -34,6 +35,7 @@ u8 umdActivated = 1; u32 umdStatus = 0; u32 umdErrorStat = 0; static int driveCBId= -1; +int umdStatTimer = 0; #define PSP_UMD_TYPE_GAME 0x10 @@ -171,6 +173,31 @@ u32 sceUmdGetDriveStat() return retVal; } +void __UmdStatTimeout(u64 userdata, int cyclesLate) +{ + SceUID threadID = (SceUID)userdata; + + u32 error; + SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_UMD, error); + // Assuming it's still waiting. + if (waitID == 1) + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); +} + +void __UmdWaitStat(u32 timeout) +{ + if (umdStatTimer == 0) + umdStatTimer = CoreTiming::RegisterEvent("MutexTimeout", &__UmdStatTimeout); + + // This happens to be how the hardware seems to time things. + if (timeout <= 4) + timeout = 15; + else if (timeout <= 215) + timeout = 250; + + CoreTiming::ScheduleEvent(usToCycles((int) timeout), umdStatTimer, __KernelGetCurThread()); +} + /** * Wait for a drive to reach a certain state * @@ -180,40 +207,51 @@ u32 sceUmdGetDriveStat() */ void sceUmdWaitDriveStat(u32 stat) { - ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat); + DEBUG_LOG(HLE,"0=sceUmdWaitDriveStat(stat = %08x)", stat); RETURN(0); if ((stat & __KernelUmdGetState()) == 0) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0); } void sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { - ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %08x)", stat, timeout); + DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout); RETURN(0); - // TODO: timeout? if ((stat & __KernelUmdGetState()) == 0) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + { + __UmdWaitStat(timeout); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0); + } } void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %08x)", stat, timeout); RETURN(0); - // TODO: wait and timeout? - if (driveCBId != -1) { + DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout); + bool callbacksProcessed = __KernelForceCallbacks(); if (callbacksProcessed) __KernelExecutePendingMipsCalls(); } else { - ERROR_LOG(HLE, "HACK 0=sceUmdWaitDriveStatCB(stat = %08x) attempting to call unset callback", stat); + WARN_LOG(HLE, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d) without callback", stat, timeout); + } + + if ((stat & __KernelUmdGetState()) == 0) + { + if (timeout == 0) + timeout = 8000; + + __UmdWaitStat(timeout); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true); + __KernelCheckCallbacks(); } } @@ -222,7 +260,9 @@ void sceUmdCancelWaitDriveStat() DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()"); RETURN(0); - __KernelTriggerWait(WAITTYPE_UMD, 0, SCE_KERNEL_ERROR_WAIT_CANCEL, false); + __KernelTriggerWait(WAITTYPE_UMD, 1, SCE_KERNEL_ERROR_WAIT_CANCEL, false); + // TODO: We should call UnscheduleEvent() event here? + // But it's not often used anyway, and worst-case it will just do nothing unless it waits again. } u32 sceUmdGetErrorStat() From 51a4ed4f755d8d65ff19bb52d159403472fa7517 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 23:19:10 -0800 Subject: [PATCH 08/11] Reschedule when activating/deactivating the UMD. This is what a PSP seems to do. --- Core/HLE/FunctionWrappers.h | 4 ++++ Core/HLE/sceUmd.cpp | 35 ++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 4e6c5c1f04..8cec9e7537 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -108,6 +108,10 @@ template void WrapV_II() { func(PARAM(0), PARAM(1)); } +template void WrapV_UC() { + func(PARAM(0), Memory::GetCharPointer(PARAM(1))); +} + template void WrapU_UU() { u32 retval = func(PARAM(0), PARAM(1)); RETURN(retval); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 9c13c7d464..310bc3b866 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -100,34 +100,44 @@ void sceUmdGetDiscInfo() RETURN(0); } -u32 sceUmdActivate(u32 unknown, const char *name) +void sceUmdActivate(u32 unknown, const char *name) { if (unknown < 1 || unknown > 2) - return PSP_ERROR_UMD_INVALID_PORT; + { + RETURN(PSP_ERROR_UMD_INVALID_PORT); + return; + } - u32 retVal = 0; + bool changed = umdActivated == 0; __KernelUmdActivate(); if (unknown == 1) { - DEBUG_LOG(HLE, "%i=sceUmdActivate(%d, %s)", retVal, unknown, name); + DEBUG_LOG(HLE, "0=sceUmdActivate(%d, %s)", unknown, name); } else { - ERROR_LOG(HLE, "UNTESTED %i=sceUmdActivate(%d, %s)", retVal, unknown, name); + ERROR_LOG(HLE, "UNTESTED 0=sceUmdActivate(%d, %s)", unknown, name); } u32 notifyArg = UMD_PRESENT | UMD_READABLE; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - return retVal; + RETURN(0); + + if (changed) + __KernelReSchedule("umd activated"); } -u32 sceUmdDeactivate(u32 unknown, const char *name) +void sceUmdDeactivate(u32 unknown, const char *name) { // Why 18? No idea. if (unknown < 0 || unknown > 18) - return PSP_ERROR_UMD_INVALID_PORT; + { + RETURN(PSP_ERROR_UMD_INVALID_PORT); + return; + } + bool changed = umdActivated != 0; __KernelUmdDeactivate(); if (unknown == 1) @@ -141,7 +151,10 @@ u32 sceUmdDeactivate(u32 unknown, const char *name) u32 notifyArg = UMD_PRESENT | UMD_READY; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - return 0; + RETURN(0); + + if (changed) + __KernelReSchedule("umd deactivated"); } u32 sceUmdRegisterUMDCallBack(u32 cbId) @@ -274,10 +287,10 @@ u32 sceUmdGetErrorStat() const HLEFunction sceUmdUser[] = { - {0xC6183D47,&WrapU_UC,"sceUmdActivate"}, + {0xC6183D47,WrapV_UC,"sceUmdActivate"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, - {0xE83742BA,&WrapU_UC,"sceUmdDeactivate"}, + {0xE83742BA,WrapV_UC,"sceUmdDeactivate"}, {0x8EF08FCE,WrapV_U,"sceUmdWaitDriveStat"}, {0x56202973,WrapV_UU,"sceUmdWaitDriveStatWithTimer"}, {0x4A9E5E29,WrapV_UU,"sceUmdWaitDriveStatCB"}, From 9ba9415df45d4d63c5e73ddb717bceb5a1f0745c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 23:48:11 -0800 Subject: [PATCH 09/11] Change the UMD callback on overwrite. --- Core/HLE/sceUmd.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 310bc3b866..8d24ffac7b 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -159,14 +159,15 @@ void sceUmdDeactivate(u32 unknown, const char *name) u32 sceUmdRegisterUMDCallBack(u32 cbId) { - DEBUG_LOG(HLE,"0=sceUmdRegisterUMDCallback(id=%i)",PARAM(0)); if (driveCBId == -1) { + DEBUG_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i)", cbId); driveCBId = cbId; } else { - ERROR_LOG(HLE," 0=sceUmdRegisterUMDCallback(id=%i) callback overwrite attempt",PARAM(0)); + WARN_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i) overwrote callacbk", cbId); + driveCBId = cbId; } return __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId); } From e5f1d701e3d59dcd13bbb785658cd55a48c25b43 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 00:20:28 -0800 Subject: [PATCH 10/11] Don't unregister a different UMD callback, cleanup. --- Core/HLE/sceUmd.cpp | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 8d24ffac7b..fbada80a6a 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -21,7 +21,7 @@ #include "sceUmd.h" #include "sceKernelThread.h" -const int PSP_ERROR_UMD_INVALID_PORT = 0x80010016; +const int PSP_ERROR_UMD_INVALID_PARAM = 0x80010016; #define UMD_NOT_PRESENT 0x01 #define UMD_PRESENT 0x02 @@ -104,7 +104,7 @@ void sceUmdActivate(u32 unknown, const char *name) { if (unknown < 1 || unknown > 2) { - RETURN(PSP_ERROR_UMD_INVALID_PORT); + RETURN(PSP_ERROR_UMD_INVALID_PARAM); return; } @@ -133,7 +133,7 @@ void sceUmdDeactivate(u32 unknown, const char *name) // Why 18? No idea. if (unknown < 0 || unknown > 18) { - RETURN(PSP_ERROR_UMD_INVALID_PORT); + RETURN(PSP_ERROR_UMD_INVALID_PARAM); return; } @@ -159,24 +159,36 @@ void sceUmdDeactivate(u32 unknown, const char *name) u32 sceUmdRegisterUMDCallBack(u32 cbId) { - if (driveCBId == -1) - { - DEBUG_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i)", cbId); - driveCBId = cbId; - } + int retVal; + + // TODO: If the callback is invalid, return PSP_ERROR_UMD_INVALID_PARAM. + if (cbId == 0) + retVal = PSP_ERROR_UMD_INVALID_PARAM; else { - WARN_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i) overwrote callacbk", cbId); + retVal = __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId); driveCBId = cbId; } - return __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId); + + DEBUG_LOG(HLE, "%d=sceUmdRegisterUMDCallback(id=%08x)", retVal, cbId); + return retVal; } u32 sceUmdUnRegisterUMDCallBack(u32 cbId) { - DEBUG_LOG(HLE,"0=sceUmdUnRegisterUMDCallBack(id=%i)",PARAM(0)); - driveCBId = -1; - return __KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId); + u32 retVal; + + if (cbId != driveCBId) + retVal = PSP_ERROR_UMD_INVALID_PARAM; + else + { + retVal = cbId; + driveCBId = -1; + __KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId); + } + + DEBUG_LOG(HLE, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId); + return retVal; } u32 sceUmdGetDriveStat() From 9e8160c88b4e08246c36fcc5dbe885a6b8892bfe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 00:33:39 -0800 Subject: [PATCH 11/11] Correct sceUmdGetDiscInfo(). The struct was wrong, also add error handling. --- Core/HLE/sceUmd.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index fbada80a6a..1a2e40afa8 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -43,7 +43,8 @@ int umdStatTimer = 0; #define PSP_UMD_TYPE_AUDIO 0x40 struct PspUmdInfo { - int type; + u32 size; + u32 type; }; @@ -87,17 +88,23 @@ int sceUmdCheckMedium() return 1; //non-zero: disc in drive } -void sceUmdGetDiscInfo() +u32 sceUmdGetDiscInfo(u32 infoAddr) { - u32 infoAddr = PARAM(0); - ERROR_LOG(HLE,"sceUmdGetDiscInfo(%08x)", infoAddr); - PspUmdInfo info; - info.type = PSP_UMD_TYPE_GAME; + DEBUG_LOG(HLE, "sceUmdGetDiscInfo(%08x)", infoAddr); + if (Memory::IsValidAddress(infoAddr)) { + PspUmdInfo info; + Memory::ReadStruct(infoAddr, &info); + if (info.size != 8) + return PSP_ERROR_UMD_INVALID_PARAM; + + info.type = PSP_UMD_TYPE_GAME; Memory::WriteStruct(infoAddr, &info); + return 0; } - RETURN(0); + else + return PSP_ERROR_UMD_INVALID_PARAM; } void sceUmdActivate(u32 unknown, const char *name) @@ -310,7 +317,7 @@ const HLEFunction sceUmdUser[] = {0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x20628E6F,&WrapU_V,"sceUmdGetErrorStat"}, - {0x340B7686,sceUmdGetDiscInfo,"sceUmdGetDiscInfo"}, + {0x340B7686,WrapU_U,"sceUmdGetDiscInfo"}, {0xAEE7404D,&WrapU_U,"sceUmdRegisterUMDCallBack"}, {0xBD2BDE07,&WrapU_U,"sceUmdUnRegisterUMDCallBack"}, {0x87533940,0,"sceUmdReplaceProhibit"}, // ??? sounds bogus