From c6087ea3db4d2dee4502ab18c0e661432538141d Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 31 Mar 2013 00:51:34 +0800 Subject: [PATCH 01/34] Improve few sceKernel clock functions --- Core/HLE/sceKernelTime.cpp | 45 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/Core/HLE/sceKernelTime.cpp b/Core/HLE/sceKernelTime.cpp index ba1fc75ea2fa..6bc571ca32e9 100644 --- a/Core/HLE/sceKernelTime.cpp +++ b/Core/HLE/sceKernelTime.cpp @@ -62,7 +62,8 @@ struct SceKernelSysClock int sceKernelGetSystemTime(u32 sysclockPtr) { u64 t = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); - Memory::Write_U64(t, sysclockPtr); + if (Memory::IsValidAddress(sysclockPtr)) + Memory::Write_U64(t, sysclockPtr); DEBUG_LOG(HLE, "sceKernelGetSystemTime(out:%16llx)", t); hleEatCycles(2 * 222); return 0; @@ -72,8 +73,8 @@ u32 sceKernelGetSystemTimeLow() { // This clock should tick at 1 Mhz. u64 t = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); - // DEBUG_LOG(HLE,"%08x=sceKernelGetSystemTimeLow()",(u32)t); - return (u32)t; + DEBUG_LOG(HLE,"%08x=sceKernelGetSystemTimeLow()",(u32)t); + return (u32)(t & 0xFFFFFFFFL); } u64 sceKernelGetSystemTimeWide() @@ -83,43 +84,43 @@ u64 sceKernelGetSystemTimeWide() return t; } -int sceKernelUSec2SysClock(u32 microsec, u32 clockPtr) +int sceKernelUSec2SysClock(u32 usec, u32 clockPtr) { - u32 microseconds = microsec; - SceKernelSysClock *clock = (SceKernelSysClock*)Memory::GetPointer(clockPtr); - clock->lo = microseconds; //TODO: fix - DEBUG_LOG(HLE,"sceKernelUSec2SysClock(%i, %08x )",microsec,clockPtr); + DEBUG_LOG(HLE,"sceKernelUSec2SysClock(%i, %08x )", usec, clockPtr); + if (Memory::IsValidAddress(clockPtr)) + Memory::Write_U32((usec & 0xFFFFFFFFL), clockPtr); + hleEatCycles(2 * 222); return 0; } u64 sceKernelUSec2SysClockWide(u32 usec) { DEBUG_LOG(HLE, "sceKernelUSec2SysClockWide(%i)", usec); - return usec; // ? + return (usec & 0xFFFFFFFFL); } -int sceKernelSysClock2USec(u32 sysclockPtr, u32 highPtr, u32 lowPtr) +int sceKernelSysClock2USec(u32 sysclockPtr, u32 lowPtr, u32 highPtr) { DEBUG_LOG(HLE, "sceKernelSysClock2USec(clock = %08x, lo = %08x, hi = %08x)", sysclockPtr, highPtr, lowPtr); - u64 time = Memory::Read_U64(sysclockPtr); - u32 highResult = (u32)(time / 1000000); - u32 lowResult = (u32)(time % 1000000); - if (Memory::IsValidAddress(highPtr)) - Memory::Write_U32(highResult, highPtr); - if (Memory::IsValidAddress(lowPtr)) - Memory::Write_U32(lowResult, lowPtr); + u64 sysClock = Memory::Read_U64(sysclockPtr); + if (Memory::IsValidAddress(lowPtr)) { + Memory::Write_U32((u32)(sysClock / 1000000), lowPtr); + Memory::Write_U32((u32)(sysClock % 1000000), highPtr); + } else + Memory::Write_U32((int) sysClock, highPtr); hleEatCycles(2 * 222); return 0; } int sceKernelSysClock2USecWide(u32 lowClock, u32 highClock, u32 lowPtr, u32 highPtr) { - u64 clock = lowClock | ((u64)highClock << 32); + u64 sysClock = lowClock | ((u64)highClock << 32); DEBUG_LOG(HLE, "sceKernelSysClock2USecWide(clock = %llu, lo = %08x, hi = %08x)", clock, lowPtr, highPtr); - if (Memory::IsValidAddress(lowPtr)) - Memory::Write_U32((u32)(clock / 1000000), lowPtr); - if (Memory::IsValidAddress(highPtr)) - Memory::Write_U32((u32)(clock % 1000000), highPtr); + if (Memory::IsValidAddress(lowPtr)) { + Memory::Write_U32((u32)(sysClock / 1000000), lowPtr); + Memory::Write_U32((u32)(sysClock % 1000000), highPtr); + } else + Memory::Write_U32((int) sysClock, highPtr); return 0; } From 7b01828ef0f1b69470961d3c7e4a8d8c3709e598 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 31 Mar 2013 01:08:23 +0800 Subject: [PATCH 02/34] Quick fix --- Core/HLE/sceKernelTime.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceKernelTime.cpp b/Core/HLE/sceKernelTime.cpp index 6bc571ca32e9..9090adf2ede2 100644 --- a/Core/HLE/sceKernelTime.cpp +++ b/Core/HLE/sceKernelTime.cpp @@ -73,8 +73,8 @@ u32 sceKernelGetSystemTimeLow() { // This clock should tick at 1 Mhz. u64 t = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); - DEBUG_LOG(HLE,"%08x=sceKernelGetSystemTimeLow()",(u32)t); - return (u32)(t & 0xFFFFFFFFL); + VERBOSE_LOG(HLE,"%08x=sceKernelGetSystemTimeLow()",(u32)t); + return (u32)t; } u64 sceKernelGetSystemTimeWide() @@ -96,7 +96,7 @@ int sceKernelUSec2SysClock(u32 usec, u32 clockPtr) u64 sceKernelUSec2SysClockWide(u32 usec) { DEBUG_LOG(HLE, "sceKernelUSec2SysClockWide(%i)", usec); - return (usec & 0xFFFFFFFFL); + return usec; } int sceKernelSysClock2USec(u32 sysclockPtr, u32 lowPtr, u32 highPtr) @@ -105,9 +105,11 @@ int sceKernelSysClock2USec(u32 sysclockPtr, u32 lowPtr, u32 highPtr) u64 sysClock = Memory::Read_U64(sysclockPtr); if (Memory::IsValidAddress(lowPtr)) { Memory::Write_U32((u32)(sysClock / 1000000), lowPtr); - Memory::Write_U32((u32)(sysClock % 1000000), highPtr); + if (Memory::IsValidAddress(highPtr)) + Memory::Write_U32((u32)(sysClock % 1000000), highPtr); } else - Memory::Write_U32((int) sysClock, highPtr); + if (Memory::IsValidAddress(highPtr)) + Memory::Write_U32((int) sysClock, highPtr); hleEatCycles(2 * 222); return 0; } @@ -118,9 +120,11 @@ int sceKernelSysClock2USecWide(u32 lowClock, u32 highClock, u32 lowPtr, u32 high DEBUG_LOG(HLE, "sceKernelSysClock2USecWide(clock = %llu, lo = %08x, hi = %08x)", clock, lowPtr, highPtr); if (Memory::IsValidAddress(lowPtr)) { Memory::Write_U32((u32)(sysClock / 1000000), lowPtr); - Memory::Write_U32((u32)(sysClock % 1000000), highPtr); + if (Memory::IsValidAddress(highPtr)) + Memory::Write_U32((u32)(sysClock % 1000000), highPtr); } else - Memory::Write_U32((int) sysClock, highPtr); + if (Memory::IsValidAddress(highPtr)) + Memory::Write_U32((int) sysClock, highPtr); return 0; } From d540ff816cd7376290bbc277c4afe2c9770e4952 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 31 Mar 2013 03:10:29 +0800 Subject: [PATCH 03/34] Improve sceMpegAvcDecode/YCbCr --- Core/HLE/sceMpeg.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp index 44c9d070c623..92973024082b 100644 --- a/Core/HLE/sceMpeg.cpp +++ b/Core/HLE/sceMpeg.cpp @@ -738,8 +738,8 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i if (ringbuffer.packetsFree + packetsConsumed >= ringbuffer.packets) { // Having not yet reached the last timestamp? if (ctx->mpegLastTimestamp > 0 && avcAu.pts < ctx->mpegLastTimestamp) { - // Do not yet consume all the remaining packets. - packetsConsumed = 0; + // Do not yet consume all the remaining packets, leave 2 packets + packetsConsumed = ringbuffer.packets - ringbuffer.packetsFree - 2; } } ctx->mediaengine->setReadLength(ctx->mediaengine->readLength() - packetsConsumed * ringbuffer.packetSize); @@ -911,8 +911,8 @@ int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr) if (ringbuffer.packetsFree + packetsConsumed >= ringbuffer.packets) { // Having not yet reached the last timestamp? if (ctx->mpegLastTimestamp > 0 && avcAu.pts < ctx->mpegLastTimestamp) { - // Do not yet consume all the remaining packets. - packetsConsumed = 0; + // Do not yet consume all the remaining packets, leave 2 packets + packetsConsumed = ringbuffer.packets - ringbuffer.packetsFree - 2; } } ctx->mediaengine->setReadLength(ctx->mediaengine->readLength() - packetsConsumed * ringbuffer.packetSize); From 33abcdafd6212052be02fd01145ea5fbfc968cfd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 22:33:19 +0100 Subject: [PATCH 04/34] Update native (TouchCrossPad breaking arrows fix) --- native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native b/native index 5bdd4bd66312..34c4700adb67 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 5bdd4bd6631290d86b82fb99b26aefda6b73c64d +Subproject commit 34c4700adb67b405fe7b1f6804cca41d49eb165e From afa21588d76ef13fb375f85b05cb6e040284515d Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 30 Mar 2013 23:32:34 +0100 Subject: [PATCH 05/34] Some work towards better control handling, includes stickyfix from native --- Core/Core.cpp | 6 +++++- Core/HLE/sceDisplay.cpp | 3 --- Core/Host.h | 3 +++ UI/NativeApp.cpp | 1 - Windows/InputDevice.h | 13 ++++++++----- Windows/KeyboardDevice.cpp | 28 ++++++++++++++++++++++++---- Windows/KeyboardDevice.h | 2 +- Windows/WindowsHost.cpp | 4 ++-- Windows/WindowsHost.h | 2 +- Windows/XinputDevice.cpp | 7 +++---- Windows/XinputDevice.h | 2 +- headless/StubHost.h | 1 - headless/WindowsHeadlessHost.cpp | 5 ----- headless/WindowsHeadlessHost.h | 1 - native | 2 +- 15 files changed, 49 insertions(+), 31 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index 33f1526f1273..655e9dea438c 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -104,14 +104,18 @@ void Core_RunLoop() UpdateScreenScale(); { { - lock_guard guard(input_state.lock); #ifdef _WIN32 + lock_guard guard(input_state.lock); + input_state.pad_buttons = 0; + input_state.pad_lstick_x = 0; + input_state.pad_lstick_y = 0; // Temporary hack. if (GetAsyncKeyState(VK_ESCAPE)) { input_state.pad_buttons |= PAD_BUTTON_MENU; } else { input_state.pad_buttons &= ~PAD_BUTTON_MENU; } + host->PollControllers(input_state); #endif } NativeUpdate(input_state); diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 72147481f72f..df367a902127 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -444,9 +444,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { void hleAfterFlip(u64 userdata, int cyclesLate) { - // This checks input on PC. Fine to do even if not calling BeginFrame. - host->BeginFrame(); - gpu->BeginFrame(); // doesn't really matter if begin or end of frame. } diff --git a/Core/Host.h b/Core/Host.h index ee0143a71c16..4d346b5921b3 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -21,6 +21,8 @@ #include #include "../Globals.h" +struct InputState; + class PMixer { public: @@ -48,6 +50,7 @@ class Host virtual void InitSound(PMixer *mixer) = 0; virtual void UpdateSound() {} virtual void ShutdownSound() = 0; + virtual void PollControllers(InputState &input_state) {} //this is sent from EMU thread! Make sure that Host handles it properly! virtual void BootDone() {} diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 05ff8ab7cba0..a7fab39c4ed3 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -112,7 +112,6 @@ class NativeHost : public Host virtual void SetDebugMode(bool mode) { } virtual bool InitGL(std::string *error_message) { return true; } - virtual void BeginFrame() {} virtual void ShutdownGL() {} virtual void InitSound(PMixer *mixer); diff --git a/Windows/InputDevice.h b/Windows/InputDevice.h index 8d651152c624..ebbc8a5a7ad4 100644 --- a/Windows/InputDevice.h +++ b/Windows/InputDevice.h @@ -1,14 +1,17 @@ +#pragma once + +#include +#include + #include "../Common/CommonTypes.h" #include "../Core/HLE/sceCtrl.h" -#pragma once +struct InputState; + class InputDevice { public: - virtual int UpdateState() = 0; + virtual int UpdateState(InputState &input_state) = 0; }; -#include -#include -#include std::list> getInputDevices(); diff --git a/Windows/KeyboardDevice.cpp b/Windows/KeyboardDevice.cpp index d0deb442b9e4..cd7349ff0a64 100644 --- a/Windows/KeyboardDevice.cpp +++ b/Windows/KeyboardDevice.cpp @@ -1,3 +1,4 @@ +#include "input/input_state.h" #include "KeyboardDevice.h" #include "../Common/CommonTypes.h" #include "../Core/HLE/sceCtrl.h" @@ -18,6 +19,21 @@ static const unsigned short key_ctrl_map[] = { VK_RIGHT, CTRL_RIGHT, }; +static const unsigned short key_pad_map[] = { + VK_SPACE, PAD_BUTTON_START, + 'V', PAD_BUTTON_SELECT, + 'A', PAD_BUTTON_X, + 'S', PAD_BUTTON_Y, + 'X', PAD_BUTTON_B, + 'Z', PAD_BUTTON_A, + 'Q', PAD_BUTTON_LBUMPER, + 'W', PAD_BUTTON_RBUMPER, + VK_UP, PAD_BUTTON_UP, + VK_DOWN, PAD_BUTTON_DOWN, + VK_LEFT, PAD_BUTTON_LEFT, + VK_RIGHT, PAD_BUTTON_RIGHT, +}; + static const unsigned short analog_ctrl_map[] = { 'I', CTRL_UP, 'K', CTRL_DOWN, @@ -25,7 +41,7 @@ static const unsigned short analog_ctrl_map[] = { 'L', CTRL_RIGHT, }; -int KeyboardDevice::UpdateState() { +int KeyboardDevice::UpdateState(InputState &input_state) { bool alternate = GetAsyncKeyState(VK_SHIFT) != 0; static u32 alternator = 0; bool doAlternate = alternate && (alternator++ % 10) < 5; @@ -33,9 +49,11 @@ int KeyboardDevice::UpdateState() { for (int i = 0; i < sizeof(key_ctrl_map)/sizeof(key_ctrl_map[0]); i += 2) { if (!GetAsyncKeyState(key_ctrl_map[i]) || doAlternate) __CtrlButtonUp(key_ctrl_map[i+1]); - else { + else __CtrlButtonDown(key_ctrl_map[i+1]); - } + + //if (GetAsyncKeyState(key_pad_map[i]) && !doAlternate) + // input_state.pad_buttons |= key_pad_map[i+1]; } float analogX = 0; @@ -61,6 +79,8 @@ int KeyboardDevice::UpdateState() { } } - __CtrlSetAnalog(analogX, analogY); + // __CtrlSetAnalog(analogX, analogY); + input_state.pad_lstick_x = analogX; + input_state.pad_lstick_y = analogY; return 0; } \ No newline at end of file diff --git a/Windows/KeyboardDevice.h b/Windows/KeyboardDevice.h index 79d238348ce3..b97ef13688ed 100644 --- a/Windows/KeyboardDevice.h +++ b/Windows/KeyboardDevice.h @@ -3,5 +3,5 @@ class KeyboardDevice : public InputDevice { public: - virtual int UpdateState(); + virtual int UpdateState(InputState &input_state); }; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index b0d8ecb9811a..87ff538cc019 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -129,10 +129,10 @@ void WindowsHost::SetDebugMode(bool mode) } -void WindowsHost::BeginFrame() +void WindowsHost::PollControllers(InputState &input_state) { for (auto iter = this->input.begin(); iter != this->input.end(); iter++) - if ((*iter)->UpdateState() == 0) + if ((*iter)->UpdateState(input_state) == 0) break; // *iter is std::shared_ptr, **iter is InputDevice } diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 9aa2f9237c9c..268abcba5989 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -37,7 +37,7 @@ class WindowsHost : public Host void AddSymbol(std::string name, u32 addr, u32 size, int type); bool InitGL(std::string *error_message); - void BeginFrame(); + void PollControllers(InputState &input_state); void ShutdownGL(); void InitSound(PMixer *mixer); diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 86fc0dab6461..5ff28fdf4acc 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -1,7 +1,6 @@ -#include "stdafx.h" -#include "XinputDevice.h" #include -#include + +#include "XinputDevice.h" #ifndef XUSER_MAX_COUNT #define XUSER_MAX_COUNT 4 @@ -19,7 +18,7 @@ struct Stick { }; static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state); -int XinputDevice::UpdateState() { +int XinputDevice::UpdateState(InputState &input_state) { if (this->check_delay-- > 0) return -1; XINPUT_STATE state; ZeroMemory( &state, sizeof(XINPUT_STATE) ); diff --git a/Windows/XinputDevice.h b/Windows/XinputDevice.h index 71a31becfe5c..c70f8d853b3a 100644 --- a/Windows/XinputDevice.h +++ b/Windows/XinputDevice.h @@ -7,7 +7,7 @@ class XinputDevice : { public: XinputDevice(); - virtual int UpdateState(); + virtual int UpdateState(InputState &input_state); private: void ApplyDiff(XINPUT_STATE &state); int gamepad_idx; diff --git a/headless/StubHost.h b/headless/StubHost.h index 727bec7e564b..5a17b07c56fc 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -34,7 +34,6 @@ class HeadlessHost : public Host virtual void SetDebugMode(bool mode) { } virtual bool InitGL(std::string *error_message) {return true;} - virtual void BeginFrame() {} virtual void ShutdownGL() {} virtual void InitSound(PMixer *mixer) {} diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index a6629982f2db..b3b13a37a961 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -213,11 +213,6 @@ bool WindowsHeadlessHost::ResizeGL() return true; } -void WindowsHeadlessHost::BeginFrame() -{ - -} - void WindowsHeadlessHost::SwapBuffers() { ::SwapBuffers(hDC); diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index d624f4d3ccea..faf5c7b54afd 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -29,7 +29,6 @@ class WindowsHeadlessHost : public HeadlessHost { public: virtual void InitGL(); - virtual void BeginFrame(); virtual void ShutdownGL(); virtual bool isGLWorking() { return glOkay; } diff --git a/native b/native index 34c4700adb67..435392b137e7 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 34c4700adb67b405fe7b1f6804cca41d49eb165e +Subproject commit 435392b137e7c80ff40db8b2af2feac6019f970e From 776d6ee21e9a82b3c6aac0583e4a75a3d385de0a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 23 Mar 2013 23:18:00 -0700 Subject: [PATCH 06/34] Use -O3 for Mac/iOS release builds. --- CMakeLists.txt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e897aa0a78e..bf756be0c6eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1013,22 +1013,26 @@ endif() # installs file(INSTALL ${NativeAssets} DESTINATION assets) -# packaging and code signing -if (IOS) +# Fix CMake some Xcode settings. +if(APPLE) # Fix CMake breaking optimization settings. set(CMAKE_CXX_FLAGS_DEBUG "-g -D_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -D_NDEBUG") - set(CMAKE_CXX_FLAGS_RELEASE "-O2 -D_NDEBUG") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -D_NDEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "-O3 -D_NDEBUG") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -D_NDEBUG") set(CMAKE_C_FLAGS_DEBUG "-g -D_DEBUG") set(CMAKE_C_FLAGS_MINSIZEREL "-Os -D_NDEBUG") - set(CMAKE_C_FLAGS_RELEASE "-O2 -D_NDEBUG") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -D_NDEBUG") + set(CMAKE_C_FLAGS_RELEASE "-O3 -D_NDEBUG") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g -D_NDEBUG") - # These can be fast. + # These can be fast even for debug. set_target_properties(cityhash PROPERTIES COMPILE_FLAGS "-O3") + set_target_properties(snappy PROPERTIES COMPILE_FLAGS "-O3") set_target_properties(zlib PROPERTIES COMPILE_FLAGS "-O3") +endif() +# packaging and code signing +if(IOS) add_dependencies(PPSSPP ${CoreLibName} GPU Common native) file(GLOB IOSAssets ios/assets/*.png) From d2abdf17beeab2caccd11753a20815315fb61427 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 27 Mar 2013 00:51:46 -0700 Subject: [PATCH 07/34] Add a waittype registry to handle callbacks right. --- Core/HLE/sceKernelThread.cpp | 73 +++++++++++++++++++++++++++++------- Core/HLE/sceKernelThread.h | 12 +++++- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 29133da21b5a..fdfcf628bfe9 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -234,6 +234,7 @@ class ActionAfterMipsCall : public Action p.Do(waitID); p.Do(waitInfo); p.Do(isProcessingCallbacks); + p.Do(currentCallbackId); p.DoMarker("ActionAfterMipsCall"); @@ -258,6 +259,7 @@ class ActionAfterMipsCall : public Action int waitID; ThreadWaitInfo waitInfo; bool isProcessingCallbacks; + SceUID currentCallbackId; Action *chainedAction; }; @@ -391,9 +393,9 @@ class Thread : public KernelObject { p.Do(nt); p.Do(waitInfo); - p.Do(sleeping); p.Do(moduleId); p.Do(isProcessingCallbacks); + p.Do(currentMipscallId); p.Do(currentCallbackId); p.Do(context); @@ -417,11 +419,11 @@ class Thread : public KernelObject NativeThread nt; ThreadWaitInfo waitInfo; - bool sleeping; SceUID moduleId; bool isProcessingCallbacks; - u32 currentCallbackId; + u32 currentMipscallId; + SceUID currentCallbackId; ThreadContext context; @@ -496,8 +498,13 @@ struct ThreadList } }; -void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter); +struct WaitTypeFuncs +{ + WaitBeginCallbackFunc beginFunc; + WaitEndCallbackFunc endFunc; +}; +void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter); Thread *__KernelCreateThread(SceUID &id, SceUID moduleID, const char *name, u32 entryPoint, u32 priority, int stacksize, u32 attr); void __KernelResetThread(Thread *t); @@ -539,6 +546,9 @@ int actionAfterMipsCall; // This seems nasty SceUID curModule; +// Doesn't need state saving. +WaitTypeFuncs waitTypeFuncs[NUM_WAITTYPES]; + ////////////////////////////////////////////////////////////////////////// //STATE END ////////////////////////////////////////////////////////////////////////// @@ -623,6 +633,7 @@ void __KernelThreadingInit() u32 blockSize = 4 * 4 + 4 * 2 * 3; // One 16-byte thread plus 3 8-byte "hacks" dispatchEnabled = true; + memset(waitTypeFuncs, 0, sizeof(waitTypeFuncs)); currentThread = 0; g_inCbCount = 0; @@ -896,6 +907,18 @@ SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error) } } +SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error) +{ + Thread *t = kernelObjects.Get(threadID, error); + if (t) + return t->currentCallbackId; + else + { + ERROR_LOG(HLE, "__KernelGetCurrentCallbackID ERROR: thread %i", threadID); + return 0; + } +} + u32 sceKernelReferThreadStatus(u32 threadID, u32 statusPtr) { if (threadID == 0) @@ -1405,7 +1428,8 @@ void __KernelResetThread(Thread *t) t->nt.exitStatus = SCE_KERNEL_ERROR_NOT_DORMANT; t->isProcessingCallbacks = false; - // TODO: Is this correct? + t->currentCallbackId = 0; + t->currentMipscallId = 0; t->pendingMipsCalls.clear(); t->context.r[MIPS_REG_RA] = threadReturnHackAddr; //hack! TODO fix @@ -2283,6 +2307,7 @@ void ActionAfterMipsCall::run(MipsCall &call) { thread->nt.waitID = waitID; thread->waitInfo = waitInfo; thread->isProcessingCallbacks = isProcessingCallbacks; + thread->currentCallbackId = currentCallbackId; } if (chainedAction) { @@ -2295,7 +2320,7 @@ ActionAfterMipsCall *Thread::getRunningCallbackAction() { if (this->GetUID() == currentThread && g_inCbCount > 0) { - MipsCall *call = mipsCalls.get(this->currentCallbackId); + MipsCall *call = mipsCalls.get(this->currentMipscallId); ActionAfterMipsCall *action = 0; if (call) action = dynamic_cast(call->doAfter); @@ -2316,7 +2341,7 @@ void Thread::setReturnValue(u32 retval) { if (this->GetUID() == currentThread) { if (g_inCbCount) { - u32 callId = this->currentCallbackId; + u32 callId = this->currentMipscallId; MipsCall *call = mipsCalls.get(callId); if (call) { call->setReturnValue(retval); @@ -2335,7 +2360,7 @@ void Thread::setReturnValue(u64 retval) { if (this->GetUID() == currentThread) { if (g_inCbCount) { - u32 callId = this->currentCallbackId; + u32 callId = this->currentMipscallId; MipsCall *call = mipsCalls.get(callId); if (call) { call->setReturnValue(retval); @@ -2516,11 +2541,19 @@ void __KernelCallAddress(Thread *thread, u32 entryPoint, Action *afterAction, co after->waitID = thread->nt.waitID; after->waitInfo = thread->waitInfo; after->isProcessingCallbacks = thread->isProcessingCallbacks; + after->currentCallbackId = thread->currentCallbackId; afterAction = after; - // Release thread from waiting - thread->nt.waitType = WAITTYPE_NONE; + if (thread->nt.waitType != WAITTYPE_NONE) { + // If it's a callback, tell the wait to stop. + if (waitTypeFuncs[thread->nt.waitType].beginFunc != NULL && cbId > 0) { + waitTypeFuncs[thread->nt.waitType].beginFunc(after->threadID, thread->currentCallbackId); + } + + // Release thread from waiting + thread->nt.waitType = WAITTYPE_NONE; + } __KernelChangeThreadState(thread, THREADSTATUS_READY); } @@ -2583,7 +2616,7 @@ void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter) call->savedV0 = currentMIPS->r[MIPS_REG_V0]; call->savedV1 = currentMIPS->r[MIPS_REG_V1]; call->savedIdRegister = currentMIPS->r[MIPS_REG_CALL_ID]; - call->savedId = cur->currentCallbackId; + call->savedId = cur->currentMipscallId; call->reschedAfter = reschedAfter; // Set up the new state @@ -2592,7 +2625,7 @@ void __KernelExecuteMipsCallOnCurrentThread(u32 callId, bool reschedAfter) // We put this two places in case the game overwrites it. // We may want it later to "inject" return values. currentMIPS->r[MIPS_REG_CALL_ID] = callId; - cur->currentCallbackId = callId; + cur->currentMipscallId = callId; for (int i = 0; i < call->numArgs; i++) { currentMIPS->r[MIPS_REG_A0 + i] = call->args[i]; } @@ -2611,7 +2644,7 @@ void __KernelReturnFromMipsCall() return; } - u32 callId = cur->currentCallbackId; + u32 callId = cur->currentMipscallId; if (currentMIPS->r[MIPS_REG_CALL_ID] != callId) WARN_LOG_REPORT(HLE, "__KernelReturnFromMipsCall(): s0 is %08x != %08x", currentMIPS->r[MIPS_REG_CALL_ID], callId); @@ -2633,12 +2666,18 @@ void __KernelReturnFromMipsCall() currentMIPS->r[MIPS_REG_V0] = call->savedV0; currentMIPS->r[MIPS_REG_V1] = call->savedV1; currentMIPS->r[MIPS_REG_CALL_ID] = call->savedIdRegister; - cur->currentCallbackId = call->savedId; + cur->currentMipscallId = call->savedId; if (call->cbId != 0) g_inCbCount--; currentCallbackThreadID = 0; + if (cur->nt.waitType != WAITTYPE_NONE) + { + if (waitTypeFuncs[cur->nt.waitType].endFunc != NULL && call->cbId > 0) + waitTypeFuncs[cur->nt.waitType].endFunc(cur->GetUID(), cur->currentCallbackId, currentMIPS->r[MIPS_REG_V0]); + } + // yeah! back in the real world, let's keep going. Should we process more callbacks? if (!__KernelExecutePendingMipsCalls(cur, call->reschedAfter)) { @@ -2887,6 +2926,12 @@ u32 __KernelNotifyCallbackType(RegisteredCallbackType type, SceUID cbId, int not return 0; } +void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc) +{ + waitTypeFuncs[type].beginFunc = beginFunc; + waitTypeFuncs[type].endFunc = endFunc; +} + std::vector GetThreadsInfo() { std::vector threadList; diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index b1b594bc62ab..7d3a405a9ca7 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -65,7 +65,8 @@ struct SceKernelSysClock { }; -enum WaitType //probably not the real values +// TODO: Map these to PSP wait types. +enum WaitType { WAITTYPE_NONE = 0, WAITTYPE_SLEEP = 1, @@ -84,8 +85,16 @@ enum WaitType //probably not the real values WAITTYPE_LWMUTEX = 14, WAITTYPE_CTRL = 15, WAITTYPE_IO = 16, + + NUM_WAITTYPES }; +// Suspend wait and timeout while a thread enters a callback. +typedef void (* WaitBeginCallbackFunc)(SceUID threadID, SceUID prevCallbackId); +// Resume wait and timeout as a thread exits a callback. +typedef void (* WaitEndCallbackFunc)(SceUID threadID, SceUID prevCallbackId, u32 &returnValue); + +void __KernelRegisterWaitTypeFuncs(WaitType type, WaitBeginCallbackFunc beginFunc, WaitEndCallbackFunc endFunc); struct ThreadContext { @@ -144,6 +153,7 @@ inline u32 __KernelResumeThreadFromWait(SceUID threadID, s64 retval) u32 __KernelGetWaitValue(SceUID threadID, u32 &error); u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error); SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error); +SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error); void __KernelWaitCurThread(WaitType type, SceUID waitId, u32 waitValue, u32 timeoutPtr, bool processCallbacks, const char *reason); void __KernelReSchedule(const char *reason = "no reason"); void __KernelReSchedule(bool doCallbacks, const char *reason); From 63bde2cb5910bcefd675a7f4add4026f777c8e80 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 28 Mar 2013 23:59:05 -0700 Subject: [PATCH 08/34] Handle waits inside semaphore waits properly. --- Core/HLE/sceKernelSemaphore.cpp | 89 +++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 2af329f7a15a..53d9b2b4269a 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -64,18 +64,25 @@ struct Semaphore : public KernelObject p.Do(ns); SceUID dv = 0; p.Do(waitingThreads, dv); + p.Do(pausedWaitTimeouts); p.DoMarker("Semaphore"); } NativeSemaphore ns; std::vector waitingThreads; + // Key is the callback id it was for, or if no callback, the thread id. + std::map pausedWaitTimeouts; }; static int semaWaitTimer = -1; +void __KernelSemaBeginCallback(SceUID threadID, SceUID prevCallbackId); +void __KernelSemaEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue); + void __KernelSemaInit() { semaWaitTimer = CoreTiming::RegisterEvent("SemaphoreTimeout", __KernelSemaTimeout); + __KernelRegisterWaitTypeFuncs(WAITTYPE_SEMA, __KernelSemaBeginCallback, __KernelSemaEndCallback); } void __KernelSemaDoState(PointerWrap &p) @@ -115,6 +122,8 @@ bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &error, int { // Remove any event for this thread. u64 cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); + if (cyclesLeft < 0) + cyclesLeft = 0; Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); } @@ -123,6 +132,86 @@ bool __KernelUnlockSemaForThread(Semaphore *s, SceUID threadID, u32 &error, int return true; } +void __KernelSemaBeginCallback(SceUID threadID, SceUID prevCallbackId) +{ + SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; + + u32 error; + SceUID semaID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + Semaphore *s = semaID == 0 ? NULL : kernelObjects.Get(semaID, error); + if (s) + { + if (s->pausedWaitTimeouts.find(pauseKey) != s->pausedWaitTimeouts.end()) + WARN_LOG_REPORT(HLE, "sceKernelWaitSemaCB: Callback %08x triggered within itself, should not happen (PSP crashes.)", prevCallbackId); + + if (timeoutPtr != 0 && semaWaitTimer != -1) + { + u64 cyclesLeft = CoreTiming::UnscheduleEvent(semaWaitTimer, threadID); + s->pausedWaitTimeouts[pauseKey] = CoreTiming::GetTicks() + cyclesLeft; + } + else + s->pausedWaitTimeouts[pauseKey] = 0; + + // TODO: Hmm, what about priority/fifo order? Does it lose its place in line? + s->waitingThreads.erase(std::remove(s->waitingThreads.begin(), s->waitingThreads.end(), threadID), s->waitingThreads.end()); + s->ns.numWaitThreads--; + + DEBUG_LOG(HLE, "sceKernelWaitSemaCB: Suspending sema wait for callback"); + } + else + WARN_LOG_REPORT(HLE, "sceKernelWaitSemaCB: beginning callback with bad wait id?"); +} + +void __KernelSemaEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue) +{ + SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; + + // Note: Cancel does not affect suspended semaphore waits. + + u32 error; + SceUID semaID = __KernelGetWaitID(threadID, WAITTYPE_SEMA, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + Semaphore *s = semaID == 0 ? NULL : kernelObjects.Get(semaID, error); + if (!s || s->pausedWaitTimeouts.find(pauseKey) == s->pausedWaitTimeouts.end()) + { + // TODO: Since it was deleted, we don't know how long was actually left. + // For now, we just say the full time was taken. + if (timeoutPtr != 0 && semaWaitTimer != -1) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE); + return; + } + + u64 waitDeadline = s->pausedWaitTimeouts[pauseKey]; + s->pausedWaitTimeouts.erase(pauseKey); + s->ns.numWaitThreads++; + + bool wokeThreads; + // Attempt to unlock. + if (__KernelUnlockSemaForThread(s, threadID, error, 0, wokeThreads)) + return; + + // We only check if it timed out if it couldn't unlock. + s64 cyclesLeft = waitDeadline - CoreTiming::GetTicks(); + if (cyclesLeft < 0 && waitDeadline != 0) + { + if (timeoutPtr != 0 && semaWaitTimer != -1) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); + s->ns.numWaitThreads--; + } + else + { + // TODO: Should this not go at the end? + s->waitingThreads.push_back(threadID); + + DEBUG_LOG(HLE, "sceKernelWaitSemaCB: Resuming sema wait for callback"); + } +} + // Resume all waiting threads (for delete / cancel.) // Returns true if it woke any threads. bool __KernelClearSemaThreads(Semaphore *s, int reason) From eace0e75c1b789d0a31d67427160655fc1512c7f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 29 Mar 2013 00:27:33 -0700 Subject: [PATCH 09/34] sceKernelWaitSemaCB() should run callbacks first. Patapon 2 gets back to the menu with this. --- Core/HLE/sceKernelSemaphore.cpp | 6 +++++- Core/HLE/sceKernelThread.cpp | 14 ++++++++++++++ Core/HLE/sceKernelThread.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 53d9b2b4269a..09e808ee55a7 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -188,6 +188,8 @@ void __KernelSemaEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &return s->pausedWaitTimeouts.erase(pauseKey); s->ns.numWaitThreads++; + // TODO: Don't wake up if __KernelCurHasReadyCallbacks()? + bool wokeThreads; // Attempt to unlock. if (__KernelUnlockSemaForThread(s, threadID, error, 0, wokeThreads)) @@ -419,7 +421,9 @@ int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *bad if (wantedCount > s->ns.maxCount || wantedCount <= 0) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - if (s->ns.currentCount >= wantedCount && s->ns.numWaitThreads == 0) + // If there are any callbacks, we always wait, and wake after the callbacks. + bool hasCallbacks = processCallbacks && __KernelCurHasReadyCallbacks(); + if (s->ns.currentCount >= wantedCount && s->ns.numWaitThreads == 0 && !hasCallbacks) { s->ns.currentCount -= wantedCount; if (processCallbacks) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index fdfcf628bfe9..72704cac2de3 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2765,6 +2765,20 @@ void ActionAfterCallback::run(MipsCall &call) { } } +bool __KernelCurHasReadyCallbacks() { + if (readyCallbacksCount == 0) + return false; + + Thread *thread = __GetCurrentThread(); + for (int i = 0; i < THREAD_CALLBACK_NUM_TYPES; i++) { + if (thread->readyCallbacks[i].size()) { + return true; + } + } + + return false; +} + // Check callbacks on the current thread only. // Returns true if any callbacks were processed on the current thread. bool __KernelCheckThreadCallbacks(Thread *thread, bool force) diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 7d3a405a9ca7..ba5532a0e44d 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -216,6 +216,7 @@ bool __KernelInCallback(); // Should be called by (nearly) all ...CB functions. bool __KernelCheckCallbacks(); bool __KernelForceCallbacks(); +bool __KernelCurHasReadyCallbacks(); class Thread; void __KernelSwitchContext(Thread *target, const char *reason); bool __KernelExecutePendingMipsCalls(Thread *currentThread, bool reschedAfter); From fe60677f751f324e510ad3afd8b2f676a95985bd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 13:48:29 -0700 Subject: [PATCH 10/34] Make mutexes handle callbacks better + before. Mutex and semaphores (but NOT lwmutexes) call callbacks before attempting the lock, but only if it would not generate errors. Have not yet tested other wait types. --- Core/HLE/sceKernelMutex.cpp | 216 +++++++++++++++++++++++--------- Core/HLE/sceKernelSemaphore.cpp | 15 ++- Core/HLE/sceKernelThread.cpp | 20 +++ Core/HLE/sceKernelThread.h | 1 + 4 files changed, 193 insertions(+), 59 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index bf7c4565c564..8fc998fc8913 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -71,11 +71,14 @@ struct Mutex : public KernelObject p.Do(nm); SceUID dv = 0; p.Do(waitingThreads, dv); + p.Do(pausedWaitTimeouts); p.DoMarker("Mutex"); } NativeMutex nm; std::vector waitingThreads; + // Key is the callback id it was for, or if no callback, the thread id. + std::map pausedWaitTimeouts; }; @@ -142,12 +145,16 @@ static int lwMutexWaitTimer = -1; typedef std::multimap MutexMap; static MutexMap mutexHeldLocks; +void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId); +void __KernelMutexEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue); + void __KernelMutexInit() { mutexWaitTimer = CoreTiming::RegisterEvent("MutexTimeout", __KernelMutexTimeout); lwMutexWaitTimer = CoreTiming::RegisterEvent("LwMutexTimeout", __KernelLwMutexTimeout); __KernelListenThreadEnd(&__KernelMutexThreadEnd); + __KernelRegisterWaitTypeFuncs(WAITTYPE_MUTEX, __KernelMutexBeginCallback, __KernelMutexEndCallback); } void __KernelMutexDoState(PointerWrap &p) @@ -232,6 +239,109 @@ std::vector::iterator __KernelMutexFindPriority(std::vector &wai return best; } +bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int result) +{ + SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + + // The waitID may be different after a timeout. + if (waitID != mutex->GetUID()) + return false; + + // If result is an error code, we're just letting it go. + if (result == 0) + { + int wVal = (int)__KernelGetWaitValue(threadID, error); + __KernelMutexAcquireLock(mutex, wVal, threadID); + } + + if (timeoutPtr != 0 && mutexWaitTimer != -1) + { + // Remove any event for this thread. + u64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); + Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); + } + + __KernelResumeThreadFromWait(threadID, result); + return true; +} + +void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId) +{ + SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; + + u32 error; + SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + Mutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get(mutexID, error); + if (mutex) + { + if (mutex->pausedWaitTimeouts.find(pauseKey) != mutex->pausedWaitTimeouts.end()) + WARN_LOG_REPORT(HLE, "sceKernelLockMutexCB: Callback %08x triggered within itself, should not happen (PSP crashes.)", prevCallbackId); + + if (timeoutPtr != 0 && mutexWaitTimer != -1) + { + u64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); + mutex->pausedWaitTimeouts[pauseKey] = CoreTiming::GetTicks() + cyclesLeft; + } + else + mutex->pausedWaitTimeouts[pauseKey] = 0; + + // TODO: Hmm, what about priority/fifo order? Does it lose its place in line? + mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end()); + + DEBUG_LOG(HLE, "sceKernelLockMutexCB: Suspending lock wait for callback"); + } + else + WARN_LOG_REPORT(HLE, "sceKernelLockMutexCB: beginning callback with bad wait id?"); +} + +void __KernelMutexEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue) +{ + SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; + + u32 error; + SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + Mutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get(mutexID, error); + if (!mutex || mutex->pausedWaitTimeouts.find(pauseKey) == mutex->pausedWaitTimeouts.end()) + { + // TODO: Since it was deleted, we don't know how long was actually left. + // For now, we just say the full time was taken. + if (timeoutPtr != 0 && mutexWaitTimer != -1) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE); + return; + } + + u64 waitDeadline = mutex->pausedWaitTimeouts[pauseKey]; + mutex->pausedWaitTimeouts.erase(pauseKey); + + // TODO: Don't wake up if __KernelCurHasReadyCallbacks()? + + // Attempt to unlock. + if (mutex->nm.lockThread == -1 && __KernelUnlockMutexForThread(mutex, threadID, error, 0)) + return; + + // We only check if it timed out if it couldn't unlock. + s64 cyclesLeft = waitDeadline - CoreTiming::GetTicks(); + if (cyclesLeft < 0 && waitDeadline != 0) + { + if (timeoutPtr != 0 && mutexWaitTimer != -1) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); + } + else + { + // TODO: Should this not go at the end? + mutex->waitingThreads.push_back(threadID); + + DEBUG_LOG(HLE, "sceKernelLockMutexCB: Resuming lock wait for callback"); + } +} + int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optionsPtr) { if (!name) @@ -276,33 +386,6 @@ int sceKernelCreateMutex(const char *name, u32 attr, int initialCount, u32 optio return id; } -bool __KernelUnlockMutexForThread(Mutex *mutex, SceUID threadID, u32 &error, int result) -{ - SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_MUTEX, error); - u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); - - // The waitID may be different after a timeout. - if (waitID != mutex->GetUID()) - return false; - - // If result is an error code, we're just letting it go. - if (result == 0) - { - int wVal = (int)__KernelGetWaitValue(threadID, error); - __KernelMutexAcquireLock(mutex, wVal, threadID); - } - - if (timeoutPtr != 0 && mutexWaitTimer != -1) - { - // Remove any event for this thread. - u64 cyclesLeft = CoreTiming::UnscheduleEvent(mutexWaitTimer, threadID); - Memory::Write_U32((u32) cyclesToUs(cyclesLeft), timeoutPtr); - } - - __KernelResumeThreadFromWait(threadID, result); - return true; -} - int sceKernelDeleteMutex(SceUID id) { DEBUG_LOG(HLE,"sceKernelDeleteMutex(%i)", id); @@ -328,20 +411,38 @@ int sceKernelDeleteMutex(SceUID id) return error; } -bool __KernelLockMutex(Mutex *mutex, int count, u32 &error) +bool __KernelLockMutexCheck(Mutex *mutex, int count, u32 &error) { - if (!error) + if (error) + return false; + + const bool mutexIsRecursive = (mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) != 0; + + if (count <= 0) + error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + else if (count > 1 && !mutexIsRecursive) + error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; + // Two positive ints will always overflow to negative. + else if (count + mutex->nm.lockLevel < 0) + error = PSP_MUTEX_ERROR_LOCK_OVERFLOW; + // Only a recursive mutex can re-lock. + else if (mutex->nm.lockThread == __KernelGetCurThread()) { - if (count <= 0) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if (count > 1 && !(mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE)) - error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - // Two positive ints will always overflow to negative. - else if (count + mutex->nm.lockLevel < 0) - error = PSP_MUTEX_ERROR_LOCK_OVERFLOW; + if (mutexIsRecursive) + return true; + + error = PSP_MUTEX_ERROR_ALREADY_LOCKED; } + // Otherwise it would lock or wait. + else if (mutex->nm.lockLevel == 0) + return true; - if (error) + return false; +} + +bool __KernelLockMutex(Mutex *mutex, int count, u32 &error) +{ + if (!__KernelLockMutexCheck(mutex, count, error)) return false; if (mutex->nm.lockLevel == 0) @@ -353,17 +454,9 @@ bool __KernelLockMutex(Mutex *mutex, int count, u32 &error) if (mutex->nm.lockThread == __KernelGetCurThread()) { - // Recursive mutex, let's just increase the lock count and keep going - if (mutex->nm.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) - { - mutex->nm.lockLevel += count; - return true; - } - else - { - error = PSP_MUTEX_ERROR_ALREADY_LOCKED; - return false; - } + // __KernelLockMutexCheck() would've returned an error, so this must be recursive. + mutex->nm.lockLevel += count; + return true; } return false; @@ -489,15 +582,11 @@ int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) u32 error; Mutex *mutex = kernelObjects.Get(id, error); - if (__KernelLockMutex(mutex, count, error)) - { - hleCheckCurrentCallbacks(); - return 0; - } - else if (error) - return error; - else + if (!__KernelLockMutexCheck(mutex, count, error)) { + if (error) + return error; + SceUID threadID = __KernelGetCurThread(); // May be in a tight loop timing out (where we don't remove from waitingThreads yet), don't want to add duplicates. if (std::find(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID) == mutex->waitingThreads.end()) @@ -508,6 +597,21 @@ int sceKernelLockMutexCB(SceUID id, int count, u32 timeoutPtr) // Return value will be overwritten by wait. return 0; } + else + { + if (__KernelCurHasReadyCallbacks()) + { + // Might actually end up having to wait, so set the timeout. + __KernelWaitMutex(mutex, timeoutPtr); + __KernelWaitCallbacksCurThread(WAITTYPE_MUTEX, id, count, timeoutPtr); + + // Return value will be written to callback's v0, but... that's probably fine? + } + else + __KernelLockMutex(mutex, count, error); + + return 0; + } } // int sceKernelTryLockMutex(SceUID id, int count) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 09e808ee55a7..2b7109d9db3d 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -425,9 +425,18 @@ int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, const char *bad bool hasCallbacks = processCallbacks && __KernelCurHasReadyCallbacks(); if (s->ns.currentCount >= wantedCount && s->ns.numWaitThreads == 0 && !hasCallbacks) { - s->ns.currentCount -= wantedCount; - if (processCallbacks) - hleCheckCurrentCallbacks(); + if (hasCallbacks) + { + // __KernelSemaBeginCallback() will decrement this, so increment it here. + // TODO: Clean this up a bit better. + s->ns.numWaitThreads++; + + // Might actually end up having to wait, so set the timeout. + __KernelSetSemaTimeout(s, timeoutPtr); + __KernelWaitCallbacksCurThread(WAITTYPE_SEMA, id, wantedCount, timeoutPtr); + } + else + s->ns.currentCount -= wantedCount; } else { diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 72704cac2de3..38c7e691e802 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1195,6 +1195,26 @@ void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 time // TODO: Remove thread from Ready queue? } +void __KernelWaitCallbacksCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr) +{ + if (!dispatchEnabled) + { + WARN_LOG_REPORT(HLE, "Ignoring wait, dispatching disabled... right thing to do?"); + return; + } + + Thread *thread = __GetCurrentThread(); + thread->nt.waitID = waitID; + thread->nt.waitType = type; + __KernelChangeThreadState(thread, THREADSTATUS_WAIT); + // TODO: Probably not...? + thread->nt.numReleases++; + thread->waitInfo.waitValue = waitValue; + thread->waitInfo.timeoutPtr = timeoutPtr; + + __KernelForceCallbacks(); +} + void hleScheduledWakeup(u64 userdata, int cyclesLate) { SceUID threadID = (SceUID)userdata; diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index ba5532a0e44d..e26536c7e9e1 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -155,6 +155,7 @@ u32 __KernelGetWaitTimeoutPtr(SceUID threadID, u32 &error); SceUID __KernelGetWaitID(SceUID threadID, WaitType type, u32 &error); SceUID __KernelGetCurrentCallbackID(SceUID threadID, u32 &error); void __KernelWaitCurThread(WaitType type, SceUID waitId, u32 waitValue, u32 timeoutPtr, bool processCallbacks, const char *reason); +void __KernelWaitCallbacksCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr); void __KernelReSchedule(const char *reason = "no reason"); void __KernelReSchedule(bool doCallbacks, const char *reason); From 2ecc3157deb7487cc4874b169eb56bd4dc9b3837 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 15:23:52 -0700 Subject: [PATCH 11/34] Fix waits within waits for lwmutexes. Also, it turns out sceKernelLockMutexCB() doesn't call callbacks on lock. --- Core/HLE/sceKernelMutex.cpp | 88 ++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 8fc998fc8913..f6fe5bd31b54 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -132,11 +132,14 @@ struct LwMutex : public KernelObject p.Do(nm); SceUID dv = 0; p.Do(waitingThreads, dv); + p.Do(pausedWaitTimeouts); p.DoMarker("LwMutex"); } NativeLwMutex nm; std::vector waitingThreads; + // Key is the callback id it was for, or if no callback, the thread id. + std::map pausedWaitTimeouts; }; static int mutexWaitTimer = -1; @@ -147,6 +150,8 @@ static MutexMap mutexHeldLocks; void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId); void __KernelMutexEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue); +void __KernelLwMutexBeginCallback(SceUID threadID, SceUID prevCallbackId); +void __KernelLwMutexEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue); void __KernelMutexInit() { @@ -155,6 +160,7 @@ void __KernelMutexInit() __KernelListenThreadEnd(&__KernelMutexThreadEnd); __KernelRegisterWaitTypeFuncs(WAITTYPE_MUTEX, __KernelMutexBeginCallback, __KernelMutexEndCallback); + __KernelRegisterWaitTypeFuncs(WAITTYPE_LWMUTEX, __KernelLwMutexBeginCallback, __KernelLwMutexEndCallback); } void __KernelMutexDoState(PointerWrap &p) @@ -907,6 +913,87 @@ void __KernelWaitLwMutex(LwMutex *mutex, u32 timeoutPtr) CoreTiming::ScheduleEvent(usToCycles(micro), lwMutexWaitTimer, __KernelGetCurThread()); } +void __KernelLwMutexBeginCallback(SceUID threadID, SceUID prevCallbackId) +{ + SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; + + u32 error; + SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + LwMutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get(mutexID, error); + if (mutex) + { + if (mutex->pausedWaitTimeouts.find(pauseKey) != mutex->pausedWaitTimeouts.end()) + WARN_LOG_REPORT(HLE, "sceKernelLockLwMutexCB: Callback %08x triggered within itself, should not happen (PSP crashes.)", prevCallbackId); + + if (timeoutPtr != 0 && lwMutexWaitTimer != -1) + { + u64 cyclesLeft = CoreTiming::UnscheduleEvent(lwMutexWaitTimer, threadID); + mutex->pausedWaitTimeouts[pauseKey] = CoreTiming::GetTicks() + cyclesLeft; + } + else + mutex->pausedWaitTimeouts[pauseKey] = 0; + + // TODO: Hmm, what about priority/fifo order? Does it lose its place in line? + mutex->waitingThreads.erase(std::remove(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID), mutex->waitingThreads.end()); + + DEBUG_LOG(HLE, "sceKernelLockLwMutexCB: Suspending lock wait for callback"); + } + else + WARN_LOG_REPORT(HLE, "sceKernelLockLwMutexCB: beginning callback with bad wait id?"); +} + +void __KernelLwMutexEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &returnValue) +{ + SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId; + + u32 error; + SceUID mutexID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); + u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); + LwMutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get(mutexID, error); + if (!mutex || mutex->pausedWaitTimeouts.find(pauseKey) == mutex->pausedWaitTimeouts.end()) + { + // TODO: Since it was deleted, we don't know how long was actually left. + // For now, we just say the full time was taken. + if (timeoutPtr != 0 && lwMutexWaitTimer != -1) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_DELETE); + return; + } + + u64 waitDeadline = mutex->pausedWaitTimeouts[pauseKey]; + mutex->pausedWaitTimeouts.erase(pauseKey); + + // TODO: Don't wake up if __KernelCurHasReadyCallbacks()? + + // Attempt to unlock. + NativeLwMutexWorkarea workarea; + Memory::ReadStruct(mutex->nm.workareaPtr, &workarea); + if (mutex->nm.lockThread == -1 && __KernelUnlockLwMutexForThread(mutex, workarea, threadID, error, 0)) + { + Memory::WriteStruct(mutex->nm.workareaPtr, &workarea); + return; + } + + // We only check if it timed out if it couldn't unlock. + s64 cyclesLeft = waitDeadline - CoreTiming::GetTicks(); + if (cyclesLeft < 0 && waitDeadline != 0) + { + if (timeoutPtr != 0 && lwMutexWaitTimer != -1) + Memory::Write_U32(0, timeoutPtr); + + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); + } + else + { + // TODO: Should this not go at the end? + mutex->waitingThreads.push_back(threadID); + + DEBUG_LOG(HLE, "sceKernelLockLwMutexCB: Resuming lock wait for callback"); + } +} + int sceKernelTryLockLwMutex(u32 workareaPtr, int count) { DEBUG_LOG(HLE, "sceKernelTryLockLwMutex(%08x, %i)", workareaPtr, count); @@ -992,7 +1079,6 @@ int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) if (__KernelLockLwMutex(workarea, count, error)) { Memory::WriteStruct(workareaPtr, &workarea); - hleCheckCurrentCallbacks(); return 0; } else if (error) From 52a89970067addb5afc1a8b61e21da17f21884c8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 15:59:14 -0700 Subject: [PATCH 12/34] These are actually okay, happen on the second cb. --- Core/HLE/sceKernelMutex.cpp | 8 ++++++-- Core/HLE/sceKernelSemaphore.cpp | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index f6fe5bd31b54..0c236bcaa330 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -282,8 +282,10 @@ void __KernelMutexBeginCallback(SceUID threadID, SceUID prevCallbackId) Mutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get(mutexID, error); if (mutex) { + // This means two callbacks in a row. PSP crashes if the same callback runs inside itself. + // TODO: Handle this better? if (mutex->pausedWaitTimeouts.find(pauseKey) != mutex->pausedWaitTimeouts.end()) - WARN_LOG_REPORT(HLE, "sceKernelLockMutexCB: Callback %08x triggered within itself, should not happen (PSP crashes.)", prevCallbackId); + return; if (timeoutPtr != 0 && mutexWaitTimer != -1) { @@ -923,8 +925,10 @@ void __KernelLwMutexBeginCallback(SceUID threadID, SceUID prevCallbackId) LwMutex *mutex = mutexID == 0 ? NULL : kernelObjects.Get(mutexID, error); if (mutex) { + // This means two callbacks in a row. PSP crashes if the same callback runs inside itself. + // TODO: Handle this better? if (mutex->pausedWaitTimeouts.find(pauseKey) != mutex->pausedWaitTimeouts.end()) - WARN_LOG_REPORT(HLE, "sceKernelLockLwMutexCB: Callback %08x triggered within itself, should not happen (PSP crashes.)", prevCallbackId); + return; if (timeoutPtr != 0 && lwMutexWaitTimer != -1) { diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index 2b7109d9db3d..a4aba4b6fa77 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -142,8 +142,10 @@ void __KernelSemaBeginCallback(SceUID threadID, SceUID prevCallbackId) Semaphore *s = semaID == 0 ? NULL : kernelObjects.Get(semaID, error); if (s) { + // This means two callbacks in a row. PSP crashes if the same callback runs inside itself. + // TODO: Handle this better? if (s->pausedWaitTimeouts.find(pauseKey) != s->pausedWaitTimeouts.end()) - WARN_LOG_REPORT(HLE, "sceKernelWaitSemaCB: Callback %08x triggered within itself, should not happen (PSP crashes.)", prevCallbackId); + return; if (timeoutPtr != 0 && semaWaitTimer != -1) { From 634e3249751f20fef992b0bfef94b64512e993e0 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 00:25:10 +0100 Subject: [PATCH 13/34] More work on control --- Core/Core.cpp | 4 +-- UI/EmuScreen.cpp | 4 ++- Windows/KeyboardDevice.cpp | 15 ++++-------- Windows/WndMainWindow.cpp | 12 ++++++--- Windows/XinputDevice.cpp | 50 ++++++++++++++++++++------------------ Windows/XinputDevice.h | 2 +- native | 2 +- 7 files changed, 46 insertions(+), 43 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index 655e9dea438c..fd58612af2c4 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -112,13 +112,13 @@ void Core_RunLoop() // Temporary hack. if (GetAsyncKeyState(VK_ESCAPE)) { input_state.pad_buttons |= PAD_BUTTON_MENU; - } else { - input_state.pad_buttons &= ~PAD_BUTTON_MENU; } host->PollControllers(input_state); + UpdateInputState(&input_state); #endif } NativeUpdate(input_state); + EndInputState(&input_state); } NativeRender(); // Simple throttling to not burn the GPU in the menu. diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index a9c68f662145..4be966281c55 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -169,7 +169,9 @@ void EmuScreen::update(InputState &input) { return; // First translate touches into native pad input. - UpdateGamepad(input); + if (g_Config.bShowTouchControls) + UpdateGamepad(input); + UpdateInputState(&input); // Then translate pad input into PSP pad input. Also, add in tilt. diff --git a/Windows/KeyboardDevice.cpp b/Windows/KeyboardDevice.cpp index cd7349ff0a64..1a6dbabc14d7 100644 --- a/Windows/KeyboardDevice.cpp +++ b/Windows/KeyboardDevice.cpp @@ -47,13 +47,9 @@ int KeyboardDevice::UpdateState(InputState &input_state) { bool doAlternate = alternate && (alternator++ % 10) < 5; for (int i = 0; i < sizeof(key_ctrl_map)/sizeof(key_ctrl_map[0]); i += 2) { - if (!GetAsyncKeyState(key_ctrl_map[i]) || doAlternate) - __CtrlButtonUp(key_ctrl_map[i+1]); - else - __CtrlButtonDown(key_ctrl_map[i+1]); - - //if (GetAsyncKeyState(key_pad_map[i]) && !doAlternate) - // input_state.pad_buttons |= key_pad_map[i+1]; + if (GetAsyncKeyState(key_pad_map[i]) && !doAlternate) { + input_state.pad_buttons |= key_pad_map[i+1]; + } } float analogX = 0; @@ -79,8 +75,7 @@ int KeyboardDevice::UpdateState(InputState &input_state) { } } - // __CtrlSetAnalog(analogX, analogY); - input_state.pad_lstick_x = analogX; - input_state.pad_lstick_y = analogY; + input_state.pad_lstick_x += analogX; + input_state.pad_lstick_y += analogY; return 0; } \ No newline at end of file diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index aa97685dd48c..a59e5d684bd0 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -108,14 +108,18 @@ namespace MainWindow void GetWindowRectAtZoom(int zoom, RECT &rcInner, RECT &rcOuter) { // GetWindowRect(hwndMain, &rcInner); - rcInner.left = g_Config.iWindowX; - rcInner.top = g_Config.iWindowY; + rcInner.left = 0; + rcInner.top = 0; - rcInner.right=480*zoom + rcInner.left;//+client edge - rcInner.bottom=272*zoom + rcInner.top; //+client edge + rcInner.right=480*zoom;//+client edge + rcInner.bottom=272*zoom; //+client edge rcOuter=rcInner; AdjustWindowRect(&rcOuter, WS_OVERLAPPEDWINDOW, TRUE); + rcOuter.right += g_Config.iWindowX - rcOuter.left; + rcOuter.bottom += g_Config.iWindowY - rcOuter.top; + rcOuter.left = g_Config.iWindowX; + rcOuter.top = g_Config.iWindowY; } void SavePosition() { diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index 5ff28fdf4acc..b65e1fd0f99a 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -1,6 +1,6 @@ #include - #include "XinputDevice.h" +#include "input/input_state.h" #ifndef XUSER_MAX_COUNT #define XUSER_MAX_COUNT 4 @@ -16,7 +16,7 @@ struct Stick { float x; float y; }; -static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state); +static Stick NormalizedDeadzoneFilter(short x, short y); int XinputDevice::UpdateState(InputState &input_state) { if (this->check_delay-- > 0) return -1; @@ -38,9 +38,13 @@ int XinputDevice::UpdateState(InputState &input_state) { } if ( dwResult == ERROR_SUCCESS ) { - this->ApplyDiff(state); - Stick left = NormalizedDeadzoneFilter(state); - __CtrlSetAnalog(left.x, left.y); + ApplyDiff(state, input_state); + Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY); + Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY); + input_state.pad_lstick_x += left.x; + input_state.pad_lstick_y += left.y; + input_state.pad_rstick_x += right.x; + input_state.pad_rstick_y += right.y; this->prevState = state; this->check_delay = 0; return 0; @@ -53,11 +57,11 @@ int XinputDevice::UpdateState(InputState &input_state) { } // We only filter the left stick since PSP has no analog triggers or right stick -static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state) { +static Stick NormalizedDeadzoneFilter(short x, short y) { static const short DEADZONE = XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE; Stick left; - left.x = state.Gamepad.sThumbLX; - left.y = state.Gamepad.sThumbLY; + left.x = x; + left.y = y; float magnitude = sqrt(left.x*left.x + left.y*left.y); @@ -82,18 +86,18 @@ static Stick NormalizedDeadzoneFilter(XINPUT_STATE &state) { } static const unsigned short xinput_ctrl_map[] = { - XINPUT_GAMEPAD_DPAD_UP, CTRL_UP, - XINPUT_GAMEPAD_DPAD_DOWN, CTRL_DOWN, - XINPUT_GAMEPAD_DPAD_LEFT, CTRL_LEFT, - XINPUT_GAMEPAD_DPAD_RIGHT, CTRL_RIGHT, - XINPUT_GAMEPAD_START, CTRL_START, - XINPUT_GAMEPAD_BACK, CTRL_SELECT, - XINPUT_GAMEPAD_LEFT_SHOULDER, CTRL_LTRIGGER, - XINPUT_GAMEPAD_RIGHT_SHOULDER, CTRL_RTRIGGER, - XINPUT_GAMEPAD_A, CTRL_CROSS, - XINPUT_GAMEPAD_B, CTRL_CIRCLE, - XINPUT_GAMEPAD_X, CTRL_SQUARE, - XINPUT_GAMEPAD_Y, CTRL_TRIANGLE, + XINPUT_GAMEPAD_DPAD_UP, PAD_BUTTON_UP, + XINPUT_GAMEPAD_DPAD_DOWN, PAD_BUTTON_DOWN, + XINPUT_GAMEPAD_DPAD_LEFT, PAD_BUTTON_LEFT, + XINPUT_GAMEPAD_DPAD_RIGHT, PAD_BUTTON_RIGHT, + XINPUT_GAMEPAD_START, PAD_BUTTON_START, + XINPUT_GAMEPAD_BACK, PAD_BUTTON_SELECT, + XINPUT_GAMEPAD_LEFT_SHOULDER, PAD_BUTTON_LBUMPER, + XINPUT_GAMEPAD_RIGHT_SHOULDER, PAD_BUTTON_RBUMPER, + XINPUT_GAMEPAD_A, PAD_BUTTON_A, + XINPUT_GAMEPAD_B, PAD_BUTTON_B, + XINPUT_GAMEPAD_X, PAD_BUTTON_X, + XINPUT_GAMEPAD_Y, PAD_BUTTON_Y, }; static inline u32 CtrlForXinput(int xinput) { for (int i = 0; i < sizeof(xinput_ctrl_map)/sizeof(xinput_ctrl_map[0]); i += 2) @@ -101,14 +105,12 @@ static inline u32 CtrlForXinput(int xinput) { return 0; } -void XinputDevice::ApplyDiff(XINPUT_STATE &state) { +void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) { unsigned short pressed = state.Gamepad.wButtons & ~this->prevState.Gamepad.wButtons; unsigned short released = ~state.Gamepad.wButtons & this->prevState.Gamepad.wButtons; for (int i = 1; i < USHRT_MAX; i <<= 1) { if (pressed & i) - __CtrlButtonDown(CtrlForXinput(i)); - if (released & i) - __CtrlButtonUp(CtrlForXinput(i)); + input_state.pad_buttons |= CtrlForXinput(i); } } \ No newline at end of file diff --git a/Windows/XinputDevice.h b/Windows/XinputDevice.h index c70f8d853b3a..9ed0d92d65f9 100644 --- a/Windows/XinputDevice.h +++ b/Windows/XinputDevice.h @@ -9,7 +9,7 @@ class XinputDevice : XinputDevice(); virtual int UpdateState(InputState &input_state); private: - void ApplyDiff(XINPUT_STATE &state); + void ApplyDiff(XINPUT_STATE &state, InputState &input_state); int gamepad_idx; int check_delay; XINPUT_STATE prevState; diff --git a/native b/native index 435392b137e7..d7a58a315432 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 435392b137e7c80ff40db8b2af2feac6019f970e +Subproject commit d7a58a31543230acc2c3850cf2523f1e40bf85ec From 0eda1a8fe5cd7586bf85f143349d2bb082aea439 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 01:04:46 +0100 Subject: [PATCH 14/34] Show bg and icon on pause screen. --- UI/GameInfoCache.cpp | 9 ++++++++- UI/GameInfoCache.h | 2 ++ UI/MenuScreens.cpp | 21 +++++++++++++++++++++ Windows/InputDevice.h | 1 - 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 9e75f03f41c2..daab7ccf77a3 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -77,6 +77,11 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { auto iter = info_.find(gamePath); if (iter != info_.end()) { GameInfo *info = iter->second; + if (!info->wantBG && wantBG) { + // Need to start over. + delete info; + goto again; + } if (info->iconTextureData.size()) { info->iconTexture = new Texture(); // TODO: We could actually do the PNG decoding as well on the async thread. @@ -97,6 +102,8 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { return iter->second; } +again: + // return info; // TODO: Everything below here should be asynchronous and run on a thread, @@ -116,7 +123,7 @@ GameInfo *GameInfoCache::GetInfo(const std::string &gamePath, bool wantBG) { ISOFileSystem umd(&handles, bd); GameInfo *info = new GameInfo(); - + info->wantBG = wantBG; // Alright, let's fetch the PARAM.SFO. std::string paramSFOcontents; diff --git a/UI/GameInfoCache.h b/UI/GameInfoCache.h index c24b19ad130f..982b8f530675 100644 --- a/UI/GameInfoCache.h +++ b/UI/GameInfoCache.h @@ -41,6 +41,8 @@ struct GameInfo { std::string bgTextureData; Texture *bgTexture; + bool wantBG; + double lastAccessedTime; // The time at which the Icon and the BG were loaded. diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index 4327f69f8b96..e50994426ca7 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -47,6 +47,7 @@ namespace MainWindow { #include "Common/StringUtil.h" #include "Core/System.h" +#include "Core/CoreParameter.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" #include "GPU/GPUInterface.h" @@ -303,6 +304,26 @@ void PauseScreen::render() { title = game_title.c_str(); } + + UIContext *ctx = screenManager()->getUIContext(); + // This might create a texture so we must flush first. + UIFlush(); + GameInfo *ginfo = g_gameInfoCache.GetInfo(PSP_CoreParameter().fileToStart, true); + + if (ginfo && ginfo->bgTexture) { + ginfo->bgTexture->Bind(0); + ui_draw2d.DrawTexRect(0,0,dp_xres, dp_yres, 0,0,1,1,0xFFc0c0c0); + ui_draw2d.Flush(); + ctx->RebindTexture(); + } + + if (ginfo && ginfo->iconTexture) { + ginfo->iconTexture->Bind(0); + ui_draw2d.DrawTexRect(10,10,10+144, 10+80, 0,0,1,1,0xFFFFFFFF); + ui_draw2d.Flush(); + ctx->RebindTexture(); + } + ui_draw2d.DrawText(UBUNTU48, title, dp_xres / 2, 30, 0xFFFFFFFF, ALIGN_HCENTER); int x = 30; diff --git a/Windows/InputDevice.h b/Windows/InputDevice.h index ebbc8a5a7ad4..372d16a8c8cb 100644 --- a/Windows/InputDevice.h +++ b/Windows/InputDevice.h @@ -4,7 +4,6 @@ #include #include "../Common/CommonTypes.h" -#include "../Core/HLE/sceCtrl.h" struct InputState; From 63db2081eec11eb1c3289326dd29fd40c806d0cd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 17:09:44 -0700 Subject: [PATCH 15/34] iOS: Oops, need -O2 on RelWithDebInfo for profiling. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf756be0c6eb..cc737103a825 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1019,11 +1019,11 @@ if(APPLE) set(CMAKE_CXX_FLAGS_DEBUG "-g -D_DEBUG") set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -D_NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O3 -D_NDEBUG") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -D_NDEBUG") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g -D_NDEBUG") set(CMAKE_C_FLAGS_DEBUG "-g -D_DEBUG") set(CMAKE_C_FLAGS_MINSIZEREL "-Os -D_NDEBUG") set(CMAKE_C_FLAGS_RELEASE "-O3 -D_NDEBUG") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 -g -D_NDEBUG") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -D_NDEBUG") # These can be fast even for debug. set_target_properties(cityhash PROPERTIES COMPILE_FLAGS "-O3") From 7417188671c43a6f2142469a1c4c58d2c745080f Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 16:40:36 -0700 Subject: [PATCH 16/34] iOS: Port Android control fix. --- ios/ViewController.mm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 6841b6aae220..ac493f5e14f6 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -28,6 +28,7 @@ static uint32_t pad_buttons_async_set = 0; static uint32_t pad_buttons_async_clear = 0; +static uint32_t pad_buttons_down = 0; extern ScreenManager *screenManager; InputState input_state; @@ -60,6 +61,9 @@ - (id)init self.bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/assets/"]; memset(&input_state, 0, sizeof(input_state)); + pad_buttons_async_clear = 0; + pad_buttons_async_set = 0; + pad_buttons_down = 0; net::Init(); @@ -160,8 +164,9 @@ - (NSUInteger)supportedInterfaceOrientations - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { lock_guard guard(input_state.lock); - input_state.pad_buttons |= pad_buttons_async_set; - input_state.pad_buttons &= ~pad_buttons_async_clear; + pad_buttons_down |= pad_buttons_async_set; + pad_buttons_down &= ~pad_buttons_async_clear; + input_state.pad_buttons = pad_buttons_down; UpdateInputState(&input_state); { From 4208f17c7c78243ebc4b8fa78b9095f40283bcd5 Mon Sep 17 00:00:00 2001 From: rock88 Date: Sat, 30 Mar 2013 16:57:11 -0700 Subject: [PATCH 17/34] iOS: Fix input buttons sticking. --- ios/ViewController.mm | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index ac493f5e14f6..3ed273075c5d 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -112,7 +112,7 @@ - (void)viewDidLoad dp_yscale = (float)dp_yres / (float)pixel_yres; if (g_Config.bEnableSound) - self.audioEngine = [[[AudioEngine alloc] init] autorelease]; + self.audioEngine = [[[AudioEngine alloc] init] autorelease]; /* UISwipeGestureRecognizer* gesture = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)] autorelease]; [self.view addGestureRecognizer:gesture]; @@ -138,7 +138,7 @@ - (void)dealloc { [self viewDidUnload]; - self.audioEngine = nil; + self.audioEngine = nil; self.touches = nil; self.documentsPath = nil; self.bundlePath = nil; @@ -224,12 +224,36 @@ - (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId input_state.mouse_valid = true; } +- (NSDictionary*)touchDictBy:(UITouch*)touch +{ + for (NSDictionary* dict in self.touches) { + if ([dict objectForKey:@"touch"] == touch) + return dict; + } + return nil; +} + +- (int)freeTouchIndex +{ + int index = 0; + + for (NSDictionary* dict in self.touches) + { + int i = [[dict objectForKey:@"index"] intValue]; + if (index == i) + index = i+1; + } + + return index; +} + - (void)touchesBegan:(NSSet *)_touches withEvent:(UIEvent *)event { for(UITouch* touch in _touches) { - [self.touches addObject:touch]; + NSDictionary* dict = @{@"touch":touch,@"index":@([self freeTouchIndex])}; + [self.touches addObject:dict]; CGPoint point = [touch locationInView:self.view]; - [self touchX:point.x y:point.y code:1 pointerId:[self.touches indexOfObject:touch]]; + [self touchX:point.x y:point.y code:1 pointerId:[[dict objectForKey:@"index"] intValue]]; } } @@ -237,7 +261,8 @@ - (void)touchesMoved:(NSSet *)_touches withEvent:(UIEvent *)event { for(UITouch* touch in _touches) { CGPoint point = [touch locationInView:self.view]; - [self touchX:point.x y:point.y code:0 pointerId:[self.touches indexOfObject:touch]]; + NSDictionary* dict = [self touchDictBy:touch]; + [self touchX:point.x y:point.y code:0 pointerId:[[dict objectForKey:@"index"] intValue]]; } } @@ -245,8 +270,9 @@ - (void)touchesEnded:(NSSet *)_touches withEvent:(UIEvent *)event { for(UITouch* touch in _touches) { CGPoint point = [touch locationInView:self.view]; - [self touchX:point.x y:point.y code:2 pointerId:[self.touches indexOfObject:touch]]; - [self.touches removeObject:touch]; + NSDictionary* dict = [self touchDictBy:touch]; + [self touchX:point.x y:point.y code:2 pointerId:[[dict objectForKey:@"index"] intValue]]; + [self.touches removeObject:dict]; } } From 31206e356bb3298eec2097711920c69e4ac59bce Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 17:44:00 -0700 Subject: [PATCH 18/34] iOS: Don't lock input state for so long. --- ios/ViewController.mm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 3ed273075c5d..8e44b7410523 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -163,11 +163,13 @@ - (NSUInteger)supportedInterfaceOrientations - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { - lock_guard guard(input_state.lock); - pad_buttons_down |= pad_buttons_async_set; - pad_buttons_down &= ~pad_buttons_async_clear; - input_state.pad_buttons = pad_buttons_down; - UpdateInputState(&input_state); + { + lock_guard guard(input_state.lock); + pad_buttons_down |= pad_buttons_async_set; + pad_buttons_down &= ~pad_buttons_async_clear; + input_state.pad_buttons = pad_buttons_down; + UpdateInputState(&input_state); + } { lock_guard guard(input_state.lock); From 1cfdaa934987bd9b059cb1f5c64b840ea20dae0a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 20:12:22 -0700 Subject: [PATCH 19/34] Read structs directly from PSP ram on LE. On BE, which doesn't even really work atm, this can be an auto class. --- Core/HLE/sceKernelMutex.cpp | 133 ++++++++++++++---------------------- Core/MemMap.h | 7 ++ 2 files changed, 60 insertions(+), 80 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index 0c236bcaa330..af60794e61ef 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -719,17 +719,15 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init mutex->nm.uid = id; mutex->nm.workareaPtr = workareaPtr; mutex->nm.initialCount = initialCount; - NativeLwMutexWorkarea workarea; - workarea.init(); - workarea.lockLevel = initialCount; + auto workarea = Memory::GetStruct(workareaPtr); + workarea->init(); + workarea->lockLevel = initialCount; if (initialCount == 0) - workarea.lockThread = 0; + workarea->lockThread = 0; else - workarea.lockThread = __KernelGetCurThread(); - workarea.attr = attr; - workarea.uid = id; - - Memory::WriteStruct(workareaPtr, &workarea); + workarea->lockThread = __KernelGetCurThread(); + workarea->attr = attr; + workarea->uid = id; DEBUG_LOG(HLE, "sceKernelCreateLwMutex(%08x, %s, %08x, %d, %08x)", workareaPtr, name, attr, initialCount, optionsPtr); @@ -741,7 +739,8 @@ int sceKernelCreateLwMutex(u32 workareaPtr, const char *name, u32 attr, int init return 0; } -bool __KernelUnlockLwMutexForThread(LwMutex *mutex, NativeLwMutexWorkarea &workarea, SceUID threadID, u32 &error, int result) +template +bool __KernelUnlockLwMutexForThread(LwMutex *mutex, T workarea, SceUID threadID, u32 &error, int result) { SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_LWMUTEX, error); u32 timeoutPtr = __KernelGetWaitTimeoutPtr(threadID, error); @@ -753,8 +752,8 @@ bool __KernelUnlockLwMutexForThread(LwMutex *mutex, NativeLwMutexWorkarea &worka // If result is an error code, we're just letting it go. if (result == 0) { - workarea.lockLevel = (int) __KernelGetWaitValue(threadID, error); - workarea.lockThread = threadID; + workarea->lockLevel = (int) __KernelGetWaitValue(threadID, error); + workarea->lockThread = threadID; } if (timeoutPtr != 0 && lwMutexWaitTimer != -1) @@ -775,11 +774,10 @@ int sceKernelDeleteLwMutex(u32 workareaPtr) if (!workareaPtr || !Memory::IsValidAddress(workareaPtr)) return SCE_KERNEL_ERROR_ILLEGAL_ADDR; - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); u32 error; - LwMutex *mutex = kernelObjects.Get(workarea.uid, error); + LwMutex *mutex = kernelObjects.Get(workarea->uid, error); if (mutex) { bool wokeThreads = false; @@ -788,8 +786,7 @@ int sceKernelDeleteLwMutex(u32 workareaPtr) wokeThreads |= __KernelUnlockLwMutexForThread(mutex, workarea, *iter, error, SCE_KERNEL_ERROR_WAIT_DELETE); mutex->waitingThreads.clear(); - workarea.clear(); - Memory::WriteStruct(workareaPtr, &workarea); + workarea->clear(); if (wokeThreads) hleReSchedule("lwmutex deleted"); @@ -800,45 +797,46 @@ int sceKernelDeleteLwMutex(u32 workareaPtr) return error; } -bool __KernelLockLwMutex(NativeLwMutexWorkarea &workarea, int count, u32 &error) +template +bool __KernelLockLwMutex(T workarea, int count, u32 &error) { if (!error) { if (count <= 0) error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if (count > 1 && !(workarea.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE)) + else if (count > 1 && !(workarea->attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE)) error = SCE_KERNEL_ERROR_ILLEGAL_COUNT; // Two positive ints will always overflow to negative. - else if (count + workarea.lockLevel < 0) + else if (count + workarea->lockLevel < 0) error = PSP_LWMUTEX_ERROR_LOCK_OVERFLOW; - else if (workarea.uid == -1) + else if (workarea->uid == -1) error = PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; } if (error) return false; - if (workarea.lockLevel == 0) + if (workarea->lockLevel == 0) { - if (workarea.lockThread != 0) + if (workarea->lockThread != 0) { // Validate that it actually exists so we can return an error if not. - kernelObjects.Get(workarea.uid, error); + kernelObjects.Get(workarea->uid, error); if (error) return false; } - workarea.lockLevel = count; - workarea.lockThread = __KernelGetCurThread(); + workarea->lockLevel = count; + workarea->lockThread = __KernelGetCurThread(); return true; } - if (workarea.lockThread == __KernelGetCurThread()) + if (workarea->lockThread == __KernelGetCurThread()) { // Recursive mutex, let's just increase the lock count and keep going - if (workarea.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) + if (workarea->attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) { - workarea.lockLevel += count; + workarea->lockLevel += count; return true; } else @@ -851,12 +849,13 @@ bool __KernelLockLwMutex(NativeLwMutexWorkarea &workarea, int count, u32 &error) return false; } -bool __KernelUnlockLwMutex(NativeLwMutexWorkarea &workarea, u32 &error) +template +bool __KernelUnlockLwMutex(T workarea, u32 &error) { - LwMutex *mutex = kernelObjects.Get(workarea.uid, error); + LwMutex *mutex = kernelObjects.Get(workarea->uid, error); if (error) { - workarea.lockThread = 0; + workarea->lockThread = 0; return false; } @@ -874,7 +873,7 @@ bool __KernelUnlockLwMutex(NativeLwMutexWorkarea &workarea, u32 &error) } if (!wokeThreads) - workarea.lockThread = 0; + workarea->lockThread = 0; return wokeThreads; } @@ -972,13 +971,9 @@ void __KernelLwMutexEndCallback(SceUID threadID, SceUID prevCallbackId, u32 &ret // TODO: Don't wake up if __KernelCurHasReadyCallbacks()? // Attempt to unlock. - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(mutex->nm.workareaPtr, &workarea); + auto workarea = Memory::GetStruct(mutex->nm.workareaPtr); if (mutex->nm.lockThread == -1 && __KernelUnlockLwMutexForThread(mutex, workarea, threadID, error, 0)) - { - Memory::WriteStruct(mutex->nm.workareaPtr, &workarea); return; - } // We only check if it timed out if it couldn't unlock. s64 cyclesLeft = waitDeadline - CoreTiming::GetTicks(); @@ -1002,15 +997,11 @@ int sceKernelTryLockLwMutex(u32 workareaPtr, int count) { DEBUG_LOG(HLE, "sceKernelTryLockLwMutex(%08x, %i)", workareaPtr, count); - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); u32 error = 0; if (__KernelLockLwMutex(workarea, count, error)) - { - Memory::WriteStruct(workareaPtr, &workarea); return 0; - } // Unlike sceKernelTryLockLwMutex_600, this always returns the same error. else if (error) return PSP_MUTEX_ERROR_TRYLOCK_FAILED; @@ -1022,15 +1013,11 @@ int sceKernelTryLockLwMutex_600(u32 workareaPtr, int count) { DEBUG_LOG(HLE, "sceKernelTryLockLwMutex_600(%08x, %i)", workareaPtr, count); - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); u32 error = 0; if (__KernelLockLwMutex(workarea, count, error)) - { - Memory::WriteStruct(workareaPtr, &workarea); return 0; - } else if (error) return error; else @@ -1041,20 +1028,16 @@ int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) { VERBOSE_LOG(HLE, "sceKernelLockLwMutex(%08x, %i, %08x)", workareaPtr, count, timeoutPtr); - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); u32 error = 0; if (__KernelLockLwMutex(workarea, count, error)) - { - Memory::WriteStruct(workareaPtr, &workarea); return 0; - } else if (error) return error; else { - LwMutex *mutex = kernelObjects.Get(workarea.uid, error); + LwMutex *mutex = kernelObjects.Get(workarea->uid, error); if (mutex) { SceUID threadID = __KernelGetCurThread(); @@ -1062,7 +1045,7 @@ int sceKernelLockLwMutex(u32 workareaPtr, int count, u32 timeoutPtr) if (std::find(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID) == mutex->waitingThreads.end()) mutex->waitingThreads.push_back(threadID); __KernelWaitLwMutex(mutex, timeoutPtr); - __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, false, "lwmutex waited"); + __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea->uid, count, timeoutPtr, false, "lwmutex waited"); // Return value will be overwritten by wait. return 0; @@ -1076,20 +1059,16 @@ int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) { VERBOSE_LOG(HLE, "sceKernelLockLwMutexCB(%08x, %i, %08x)", workareaPtr, count, timeoutPtr); - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); u32 error = 0; if (__KernelLockLwMutex(workarea, count, error)) - { - Memory::WriteStruct(workareaPtr, &workarea); return 0; - } else if (error) return error; else { - LwMutex *mutex = kernelObjects.Get(workarea.uid, error); + LwMutex *mutex = kernelObjects.Get(workarea->uid, error); if (mutex) { SceUID threadID = __KernelGetCurThread(); @@ -1097,7 +1076,7 @@ int sceKernelLockLwMutexCB(u32 workareaPtr, int count, u32 timeoutPtr) if (std::find(mutex->waitingThreads.begin(), mutex->waitingThreads.end(), threadID) == mutex->waitingThreads.end()) mutex->waitingThreads.push_back(threadID); __KernelWaitLwMutex(mutex, timeoutPtr); - __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea.uid, count, timeoutPtr, true, "lwmutex cb waited"); + __KernelWaitCurThread(WAITTYPE_LWMUTEX, workarea->uid, count, timeoutPtr, true, "lwmutex cb waited"); // Return value will be overwritten by wait. return 0; @@ -1111,31 +1090,27 @@ int sceKernelUnlockLwMutex(u32 workareaPtr, int count) { VERBOSE_LOG(HLE, "sceKernelUnlockLwMutex(%08x, %i)", workareaPtr, count); - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); - if (workarea.uid == -1) + if (workarea->uid == -1) return PSP_LWMUTEX_ERROR_NO_SUCH_LWMUTEX; else if (count <= 0) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if ((workarea.attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && count > 1) + else if ((workarea->attr & PSP_MUTEX_ATTR_ALLOW_RECURSIVE) == 0 && count > 1) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; - else if (workarea.lockLevel == 0 || workarea.lockThread != __KernelGetCurThread()) + else if (workarea->lockLevel == 0 || workarea->lockThread != __KernelGetCurThread()) return PSP_LWMUTEX_ERROR_NOT_LOCKED; - else if (workarea.lockLevel < count) + else if (workarea->lockLevel < count) return PSP_LWMUTEX_ERROR_UNLOCK_UNDERFLOW; - workarea.lockLevel -= count; + workarea->lockLevel -= count; - if (workarea.lockLevel == 0) + if (workarea->lockLevel == 0) { u32 error; if (__KernelUnlockLwMutex(workarea, error)) hleReSchedule("lwmutex unlocked"); - Memory::WriteStruct(workareaPtr, &workarea); } - else - Memory::WriteStruct(workareaPtr, &workarea); return 0; } @@ -1153,12 +1128,11 @@ int __KernelReferLwMutexStatus(SceUID uid, u32 infoPtr) if (Memory::Read_U32(infoPtr) != 0) { - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(m->nm.workareaPtr, &workarea); + auto workarea = Memory::GetStruct(m->nm.workareaPtr); // Refresh and write - m->nm.currentCount = workarea.lockLevel; - m->nm.lockThread = workarea.lockThread == 0 ? -1 : workarea.lockThread; + m->nm.currentCount = workarea->lockLevel; + m->nm.lockThread = workarea->lockThread == 0 ? -1 : workarea->lockThread; m->nm.numWaitThreads = m->waitingThreads.size(); Memory::WriteStruct(infoPtr, &m->nm); } @@ -1185,10 +1159,9 @@ int sceKernelReferLwMutexStatus(u32 workareaPtr, u32 infoPtr) if (!Memory::IsValidAddress(workareaPtr)) return -1; - NativeLwMutexWorkarea workarea; - Memory::ReadStruct(workareaPtr, &workarea); + auto workarea = Memory::GetStruct(workareaPtr); - int error = __KernelReferLwMutexStatus(workarea.uid, infoPtr); + int error = __KernelReferLwMutexStatus(workarea->uid, infoPtr); if (error >= 0) { DEBUG_LOG(HLE, "sceKernelReferLwMutexStatus(%08x, %08x)", workareaPtr, infoPtr); diff --git a/Core/MemMap.h b/Core/MemMap.h index 52afa19ae2ce..96b583fed2a7 100644 --- a/Core/MemMap.h +++ b/Core/MemMap.h @@ -253,6 +253,13 @@ void WriteStruct(u32 address, T *ptr) memcpy(GetPointer(address), ptr, sz); } +// Expect this to be some form of auto class on big endian. +template +T *GetStruct(u32 address) +{ + return (T *)GetPointer(address); +} + const char *GetAddressName(u32 address); }; From 8f911a0ebe72a9d055c8b6215178bf92b966343b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 21:42:43 -0700 Subject: [PATCH 20/34] Add a setting to autosave the symbol map. And move it into system, needs to be after the coreParameter too. --- Core/Config.cpp | 2 ++ Core/Config.h | 1 + Core/HLE/sceKernelModule.cpp | 4 ++++ Core/Host.h | 1 + Core/System.cpp | 5 +++++ UI/EmuScreen.cpp | 3 --- Windows/WindowsHost.cpp | 11 ++++++++++- Windows/WindowsHost.h | 3 +++ 8 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index fd0496a966a5..b3eb46007809 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -60,6 +60,7 @@ void Config::Load(const char *iniFileName) general->Get("Recent", recentIsos); general->Get("WindowX", &iWindowX, 40); general->Get("WindowY", &iWindowY, 100); + general->Get("AutoSaveSymbolMap", &bAutoSaveSymbolMap, false); if (recentIsos.size() > MAX_RECENT) recentIsos.resize(MAX_RECENT); @@ -139,6 +140,7 @@ void Config::Save() general->Set("Recent", recentIsos); general->Set("WindowX", iWindowX); general->Set("WindowY", iWindowY); + general->Set("AutoSaveSymbolMap", bAutoSaveSymbolMap); IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); cpu->Set("Jit", bJit); diff --git a/Core/Config.h b/Core/Config.h index 6c963150cb87..026da45c7ef0 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -44,6 +44,7 @@ struct Config bool bIgnoreBadMemAccess; bool bFastMemory; bool bJit; + bool bAutoSaveSymbolMap; std::string sReportHost; std::vector recentIsos; diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 86340bc51408..e127ca36e9e4 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -391,6 +391,10 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro dontadd = true; } } + else if (host->AttemptLoadSymbolMap()) + { + dontadd = true; + } INFO_LOG(LOADER,"Module %s: %08x %08x %08x", modinfo->name, modinfo->gp, modinfo->libent,modinfo->libstub); diff --git a/Core/Host.h b/Core/Host.h index 4d346b5921b3..966af3748a6b 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -57,6 +57,7 @@ class Host virtual bool IsDebuggingEnabled() {return true;} virtual bool AttemptLoadSymbolMap() {return false;} + virtual void SaveSymbolMap() {} virtual void SetWindowTitle(const char *message) {} virtual void SendCoreWait(bool) {} diff --git a/Core/System.cpp b/Core/System.cpp index a15f1675faa7..a17329b1e213 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -76,6 +76,8 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) mipsr4k.Reset(); mipsr4k.pc = 0; + host->AttemptLoadSymbolMap(); + if (coreParameter.enableSound) { mixer = new PSPMixer(); @@ -126,6 +128,9 @@ void PSP_Shutdown() CoreTiming::Shutdown(); + if (g_Config.bAutoSaveSymbolMap) + host->SaveSymbolMap(); + if (coreParameter.enableSound) { host->ShutdownSound(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 4be966281c55..500b211aed87 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -80,7 +80,6 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) { } host->BootDone(); - host->AttemptLoadSymbolMap(); host->UpdateDisassembly(); #ifdef _WIN32 @@ -99,8 +98,6 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) { EmuScreen::~EmuScreen() { if (!invalid_) { // If we were invalid, it would already be shutdown. - - // symbolMap.SaveSymbolMap(SymbolMapFilename(coreParam.fileToStart).c_str()); PSP_Shutdown(); } } diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 87ff538cc019..6ce7777e04aa 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -155,7 +155,16 @@ static std::string SymbolMapFilename(const char *currentFilename) bool WindowsHost::AttemptLoadSymbolMap() { - return symbolMap.LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str()).c_str()); + if (loadedSymbolMap_) + return true; + loadedSymbolMap_ = symbolMap.LoadSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str()).c_str()); + return loadedSymbolMap_; +} + +void WindowsHost::SaveSymbolMap() +{ + symbolMap.SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart.c_str()).c_str()); + loadedSymbolMap_ = false; } void WindowsHost::AddSymbol(std::string name, u32 addr, u32 size, int type=0) diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 268abcba5989..5653f311fe84 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -28,6 +28,7 @@ class WindowsHost : public Host mainWindow_ = mainWindow; displayWindow_ = displayWindow; input = getInputDevices(); + loadedSymbolMap_ = false; } void UpdateMemView(); void UpdateDisassembly(); @@ -47,10 +48,12 @@ class WindowsHost : public Host bool IsDebuggingEnabled(); void BootDone(); bool AttemptLoadSymbolMap(); + void SaveSymbolMap(); void SetWindowTitle(const char *message); private: HWND displayWindow_; HWND mainWindow_; std::list> input; + bool loadedSymbolMap_; }; \ No newline at end of file From ba131f7ffb0267043fad4bbc50f5bbdf686ecf26 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 22:36:28 -0700 Subject: [PATCH 21/34] Oops, fix potential shutdown hang. --- Core/Core.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index fd58612af2c4..ceaaa1ece975 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -83,8 +83,7 @@ void Core_WaitInactive() void Core_WaitInactive(int milliseconds) { - while (!Core_IsInactive()) - m_hInactiveEvent.wait_for(m_hInactiveMutex, milliseconds); + m_hInactiveEvent.wait_for(m_hInactiveMutex, milliseconds); } void UpdateScreenScale() { From c4a93d3bc3c5eab760b1e17734d289680a4389f2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 22:37:11 -0700 Subject: [PATCH 22/34] Make emulation -> stop actually shut down. Otherwise it pauses so it never gets around to it. --- Windows/WndMainWindow.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index a59e5d684bd0..d31cdca29a78 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -356,8 +356,6 @@ namespace MainWindow break; case ID_EMULATION_STOP: - if (disasmWindow[0]) - SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0); if (memoryWindow[0]) SendMessage(memoryWindow[0]->GetDlgHandle(), WM_CLOSE, 0, 0); From 8aeaedc597054091b38284f6e79a4b54af5551d6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Mar 2013 19:01:58 -0700 Subject: [PATCH 23/34] Don't allow sceUtility dialogs to overlap. PSP doesn't allow this, and apparently some games depend on it or else they start getting confused. --- Core/Dialog/PSPDialog.h | 3 + Core/Dialog/PSPOskDialog.cpp | 2 +- Core/Dialog/PSPSaveDialog.cpp | 2 +- Core/HLE/sceUtility.cpp | 196 +++++++++++++++++++++++++--------- 4 files changed, 153 insertions(+), 50 deletions(-) diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index ea170ada2636..6b5dedb9e55a 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -26,6 +26,9 @@ class PointerWrap; #define SCE_UTILITY_DIALOG_RESULT_CANCEL 1 #define SCE_UTILITY_DIALOG_RESULT_ABORT 2 +const int SCE_ERROR_UTILITY_INVALID_STATUS = 0x80110001; +const int SCE_ERROR_UTILITY_WRONG_TYPE = 0x80110005; + typedef struct { unsigned int size; /** Size of the structure */ diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index f1173e19c0ef..c324c5634f86 100644 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -65,7 +65,7 @@ int PSPOskDialog::Init(u32 oskPtr) // Ignore if already running if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) { - return -1; + return SCE_ERROR_UTILITY_INVALID_STATUS; } status = SCE_UTILITY_STATUS_INITIALIZE; diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 4821045305f4..c123c7703208 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -40,7 +40,7 @@ int PSPSaveDialog::Init(int paramAddr) if (status != SCE_UTILITY_STATUS_NONE && status != SCE_UTILITY_STATUS_SHUTDOWN) { ERROR_LOG(HLE,"A save request is already running !"); - return 0; + return SCE_ERROR_UTILITY_INVALID_STATUS; } int size = Memory::Read_U32(paramAddr); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 48665cc6ff2a..1af0475563b0 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -33,18 +33,33 @@ const int SCE_ERROR_MODULE_BAD_ID = 0x80111101; const int SCE_ERROR_AV_MODULE_BAD_ID = 0x80110F01; -PSPSaveDialog saveDialog; -PSPMsgDialog msgDialog; -PSPOskDialog oskDialog; -PSPPlaceholderDialog netDialog; +enum UtilityDialogType { + UTILITY_DIALOG_NONE, + UTILITY_DIALOG_SAVEDATA, + UTILITY_DIALOG_MSG, + UTILITY_DIALOG_OSK, + UTILITY_DIALOG_NET, +}; + +// Only a single dialog is allowed at a time. +static UtilityDialogType currentDialogType; +static bool currentDialogActive; +static PSPSaveDialog saveDialog; +static PSPMsgDialog msgDialog; +static PSPOskDialog oskDialog; +static PSPPlaceholderDialog netDialog; void __UtilityInit() { + currentDialogType = UTILITY_DIALOG_NONE; + currentDialogActive = false; SavedataParam::Init(); } void __UtilityDoState(PointerWrap &p) { + p.Do(currentDialogType); + p.Do(currentDialogActive); saveDialog.DoState(p); msgDialog.DoState(p); oskDialog.DoState(p); @@ -62,25 +77,52 @@ void __UtilityShutdown() int sceUtilitySavedataInitStart(u32 paramAddr) { + if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SAVEDATA) + { + WARN_LOG(HLE, "sceUtilitySavedataInitStart(%08x): wrong dialog type", paramAddr); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogType = UTILITY_DIALOG_SAVEDATA; + currentDialogActive = true; + DEBUG_LOG(HLE,"sceUtilitySavedataInitStart(%08x)", paramAddr); return saveDialog.Init(paramAddr); } int sceUtilitySavedataShutdownStart() { + if (currentDialogType != UTILITY_DIALOG_SAVEDATA) + { + WARN_LOG(HLE, "sceUtilitySavedataShutdownStart(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogActive = false; + DEBUG_LOG(HLE,"sceUtilitySavedataShutdownStart()"); return saveDialog.Shutdown(); } int sceUtilitySavedataGetStatus() { + if (currentDialogType != UTILITY_DIALOG_SAVEDATA) + { + WARN_LOG(HLE, "sceUtilitySavedataGetStatus(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + int status = saveDialog.GetStatus(); - DEBUG_LOG(HLE,"%08x=sceUtilitySavedataGetStatus()", status); + DEBUG_LOG(HLE, "%08x=sceUtilitySavedataGetStatus()", status); return status; } int sceUtilitySavedataUpdate(int animSpeed) { + if (currentDialogType != UTILITY_DIALOG_SAVEDATA) + { + WARN_LOG(HLE, "sceUtilitySavedataUpdate(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + DEBUG_LOG(HLE,"sceUtilitySavedataUpdate(%d)", animSpeed); return hleDelayResult(saveDialog.Update(), "savedata update", 300); } @@ -150,26 +192,54 @@ u32 sceUtilityUnloadModule(u32 module) int sceUtilityMsgDialogInitStart(u32 structAddr) { - DEBUG_LOG(HLE,"sceUtilityMsgDialogInitStart(%i)", structAddr); + if (currentDialogActive && currentDialogType != UTILITY_DIALOG_MSG) + { + WARN_LOG(HLE, "sceUtilityMsgDialogInitStart(%08x): wrong dialog type", structAddr); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogType = UTILITY_DIALOG_MSG; + currentDialogActive = true; + + DEBUG_LOG(HLE, "sceUtilityMsgDialogInitStart(%08x)", structAddr); return msgDialog.Init(structAddr); } -int sceUtilityMsgDialogShutdownStart(u32 unknown) +int sceUtilityMsgDialogShutdownStart() { - DEBUG_LOG(HLE,"sceUtilityMsgDialogShutdownStart(%i)", unknown); + if (currentDialogType != UTILITY_DIALOG_MSG) + { + WARN_LOG(HLE, "sceUtilityMsgDialogShutdownStart(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogActive = false; + + DEBUG_LOG(HLE, "sceUtilityMsgDialogShutdownStart()"); return msgDialog.Shutdown(); } int sceUtilityMsgDialogUpdate(int animSpeed) { + if (currentDialogType != UTILITY_DIALOG_MSG) + { + WARN_LOG(HLE, "sceUtilityMsgDialogUpdate(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + DEBUG_LOG(HLE,"sceUtilityMsgDialogUpdate(%i)", animSpeed); return msgDialog.Update(); } int sceUtilityMsgDialogGetStatus() { - DEBUG_LOG(HLE,"sceUtilityMsgDialogGetStatus()"); - return msgDialog.GetStatus(); + if (currentDialogType != UTILITY_DIALOG_MSG) + { + WARN_LOG(HLE, "sceUtilityMsgDialogGetStatus(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + + int status = msgDialog.GetStatus(); + DEBUG_LOG(HLE, "%08x=sceUtilityMsgDialogGetStatus()", status); + return status; } @@ -177,74 +247,104 @@ int sceUtilityMsgDialogGetStatus() int sceUtilityOskInitStart(u32 oskPtr) { - DEBUG_LOG(HLE,"sceUtilityOskInitStart(%i)", PARAM(0)); + if (currentDialogActive && currentDialogType != UTILITY_DIALOG_OSK) + { + WARN_LOG(HLE, "sceUtilityOskInitStart(%08x): wrong dialog type", oskPtr); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogType = UTILITY_DIALOG_OSK; + currentDialogActive = true; + + DEBUG_LOG(HLE, "sceUtilityOskInitStart(%08x)", oskPtr); return oskDialog.Init(oskPtr); } int sceUtilityOskShutdownStart() { - DEBUG_LOG(HLE,"sceUtilityOskShutdownStart(%i)", PARAM(0)); + if (currentDialogType != UTILITY_DIALOG_OSK) + { + WARN_LOG(HLE, "sceUtilityOskShutdownStart(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogActive = false; + + DEBUG_LOG(HLE, "sceUtilityOskShutdownStart()"); return oskDialog.Shutdown(); } -int sceUtilityOskUpdate(unsigned int unknown) +int sceUtilityOskUpdate(int animSpeed) { - DEBUG_LOG(HLE,"FAKE sceUtilityOskUpdate(%i)", unknown); + if (currentDialogType != UTILITY_DIALOG_OSK) + { + WARN_LOG(HLE, "sceUtilityMsgDialogUpdate(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + + DEBUG_LOG(HLE, "sceUtilityOskUpdate(%i)", animSpeed); return oskDialog.Update(); } int sceUtilityOskGetStatus() { + if (currentDialogType != UTILITY_DIALOG_OSK) + { + WARN_LOG(HLE, "sceUtilityOskGetStatus(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + int status = oskDialog.GetStatus(); + // Seems that 4 is the cancelled status for OSK? if (status == 4) { status = 5; } + + DEBUG_LOG(HLE, "%08x=sceUtilityOskGetStatus()", status); return status; } int sceUtilityNetconfInitStart(u32 structAddr) { - DEBUG_LOG(HLE,"FAKE sceUtilityNetconfInitStart(%08x)", structAddr); + ERROR_LOG(HLE, "UNIMPL sceUtilityNetconfInitStart(%08x)", structAddr); return netDialog.Init(); } int sceUtilityNetconfShutdownStart(unsigned int unknown) { - DEBUG_LOG(HLE,"FAKE sceUtilityNetconfShutdownStart(%i)", unknown); + ERROR_LOG(HLE, "UNIMPL sceUtilityNetconfShutdownStart(%i)", unknown); return netDialog.Shutdown(); } int sceUtilityNetconfUpdate(int animSpeed) { - DEBUG_LOG(HLE,"FAKE sceUtilityNetconfUpdate(%i)", animSpeed); + ERROR_LOG(HLE, "UNIMPL sceUtilityNetconfUpdate(%i)", animSpeed); return netDialog.Update(); } int sceUtilityNetconfGetStatus() { - DEBUG_LOG(HLE,"sceUtilityNetconfGetStatus()"); + ERROR_LOG(HLE, "UNIMPL sceUtilityNetconfGetStatus()"); return netDialog.GetStatus(); } int sceUtilityScreenshotGetStatus() { u32 retval = 0;//__UtilityGetStatus(); - DEBUG_LOG(HLE,"%i=sceUtilityScreenshotGetStatus()", retval); + ERROR_LOG(HLE, "UNIMPL %i=sceUtilityScreenshotGetStatus()", retval); return retval; } void sceUtilityGamedataInstallInitStart(u32 unkown) { - DEBUG_LOG(HLE,"UNIMPL sceUtilityGamedataInstallInitStart(%i)", unkown); + ERROR_LOG(HLE, "UNIMPL sceUtilityGamedataInstallInitStart(%i)", unkown); } int sceUtilityGamedataInstallGetStatus() { u32 retval = 0;//__UtilityGetStatus(); - DEBUG_LOG(HLE,"UNIMPL %i=sceUtilityGamedataInstallGetStatus()", retval); + ERROR_LOG(HLE, "UNIMPL %i=sceUtilityGamedataInstallGetStatus()", retval); return retval; } @@ -386,55 +486,55 @@ void sceUtilityInstallInitStart(u32 unknown) const HLEFunction sceUtility[] = { {0x1579a159, &WrapU_U, "sceUtilityLoadNetModule"}, - {0x64d50c56, &WrapU_U, "sceUtilityUnloadNetModule"}, + {0x64d50c56, &WrapU_U, "sceUtilityUnloadNetModule"}, {0xf88155f6, &WrapI_U, "sceUtilityNetconfShutdownStart"}, {0x4db1e739, &WrapI_U, "sceUtilityNetconfInitStart"}, {0x91e70e35, &WrapI_I, "sceUtilityNetconfUpdate"}, {0x6332aa39, &WrapI_V, "sceUtilityNetconfGetStatus"}, - {0x5eee6548, 0, "sceUtilityCheckNetParam"}, - {0x434d4b3a, 0, "sceUtilityGetNetParam"}, + {0x5eee6548, 0, "sceUtilityCheckNetParam"}, + {0x434d4b3a, 0, "sceUtilityGetNetParam"}, {0x4FED24D8, 0, "sceUtilityGetNetParamLatestID"}, - {0x67af3428, &WrapI_U, "sceUtilityMsgDialogShutdownStart"}, - {0x2ad8e239, &WrapI_U, "sceUtilityMsgDialogInitStart"}, - {0x95fc253b, &WrapI_I, "sceUtilityMsgDialogUpdate"}, - {0x9a1c91d7, &WrapI_V, "sceUtilityMsgDialogGetStatus"}, - {0x4928bd96, 0, "sceUtilityMsgDialogAbort"}, + {0x67af3428, &WrapI_V, "sceUtilityMsgDialogShutdownStart"}, + {0x2ad8e239, &WrapI_U, "sceUtilityMsgDialogInitStart"}, + {0x95fc253b, &WrapI_I, "sceUtilityMsgDialogUpdate"}, + {0x9a1c91d7, &WrapI_V, "sceUtilityMsgDialogGetStatus"}, + {0x4928bd96, 0, "sceUtilityMsgDialogAbort"}, - {0x9790b33c, &WrapI_V, "sceUtilitySavedataShutdownStart"}, - {0x50c4cd57, &WrapI_U, "sceUtilitySavedataInitStart"}, - {0xd4b95ffb, &WrapI_I, "sceUtilitySavedataUpdate"}, + {0x9790b33c, &WrapI_V, "sceUtilitySavedataShutdownStart"}, + {0x50c4cd57, &WrapI_U, "sceUtilitySavedataInitStart"}, + {0xd4b95ffb, &WrapI_I, "sceUtilitySavedataUpdate"}, {0x8874dbe0, &WrapI_V, "sceUtilitySavedataGetStatus"}, {0x3dfaeba9, &WrapI_V, "sceUtilityOskShutdownStart"}, {0xf6269b82, &WrapI_U, "sceUtilityOskInitStart"}, - {0x4b85c861, &WrapI_U, "sceUtilityOskUpdate"}, + {0x4b85c861, &WrapI_I, "sceUtilityOskUpdate"}, {0xf3f76017, &WrapI_V, "sceUtilityOskGetStatus"}, {0x41e30674, &WrapU_UU, "sceUtilitySetSystemParamString"}, {0x45c18506, 0, "sceUtilitySetSystemParamInt"}, - {0x34b78343, &WrapU_UUU, "sceUtilityGetSystemParamString"}, + {0x34b78343, &WrapU_UUU, "sceUtilityGetSystemParamString"}, {0xA5DA2406, &WrapU_UU, "sceUtilityGetSystemParamInt"}, - {0xc492f751, 0, "sceUtilityGameSharingInitStart"}, - {0xefc6f80f, 0, "sceUtilityGameSharingShutdownStart"}, - {0x7853182d, 0, "sceUtilityGameSharingUpdate"}, - {0x946963f3, 0, "sceUtilityGameSharingGetStatus"}, + {0xc492f751, 0, "sceUtilityGameSharingInitStart"}, + {0xefc6f80f, 0, "sceUtilityGameSharingShutdownStart"}, + {0x7853182d, 0, "sceUtilityGameSharingUpdate"}, + {0x946963f3, 0, "sceUtilityGameSharingGetStatus"}, - {0x2995d020, 0, "sceUtility_2995d020"}, - {0xb62a4061, 0, "sceUtility_b62a4061"}, - {0xed0fad38, 0, "sceUtility_ed0fad38"}, - {0x88bc7406, 0, "sceUtility_88bc7406"}, + {0x2995d020, 0, "sceUtility_2995d020"}, + {0xb62a4061, 0, "sceUtility_b62a4061"}, + {0xed0fad38, 0, "sceUtility_ed0fad38"}, + {0x88bc7406, 0, "sceUtility_88bc7406"}, - {0xbda7d894, 0, "sceUtilityHtmlViewerGetStatus"}, - {0xcdc3aa41, 0, "sceUtilityHtmlViewerInitStart"}, - {0xf5ce1134, 0, "sceUtilityHtmlViewerShutdownStart"}, - {0x05afb9e4, 0, "sceUtilityHtmlViewerUpdate"}, + {0xbda7d894, 0, "sceUtilityHtmlViewerGetStatus"}, + {0xcdc3aa41, 0, "sceUtilityHtmlViewerInitStart"}, + {0xf5ce1134, 0, "sceUtilityHtmlViewerShutdownStart"}, + {0x05afb9e4, 0, "sceUtilityHtmlViewerUpdate"}, - {0xc629af26, &WrapU_U, "sceUtilityLoadAvModule"}, + {0xc629af26, &WrapU_U, "sceUtilityLoadAvModule"}, {0xf7d8d092, &WrapU_U, "sceUtilityUnloadAvModule"}, {0x2a2b3de0, &WrapU_U, "sceUtilityLoadModule"}, @@ -463,7 +563,7 @@ const HLEFunction sceUtility[] = {0x1281DA8E, &WrapV_U, "sceUtilityInstallInitStart"}, {0x5EF1C24A, 0, "sceUtilityInstallShutdownStart"}, {0xA03D29BA, 0, "sceUtilityInstallUpdate"}, - {0xC4700FA3, 0, "sceUtilityInstallGetStatus"}, + {0xC4700FA3, 0, "sceUtilityInstallGetStatus"}, }; From 74302a9ecfb5702df87c69bd64eb67cd6522ca98 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 17 Mar 2013 21:39:06 -0700 Subject: [PATCH 24/34] Savedata doesn't always resched, add some errcodes. --- Core/Dialog/PSPSaveDialog.cpp | 5 ++++- Core/HLE/sceUtility.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index c123c7703208..c4396c263f12 100644 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -379,7 +379,7 @@ int PSPSaveDialog::Update() if (status != SCE_UTILITY_STATUS_RUNNING) { - return 0; + return SCE_ERROR_UTILITY_INVALID_STATUS; } if (!param.GetPspParam()) { @@ -798,6 +798,9 @@ int PSPSaveDialog::Update() int PSPSaveDialog::Shutdown() { + if (status != SCE_UTILITY_STATUS_FINISHED) + return SCE_ERROR_UTILITY_INVALID_STATUS; + PSPDialog::Shutdown(); param.SetPspParam(0); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 1af0475563b0..2246f4d0a377 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -124,7 +124,10 @@ int sceUtilitySavedataUpdate(int animSpeed) } DEBUG_LOG(HLE,"sceUtilitySavedataUpdate(%d)", animSpeed); - return hleDelayResult(saveDialog.Update(), "savedata update", 300); + int result = saveDialog.Update(); + if (result >= 0) + return hleDelayResult(result, "savedata update", 300); + return result; } #define PSP_AV_MODULE_AVCODEC 0 From 1f2de11dbefe7b2ec1ff3c71e3ca19d967238fd4 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 30 Mar 2013 22:54:00 -0700 Subject: [PATCH 25/34] Add a basic impl of sceUtilityMsgDialogAbort(). Makes Enigmo work anyway. Doesn't seem like a popular function. --- Core/Dialog/PSPMsgDialog.cpp | 6 ++++++ Core/Dialog/PSPMsgDialog.h | 1 + Core/HLE/sceUtility.cpp | 17 +++++++++++++++-- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index 0229403531b3..6ccf85e0bb43 100644 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -230,6 +230,12 @@ int PSPMsgDialog::Update() return 0; } +int PSPMsgDialog::Abort() +{ + // TODO: Probably not exactly the same? + return PSPDialog::Shutdown(); +} + int PSPMsgDialog::Shutdown() { return PSPDialog::Shutdown(); diff --git a/Core/Dialog/PSPMsgDialog.h b/Core/Dialog/PSPMsgDialog.h index c9cd38474e0d..d96a0e389aeb 100644 --- a/Core/Dialog/PSPMsgDialog.h +++ b/Core/Dialog/PSPMsgDialog.h @@ -61,6 +61,7 @@ class PSPMsgDialog: public PSPDialog { virtual int Update(); virtual int Shutdown(); virtual void DoState(PointerWrap &p); + int Abort(); private : void DisplayBack(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 2246f4d0a377..4c6b40f2d101 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -245,6 +245,19 @@ int sceUtilityMsgDialogGetStatus() return status; } +int sceUtilityMsgDialogAbort() +{ + if (currentDialogType != UTILITY_DIALOG_MSG) + { + WARN_LOG(HLE, "sceUtilityMsgDialogShutdownStart(): wrong dialog type"); + return SCE_ERROR_UTILITY_WRONG_TYPE; + } + currentDialogActive = false; + + DEBUG_LOG(HLE, "sceUtilityMsgDialogAbort()"); + return msgDialog.Abort(); +} + // On screen keyboard @@ -504,7 +517,7 @@ const HLEFunction sceUtility[] = {0x2ad8e239, &WrapI_U, "sceUtilityMsgDialogInitStart"}, {0x95fc253b, &WrapI_I, "sceUtilityMsgDialogUpdate"}, {0x9a1c91d7, &WrapI_V, "sceUtilityMsgDialogGetStatus"}, - {0x4928bd96, 0, "sceUtilityMsgDialogAbort"}, + {0x4928bd96, &WrapI_V, "sceUtilityMsgDialogAbort"}, {0x9790b33c, &WrapI_V, "sceUtilitySavedataShutdownStart"}, {0x50c4cd57, &WrapI_U, "sceUtilitySavedataInitStart"}, @@ -556,7 +569,7 @@ const HLEFunction sceUtility[] = {0x32E32DCB, 0, "sceUtilityGamedataInstallShutdownStart"}, {0x4AECD179, 0, "sceUtilityGamedataInstallUpdate"}, {0xB57E95D9, &WrapI_V, "sceUtilityGamedataInstallGetStatus"}, - {0x180F7B62, 0, "sceUtilityGamedataInstallAbortFunction"}, + {0x180F7B62, 0, "sceUtilityGamedataInstallAbort"}, {0x16D02AF0, 0, "sceUtilityNpSigninInitStart"}, {0xE19C97D6, 0, "sceUtilityNpSigninShutdownStart"}, From 7282a1c6a37c29813693d54f56778a049b1ef0b5 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 31 Mar 2013 16:55:48 +1000 Subject: [PATCH 26/34] Support loading assets from QRC (inbuilt in binary). Some Qt fixes. Mobile UI compiles. Qt still has issues. --- Core/Core.cpp | 2 +- Core/Core.h | 4 ++-- Qt/EmuThread.cpp | 6 +++--- Qt/Native.pro | 6 ++---- Qt/PPSSPP.pro | 6 ++++-- Qt/assets.qrc | 6 ++++++ native | 2 +- 7 files changed, 19 insertions(+), 13 deletions(-) create mode 100644 Qt/assets.qrc diff --git a/Core/Core.cpp b/Core/Core.cpp index ceaaa1ece975..062712f5c263 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -41,7 +41,7 @@ recursive_mutex m_hStepMutex; event m_hInactiveEvent; recursive_mutex m_hInactiveMutex; -#ifdef _WIN32 +#ifndef ANDROID InputState input_state; #else extern InputState input_state; diff --git a/Core/Core.h b/Core/Core.h index cb49f6df39bf..2994ca55fe1d 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -18,7 +18,7 @@ #pragma once #include "Globals.h" -#include "Core/Core.h" +#include "Core/System.h" #include "Core/CoreParameter.h" // called from emu thread @@ -37,4 +37,4 @@ bool Core_IsInactive(); void Core_WaitInactive(); void Core_WaitInactive(int milliseconds); -void UpdateScreenScale(); \ No newline at end of file +void UpdateScreenScale(); diff --git a/Qt/EmuThread.cpp b/Qt/EmuThread.cpp index 1e5924b277fe..5291bde76aa0 100644 --- a/Qt/EmuThread.cpp +++ b/Qt/EmuThread.cpp @@ -10,14 +10,14 @@ #include "Core/Core.h" #include "math/lin/matrix4x4.h" #include "native/ui/ui.h" -#include "android/jni/UIShader.h" -#include "android/jni/GamepadEmu.h" +#include "UI/UIShader.h" +#include "UI/GamepadEmu.h" +#include "UI/ui_atlas.h" #include "base/NativeApp.h" #include "base/threadutil.h" #include "gfx_es2/fbo.h" #include "gfx_es2/gl_state.h" #include "GPU/GPUState.h" -#include "android/jni/ui_atlas.h" #include "native/base/timeutil.h" #include "native/base/colorutil.h" #include "GPU/GPUState.h" diff --git a/Qt/Native.pro b/Qt/Native.pro index 420888c42f4d..c550ebeff8d7 100755 --- a/Qt/Native.pro +++ b/Qt/Native.pro @@ -17,7 +17,7 @@ x86:!mobile_platform: { HEADERS += ../native/base/backtrace.h } -# RG_ETC +# RG_ETC1 SOURCES += ../native/ext/rg_etc1/rg_etc1.cpp HEADERS += ../native/ext/rg_etc1/rg_etc1.h @@ -80,9 +80,7 @@ SOURCES += ../native/audio/*.cpp \ ../native/midi/midi_input.cpp \ ../native/net/*.cpp \ ../native/profiler/profiler.cpp \ - ../native/ui/screen.cpp \ - ../native/ui/ui.cpp \ - ../native/ui/virtual_input.cpp \ + ../native/ui/*.cpp \ ../native/util/bits/*.cpp \ ../native/util/hash/hash.cpp \ ../native/util/random/perlin.cpp \ diff --git a/Qt/PPSSPP.pro b/Qt/PPSSPP.pro index fb97b72c93e8..adebc78b6852 100755 --- a/Qt/PPSSPP.pro +++ b/Qt/PPSSPP.pro @@ -38,6 +38,7 @@ HEADERS += ../native/base/QtMain.h SOURCES += ../UI/EmuScreen.cpp \ ../UI/MenuScreens.cpp \ ../UI/GamepadEmu.cpp \ + ../UI/GameInfoCache.cpp \ ../android/jni/TestRunner.cpp \ ../UI/UIShader.cpp \ ../UI/ui_atlas.cpp @@ -55,8 +56,9 @@ linux:!mobile_platform { RESOURCES += resources.qrc INCLUDEPATH += ../Qt } else { - SOURCES += ../android/jni/NativeApp.cpp + SOURCES += ../UI/NativeApp.cpp } +RESOURCES += assets.qrc # Translations TRANSLATIONS = $$files(languages/ppsspp_*.ts) @@ -72,7 +74,7 @@ PRE_TARGETDEPS += compiler_lang_make_all # Packaging symbian { deploy.pkg_prerules = "$${LITERAL_HASH}{\"PPSSPP\"}, (0xE0095B1D), 0, 7, 0, TYPE=SA" "%{\"Qtness\"}" ":\"Qtness\"" - assets.sources = ../android/assets/ui_atlas.zim ../assets/ppge_atlas.zim ../assets/flash + assets.sources = ../assets/flash assets.path = E:/PPSSPP DEPLOYMENT += deploy assets ICON = ../assets/icon.svg diff --git a/Qt/assets.qrc b/Qt/assets.qrc new file mode 100644 index 000000000000..b512dfe6091a --- /dev/null +++ b/Qt/assets.qrc @@ -0,0 +1,6 @@ + + + assets/ui_atlas.zim + assets/ppge_atlas.zim + + diff --git a/native b/native index d7a58a315432..73177ff46348 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit d7a58a31543230acc2c3850cf2523f1e40bf85ec +Subproject commit 73177ff463480f959d55bb228a9a9b967252cb9b From 21e8a882977e6bbeb4b1eef2309bc0d2adfd2493 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 31 Mar 2013 17:02:15 +1000 Subject: [PATCH 27/34] Buildfix. Recently changed. --- Core/Core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index 062712f5c263..ceaaa1ece975 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -41,7 +41,7 @@ recursive_mutex m_hStepMutex; event m_hInactiveEvent; recursive_mutex m_hInactiveMutex; -#ifndef ANDROID +#ifdef _WIN32 InputState input_state; #else extern InputState input_state; From cce038b00985c89a601612bc3fad5f0c16a085d1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 31 Mar 2013 00:42:20 -0700 Subject: [PATCH 28/34] iOS: Update Info.plist for iPad support (thanks @bsauvage1.) Reportedly fixes #1015, reportedly fixes #1067. --- ios/PPSSPP-Info.plist | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ios/PPSSPP-Info.plist b/ios/PPSSPP-Info.plist index 9707c3230e19..940c30dcf781 100644 --- a/ios/PPSSPP-Info.plist +++ b/ios/PPSSPP-Info.plist @@ -51,5 +51,10 @@ assets/Default.png UIFileSharingEnabled + UIDeviceFamily + + 1 + 2 + From 0fd3dfb160ed9fd80775cdddfdfbf7e5676df920 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 31 Mar 2013 01:01:20 -0700 Subject: [PATCH 29/34] Fix psmf typo in debug log output. --- Core/HLE/scePsmf.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/scePsmf.cpp b/Core/HLE/scePsmf.cpp index 6c4cc456dc8d..2bc7afbfb43e 100644 --- a/Core/HLE/scePsmf.cpp +++ b/Core/HLE/scePsmf.cpp @@ -378,12 +378,12 @@ u32 scePsmfSetPsmf(u32 psmfStruct, u32 psmfData) u32 scePsmfGetNumberOfStreams(u32 psmfStruct) { - DEBUG_LOG(HLE, "scePsmfGetNumberOfSpecificStreams(%08x)", psmfStruct); Psmf *psmf = getPsmf(psmfStruct); if (!psmf) { ERROR_LOG(HLE, "scePsmfGetNumberOfStreams - invalid psmf"); return ERROR_PSMF_NOT_FOUND; } + DEBUG_LOG(HLE, "scePsmfGetNumberOfStreams(%08x)", psmfStruct); return psmf->numStreams; } From 9f263349531d7f08171b03d02b157e324d59756b Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 10:04:30 +0200 Subject: [PATCH 30/34] Update native (attempt to fix black icons) --- native | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/native b/native index 73177ff46348..22e648bb1a5e 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 73177ff463480f959d55bb228a9a9b967252cb9b +Subproject commit 22e648bb1a5e8fe6e427efc906194edbb9ce6ed8 From 2301ad0b7c5ea736705a84d69192844a4b2c0139 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 11:30:50 +0200 Subject: [PATCH 31/34] X360 controller: Left thumb speedup, right thumb menu, keyboard still works --- Core/CoreParameter.h | 5 ++++- Core/HLE/sceDisplay.cpp | 7 ++----- UI/EmuScreen.cpp | 8 +++++++- UI/NativeApp.cpp | 1 - Windows/KeyboardDevice.cpp | 20 +++---------------- Windows/WindowsHost.cpp | 3 +-- Windows/XinputDevice.cpp | 12 ++++++----- android/jni/TestRunner.cpp | 1 + .../src/org/ppsspp/ppsspp/PpssppActivity.java | 2 +- native | 2 +- 10 files changed, 27 insertions(+), 34 deletions(-) diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h index 1cd6e08f3f3d..5b9124860fef 100644 --- a/Core/CoreParameter.h +++ b/Core/CoreParameter.h @@ -33,7 +33,7 @@ enum GPUCore { struct CoreParameter { - CoreParameter() : collectEmuLog(0) {} + CoreParameter() : collectEmuLog(0), unthrottle(false) {} // 0 = Interpreter // 1 = Jit // 2 = JitIL @@ -63,4 +63,7 @@ struct CoreParameter // Actual pixel output resolution (for use by glViewport and the like) int pixelWidth; int pixelHeight; + + // Can be modified at runtime. + bool unthrottle; }; diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index df367a902127..177532a32885 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -300,11 +300,8 @@ void DebugStats() // Let's collect all the throttling and frameskipping logic here. void DoFrameTiming(bool &throttle, bool &skipFrame) { -#ifdef _WIN32 - throttle = !GetAsyncKeyState(VK_TAB); -#else - throttle = true; -#endif + throttle = !PSP_CoreParameter().unthrottle; + skipFrame = false; if (PSP_CoreParameter().headLess) throttle = false; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 500b211aed87..1a5368c2f132 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -207,7 +207,13 @@ void EmuScreen::update(InputState &input) { __CtrlSetAnalog(stick_x, stick_y); - if (input.pad_buttons_down & (PAD_BUTTON_MENU | PAD_BUTTON_BACK)) { + if (input.pad_buttons & PAD_BUTTON_LEFT_THUMB) { + PSP_CoreParameter().unthrottle = true; + } else { + PSP_CoreParameter().unthrottle = false; + } + + if (input.pad_buttons_down & (PAD_BUTTON_MENU | PAD_BUTTON_BACK | PAD_BUTTON_RIGHT_THUMB)) { if (g_Config.bBufferedRendering) fbo_unbind(); screenManager()->push(new PauseScreen()); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index a7fab39c4ed3..91b619359281 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -303,7 +303,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_directory, co void NativeInitGraphics() { - INFO_LOG(BOOT, "NativeInitGraphics - should only be called once!"); gl_lost_manager_init(); ui_draw2d.SetAtlas(&ui_atlas); diff --git a/Windows/KeyboardDevice.cpp b/Windows/KeyboardDevice.cpp index 1a6dbabc14d7..5df18f62046c 100644 --- a/Windows/KeyboardDevice.cpp +++ b/Windows/KeyboardDevice.cpp @@ -4,22 +4,8 @@ #include "../Core/HLE/sceCtrl.h" #include "WinUser.h" -static const unsigned short key_ctrl_map[] = { - VK_SPACE, CTRL_START, - 'V', CTRL_SELECT, - 'A', CTRL_SQUARE, - 'S', CTRL_TRIANGLE, - 'X', CTRL_CIRCLE, - 'Z', CTRL_CROSS, - 'Q', CTRL_LTRIGGER, - 'W', CTRL_RTRIGGER, - VK_UP, CTRL_UP, - VK_DOWN, CTRL_DOWN, - VK_LEFT, CTRL_LEFT, - VK_RIGHT, CTRL_RIGHT, -}; - -static const unsigned short key_pad_map[] = { +static const unsigned int key_pad_map[] = { + VK_TAB, PAD_BUTTON_LEFT_THUMB, VK_SPACE, PAD_BUTTON_START, 'V', PAD_BUTTON_SELECT, 'A', PAD_BUTTON_X, @@ -46,7 +32,7 @@ int KeyboardDevice::UpdateState(InputState &input_state) { static u32 alternator = 0; bool doAlternate = alternate && (alternator++ % 10) < 5; - for (int i = 0; i < sizeof(key_ctrl_map)/sizeof(key_ctrl_map[0]); i += 2) { + for (int i = 0; i < sizeof(key_pad_map)/sizeof(key_pad_map[0]); i += 2) { if (GetAsyncKeyState(key_pad_map[i]) && !doAlternate) { input_state.pad_buttons |= key_pad_map[i+1]; } diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 6ce7777e04aa..908a14d4fe03 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -132,8 +132,7 @@ void WindowsHost::SetDebugMode(bool mode) void WindowsHost::PollControllers(InputState &input_state) { for (auto iter = this->input.begin(); iter != this->input.end(); iter++) - if ((*iter)->UpdateState(input_state) == 0) - break; // *iter is std::shared_ptr, **iter is InputDevice + (*iter)->UpdateState(input_state); } void WindowsHost::BootDone() diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index b65e1fd0f99a..a9d104f6ccc8 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -85,7 +85,9 @@ static Stick NormalizedDeadzoneFilter(short x, short y) { return left; } -static const unsigned short xinput_ctrl_map[] = { +// Yes, this maps more than the PSP has, but that's fine as this lets us +// map buttons to extra functionality like speedup. +static const unsigned int xinput_ctrl_map[] = { XINPUT_GAMEPAD_DPAD_UP, PAD_BUTTON_UP, XINPUT_GAMEPAD_DPAD_DOWN, PAD_BUTTON_DOWN, XINPUT_GAMEPAD_DPAD_LEFT, PAD_BUTTON_LEFT, @@ -98,7 +100,10 @@ static const unsigned short xinput_ctrl_map[] = { XINPUT_GAMEPAD_B, PAD_BUTTON_B, XINPUT_GAMEPAD_X, PAD_BUTTON_X, XINPUT_GAMEPAD_Y, PAD_BUTTON_Y, + XINPUT_GAMEPAD_LEFT_THUMB, PAD_BUTTON_LEFT_THUMB, + XINPUT_GAMEPAD_RIGHT_THUMB, PAD_BUTTON_RIGHT_THUMB, }; + static inline u32 CtrlForXinput(int xinput) { for (int i = 0; i < sizeof(xinput_ctrl_map)/sizeof(xinput_ctrl_map[0]); i += 2) if (xinput_ctrl_map[i] == xinput) return (u32) xinput_ctrl_map[i+1]; @@ -106,11 +111,8 @@ static inline u32 CtrlForXinput(int xinput) { } void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) { - unsigned short pressed = state.Gamepad.wButtons & ~this->prevState.Gamepad.wButtons; - unsigned short released = ~state.Gamepad.wButtons & this->prevState.Gamepad.wButtons; - for (int i = 1; i < USHRT_MAX; i <<= 1) { - if (pressed & i) + if (state.Gamepad.wButtons & i) input_state.pad_buttons |= CtrlForXinput(i); } } \ No newline at end of file diff --git a/android/jni/TestRunner.cpp b/android/jni/TestRunner.cpp index 7e0c6de73057..dd65b0af83aa 100644 --- a/android/jni/TestRunner.cpp +++ b/android/jni/TestRunner.cpp @@ -70,6 +70,7 @@ void RunTests() coreParam.pixelHeight = 272; coreParam.useMediaEngine = false; coreParam.collectEmuLog = &output; + coreParam.unthrottle = true; #ifdef IOS std::string baseDirectory = g_Config.flashDirectory + "../"; diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index bd47aac3072c..005b5075a7c7 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -16,4 +16,4 @@ public boolean overrideKeys() return false; } } - \ No newline at end of file + \ No newline at end of file diff --git a/native b/native index 22e648bb1a5e..79e14282ecf0 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit 22e648bb1a5e8fe6e427efc906194edbb9ce6ed8 +Subproject commit 79e14282ecf006caef6fe12d19358952741ad7fc From bd413d4caf6705f2b5df8f90b7d04d6e9ec032a7 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 31 Mar 2013 18:09:27 +0800 Subject: [PATCH 32/34] Revert sceKernelSysClock2USec() --- Core/HLE/sceKernelTime.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Core/HLE/sceKernelTime.cpp b/Core/HLE/sceKernelTime.cpp index 9090adf2ede2..072d7ede7e17 100644 --- a/Core/HLE/sceKernelTime.cpp +++ b/Core/HLE/sceKernelTime.cpp @@ -99,17 +99,16 @@ u64 sceKernelUSec2SysClockWide(u32 usec) return usec; } -int sceKernelSysClock2USec(u32 sysclockPtr, u32 lowPtr, u32 highPtr) +int sceKernelSysClock2USec(u32 sysclockPtr, u32 highPtr, u32 lowPtr) { DEBUG_LOG(HLE, "sceKernelSysClock2USec(clock = %08x, lo = %08x, hi = %08x)", sysclockPtr, highPtr, lowPtr); - u64 sysClock = Memory::Read_U64(sysclockPtr); - if (Memory::IsValidAddress(lowPtr)) { - Memory::Write_U32((u32)(sysClock / 1000000), lowPtr); - if (Memory::IsValidAddress(highPtr)) - Memory::Write_U32((u32)(sysClock % 1000000), highPtr); - } else - if (Memory::IsValidAddress(highPtr)) - Memory::Write_U32((int) sysClock, highPtr); + u64 time = Memory::Read_U64(sysclockPtr); + u32 highResult = (u32)(time / 1000000); + u32 lowResult = (u32)(time % 1000000); + if (Memory::IsValidAddress(highPtr)) + Memory::Write_U32(highResult, highPtr); + if (Memory::IsValidAddress(lowPtr)) + Memory::Write_U32(lowResult, lowPtr); hleEatCycles(2 * 222); return 0; } From 44925416674017583596f81dafc8ff16b3ab4a53 Mon Sep 17 00:00:00 2001 From: raven02 Date: Sun, 31 Mar 2013 18:42:21 +0800 Subject: [PATCH 33/34] Better align title with game icon in pause screen --- UI/MenuScreens.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index e50994426ca7..380ec43ecf74 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -324,7 +324,7 @@ void PauseScreen::render() { ctx->RebindTexture(); } - ui_draw2d.DrawText(UBUNTU48, title, dp_xres / 2, 30, 0xFFFFFFFF, ALIGN_HCENTER); + ui_draw2d.DrawText(UBUNTU48, title, 10+144+10, 30, 0xFFFFFFFF, ALIGN_LEFT); int x = 30; int y = 50; From 3bd5146fbfb0981b9d812dde3de121b535ddb0e4 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sun, 31 Mar 2013 14:21:04 +0200 Subject: [PATCH 34/34] iOS: Try to fix analog stick getting stuck. Blind fix :) --- Core/Core.cpp | 2 ++ ios/ViewController.mm | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/Core/Core.cpp b/Core/Core.cpp index ceaaa1ece975..a4e2211a89cf 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -108,6 +108,8 @@ void Core_RunLoop() input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; + input_state.pad_rstick_x = 0; + input_state.pad_rstick_y = 0; // Temporary hack. if (GetAsyncKeyState(VK_ESCAPE)) { input_state.pad_buttons |= PAD_BUTTON_MENU; diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 8e44b7410523..a41b97ebeb03 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -167,6 +167,10 @@ - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect lock_guard guard(input_state.lock); pad_buttons_down |= pad_buttons_async_set; pad_buttons_down &= ~pad_buttons_async_clear; + input_state.pad_lstick_x = 0; + input_state.pad_lstick_y = 0; + input_state.pad_rstick_x = 0; + input_state.pad_rstick_y = 0; input_state.pad_buttons = pad_buttons_down; UpdateInputState(&input_state); }