diff --git a/CMakeLists.txt b/CMakeLists.txt index dd5a4822eb..4694274ce5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -374,6 +374,7 @@ add_library(Common STATIC Common/StringUtils.h Common/ThreadPools.cpp Common/ThreadPools.h + Common/ThreadSafeList.h Common/Timer.cpp Common/Timer.h) include_directories(Common) diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 12214ead77..02df902965 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -222,6 +222,7 @@ + @@ -288,4 +289,4 @@ - \ No newline at end of file + diff --git a/Common/ThreadSafeList.h b/Common/ThreadSafeList.h new file mode 100644 index 0000000000..5df49b033d --- /dev/null +++ b/Common/ThreadSafeList.h @@ -0,0 +1,85 @@ +// Copyright (c) 2015- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// 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 +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include + +template < typename T, class Alloc = std::allocator > +class ThreadSafeList { +public: + explicit ThreadSafeList(const Alloc &a = Alloc()) : list(a) {} + explicit ThreadSafeList(std::size_t n, const T &v = T(), const Alloc &a = Alloc()) : list(n, v, a) {} + ThreadSafeList(const std::list &other) : list(other) {} + ThreadSafeList(const ThreadSafeList &other) { + lock_guard guard(other.lock); + list.assign(other.list); + } + + template + ThreadSafeList(Iter first, Iter last, const Alloc &a = Alloc()) : list(first, last, a) {} + + inline T front() const { + lock_guard guard(lock); + return list.front(); + } + + inline void pop_front() { + lock_guard guard(lock); + return list.pop_front(); + } + + inline void push_front(const T &v) { + lock_guard guard(lock); + return list.push_front(v); + } + + inline T back() const { + lock_guard guard(lock); + return list.back(); + } + + inline void pop_back() { + lock_guard guard(lock); + return list.pop_back(); + } + + inline void push_back(const T &v) { + lock_guard guard(lock); + return list.push_back(v); + } + + bool empty() const { + lock_guard guard(lock); + return list.empty(); + } + + inline void clear() { + lock_guard guard(lock); + return list.clear(); + } + + void DoState(PointerWrap &p) { + lock_guard guard(lock); + p.Do(list); + } + +private: + mutable recursive_mutex lock; + std::list list; +}; + diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 7f9baa0c9f..7770c7a217 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -20,6 +20,7 @@ #include "base/mutex.h" #include "Common/ChunkFile.h" +#include "Common/ThreadSafeList.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/MIPS/MIPS.h" @@ -36,6 +37,8 @@ #include "GPU/GPUState.h" #include "GPU/GPUInterface.h" +static const int LIST_ID_MAGIC = 0x35000000; + static PspGeCallbackData ge_callback_data[16]; static bool ge_used_callbacks[16] = {0}; @@ -43,104 +46,35 @@ typedef std::vector WaitingThreadList; static std::map listWaitingThreads; static WaitingThreadList drawWaitingThreads; -struct GeInterruptData -{ +struct GeInterruptData { int listid; u32 pc; u32 cmd; }; -template < typename T, class Alloc = std::allocator > -class ThreadSafeList { -public: - explicit ThreadSafeList(const Alloc &a = Alloc()) : list(a) {} - explicit ThreadSafeList(std::size_t n, const T &v = T(), const Alloc &a = Alloc()) : list(n, v, a) {} - ThreadSafeList(const std::list &other) : list(other) {} - ThreadSafeList(const ThreadSafeList &other) { - lock_guard guard(other.lock); - list.assign(other.list); - } - - template - ThreadSafeList(Iter first, Iter last, const Alloc &a = Alloc()) : list(first, last, a) {} - - inline T front() const { - lock_guard guard(lock); - return list.front(); - } - - inline void pop_front() { - lock_guard guard(lock); - return list.pop_front(); - } - - inline void push_front(const T &v) { - lock_guard guard(lock); - return list.push_front(v); - } - - inline T back() const { - lock_guard guard(lock); - return list.back(); - } - - inline void pop_back() { - lock_guard guard(lock); - return list.pop_back(); - } - - inline void push_back(const T &v) { - lock_guard guard(lock); - return list.push_back(v); - } - - bool empty() const { - lock_guard guard(lock); - return list.empty(); - } - - inline void clear() { - lock_guard guard(lock); - return list.clear(); - } - - void DoState(PointerWrap &p) { - lock_guard guard(lock); - p.Do(list); - } - -private: - mutable recursive_mutex lock; - std::list list; -}; - static ThreadSafeList ge_pending_cb; static int geSyncEvent; static int geInterruptEvent; static int geCycleEvent; -// Let's try updating 10 times per vblank. +// Let's try updating 10 times per vblank - this is the interval for geCycleEvent. const int geIntervalUs = 1000000 / (60 * 10); const int geBehindThresholdUs = 1000000 / (60 * 10); -class GeIntrHandler : public IntrHandler -{ +class GeIntrHandler : public IntrHandler { public: GeIntrHandler() : IntrHandler(PSP_GE_INTR) {} - bool run(PendingInterrupt& pend) override - { + bool run(PendingInterrupt& pend) override { GeInterruptData intrdata = ge_pending_cb.front(); DisplayList* dl = gpu->getList(intrdata.listid); - if (dl == NULL) - { + if (dl == NULL) { WARN_LOG(SCEGE, "Unable to run GE interrupt: list doesn't exist: %d", intrdata.listid); return false; } - if (!dl->interruptsEnabled) - { + if (!dl->interruptsEnabled) { ERROR_LOG_REPORT(SCEGE, "Unable to run GE interrupt: list has interrupts disabled, should not happen"); return false; } @@ -149,10 +83,8 @@ public: const u32 cmd = intrdata.cmd; int subintr = -1; - if (dl->subIntrBase >= 0) - { - switch (dl->signal) - { + if (dl->subIntrBase >= 0) { + switch (dl->signal) { case PSP_GE_SIGNAL_SYNC: case PSP_GE_SIGNAL_JUMP: case PSP_GE_SIGNAL_CALL: @@ -181,8 +113,7 @@ public: } SubIntrHandler* handler = get(subintr); - if (handler != NULL) - { + if (handler != NULL) { DEBUG_LOG(CPU, "Entering GE interrupt handler %08x", handler->handlerAddress); currentMIPS->pc = handler->handlerAddress; u32 data = dl->subIntrToken; @@ -211,30 +142,27 @@ public: return false; } - void handleResult(PendingInterrupt& pend) override - { + void handleResult(PendingInterrupt& pend) override { GeInterruptData intrdata = ge_pending_cb.front(); ge_pending_cb.pop_front(); DisplayList* dl = gpu->getList(intrdata.listid); - if (!dl->interruptsEnabled) - { + if (!dl->interruptsEnabled) { ERROR_LOG_REPORT(SCEGE, "Unable to finish GE interrupt: list has interrupts disabled, should not happen"); return; } - switch (dl->signal) - { + switch (dl->signal) { case PSP_GE_SIGNAL_HANDLER_SUSPEND: - if (sceKernelGetCompiledSdkVersion() <= 0x02000010) - { + if (sceKernelGetCompiledSdkVersion() <= 0x02000010) { // uofw says dl->state = endCmd & 0xFF; DisplayListState newState = static_cast(Memory::ReadUnchecked_U32(intrdata.pc - 4) & 0xFF); //dl->status = static_cast(Memory::ReadUnchecked_U32(intrdata.pc) & 0xFF); //if(dl->status < 0 || dl->status > PSP_GE_LIST_PAUSED) // ERROR_LOG(SCEGE, "Weird DL status after signal suspend %x", dl->status); - if (newState != PSP_GE_DL_STATE_RUNNING) + if (newState != PSP_GE_DL_STATE_RUNNING) { DEBUG_LOG_REPORT(SCEGE, "GE Interrupt: newState might be %d", newState); + } if (dl->state != PSP_GE_DL_STATE_NONE && dl->state != PSP_GE_DL_STATE_COMPLETED) { dl->state = PSP_GE_DL_STATE_QUEUED; @@ -249,38 +177,35 @@ public: } }; -static void __GeExecuteSync(u64 userdata, int cyclesLate) -{ +static void __GeExecuteSync(u64 userdata, int cyclesLate) { int listid = userdata >> 32; GPUSyncType type = (GPUSyncType) (userdata & 0xFFFFFFFF); bool wokeThreads = __GeTriggerWait(type, listid); gpu->SyncEnd(type, listid, wokeThreads); } -static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) -{ +static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) { __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_GE_INTR, PSP_INTR_SUB_NONE); } -static void __GeCheckCycles(u64 userdata, int cyclesLate) -{ +static void __GeCheckCycles(u64 userdata, int cyclesLate) { u64 geTicks = gpu->GetTickEstimate(); - if (geTicks != 0) - { + if (geTicks != 0) { if (CoreTiming::GetTicks() > geTicks + usToCycles(geBehindThresholdUs)) { u64 diff = CoreTiming::GetTicks() - geTicks; + // Let the GPU thread catch up. gpu->SyncThread(); CoreTiming::Advance(); } } - // This may get out of step if we synced, but that's okay. + // This may get out of step if we synced (why?), but that's okay. CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0); } -void __GeInit() -{ +void __GeInit() { memset(&ge_used_callbacks, 0, sizeof(ge_used_callbacks)); + memset(&ge_callback_data, 0, sizeof(ge_callback_data)); ge_pending_cb.clear(); __RegisterIntrHandler(PSP_GE_INTR, new GeIntrHandler()); @@ -297,14 +222,12 @@ void __GeInit() } } -struct GeInterruptData_v1 -{ +struct GeInterruptData_v1 { int listid; u32 pc; }; -void __GeDoState(PointerWrap &p) -{ +void __GeDoState(PointerWrap &p) { auto s = p.Section("sceGe", 1, 2); if (!s) return; @@ -338,18 +261,14 @@ void __GeDoState(PointerWrap &p) // Everything else is done in sceDisplay. } -void __GeShutdown() -{ - +void __GeShutdown() { } -// Warning: may be called from the GPU thread. -bool __GeTriggerSync(GPUSyncType type, int id, u64 atTicks) -{ - u64 userdata = (u64)id << 32 | (u64) type; +// Warning: may be called asynchronously from the GPU thread. +bool __GeTriggerSync(GPUSyncType type, int id, u64 atTicks) { + u64 userdata = (u64)id << 32 | (u64)type; s64 future = atTicks - CoreTiming::GetTicks(); - if (type == GPU_SYNC_DRAW) - { + if (type == GPU_SYNC_DRAW) { s64 left = CoreTiming::UnscheduleThreadsafeEvent(geSyncEvent, userdata); if (left > future) future = left; @@ -358,9 +277,8 @@ bool __GeTriggerSync(GPUSyncType type, int id, u64 atTicks) return true; } -// Warning: may be called from the GPU thread. -bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) -{ +// Warning: may be called asynchronously from the GPU thread. +bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) { GeInterruptData intrdata; intrdata.listid = listid; intrdata.pc = pc; @@ -373,8 +291,7 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) return true; } -void __GeWaitCurrentThread(GPUSyncType type, SceUID waitId, const char *reason) -{ +void __GeWaitCurrentThread(GPUSyncType type, SceUID waitId, const char *reason) { WaitType waitType; if (type == GPU_SYNC_DRAW) { drawWaitingThreads.push_back(__KernelGetCurThread()); @@ -390,8 +307,7 @@ void __GeWaitCurrentThread(GPUSyncType type, SceUID waitId, const char *reason) __KernelWaitCurThread(waitType, waitId, 0, 0, false, reason); } -static bool __GeTriggerWait(WaitType waitType, SceUID waitId, WaitingThreadList &waitingThreads) -{ +static bool __GeTriggerWait(WaitType waitType, SceUID waitId, WaitingThreadList &waitingThreads) { // TODO: Do they ever get a result other than 0? bool wokeThreads = false; for (auto it = waitingThreads.begin(), end = waitingThreads.end(); it != end; ++it) @@ -400,8 +316,7 @@ static bool __GeTriggerWait(WaitType waitType, SceUID waitId, WaitingThreadList return wokeThreads; } -bool __GeTriggerWait(GPUSyncType type, SceUID waitId) -{ +bool __GeTriggerWait(GPUSyncType type, SceUID waitId) { // We check for the old type for old savestate compatibility. if (type == GPU_SYNC_DRAW || (WaitType)type == WAITTYPE_GEDRAWSYNC) return __GeTriggerWait(WAITTYPE_GEDRAWSYNC, waitId, drawWaitingThreads); @@ -412,29 +327,25 @@ bool __GeTriggerWait(GPUSyncType type, SceUID waitId) return false; } -static u32 sceGeEdramGetAddr() -{ +static u32 sceGeEdramGetAddr() { u32 retVal = 0x04000000; DEBUG_LOG(SCEGE, "%08x = sceGeEdramGetAddr", retVal); hleEatCycles(150); return retVal; } -static u32 sceGeEdramGetSize() -{ - u32 retVal = 0x00200000; +// TODO: Return a different value for the PS3 enhanced-emulator games? +static u32 sceGeEdramGetSize() { + const u32 retVal = 0x00200000; DEBUG_LOG(SCEGE, "%08x = sceGeEdramGetSize()", retVal); return retVal; } -static int __GeSubIntrBase(int callbackId) -{ +static int __GeSubIntrBase(int callbackId) { return callbackId * 2; } -u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, - u32 optParamAddr) -{ +u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, u32 optParamAddr) { DEBUG_LOG(SCEGE, "sceGeListEnQueue(addr=%08x, stall=%08x, cbid=%08x, param=%08x)", listAddress, stallAddress, callbackId, optParamAddr); @@ -442,7 +353,7 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, false); if ((int)listID >= 0) - listID = 0x35000000 ^ listID; + listID = LIST_ID_MAGIC ^ listID; DEBUG_LOG(SCEGE, "List %i enqueued.", listID); hleEatCycles(490); @@ -450,9 +361,7 @@ u32 sceGeListEnQueue(u32 listAddress, u32 stallAddress, int callbackId, return listID; } -u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, - u32 optParamAddr) -{ +u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, u32 optParamAddr) { DEBUG_LOG(SCEGE, "sceGeListEnQueueHead(addr=%08x, stall=%08x, cbid=%08x, param=%08x)", listAddress, stallAddress, callbackId, optParamAddr); @@ -460,48 +369,44 @@ u32 sceGeListEnQueueHead(u32 listAddress, u32 stallAddress, int callbackId, u32 listID = gpu->EnqueueList(listAddress, stallAddress, __GeSubIntrBase(callbackId), optParam, true); if ((int)listID >= 0) - listID = 0x35000000 ^ listID; + listID = LIST_ID_MAGIC ^ listID; - DEBUG_LOG(SCEGE, "List %i enqueued.", listID); + DEBUG_LOG(SCEGE, "List %i enqueued at head.", listID); hleEatCycles(480); CoreTiming::ForceCheck(); return listID; } -static int sceGeListDeQueue(u32 listID) -{ +static int sceGeListDeQueue(u32 listID) { WARN_LOG(SCEGE, "sceGeListDeQueue(%08x)", listID); - int result = gpu->DequeueList(0x35000000 ^ listID); + int result = gpu->DequeueList(LIST_ID_MAGIC ^ listID); hleReSchedule("dlist dequeued"); return result; } -static int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress) -{ +static int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress) { // Advance() might cause an interrupt, so defer the Advance but do it ASAP. // Final Fantasy Type-0 has a graphical artifact without this (timing issue.) hleEatCycles(190); CoreTiming::ForceCheck(); DEBUG_LOG(SCEGE, "sceGeListUpdateStallAddr(dlid=%i, stalladdr=%08x)", displayListID, stallAddress); - return gpu->UpdateStall(0x35000000 ^ displayListID, stallAddress); + return gpu->UpdateStall(LIST_ID_MAGIC ^ displayListID, stallAddress); } -int sceGeListSync(u32 displayListID, u32 mode) //0 : wait for completion 1:check and return -{ +// 0 : wait for completion. 1:check and return +int sceGeListSync(u32 displayListID, u32 mode) { DEBUG_LOG(SCEGE, "sceGeListSync(dlid=%08x, mode=%08x)", displayListID, mode); - return gpu->ListSync(0x35000000 ^ displayListID, mode); + return gpu->ListSync(LIST_ID_MAGIC ^ displayListID, mode); } -static u32 sceGeDrawSync(u32 mode) -{ +static u32 sceGeDrawSync(u32 mode) { //wait/check entire drawing state DEBUG_LOG(SCEGE, "sceGeDrawSync(mode=%d) (0=wait for completion, 1=peek)", mode); return gpu->DrawSync(mode); } -int sceGeContinue() -{ +int sceGeContinue() { DEBUG_LOG(SCEGE, "sceGeContinue"); int ret = gpu->Continue(); hleEatCycles(220); @@ -509,44 +414,40 @@ int sceGeContinue() return ret; } -static int sceGeBreak(u32 mode, u32 unknownPtr) -{ - if (mode > 1) - { +static int sceGeBreak(u32 mode, u32 unknownPtr) { + if (mode > 1) { WARN_LOG(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): invalid mode", mode, unknownPtr); return SCE_KERNEL_ERROR_INVALID_MODE; } // Not sure what this is supposed to be for... - if ((int)unknownPtr < 0 || (int)unknownPtr + 16 < 0) - { + if ((int)unknownPtr < 0 || (int)unknownPtr + 16 < 0) { WARN_LOG_REPORT(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): invalid ptr", mode, unknownPtr); return SCE_KERNEL_ERROR_PRIV_REQUIRED; - } - else if (unknownPtr != 0) + } else if (unknownPtr != 0) { WARN_LOG_REPORT(SCEGE, "sceGeBreak(mode=%d, unknown=%08x): unknown ptr (%s)", mode, unknownPtr, Memory::IsValidAddress(unknownPtr) ? "valid" : "invalid"); + } //mode => 0 : current dlist 1: all drawing DEBUG_LOG(SCEGE, "sceGeBreak(mode=%d, unknown=%08x)", mode, unknownPtr); int result = gpu->Break(mode); - if (result >= 0 && mode == 0) - return 0x35000000 ^ result; + if (result >= 0 && mode == 0) { + return LIST_ID_MAGIC ^ result; + } return result; } -static u32 sceGeSetCallback(u32 structAddr) -{ +static u32 sceGeSetCallback(u32 structAddr) { DEBUG_LOG(SCEGE, "sceGeSetCallback(struct=%08x)", structAddr); int cbID = -1; - for (size_t i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i) - if (!ge_used_callbacks[i]) - { + for (size_t i = 0; i < ARRAY_SIZE(ge_used_callbacks); ++i) { + if (!ge_used_callbacks[i]) { cbID = (int) i; break; } + } - if (cbID == -1) - { + if (cbID == -1) { WARN_LOG(SCEGE, "sceGeSetCallback(): out of callback ids"); return SCE_KERNEL_ERROR_OUT_OF_MEMORY; } @@ -556,14 +457,12 @@ static u32 sceGeSetCallback(u32 structAddr) int subIntrBase = __GeSubIntrBase(cbID); - if (ge_callback_data[cbID].finish_func != 0) - { + if (ge_callback_data[cbID].finish_func != 0) { sceKernelRegisterSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_FINISH, ge_callback_data[cbID].finish_func, ge_callback_data[cbID].finish_arg); sceKernelEnableSubIntr(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_FINISH); } - if (ge_callback_data[cbID].signal_func != 0) - { + if (ge_callback_data[cbID].signal_func != 0) { sceKernelRegisterSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_SIGNAL, ge_callback_data[cbID].signal_func, ge_callback_data[cbID].signal_arg); sceKernelEnableSubIntr(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_SIGNAL); @@ -572,48 +471,41 @@ static u32 sceGeSetCallback(u32 structAddr) return cbID; } -static int sceGeUnsetCallback(u32 cbID) -{ +static int sceGeUnsetCallback(u32 cbID) { DEBUG_LOG(SCEGE, "sceGeUnsetCallback(cbid=%08x)", cbID); - if (cbID >= ARRAY_SIZE(ge_used_callbacks)) - { + if (cbID >= ARRAY_SIZE(ge_used_callbacks)) { WARN_LOG(SCEGE, "sceGeUnsetCallback(cbid=%08x): invalid callback id", cbID); return SCE_KERNEL_ERROR_INVALID_ID; } - if (ge_used_callbacks[cbID]) - { + if (ge_used_callbacks[cbID]) { int subIntrBase = __GeSubIntrBase(cbID); sceKernelReleaseSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_FINISH); sceKernelReleaseSubIntrHandler(PSP_GE_INTR, subIntrBase | PSP_GE_SUBINTR_SIGNAL); - } - else + } else { WARN_LOG(SCEGE, "sceGeUnsetCallback(cbid=%08x): ignoring unregistered callback id", cbID); + } ge_used_callbacks[cbID] = false; - return 0; } // Points to 512 32-bit words, where we can probably layout the context however we want // unless some insane game pokes it and relies on it... -u32 sceGeSaveContext(u32 ctxAddr) -{ +u32 sceGeSaveContext(u32 ctxAddr) { DEBUG_LOG(SCEGE, "sceGeSaveContext(%08x)", ctxAddr); gpu->SyncThread(); - if (gpu->BusyDrawing()) - { + if (gpu->BusyDrawing()) { WARN_LOG(SCEGE, "sceGeSaveContext(%08x): lists in process, aborting", ctxAddr); // Real error code. return -1; } // Let's just dump gstate. - if (Memory::IsValidAddress(ctxAddr)) - { + if (Memory::IsValidAddress(ctxAddr)) { gstate.Save((u32_le *)Memory::GetPointer(ctxAddr)); } @@ -622,23 +514,20 @@ u32 sceGeSaveContext(u32 ctxAddr) return 0; } -u32 sceGeRestoreContext(u32 ctxAddr) -{ +u32 sceGeRestoreContext(u32 ctxAddr) { DEBUG_LOG(SCEGE, "sceGeRestoreContext(%08x)", ctxAddr); gpu->SyncThread(); - if (gpu->BusyDrawing()) - { + if (gpu->BusyDrawing()) { WARN_LOG(SCEGE, "sceGeRestoreContext(%08x): lists in process, aborting", ctxAddr); return SCE_KERNEL_ERROR_BUSY; } - if (Memory::IsValidAddress(ctxAddr)) - { + if (Memory::IsValidAddress(ctxAddr)) { gstate.Restore((u32_le *)Memory::GetPointer(ctxAddr)); } - ReapplyGfxState(); + ReapplyGfxState(); return 0; } @@ -710,14 +599,15 @@ static u32 sceGeEdramSetAddrTranslation(int new_size) { } DEBUG_LOG(SCEGE, "sceGeEdramSetAddrTranslation(%i)", new_size); + + // TODO: This isn't safe. EDRamWidth should be global and saved. static int EDRamWidth = 0x400; int last = EDRamWidth; EDRamWidth = new_size; return last; } -const HLEFunction sceGe_user[] = -{ +const HLEFunction sceGe_user[] = { {0XE47E40E4, &WrapU_V, "sceGeEdramGetAddr", 'x', "" }, {0XAB49E76A, &WrapU_UUIU, "sceGeListEnQueue", 'x', "xxix"}, {0X1C0D95A6, &WrapU_UUIU, "sceGeListEnQueueHead", 'x', "xxix"}, @@ -738,7 +628,6 @@ const HLEFunction sceGe_user[] = {0XE66CB92E, &WrapI_IU, "sceGeGetStack", 'i', "ix" }, }; -void Register_sceGe_user() -{ +void Register_sceGe_user() { RegisterModule("sceGe_user", ARRAY_SIZE(sceGe_user), sceGe_user); } diff --git a/Qt/Common.pro b/Qt/Common.pro index 2bea1516b8..ec3b4a8d0e 100644 --- a/Qt/Common.pro +++ b/Qt/Common.pro @@ -67,6 +67,7 @@ HEADERS += $$P/Common/ChunkFile.h \ $$P/Common/MsgHandler.h \ $$P/Common/StringUtils.h \ $$P/Common/ThreadPools.h \ + $$P/Common/ThreadSafeList.h \ $$P/Common/Timer.h \ $$P/Common/Crypto/*.h