From 4078dcd9179393206e3e33a8e347388d9b15e227 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 20 Sep 2013 09:42:09 -0700 Subject: [PATCH] Support save/restore of context on list run/finish. --- Core/HLE/sceGe.cpp | 13 ++++++++----- Core/HLE/sceGe.h | 8 ++++++++ GPU/GPUCommon.cpp | 15 ++++++++++++++- GPU/GPUCommon.h | 2 +- GPU/GPUInterface.h | 5 ++++- GPU/GPUState.cpp | 4 ++-- 6 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index bb75ead3c..c55bd48ef 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -333,12 +333,12 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, DEBUG_LOG(SCEGE, "sceGeListEnQueue(addr=%08x, stall=%08x, cbid=%08x, param=%08x)", listAddress, stallAddress, callbackId, optParamAddr); - //if (!stallAddress) - // stallAddress = listAddress; - u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), false); + PSPPointer optParam; + optParam = optParamAddr; + + u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, false); DEBUG_LOG(SCEGE, "List %i enqueued.", listID); - //return display list ID return listID; } @@ -348,7 +348,10 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, DEBUG_LOG(SCEGE, "sceGeListEnQueueHead(addr=%08x, stall=%08x, cbid=%08x, param=%08x)", listAddress, stallAddress, callbackId, optParamAddr); - u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), true); + PSPPointer optParam; + optParam = optParamAddr; + + u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, true); DEBUG_LOG(SCEGE, "List %i enqueued.", listID); return listID; diff --git a/Core/HLE/sceGe.h b/Core/HLE/sceGe.h index 415b2db36..4291f6d71 100644 --- a/Core/HLE/sceGe.h +++ b/Core/HLE/sceGe.h @@ -36,6 +36,14 @@ struct PspGeCallbackData u32_le finish_arg; }; +struct PspGeListArgs +{ + SceSize_le size; + PSPPointer context; + u32_le numStacks; + u32_le unknown1; +}; + void Register_sceGe_user(); void __GeInit(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index d73dd57f7..1b6d69aac 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -157,7 +157,7 @@ int GPUCommon::ListSync(int listid, int mode) { return PSP_GE_LIST_COMPLETED; } -u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head) { +u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head) { easy_guard guard(listLock); // TODO Check the stack values in missing arg and ajust the stack depth @@ -219,6 +219,11 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head) { dl.interrupted = false; dl.waitTicks = (u64)-1; dl.interruptsEnabled = interruptsEnabled_; + dl.started = false; + if (args.IsValid() && args->context.IsValid()) + dl.context = args->context; + else + dl.context = NULL; if (head) { if (currentList) { @@ -409,6 +414,11 @@ bool GPUCommon::InterpretList(DisplayList &list) { // return false; currentList = &list; + if (!list.started && list.context != NULL) { + gstate.Save(list.context); + } + list.started = true; + // I don't know if this is the correct place to zero this, but something // need to do it. See Sol Trigger title screen. // TODO: Maybe this is per list? Should a stalled list remember the old value? @@ -884,6 +894,9 @@ void GPUCommon::InterruptEnd(int listid) { dl.pendingInterrupt = false; // TODO: Unless the signal handler could change it? if (dl.state == PSP_GE_DL_STATE_COMPLETED || dl.state == PSP_GE_DL_STATE_NONE) { + if (dl.started && dl.context != NULL) { + gstate.Restore(dl.context); + } dl.waitTicks = 0; __GeTriggerWait(WAITTYPE_GELISTSYNC, listid); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 8dda336cf..bd3333276 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -30,7 +30,7 @@ public: virtual bool InterpretList(DisplayList &list); virtual bool ProcessDLQueue(); virtual u32 UpdateStall(int listid, u32 newstall); - virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head); + virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head); virtual u32 DequeueList(int listid); virtual int ListSync(int listid, int mode); virtual u32 DrawSync(int mode); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 5089423b6..4c4943d5c 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -20,6 +20,7 @@ #include "Globals.h" #include "GPU/GPUState.h" #include "Core/HLE/sceKernelThread.h" +#include "Core/HLE/sceGe.h" #include #include @@ -130,6 +131,8 @@ struct DisplayList u64 waitTicks; bool interruptsEnabled; bool pendingInterrupt; + bool started; + u32_le *context; }; enum GPUInvalidationType { @@ -186,7 +189,7 @@ public: // Draw queue management virtual DisplayList* getList(int listid) = 0; // TODO: Much of this should probably be shared between the different GPU implementations. - virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head) = 0; + virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head) = 0; virtual u32 DequeueList(int listid) = 0; virtual u32 UpdateStall(int listid, u32 newstall) = 0; virtual u32 DrawSync(int mode) = 0; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index f0ecc1fa6..481a6668f 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -139,7 +139,7 @@ void GPUgstate::Save(u32_le *ptr) { ptr[6] = gstate_c.indexAddr; ptr[7] = gstate_c.offsetAddr; - // Command values start 17 bytes in. + // Command values start 17 ints in. u32_le *cmds = ptr + 17; for (size_t i = 0; i < ARRAY_SIZE(contextCmdRanges); ++i) { for (int n = contextCmdRanges[i].start; n <= contextCmdRanges[i].end; ++n) { @@ -171,7 +171,7 @@ void GPUgstate::Restore(u32_le *ptr) { gstate_c.indexAddr = ptr[6]; gstate_c.offsetAddr = ptr[7]; - // Command values start 17 bytes in. + // Command values start 17 ints in. u32_le *cmds = ptr + 17; for (size_t i = 0; i < ARRAY_SIZE(contextCmdRanges); ++i) { for (int n = contextCmdRanges[i].start; n <= contextCmdRanges[i].end; ++n) {