Skip to content

Commit

Permalink
Showing 5 changed files with 457 additions and 198 deletions.
12 changes: 11 additions & 1 deletion Core/HLE/HLE.cpp
Original file line number Diff line number Diff line change
@@ -65,7 +65,9 @@ void hleDelayResultFinish(u64 userdata, int cycleslate)
u32 error;
SceUID threadID = (SceUID) userdata;
SceUID verify = __KernelGetWaitID(threadID, WAITTYPE_DELAY, error);
SceUID result = __KernelGetWaitValue(threadID, error);
// The top 32 bits of userdata are the top 32 bits of the 64 bit result.
// We can't just put it all in userdata because we need to know the threadID...
u64 result = (userdata & 0xFFFFFFFF00000000ULL) | __KernelGetWaitValue(threadID, error);

if (error == 0 && verify == 1)
__KernelResumeThreadFromWait(threadID, result);
@@ -335,6 +337,14 @@ u32 hleDelayResult(u32 result, const char *reason, int usec)
return result;
}

u64 hleDelayResult(u64 result, const char *reason, int usec)
{
u64 param = (result & 0xFFFFFFFF00000000) | __KernelGetCurThread();
CoreTiming::ScheduleEvent(usToCycles(usec), delayedResultEvent, param);
__KernelWaitCurThread(WAITTYPE_DELAY, 1, (u32) result, 0, false, reason);
return result;
}

void hleEatMicro(int usec)
{
// Maybe this should Idle, at least for larger delays? Could that cause issues?
11 changes: 11 additions & 0 deletions Core/HLE/HLE.h
Original file line number Diff line number Diff line change
@@ -89,8 +89,19 @@ void hleDebugBreak();

// Delays the result for usec microseconds, allowing other threads to run during this time.
u32 hleDelayResult(u32 result, const char *reason, int usec);
u64 hleDelayResult(u64 result, const char *reason, int usec);
void hleEatMicro(int usec);

inline int hleDelayResult(int result, const char *reason, int usec)
{
return hleDelayResult((u32) result, reason, usec);
}

inline s64 hleDelayResult(s64 result, const char *reason, int usec)
{
return hleDelayResult((u64) result, reason, usec);
}

void HLEInit();
void HLEDoState(PointerWrap &p);
void HLEShutdown();
560 changes: 366 additions & 194 deletions Core/HLE/sceIo.cpp

Large diffs are not rendered by default.

49 changes: 47 additions & 2 deletions Core/HLE/sceKernelThread.cpp
Original file line number Diff line number Diff line change
@@ -372,6 +372,7 @@ class Thread : public KernelObject

ActionAfterMipsCall *getRunningCallbackAction();
void setReturnValue(u32 retval);
void setReturnValue(u64 retval);
void resumeFromWait();
bool isWaitingFor(WaitType type, int id);
int getWaitID(WaitType type);
@@ -588,6 +589,12 @@ void MipsCall::setReturnValue(u32 value)
savedV0 = value;
}

void MipsCall::setReturnValue(u64 value)
{
savedV0 = value & 0xFFFFFFFF;
savedV1 = (value >> 32) & 0xFFFFFFFF;
}

// TODO: Should move to this wrapper so we can keep the current thread as a SceUID instead
// of a dangerous raw pointer.
Thread *__GetCurrentThread() {
@@ -1058,7 +1065,24 @@ u32 __KernelResumeThreadFromWait(SceUID threadID)
}
}

u32 __KernelResumeThreadFromWait(SceUID threadID, int retval)
u32 __KernelResumeThreadFromWait(SceUID threadID, u32 retval)
{
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
if (t)
{
t->resumeFromWait();
t->setReturnValue(retval);
return 0;
}
else
{
ERROR_LOG(HLE, "__KernelResumeThreadFromWait(%d): bad thread: %08x", threadID, error);
return error;
}
}

u32 __KernelResumeThreadFromWait(SceUID threadID, u64 retval)
{
u32 error;
Thread *t = kernelObjects.Get<Thread>(threadID, error);
@@ -1091,7 +1115,7 @@ bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, cons
// This thread was waiting for the triggered object.
t->resumeFromWait();
if (useRetVal)
t->setReturnValue(retVal);
t->setReturnValue((u32)retVal);
doneAnything = true;
}
}
@@ -2279,6 +2303,27 @@ void Thread::setReturnValue(u32 retval)
}
}

void Thread::setReturnValue(u64 retval)
{
if (this->GetUID() == currentThread) {
if (g_inCbCount) {
u32 callId = this->currentCallbackId;
MipsCall *call = mipsCalls.get(callId);
if (call) {
call->setReturnValue(retval);
} else {
ERROR_LOG(HLE, "Failed to inject return value %08llx in thread", retval);
}
} else {
currentMIPS->r[2] = retval & 0xFFFFFFFF;
currentMIPS->r[3] = (retval >> 32) & 0xFFFFFFFF;
}
} else {
context.r[2] = retval & 0xFFFFFFFF;
context.r[3] = (retval >> 32) & 0xFFFFFFFF;
}
}

void Thread::resumeFromWait()
{
// Do we need to "inject" it?
23 changes: 22 additions & 1 deletion Core/HLE/sceKernelThread.h
Original file line number Diff line number Diff line change
@@ -83,6 +83,7 @@ enum WaitType //probably not the real values
WAITTYPE_MUTEX = 13,
WAITTYPE_LWMUTEX = 14,
WAITTYPE_CTRL = 15,
WAITTYPE_IO = 16,
};


@@ -126,7 +127,18 @@ void __KernelLoadContext(ThreadContext *ctx);
bool __KernelTriggerWait(WaitType type, int id, const char *reason, bool dontSwitch = false);
bool __KernelTriggerWait(WaitType type, int id, int retVal, const char *reason, bool dontSwitch);
u32 __KernelResumeThreadFromWait(SceUID threadID); // can return an error value
u32 __KernelResumeThreadFromWait(SceUID threadID, int retval);
u32 __KernelResumeThreadFromWait(SceUID threadID, u32 retval);
u32 __KernelResumeThreadFromWait(SceUID threadID, u64 retval);

inline u32 __KernelResumeThreadFromWait(SceUID threadID, int retval)
{
return __KernelResumeThreadFromWait(threadID, (u32)retval);
}

inline u32 __KernelResumeThreadFromWait(SceUID threadID, s64 retval)
{
return __KernelResumeThreadFromWait(threadID, (u64)retval);
}

u32 __KernelGetWaitValue(SceUID threadID, u32 &error);
u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error);
@@ -230,6 +242,15 @@ struct MipsCall {

void DoState(PointerWrap &p);
void setReturnValue(u32 value);
void setReturnValue(u64 value);
inline void setReturnValue(int value)
{
setReturnValue((u32)value);
}
inline void setReturnValue(s64 value)
{
setReturnValue((u64)value);
}
};

class Action

0 comments on commit 3efb748

Please sign in to comment.