mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
HLE: Make calling mips funcs simpler.
This makes their return value handling, scheduling, etc. more straight-forward.
This commit is contained in:
parent
a70f00ca8e
commit
54e1afda1e
9 changed files with 234 additions and 32 deletions
195
Core/HLE/HLE.cpp
195
Core/HLE/HLE.cpp
|
@ -59,6 +59,8 @@ enum
|
|||
HLE_AFTER_DEBUG_BREAK = 0x20,
|
||||
// Don't fill temp regs with 0xDEADBEEF.
|
||||
HLE_AFTER_SKIP_DEADBEEF = 0x40,
|
||||
// Execute pending mips calls.
|
||||
HLE_AFTER_QUEUED_CALLS = 0x80,
|
||||
};
|
||||
|
||||
static std::vector<HLEModule> moduleDB;
|
||||
|
@ -68,6 +70,33 @@ static const char *hleAfterSyscallReschedReason;
|
|||
static const HLEFunction *latestSyscall = nullptr;
|
||||
static int idleOp;
|
||||
|
||||
struct HLEMipsCallInfo {
|
||||
u32 func;
|
||||
PSPAction *action;
|
||||
std::vector<u32> args;
|
||||
};
|
||||
|
||||
struct HLEMipsCallStack {
|
||||
u32_le nextOff;
|
||||
union {
|
||||
struct {
|
||||
u32_le func;
|
||||
u32_le actionIndex;
|
||||
u32_le argc;
|
||||
};
|
||||
struct {
|
||||
u32_le ra;
|
||||
u32_le v0;
|
||||
u32_le v1;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
// No need to save state, always flushed at a syscall end.
|
||||
static std::vector<HLEMipsCallInfo> enqueuedMipsCalls;
|
||||
// Does need to be saved, referenced by the stack and owned.
|
||||
static std::vector<PSPAction *> mipsCallActions;
|
||||
|
||||
void hleDelayResultFinish(u64 userdata, int cycleslate)
|
||||
{
|
||||
u32 error;
|
||||
|
@ -86,16 +115,14 @@ void hleDelayResultFinish(u64 userdata, int cycleslate)
|
|||
WARN_LOG(HLE, "Someone else woke up HLE-blocked thread?");
|
||||
}
|
||||
|
||||
void HLEInit()
|
||||
{
|
||||
void HLEInit() {
|
||||
RegisterAllModules();
|
||||
delayedResultEvent = CoreTiming::RegisterEvent("HLEDelayedResult", hleDelayResultFinish);
|
||||
idleOp = GetSyscallOp("FakeSysCalls", NID_IDLE);
|
||||
}
|
||||
|
||||
void HLEDoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("HLE", 1);
|
||||
void HLEDoState(PointerWrap &p) {
|
||||
auto s = p.Section("HLE", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -103,13 +130,35 @@ void HLEDoState(PointerWrap &p)
|
|||
latestSyscall = nullptr;
|
||||
p.Do(delayedResultEvent);
|
||||
CoreTiming::RestoreRegisterEvent(delayedResultEvent, "HLEDelayedResult", hleDelayResultFinish);
|
||||
|
||||
if (s >= 2) {
|
||||
int actions = (int)mipsCallActions.size();
|
||||
p.Do(actions);
|
||||
if (actions != (int)mipsCallActions.size()) {
|
||||
mipsCallActions.resize(actions);
|
||||
}
|
||||
|
||||
for (auto &action : mipsCallActions) {
|
||||
int actionTypeID = action != nullptr ? action->actionTypeID : -1;
|
||||
p.Do(actionTypeID);
|
||||
if (actionTypeID != -1) {
|
||||
if (p.mode == p.MODE_READ)
|
||||
action = __KernelCreateAction(actionTypeID);
|
||||
action->DoState(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HLEShutdown()
|
||||
{
|
||||
void HLEShutdown() {
|
||||
hleAfterSyscall = HLE_AFTER_NOTHING;
|
||||
latestSyscall = nullptr;
|
||||
moduleDB.clear();
|
||||
enqueuedMipsCalls.clear();
|
||||
for (auto p : mipsCallActions) {
|
||||
delete p;
|
||||
}
|
||||
mipsCallActions.clear();
|
||||
}
|
||||
|
||||
void RegisterModule(const char *name, int numFunctions, const HLEFunction *funcTable)
|
||||
|
@ -354,6 +403,136 @@ bool hleIsKernelMode() {
|
|||
return latestSyscall && (latestSyscall->flags & HLE_KERNEL_SYSCALL) != 0;
|
||||
}
|
||||
|
||||
void hleEnqueueCall(u32 func, int argc, const u32 *argv, PSPAction *afterAction) {
|
||||
std::vector<u32> args;
|
||||
args.resize(argc);
|
||||
memcpy(args.data(), argv, argc * sizeof(u32));
|
||||
|
||||
enqueuedMipsCalls.push_back({ func, afterAction, args });
|
||||
|
||||
hleAfterSyscall |= HLE_AFTER_QUEUED_CALLS;
|
||||
}
|
||||
|
||||
void hleFlushCalls() {
|
||||
u32 &sp = currentMIPS->r[MIPS_REG_SP];
|
||||
PSPPointer<HLEMipsCallStack> stackData;
|
||||
VERBOSE_LOG(HLE, "Flushing %d HLE mips calls from %s, sp=%08x", (int)enqueuedMipsCalls.size(), latestSyscall ? latestSyscall->name : "?", sp);
|
||||
|
||||
// First, we'll add a marker for the final return.
|
||||
sp -= sizeof(HLEMipsCallStack);
|
||||
stackData.ptr = sp;
|
||||
stackData->nextOff = 0xFFFFFFFF;
|
||||
stackData->ra = currentMIPS->pc;
|
||||
stackData->v0 = currentMIPS->r[MIPS_REG_V0];
|
||||
stackData->v1 = currentMIPS->r[MIPS_REG_V1];
|
||||
|
||||
// Now we'll set up the first in the chain.
|
||||
currentMIPS->pc = enqueuedMipsCalls[0].func;
|
||||
currentMIPS->r[MIPS_REG_RA] = HLEMipsCallReturnAddress();
|
||||
for (int i = 0; i < (int)enqueuedMipsCalls[0].args.size(); i++) {
|
||||
currentMIPS->r[MIPS_REG_A0 + i] = enqueuedMipsCalls[0].args[i];
|
||||
}
|
||||
|
||||
// For stack info, process the first enqueued call last, so we run it first.
|
||||
// We don't actually need to store 0's args, but keep it consistent.
|
||||
for (int i = (int)enqueuedMipsCalls.size() - 1; i >= 0; --i) {
|
||||
auto &info = enqueuedMipsCalls[i];
|
||||
u32 stackRequired = (int)info.args.size() * sizeof(u32) + sizeof(HLEMipsCallStack);
|
||||
u32 stackAligned = (stackRequired + 0xF) & ~0xF;
|
||||
|
||||
sp -= stackAligned;
|
||||
stackData.ptr = sp;
|
||||
stackData->nextOff = stackAligned;
|
||||
stackData->func = info.func;
|
||||
if (info.action) {
|
||||
stackData->actionIndex = (int)mipsCallActions.size();
|
||||
mipsCallActions.push_back(info.action);
|
||||
} else {
|
||||
stackData->actionIndex = 0xFFFFFFFF;
|
||||
}
|
||||
stackData->argc = (int)info.args.size();
|
||||
for (int j = 0; j < (int)info.args.size(); ++j) {
|
||||
Memory::Write_U32(info.args[j], sp + sizeof(HLEMipsCallStack) + j * sizeof(u32));
|
||||
}
|
||||
}
|
||||
enqueuedMipsCalls.clear();
|
||||
|
||||
DEBUG_LOG(HLE, "Executing HLE mips call at %08x, sp=%08x", currentMIPS->pc, sp);
|
||||
}
|
||||
|
||||
void HLEReturnFromMipsCall() {
|
||||
u32 &sp = currentMIPS->r[MIPS_REG_SP];
|
||||
PSPPointer<HLEMipsCallStack> stackData;
|
||||
|
||||
// At this point, we may have another mips call to run, or be at the end...
|
||||
stackData.ptr = sp;
|
||||
|
||||
if ((stackData->nextOff & 0x0000000F) != 0 || !Memory::IsValidAddress(sp + stackData->nextOff)) {
|
||||
ERROR_LOG(HLE, "Corrupt stack on HLE mips call return: %08x", stackData->nextOff);
|
||||
Core_UpdateState(CORE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (stackData->actionIndex != 0xFFFFFFFF && stackData->actionIndex < (u32)mipsCallActions.size()) {
|
||||
PSPAction *&action = mipsCallActions[stackData->actionIndex];
|
||||
VERBOSE_LOG(HLE, "Executing action for HLE mips call at %08x, sp=%08x", stackData->func, sp);
|
||||
|
||||
// Search for the saved v0/v1 values, to preserve the PSPAction API...
|
||||
PSPPointer<HLEMipsCallStack> finalMarker = stackData;
|
||||
while ((finalMarker->nextOff & 0x0000000F) == 0 && Memory::IsValidAddress(finalMarker.ptr + finalMarker->nextOff)) {
|
||||
finalMarker.ptr += finalMarker->nextOff;
|
||||
}
|
||||
if (finalMarker->nextOff != 0xFFFFFFFF) {
|
||||
ERROR_LOG(HLE, "Corrupt stack on HLE mips call return action: %08x", finalMarker->nextOff);
|
||||
Core_UpdateState(CORE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
MipsCall mc;
|
||||
mc.savedV0 = finalMarker->v0;
|
||||
mc.savedV1 = finalMarker->v1;
|
||||
action->run(mc);
|
||||
finalMarker->v0 = mc.savedV0;
|
||||
finalMarker->v1 = mc.savedV1;
|
||||
|
||||
delete action;
|
||||
action = nullptr;
|
||||
|
||||
// Note: the action could actually enqueue more, adding another layer on stack after this.
|
||||
}
|
||||
|
||||
sp += stackData->nextOff;
|
||||
stackData.ptr = sp;
|
||||
|
||||
if (stackData->nextOff == 0xFFFFFFFF) {
|
||||
// We're done. Grab the HLE result's v0/v1 and return from the syscall.
|
||||
currentMIPS->pc = stackData->ra;
|
||||
currentMIPS->r[MIPS_REG_V0] = stackData->v0;
|
||||
currentMIPS->r[MIPS_REG_V1] = stackData->v1;
|
||||
|
||||
sp += sizeof(HLEMipsCallStack);
|
||||
|
||||
bool canClear = true;
|
||||
for (auto p : mipsCallActions) {
|
||||
canClear = canClear && p == nullptr;
|
||||
}
|
||||
if (canClear) {
|
||||
mipsCallActions.clear();
|
||||
}
|
||||
|
||||
VERBOSE_LOG(HLE, "Finished HLE mips calls, v0=%08x, sp=%08x", currentMIPS->r[MIPS_REG_V0], sp);
|
||||
return;
|
||||
}
|
||||
|
||||
// Alright, we have another to call.
|
||||
DEBUG_LOG(HLE, "Executing HLE mips call at %08x, sp=%08x", currentMIPS->pc, sp);
|
||||
currentMIPS->pc = stackData->func;
|
||||
currentMIPS->r[MIPS_REG_RA] = HLEMipsCallReturnAddress();
|
||||
for (int i = 0; i < (int)stackData->argc; i++) {
|
||||
currentMIPS->r[MIPS_REG_A0 + i] = Memory::Read_U32(sp + sizeof(HLEMipsCallStack) + i * sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
||||
const static u32 deadbeefRegs[12] = {0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF};
|
||||
inline static void SetDeadbeefRegs()
|
||||
{
|
||||
|
@ -375,6 +554,8 @@ inline void hleFinishSyscall(const HLEFunction &info)
|
|||
if ((hleAfterSyscall & HLE_AFTER_SKIP_DEADBEEF) == 0)
|
||||
SetDeadbeefRegs();
|
||||
|
||||
if ((hleAfterSyscall & HLE_AFTER_QUEUED_CALLS) != 0)
|
||||
hleFlushCalls();
|
||||
if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0 && (hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) == 0)
|
||||
__KernelForceCallbacks();
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "Core/MIPS/MIPS.h"
|
||||
|
||||
class PointerWrap;
|
||||
class PSPAction;
|
||||
typedef void (* HLEFunc)();
|
||||
|
||||
enum {
|
||||
|
@ -116,6 +117,8 @@ void hleSkipDeadbeef();
|
|||
void hleSetSteppingTime(double t);
|
||||
// Check if the current syscall context is kernel.
|
||||
bool hleIsKernelMode();
|
||||
// Enqueue a MIPS function to be called after this HLE call finishes.
|
||||
void hleEnqueueCall(u32 func, int argc, const u32 *argv, PSPAction *afterAction = nullptr);
|
||||
|
||||
// Delays the result for usec microseconds, allowing other threads to run during this time.
|
||||
u32 hleDelayResult(u32 result, const char *reason, int usec);
|
||||
|
@ -144,6 +147,8 @@ void CallSyscall(MIPSOpcode op);
|
|||
void WriteFuncStub(u32 stubAddr, u32 symAddr);
|
||||
void WriteFuncMissingStub(u32 stubAddr, u32 nid);
|
||||
|
||||
void HLEReturnFromMipsCall();
|
||||
|
||||
const HLEFunction *GetSyscallFuncPointer(MIPSOpcode op);
|
||||
// For jit, takes arg: const HLEFunction *
|
||||
void *GetQuickSyscallFunc(MIPSOpcode op);
|
||||
|
|
|
@ -96,6 +96,7 @@ const HLEFunction FakeSysCalls[] = {
|
|||
{NID_MODULERETURN, __KernelReturnFromModuleFunc, "__KernelReturnFromModuleFunc"},
|
||||
{NID_IDLE, __KernelIdle, "_sceKernelIdle"},
|
||||
{NID_GPUREPLAY, __KernelGPUReplay, "__KernelGPUReplay"},
|
||||
{NID_HLECALLRETURN, HLEReturnFromMipsCall, "HLEReturnFromMipsCall"},
|
||||
};
|
||||
|
||||
const HLEFunction UtilsForUser[] =
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define NID_INTERRUPTRETURN 0xbadd00d5
|
||||
#define NID_EXTENDRETURN 0xbad0b0c9
|
||||
#define NID_MODULERETURN 0xbad0d318
|
||||
#define NID_HLECALLRETURN 0xbad0259b
|
||||
#define NID_IDLE 0x1d7e1d7e
|
||||
#define NID_GPUREPLAY 0x9e45bd95
|
||||
|
||||
|
|
|
@ -492,8 +492,8 @@ public:
|
|||
PostAllocCallback *action = (PostAllocCallback *) __KernelCreateAction(actionPostAllocCallback);
|
||||
action->SetFontLib(GetListID(), errorCodePtr);
|
||||
|
||||
u32 args[2] = { params_.userDataAddr, allocSize };
|
||||
__KernelDirectMipsCall(params_.allocFuncAddr, action, args, 2, true);
|
||||
u32 args[2] = { userDataAddr(), allocSize };
|
||||
hleEnqueueCall(allocFuncAddr(), 2, args, action);
|
||||
}
|
||||
|
||||
u32 GetListID() {
|
||||
|
@ -508,11 +508,11 @@ public:
|
|||
fontMap.erase(fonts_[i]);
|
||||
}
|
||||
}
|
||||
u32 args[2] = { params_.userDataAddr, (u32)handle_ };
|
||||
u32 args[2] = { userDataAddr(), (u32)handle_ };
|
||||
// TODO: The return value of this is leaking.
|
||||
if (handle_) { // Avoid calling free-callback on double-free
|
||||
if (coreState != CORE_POWERDOWN) {
|
||||
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
|
||||
hleEnqueueCall(freeFuncAddr(), 2, args);
|
||||
}
|
||||
}
|
||||
handle_ = 0;
|
||||
|
@ -620,8 +620,8 @@ public:
|
|||
action->SetFontLib(GetListID());
|
||||
action->SetFont(loadedFont->Handle(), freeFontIndex);
|
||||
|
||||
u32 args[2] = { params_.userDataAddr, allocSize };
|
||||
__KernelDirectMipsCall(params_.allocFuncAddr, action, args, 2, true);
|
||||
u32 args[2] = { userDataAddr(), allocSize };
|
||||
hleEnqueueCall(allocFuncAddr(), 2, args, action);
|
||||
|
||||
return loadedFont;
|
||||
}
|
||||
|
@ -632,7 +632,7 @@ public:
|
|||
isfontopen_[i] = 0;
|
||||
if (openAllocatedAddresses_[i] != 0 && coreState != CORE_POWERDOWN) {
|
||||
u32 args[2] = { userDataAddr(), openAllocatedAddresses_[i] };
|
||||
__KernelDirectMipsCall(freeFuncAddr(), 0, args, 2, true);
|
||||
hleEnqueueCall(freeFuncAddr(), 2, args);
|
||||
openAllocatedAddresses_[i] = 0;
|
||||
}
|
||||
break;
|
||||
|
@ -645,7 +645,7 @@ public:
|
|||
void flushFont() {
|
||||
if (charInfoBitmapAddress_ != 0 && coreState != CORE_POWERDOWN) {
|
||||
u32 args[2] = { userDataAddr(), charInfoBitmapAddress_ };
|
||||
__KernelDirectMipsCall(freeFuncAddr(), 0, args, 2, true);
|
||||
hleEnqueueCall(freeFuncAddr(), 2, args);
|
||||
charInfoBitmapAddress_ = 0;
|
||||
}
|
||||
}
|
||||
|
@ -727,6 +727,7 @@ void PostAllocCallback::run(MipsCall &call) {
|
|||
FontLib *fontLib = fontLibList[fontLibID_];
|
||||
fontLib->AllocDone(v0);
|
||||
fontLibMap[fontLib->handle()] = fontLibID_;
|
||||
// This is the same as v0 above.
|
||||
call.setReturnValue(fontLib->handle());
|
||||
}
|
||||
INFO_LOG(SCEFONT, "Leaving PostAllocCallback::run");
|
||||
|
@ -742,7 +743,6 @@ void PostOpenAllocCallback::run(MipsCall &call) {
|
|||
FontLib *fontLib = fontLibList[fontLibID_];
|
||||
u32 v0 = currentMIPS->r[MIPS_REG_V0];
|
||||
fontLib->SetOpenAllocatedAddress(fontIndex_, v0);
|
||||
call.setReturnValue(fontHandle_);
|
||||
}
|
||||
|
||||
void PostCharInfoAllocCallback::run(MipsCall &call) {
|
||||
|
@ -752,7 +752,6 @@ void PostCharInfoAllocCallback::run(MipsCall &call) {
|
|||
call.setReturnValue(ERROR_FONT_OUT_OF_MEMORY); // From JPCSP, if alloc size is 0, still this error value?
|
||||
} else {
|
||||
fontLib->SetCharInfoBitmapAddress(v0);
|
||||
call.setReturnValue(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -765,7 +764,7 @@ void PostCharInfoFreeCallback::run(MipsCall &call) {
|
|||
action->SetFontLib(fontLibID_);
|
||||
|
||||
u32 args[2] = { fontLib->userDataAddr(), allocSize };
|
||||
__KernelDirectMipsCall(fontLib->allocFuncAddr(), action, args, 2, true);
|
||||
hleEnqueueCall(fontLib->allocFuncAddr(), 2, args, action);
|
||||
}
|
||||
|
||||
inline bool LoadedFont::GetCharInfo(int charCode, PGFCharInfo *charInfo, int glyphType) const {
|
||||
|
@ -917,8 +916,8 @@ void __FontDoState(PointerWrap &p) {
|
|||
p.Do(actionPostAllocCallback);
|
||||
__KernelRestoreActionType(actionPostAllocCallback, PostAllocCallback::Create);
|
||||
p.Do(actionPostOpenCallback);
|
||||
__KernelRestoreActionType(actionPostOpenCallback, PostOpenCallback::Create);
|
||||
if (s >= 2) {
|
||||
__KernelRestoreActionType(actionPostOpenCallback, PostOpenCallback::Create);
|
||||
p.Do(actionPostOpenAllocCallback);
|
||||
__KernelRestoreActionType(actionPostOpenAllocCallback, PostOpenAllocCallback::Create);
|
||||
p.Do(actionPostCharInfoAllocCallback);
|
||||
|
@ -963,7 +962,6 @@ static int sceFontDoneLib(u32 fontLibHandle) {
|
|||
INFO_LOG(SCEFONT, "sceFontDoneLib(%08x)", fontLibHandle);
|
||||
FontLib *fl = GetFontLib(fontLibHandle);
|
||||
if (fl) {
|
||||
currentMIPS->r[MIPS_REG_V0] = 0;
|
||||
fl->Done();
|
||||
}
|
||||
return 0;
|
||||
|
@ -1098,7 +1096,6 @@ static int sceFontClose(u32 fontHandle) {
|
|||
DEBUG_LOG(SCEFONT, "sceFontClose(%x)", fontHandle);
|
||||
FontLib *fontLib = font->GetFontLib();
|
||||
if (fontLib) {
|
||||
currentMIPS->r[MIPS_REG_V0] = 0;
|
||||
fontLib->CloseFont(font);
|
||||
}
|
||||
} else
|
||||
|
@ -1293,13 +1290,13 @@ static int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
|
|||
action->SetCharInfo(charInfo);
|
||||
|
||||
u32 args[2] = { font->GetFontLib()->userDataAddr(), font->GetFontLib()->GetCharInfoBitmapAddress() };
|
||||
__KernelDirectMipsCall(font->GetFontLib()->freeFuncAddr(), action, args, 2, true);
|
||||
hleEnqueueCall(font->GetFontLib()->freeFuncAddr(), 2, args, action);
|
||||
} else {
|
||||
PostCharInfoAllocCallback *action = (PostCharInfoAllocCallback *)__KernelCreateAction(actionPostCharInfoAllocCallback);
|
||||
action->SetFontLib(font->GetFontLib()->GetListID());
|
||||
|
||||
u32 args[2] = { font->GetFontLib()->userDataAddr(), allocSize };
|
||||
__KernelDirectMipsCall(font->GetFontLib()->allocFuncAddr(), action, args, 2, true);
|
||||
hleEnqueueCall(font->GetFontLib()->allocFuncAddr(), 2, args, action);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1425,7 +1422,6 @@ static int sceFontFlush(u32 fontHandle) {
|
|||
return ERROR_FONT_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
currentMIPS->r[MIPS_REG_V0] = 0;
|
||||
font->GetFontLib()->flushFont();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -630,6 +630,7 @@ SceUID currentThread;
|
|||
PSPThread *currentThreadPtr;
|
||||
u32 idleThreadHackAddr;
|
||||
u32 threadReturnHackAddr;
|
||||
u32 hleReturnHackAddr;
|
||||
u32 cbReturnHackAddr;
|
||||
u32 intReturnHackAddr;
|
||||
u32 extendReturnHackAddr;
|
||||
|
@ -742,7 +743,7 @@ inline void __SetCurrentThread(PSPThread *thread, SceUID threadID, const char *n
|
|||
hleCurrentThreadName = name;
|
||||
}
|
||||
|
||||
u32 __KernelMipsCallReturnAddress() {
|
||||
u32 __KernelCallbackReturnAddress() {
|
||||
return cbReturnHackAddr;
|
||||
}
|
||||
|
||||
|
@ -889,6 +890,16 @@ static void __KernelWriteFakeSysCall(u32 nid, u32 *ptr, u32 &pos)
|
|||
MIPSAnalyst::PrecompileFunction(*ptr, 8);
|
||||
}
|
||||
|
||||
u32 HLEMipsCallReturnAddress() {
|
||||
if (hleReturnHackAddr == 0) {
|
||||
// From an old save state, likely... try to recover.
|
||||
u32 blockSize = 2 * sizeof(u32);
|
||||
u32 pos = kernelMemory.Alloc(blockSize, false, "hlerethack");
|
||||
__KernelWriteFakeSysCall(NID_HLECALLRETURN, &hleReturnHackAddr, pos);
|
||||
}
|
||||
return hleReturnHackAddr;
|
||||
}
|
||||
|
||||
void __KernelThreadingInit()
|
||||
{
|
||||
struct ThreadHack
|
||||
|
@ -912,6 +923,7 @@ void __KernelThreadingInit()
|
|||
{NID_INTERRUPTRETURN, &intReturnHackAddr},
|
||||
{NID_EXTENDRETURN, &extendReturnHackAddr},
|
||||
{NID_MODULERETURN, &moduleReturnHackAddr},
|
||||
{NID_HLECALLRETURN, &hleReturnHackAddr},
|
||||
};
|
||||
u32 blockSize = sizeof(idleThreadCode) + ARRAY_SIZE(threadHacks) * 2 * 4; // The thread code above plus 8 bytes per "hack"
|
||||
|
||||
|
@ -953,7 +965,7 @@ void __KernelThreadingInit()
|
|||
|
||||
void __KernelThreadingDoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("sceKernelThread", 1, 3);
|
||||
auto s = p.Section("sceKernelThread", 1, 4);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -967,6 +979,12 @@ void __KernelThreadingDoState(PointerWrap &p)
|
|||
p.Do(extendReturnHackAddr);
|
||||
p.Do(moduleReturnHackAddr);
|
||||
|
||||
if (s >= 4) {
|
||||
p.Do(hleReturnHackAddr);
|
||||
} else {
|
||||
hleReturnHackAddr = 0;
|
||||
}
|
||||
|
||||
p.Do(currentThread);
|
||||
SceUID dv = 0;
|
||||
p.Do(threadqueue, dv);
|
||||
|
@ -1158,6 +1176,7 @@ void __KernelThreadingShutdown() {
|
|||
mipsCalls.clear();
|
||||
threadReturnHackAddr = 0;
|
||||
cbReturnHackAddr = 0;
|
||||
hleReturnHackAddr = 0;
|
||||
__SetCurrentThread(NULL, 0, NULL);
|
||||
intReturnHackAddr = 0;
|
||||
pausedDelays.clear();
|
||||
|
@ -3188,7 +3207,7 @@ bool __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter)
|
|||
|
||||
// Set up the new state
|
||||
currentMIPS->pc = call->entryPoint;
|
||||
currentMIPS->r[MIPS_REG_RA] = __KernelMipsCallReturnAddress();
|
||||
currentMIPS->r[MIPS_REG_RA] = __KernelCallbackReturnAddress();
|
||||
cur->currentMipscallId = callId;
|
||||
for (int i = 0; i < call->numArgs; i++) {
|
||||
currentMIPS->r[MIPS_REG_A0 + i] = call->args[i];
|
||||
|
|
|
@ -204,7 +204,8 @@ void __KernelReturnFromExtendStack();
|
|||
|
||||
void __KernelIdle();
|
||||
|
||||
u32 __KernelMipsCallReturnAddress();
|
||||
u32 HLEMipsCallReturnAddress();
|
||||
u32 __KernelCallbackReturnAddress();
|
||||
u32 __KernelInterruptReturnAddress(); // TODO: remove
|
||||
|
||||
SceUID sceKernelCreateCallback(const char *name, u32 entrypoint, u32 signalArg);
|
||||
|
|
|
@ -1524,7 +1524,7 @@ static u32 sceMpegRingbufferPut(u32 ringbufferAddr, int numPackets, int availabl
|
|||
int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets;
|
||||
u32 packetsThisRound = std::min(numPackets, (s32)ringbuffer->packets - writeOffset);
|
||||
u32 args[3] = {(u32)ringbuffer->data + (u32)writeOffset * 2048, packetsThisRound, (u32)ringbuffer->callback_args};
|
||||
__KernelDirectMipsCall(ringbuffer->callback_addr, action, args, 3, false);
|
||||
hleEnqueueCall(ringbuffer->callback_addr, 3, args, action);
|
||||
} else {
|
||||
ERROR_LOG_REPORT(ME, "sceMpegRingbufferPut: callback_addr zero");
|
||||
}
|
||||
|
|
|
@ -75,8 +75,7 @@ static void __UpdateApctlHandlers(int oldState, int newState, int flag, int erro
|
|||
|
||||
for(std::map<int, ApctlHandler>::iterator it = apctlHandlers.begin(); it != apctlHandlers.end(); ++it) {
|
||||
args[4] = it->second.argument;
|
||||
|
||||
__KernelDirectMipsCall(it->second.entryPoint, NULL, args, 5, true);
|
||||
hleEnqueueCall(it->second.entryPoint, 5, args);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -474,7 +473,6 @@ static int sceNetApctlDisconnect() {
|
|||
ERROR_LOG(SCENET, "UNIMPL %s()", __FUNCTION__);
|
||||
// Like its 'sister' function sceNetAdhocctlDisconnect, we need to alert Apctl handlers that a disconnect took place
|
||||
// or else games like Phantasy Star Portable 2 will hang at certain points (e.g. returning to the main menu after trying to connect to PSN).
|
||||
currentMIPS->r[MIPS_REG_V0] = 0;
|
||||
__UpdateApctlHandlers(0, 0, PSP_NET_APCTL_EVENT_DISCONNECT_REQUEST, 0);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue