From 952a937fe7d98059fc4a218be16f36b5f14ca6d7 Mon Sep 17 00:00:00 2001 From: Florent Castelli Date: Sun, 2 Dec 2012 02:58:00 +0100 Subject: [PATCH 01/35] Revert changes in RC file that were breaking debug build on Windows. If the build isn't working on VS Express, notify me so we can find a fix. --- Windows/ppsspp.rc | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 7415576c8f..2af9a1b0d2 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -235,6 +235,62 @@ END ///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Swedish (Sweden) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE) +LANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_POPUPMENUS MENU +BEGIN + POPUP "memview" + BEGIN + MENUITEM "Go to in &Disasm", ID_MEMVIEW_GOTOINDISASM + MENUITEM SEPARATOR + MENUITEM "&Copy value", ID_MEMVIEW_COPYVALUE + MENUITEM "&Dump...", ID_MEMVIEW_DUMP + END + POPUP "disasm" + BEGIN + MENUITEM "Copy &address", ID_DISASM_COPYADDRESS + MENUITEM "Copy instruction (&hex)", ID_DISASM_COPYINSTRUCTIONHEX + MENUITEM "Copy instruction (&disasm)", ID_DISASM_COPYINSTRUCTIONDISASM + MENUITEM SEPARATOR + MENUITEM "&Run to here", ID_DISASM_RUNTOHERE + MENUITEM "&Set Next Statement", ID_DISASM_SETPCTOHERE + MENUITEM "&Toggle breakpoint", ID_DISASM_TOGGLEBREAKPOINT + MENUITEM "&Follow branch", ID_DISASM_FOLLOWBRANCH + MENUITEM SEPARATOR + MENUITEM "&Show Dynarec Results", ID_DISASM_DYNARECRESULTS + MENUITEM "Go to in &Memory View", ID_DISASM_GOTOINMEMORYVIEW + MENUITEM SEPARATOR + MENUITEM "&Kill function", ID_DISASM_ADDHLE + MENUITEM "&Rename function...", ID_DISASM_RENAMEFUNCTION + END + POPUP "funclist" + BEGIN + MENUITEM "&Kill function", ID_FUNCLIST_KILLFUNCTION + END + POPUP "reglist" + BEGIN + MENUITEM "Go to in &memory view", ID_REGLIST_GOTOINMEMORYVIEW + MENUITEM "Go to in &disasm", ID_REGLIST_GOTOINDISASM + MENUITEM SEPARATOR + MENUITEM "&Copy value", ID_REGLIST_COPYVALUE + MENUITEM "C&hange...", ID_REGLIST_CHANGE + END +END + + ///////////////////////////////////////////////////////////////////////////// // // RT_MANIFEST @@ -307,6 +363,25 @@ END ///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE +BEGIN + IDS_GAMELISTPATH "Path" + IDS_UNIMPLEMENTED "Unimplemented" +END + +STRINGTABLE +BEGIN + IDS_GAMELISTGENRE "Genre" + IDS_APPNAME "Potemkin" + IDS_GAMELISTTYPE "Type" +END + +#endif // Swedish (Sweden) resources +///////////////////////////////////////////////////////////////////////////// From 5316f856d1cf2b520c1c0077abb09360c657e124 Mon Sep 17 00:00:00 2001 From: Sacha Date: Sun, 2 Dec 2012 14:48:00 +1000 Subject: [PATCH 02/35] Blackberry 10 Port * Replace SDL with asound backend (removes the only dependency) * Remove all references to SDL in bar-descriptor.xml, blackberry_build.sh * Greatly simplify blackberry_build.sh * Modify CMakeLists.txt to account for removal of SDL * Remove redundancy in CMakeLists.txt (EGLv2) * Refactor nativeExtra's and setting targets * Remove android/CMakeLists.txt (unrelated file) * Update for latest Blackberry NDK (1088) * Handle bug with VSync in latest NDK * Update bar-descriptor.xml to version 0.4 * Fix define on iOS in FragmentShaderGenerator.cpp * Specify NDK used in Credits by target platform, add contributor, remove redundancy --- CMakeLists.txt | 81 ++++++++++----------- GPU/GLES/FragmentShaderGenerator.cpp | 13 ++-- SDL/bar-descriptor.xml | 6 +- SDL/blackberry_build.sh | 41 +---------- android/CMakeLists.txt | 104 --------------------------- android/jni/MenuScreens.cpp | 9 ++- 6 files changed, 56 insertions(+), 198 deletions(-) delete mode 100644 android/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index e4a2362661..b1f98c2577 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,9 @@ if(USING_GLES2) else() include(FindOpenGL REQUIRED) endif() -include(FindSDL) +if (NOT BLACKBERRY AND NOT ANDROID) + include(FindSDL) +endif() include(FindThreads) if(APPLE) find_library(COCOA_LIBRARY Cocoa) @@ -365,6 +367,7 @@ if(ANDROID) endif() set(nativeExtra) +set(nativeExtraLibs) if(ANDROID) set(nativeExtra ${nativeExtra} native/base/NativeApp.h @@ -376,10 +379,25 @@ if(ANDROID) native/android/native-audio-so.cpp native/android/native-audio-so.h) target_link_libraries(native_audio OpenSLES) -endif() -if(BLACKBERRY) - set(nativeExtra ${nativeExtra} - native/base/BlackberryMain.cpp) + # No target +elseif(BLACKBERRY) + set(nativeExtra ${nativeExtra} native/base/BlackberryMain.cpp) + set(nativeExtraLibs ${nativeExtraLibs} asound bps screen socket EGL) + set(TargetBin PPSSPPBlackberry) +elseif(SDL_FOUND) +# Require SDL + include_directories(${SDL_INCLUDE_DIR}) + set(nativeExtra ${nativeExtra} native/base/PCMain.cpp) + set(nativeExtraLibs ${nativeExtraLibs} ${SDL_LIBRARY}) + if(APPLE) + set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm) + set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY}) + endif() + if(NOT IOS) # No target + set(TargetBin PPSSPPSDL) + endif() +else() + message(FATAL_ERROR "Could not find SDL. Failing.") endif() if(X86) @@ -409,7 +427,6 @@ add_library(native STATIC native/base/linked_ptr.h native/base/logging.h native/base/mutex.h -# native/base/PCMain.cpp native/base/scoped_ptr.h native/base/stats.h native/base/stringutil.cpp @@ -826,43 +843,23 @@ if(HEADLESS) setup_target_project(PPSSPPHeadless headless) endif() -if(SDL_FOUND) - include_directories(${SDL_INCLUDE_DIR}) +set(NativeAppSource + android/jni/NativeApp.cpp + android/jni/EmuScreen.cpp + android/jni/MenuScreens.cpp + android/jni/GamepadEmu.cpp + android/jni/UIShader.cpp + android/jni/ui_atlas.cpp) +set(AndroidAssets + android/assets/ui_atlas.zim + android/assets/ppge_atlas.zim) +set(LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT} ${nativeExtraLibs}) - set(NativeAppSource - android/jni/NativeApp.cpp - android/jni/EmuScreen.cpp - android/jni/MenuScreens.cpp - android/jni/GamepadEmu.cpp - android/jni/UIShader.cpp - android/jni/ui_atlas.cpp) - set(AndroidAssets - android/assets/ui_atlas.zim - android/assets/ppge_atlas.zim) - set(LinkCommon ${CoreLibName} - ${SDL_LIBRARY} ${CMAKE_THREAD_LIBS_INIT}) - - if(BLACKBERRY) - add_executable(PPSSPPBlackberry native/base/BlackberryMain.cpp ${NativeAppSource}) - target_link_libraries(PPSSPPBlackberry ${LinkCommon} bps screen socket EGL GLESv2) - elseif(ANDROID) - # no target - elseif(IOS) - # no target - else() - set(SDL_Main native/base/PCMain.cpp) - if(APPLE) - set(SDL_Main ${SDL_Main} - SDL/SDLMain.h - SDL/SDLMain.mm) - set(LinkCommon ${LinkCommon} ${COCOA_LIBRARY}) - endif() - - add_executable(PPSSPPSDL ${SDL_Main} ${NativeAppSource}) - target_link_libraries(PPSSPPSDL ${LinkCommon}) - endif() - - file(INSTALL ${AndroidAssets} DESTINATION assets) +if (TargetBin) + add_executable(${TargetBin} ${NativeAppSource}) + target_link_libraries(${TargetBin} ${LinkCommon}) endif() +file(INSTALL ${AndroidAssets} DESTINATION assets) + #include(CPack) diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index b225c299bf..6dbbb39fa8 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -19,6 +19,12 @@ #define GLSL_ES_1_0 #else #define GLSL_1_3 + +// SDL 1.2 on Apple does not have support for OpenGL 3 and hence needs +// special treatment in the shader generator. +#if defined(__APPLE__) +#define FORCE_OPENGL_2_0 +#endif #endif @@ -30,13 +36,6 @@ // TODO: remove static char buffer[16384]; -// SDL 1.2 on Apple does not have support for OpenGL 3 and hence needs -// special treatment in the shader generator. -#ifdef __APPLE__ -#define FORCE_OPENGL_2_0 -#endif - - #define WRITE p+=sprintf // GL_NV_shader_framebuffer_fetch looks interesting.... diff --git a/SDL/bar-descriptor.xml b/SDL/bar-descriptor.xml index 25c2f82a77..13e3b2e56b 100644 --- a/SDL/bar-descriptor.xml +++ b/SDL/bar-descriptor.xml @@ -3,7 +3,7 @@ com.Qtness.PPSSPP PPSSPP PPSSPPBlackberry - 0.31 + 0.4 1 Playstation portable emulator. @@ -20,8 +20,6 @@ PPSSPPBlackberry icon-114.png assets - lib/libSDL12.so - lib/libTouchControlOverlay.so core.games @@ -33,6 +31,4 @@ run_native access_shared play_audio - - diff --git a/SDL/blackberry_build.sh b/SDL/blackberry_build.sh index 5ef80f155d..89d2c98423 100755 --- a/SDL/blackberry_build.sh +++ b/SDL/blackberry_build.sh @@ -7,45 +7,8 @@ if [ -z "$BB_OS" ]; then fi echo "Building for Blackberry ${BB_OS}" -PPSSPP_ROOT=${PWD}/.. -if [ -z "$PROJECT_ROOT" ]; then - PROJECT_ROOT=${PPSSPP_ROOT}/.. -fi -if [ -z "$SDL_PROJECT" ]; then - SDL_PROJECT="$PROJECT_ROOT/SDL" -fi -if [ -z "$TCO_PROJECT" ]; then - TCO_PROJECT="$PROJECT_ROOT/TouchControlOverlay" -fi - -while true; do - case "$1" in - -h | --help ) - echo "Build script for BlackBerry" - echo - echo "Options: " - echo " -h, --help Show this help message." - echo " -p, --project-root PATH Specify the root directory containing all projects. (default is PPSSPP's parent)" - echo "Dependency Paths (defaults are under project root): " - echo " --sdl PATH SDL 1.2 project directory (default is SDL)" - echo " --tco PATH TouchControlOverlay project directory (default is TouchControlOverlay)" - exit 0 - ;; - -p | --project-root ) PROJECT_ROOT="$2"; shift 2 ;; - --sdl ) SDL_PROJECT="$2"; shift 2 ;; - --tco ) TCO_PROJECT="$2"; shift 2 ;; - -- ) shift; break ;; - * ) break ;; - esac -done - -cmake \ --DCMAKE_C_COMPILER="${QNX_HOST}/usr/bin/ntoarmv7-gcc" \ --DCMAKE_CXX_COMPILER="${QNX_HOST}/usr/bin/ntoarmv7-g++" \ --DSDL_INCLUDE_DIR="${SDL_PROJECT}/include" \ --DSDL_LIBRARY="${SDL_PROJECT}/Device-Release/libSDL12.so;${TCO_PROJECT}/Device-Release/libTouchControlOverlay.so" \ --DBLACKBERRY=${BB_OS} \ -${PPSSPP_ROOT} +# Set up cmake with GCC 4.6.3 cross-compiler from PATH +CC=ntoarmv7-gcc CXX=ntoarmv7-g++ cmake -DBLACKBERRY=${BB_OS} .. # Compile and create unsigned PPSSPP.bar with debugtoken DEBUG="-devMode -debugToken ${HOME}/debugtoken.bar" diff --git a/android/CMakeLists.txt b/android/CMakeLists.txt deleted file mode 100644 index 19378678b3..0000000000 --- a/android/CMakeLists.txt +++ /dev/null @@ -1,104 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -project (PPSSPP) - -find_package(PkgConfig) - -find_package(PNG REQUIRED) -pkg_check_modules(SDL sdl) - -if (APPLE) - find_library(OGL_LIBRARY OpenGL) - include_directories(/usr/X11/include) -endif() - - -include(FindOpenGL) -include(FindSDL) - -add_definitions(-g) -add_definitions(-O0) -add_definitions(-Wall) -add_definitions(-DSDL) -add_definitions(-Wno-multichar) -add_definitions(-fno-strict-aliasing) -add_definitions(-DUSE_PROFILER) - -include_directories(jni) -include_directories(../native) -include_directories(../native/base) -include_directories(../native/math/lin) -include_directories(../native/audio) -include_directories(../native/ext/libzip) -include_directories(../native/ext/etcpack) -include_directories(/usr/local/include) -include_directories(${SDL_INCLUDE_DIR}) -include_directories(${PNG_INCLUDE_DIR}) - -link_directories(/usr/local/lib) -link_directories(/usr/X11/lib) - -add_subdirectory(../native/base base) -add_subdirectory(../native/gfx gfx) -add_subdirectory(../native/profiler profiler) -add_subdirectory(../native/gfx_es2 gfx_es2) -add_subdirectory(../native/file file) -add_subdirectory(../native/image image) -add_subdirectory(../native/ui ui) -add_subdirectory(../native/net net) -add_subdirectory(../native/json jsonwriter) -add_subdirectory(../native/audio audio) -add_subdirectory(../native/math math) -add_subdirectory(../native/ext/libzip libzip) -add_subdirectory(../native/ext/etcpack etcpack) -add_subdirectory(../native/ext/vjson vjson) -add_subdirectory(../native/ext/stb_vorbis stb_vorbis) -add_subdirectory(../native/ext/sha1 sha1) - -set(LIBS ${LIBS} ${SDL_LIBRARY} ${OPENGL_LIBRARIES} GLEW file lin ${PNG_LIBRARY} z gfx gfx_es2 ui etcdec image mixer net profiler timeutil file zip base lin vjson stb_vorbis sha1 jsonwriter) - -set(FILES - jni/ui_atlas.cpp - jni/ray_intersections.cpp - jni/collision.cpp - jni/AudioManager.cpp - jni/Campaign.cpp - jni/CampaignEndScreen.cpp - jni/CalibrateScreen.cpp - jni/CreditsScreen.cpp - jni/Curves.cpp - jni/CollidableMesh.cpp - jni/DrawList.cpp - jni/Globals.cpp - jni/Level.cpp - jni/CampaignEndScreen.cpp - jni/Material.cpp - jni/MainMenuScreen.cpp - jni/MessageBus.cpp - jni/Mesh.cpp - jni/MeshGenerator.cpp - jni/NativeApp.cpp - jni/GfxUtil.cpp - jni/GfxWrapper.cpp - jni/BallSimulator.cpp - jni/Node.cpp - jni/NormalGame.cpp - jni/NormalGameScreen.cpp - jni/Scene.cpp - jni/Sky.cpp - jni/ShaderManager.cpp - jni/StickSim.cpp - jni/TextureManager.cpp - jni/Transformation.cpp) - -if (APPLE) - SET(FILES ${FILES} jni/SDLMain.m) -endif (APPLE) - -add_executable(rollerball ../native/base/PCMain.cpp ${FILES}) - -target_link_libraries(rollerball ${LIBS}) - -#add_executable(meshtool jni/Meshtool.cpp ${FILES}) - -#target_link_libraries(meshtool ${LIBS}) diff --git a/android/jni/MenuScreens.cpp b/android/jni/MenuScreens.cpp index 9fc656b229..f98f6986af 100644 --- a/android/jni/MenuScreens.cpp +++ b/android/jni/MenuScreens.cpp @@ -376,16 +376,23 @@ static const char *credits[] = "ced2911", "soywiz", "kovensky", + "xsacha", "", "Written in C++ for speed and portability", "", "", "Free tools used:", +#ifdef ANDROID "Android SDK + NDK", +#elif BLACKBERRY + "Blackberry NDK", +#else + "SDL", +#endif "CMake", "freetype2", "zlib", - "the free PSP SDK", + "PSP SDK", "", "", "Check out the website:", From f3e23f2672e6f006d3f225e83cf3a3bf3bf22b7c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 16:40:13 -0800 Subject: [PATCH 03/35] Add some asserts for activating UMDs. --- Core/HLE/sceUmd.cpp | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 81929ca7e6..637f34ef26 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -20,6 +20,8 @@ #include "sceUmd.h" #include "sceKernelThread.h" +const int PSP_ERROR_UMD_INVALID_PORT = 0x80010016; + #define UMD_NOT_PRESENT 0x01 #define UMD_PRESENT 0x02 #define UMD_CHANGED 0x04 @@ -76,11 +78,11 @@ void __KernelUmdDeactivate() //int sceUmdCheckMedium(int a); -void sceUmdCheckMedium() +int sceUmdCheckMedium() { DEBUG_LOG(HLE,"1=sceUmdCheckMedium(?)"); //ignore PARAM(0) - RETURN(1); //non-zero: disc in drive + return 1; //non-zero: disc in drive } void sceUmdGetDiscInfo() @@ -98,9 +100,21 @@ void sceUmdGetDiscInfo() u32 sceUmdActivate(u32 unknown, const char *name) { + if (unknown < 1 || unknown > 2) + return PSP_ERROR_UMD_INVALID_PORT; + u32 retVal = 0; __KernelUmdActivate(); - DEBUG_LOG(HLE,"%i=sceUmdActivate(%08x, %s)", retVal, unknown, name); + + if (unknown == 1) + { + DEBUG_LOG(HLE, "%i=sceUmdActivate(%d, %s)", retVal, unknown, name); + } + else + { + ERROR_LOG(HLE, "UNTESTED %i=sceUmdActivate(%d, %s)", retVal, unknown, name); + } + u32 notifyArg = UMD_PRESENT | UMD_READABLE; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); return retVal; @@ -108,7 +122,19 @@ u32 sceUmdActivate(u32 unknown, const char *name) u32 sceUmdDeactivate(u32 unknown, const char *name) { - DEBUG_LOG(HLE,"sceUmdDeactivate()"); + // Why 18? No idea. + if (unknown < 0 || unknown > 18) + return PSP_ERROR_UMD_INVALID_PORT; + + if (unknown == 1) + { + DEBUG_LOG(HLE, "0=sceUmdDeactivate(%d, %s)", unknown, name); + } + else + { + ERROR_LOG(HLE, "UNTESTED 0=sceUmdDeactivate(%d, %s)", unknown, name); + } + u8 triggerCallback = umdActivated; __KernelUmdDeactivate(); @@ -210,7 +236,7 @@ const HLEFunction sceUmdUser[] = { {0xC6183D47,&WrapU_UC,"sceUmdActivate"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, - {0x46EBB729,sceUmdCheckMedium,"sceUmdCheckMedium"}, + {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, {0xE83742BA,&WrapU_UC,"sceUmdDeactivate"}, {0x8EF08FCE,sceUmdWaitDriveStat,"sceUmdWaitDriveStat"}, {0x56202973,sceUmdWaitDriveStatWithTimer,"sceUmdWaitDriveStatWithTimer"}, From c00f3dcdd852dc3265e6a75cc91953686a75235a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 17:09:03 -0800 Subject: [PATCH 04/35] Implement sceUmdCancelWaitDriveStat(). --- Core/HLE/sceKernelThread.cpp | 14 +++++++++++++- Core/HLE/sceKernelThread.h | 1 + Core/HLE/sceUmd.cpp | 5 +++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 3d15e657b9..03a0e28f93 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -608,7 +608,7 @@ u32 __KernelResumeThreadFromWait(SceUID threadID, int retval) // Only run when you can safely accept a context switch // Triggers a waitable event, that is, it wakes up all threads that waits for it // If any changes were made, it will context switch -bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) +bool __KernelTriggerWait(WaitType type, int id, bool useRetVal, int retVal, bool dontSwitch) { bool doneAnything = false; @@ -621,6 +621,8 @@ bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) { // This thread was waiting for the triggered object. __KernelResumeThreadFromWait(t); + if (useRetVal) + t->setReturnValue(retVal); doneAnything = true; } } @@ -639,6 +641,16 @@ bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) return true; } +bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch) +{ + return __KernelTriggerWait(type, id, false, 0, dontSwitch); +} + +bool __KernelTriggerWait(WaitType type, int id, int retVal, bool dontSwitch) +{ + return __KernelTriggerWait(type, id, true, retVal, dontSwitch); +} + // makes the current thread wait for an event void __KernelWaitCurThread(WaitType type, SceUID waitID, u32 waitValue, u32 timeoutPtr, bool processCallbacks) { diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 4e80b2afaf..f9093c0a9a 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -104,6 +104,7 @@ void __KernelLoadContext(ThreadContext *ctx); // TODO: Replace this with __KernelResumeThread over time as it's misguided. bool __KernelTriggerWait(WaitType type, int id, bool dontSwitch = false); +bool __KernelTriggerWait(WaitType type, int id, int retVal, bool dontSwitch); u32 __KernelResumeThreadFromWait(SceUID threadID); // can return an error value u32 __KernelResumeThreadFromWait(SceUID threadID, int retval); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 637f34ef26..e7ff30faac 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -220,9 +220,10 @@ void sceUmdWaitDriveStatCB() void sceUmdCancelWaitDriveStat() { - u32 stat = PARAM(0); - ERROR_LOG(HLE,"UNIMPL 0=sceUmdCancelWaitDriveStat(stat = %08x)", stat); + DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()"); RETURN(0); + + __KernelTriggerWait(WAITTYPE_UMD, 0, SCE_KERNEL_ERROR_WAIT_CANCEL, false); } u32 sceUmdGetErrorStat() From 4abcb6a8acdfcad29084da723f77e92ae8270c1b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 18:43:45 -0800 Subject: [PATCH 05/35] Fix sceUmdWaitDriveStatCB() so it fires right away. This makes Crisis Core actually show loading again. --- Core/HLE/sceKernelThread.cpp | 11 ++++++++- Core/HLE/sceKernelThread.h | 1 + Core/HLE/sceUmd.cpp | 46 ++++++++++++++++++++---------------- 3 files changed, 36 insertions(+), 22 deletions(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 03a0e28f93..509fd6e12f 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1811,7 +1811,8 @@ bool __KernelCheckCallbacks() { return processed; } -void sceKernelCheckCallback() { +bool __KernelForceCallbacks() +{ Thread *curThread = __GetCurrentThread(); // This thread can now process callbacks. @@ -1822,6 +1823,14 @@ void sceKernelCheckCallback() { // Note - same thread as above - checking callbacks may switch threads. curThread->isProcessingCallbacks = false; + return callbacksProcessed; +} + +void sceKernelCheckCallback() { + Thread *curThread = __GetCurrentThread(); + + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) { curThread->setReturnValue(1); ERROR_LOG(HLE,"sceKernelCheckCallback() - processed a callback."); diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index f9093c0a9a..36ec19c244 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -164,6 +164,7 @@ bool __KernelInCallback(); // Should be called by (nearly) all ...CB functions. bool __KernelCheckCallbacks(); +bool __KernelForceCallbacks(); class Thread; void __KernelSwitchContext(Thread *target, const char *reason); bool __KernelExecutePendingMipsCalls(); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index e7ff30faac..8624f3795b 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -181,41 +181,45 @@ u32 sceUmdGetDriveStat() * @return < 0 on error * */ -void sceUmdWaitDriveStat() +void sceUmdWaitDriveStat(u32 stat) { - u32 stat = PARAM(0); - DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat); - if ((stat & __KernelUmdGetState()) != stat) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat); RETURN(0); + + if ((stat & __KernelUmdGetState()) == 0) + __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); } -void sceUmdWaitDriveStatWithTimer() +void sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { - u32 stat = PARAM(0); - u32 timeout = PARAM(1); - DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x)", stat); - if ((stat & __KernelUmdGetState()) != stat) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %08x)", stat, timeout); RETURN(0); + + // TODO: timeout? + if ((stat & __KernelUmdGetState()) == 0) + __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); } -void sceUmdWaitDriveStatCB() +void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - u32 stat = PARAM(0); - DEBUG_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x)", stat); - // Immediately notify - RETURN(0); + ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %08x)", stat, timeout); + RETURN(0); + + // TODO: wait and timeout? + if (driveCBId != -1) { - __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, driveCBId, __KernelUmdGetState()&stat); + // TODO: This is probably the unknown parameter from sceUmdActivate()? + __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, 1, __KernelUmdGetState()); + bool callbacksProcessed = __KernelForceCallbacks(); + if (callbacksProcessed) + __KernelExecutePendingMipsCalls(); } else { ERROR_LOG(HLE, "HACK 0=sceUmdWaitDriveStatCB(stat = %08x) attempting to call unset callback", stat); } - RETURN(0); } void sceUmdCancelWaitDriveStat() @@ -239,9 +243,9 @@ const HLEFunction sceUmdUser[] = {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, {0xE83742BA,&WrapU_UC,"sceUmdDeactivate"}, - {0x8EF08FCE,sceUmdWaitDriveStat,"sceUmdWaitDriveStat"}, - {0x56202973,sceUmdWaitDriveStatWithTimer,"sceUmdWaitDriveStatWithTimer"}, - {0x4A9E5E29,sceUmdWaitDriveStatCB,"sceUmdWaitDriveStatCB"}, + {0x8EF08FCE,WrapV_U,"sceUmdWaitDriveStat"}, + {0x56202973,WrapV_UU,"sceUmdWaitDriveStatWithTimer"}, + {0x4A9E5E29,WrapV_UU,"sceUmdWaitDriveStatCB"}, {0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x20628E6F,&WrapU_V,"sceUmdGetErrorStat"}, From 1142ad3ec6250224f15271e0424afff1b36c6919 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 22:05:35 -0800 Subject: [PATCH 06/35] sceUmdDeactivate() seems to always schedule a cb. --- Core/HLE/sceUmd.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 8624f3795b..4a1c579886 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -126,6 +126,8 @@ u32 sceUmdDeactivate(u32 unknown, const char *name) if (unknown < 0 || unknown > 18) return PSP_ERROR_UMD_INVALID_PORT; + __KernelUmdDeactivate(); + if (unknown == 1) { DEBUG_LOG(HLE, "0=sceUmdDeactivate(%d, %s)", unknown, name); @@ -135,13 +137,8 @@ u32 sceUmdDeactivate(u32 unknown, const char *name) ERROR_LOG(HLE, "UNTESTED 0=sceUmdDeactivate(%d, %s)", unknown, name); } - u8 triggerCallback = umdActivated; - __KernelUmdDeactivate(); - - if (triggerCallback) { - u32 notifyArg = UMD_PRESENT | UMD_READY; - __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - } + u32 notifyArg = UMD_PRESENT | UMD_READY; + __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); return 0; } From eaaedc7adc877461e0e6b5c7e616caa10a4fe313 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 22:10:33 -0800 Subject: [PATCH 07/35] This notify isn't needed and was broken anyway. --- Core/HLE/sceUmd.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 4a1c579886..6fdc1f51ca 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -207,8 +207,6 @@ void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) if (driveCBId != -1) { - // TODO: This is probably the unknown parameter from sceUmdActivate()? - __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, 1, __KernelUmdGetState()); bool callbacksProcessed = __KernelForceCallbacks(); if (callbacksProcessed) __KernelExecutePendingMipsCalls(); From 16c29a52a8f02d389563b52e01ae31de5a99ab39 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 22:13:58 -0800 Subject: [PATCH 08/35] Improve debugging for bad callback ids. --- Core/HLE/sceKernelThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index 509fd6e12f..fb623ef17e 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -1877,7 +1877,7 @@ void __KernelNotifyCallback(RegisteredCallbackType type, SceUID threadId, SceUID Callback *cb = kernelObjects.Get(cbId, error); if (!cb) { // Yeah, we're screwed, this shouldn't happen. - ERROR_LOG(HLE, "__KernelNotifyCallback - invalid callback 0"); + ERROR_LOG(HLE, "__KernelNotifyCallback - invalid callback %08x", cbId); return; } cb->nc.notifyCount++; From 00ca9d8dc7dba6e8fbd8d46c2d817fd9230b1811 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 23:05:03 -0800 Subject: [PATCH 09/35] Make the UMD wait funcs actually wait. --- Core/HLE/sceKernelMutex.cpp | 11 +++++-- Core/HLE/sceUmd.cpp | 60 ++++++++++++++++++++++++++++++------- 2 files changed, 59 insertions(+), 12 deletions(-) diff --git a/Core/HLE/sceKernelMutex.cpp b/Core/HLE/sceKernelMutex.cpp index bf024fbd44..647650b027 100644 --- a/Core/HLE/sceKernelMutex.cpp +++ b/Core/HLE/sceKernelMutex.cpp @@ -374,8 +374,15 @@ void __KernelWaitMutex(Mutex *mutex, u32 timeoutPtr) if (timeoutPtr == 0 || mutexWaitTimer == 0) return; - // This should call __KernelMutexTimeout() later, unless we cancel it. int micro = (int) Memory::Read_U32(timeoutPtr); + + // This happens to be how the hardware seems to time things. + if (micro <= 3) + micro = 15; + else if (micro <= 249) + micro = 250; + + // This should call __KernelMutexTimeout() later, unless we cancel it. CoreTiming::ScheduleEvent(usToCycles(micro), mutexWaitTimer, __KernelGetCurThread()); } @@ -701,7 +708,7 @@ void __KernelWaitLwMutex(LwMutex *mutex, u32 timeoutPtr) else if (micro <= 249) micro = 250; - // This should call __KernelMutexTimeout() later, unless we cancel it. + // This should call __KernelLwMutexTimeout() later, unless we cancel it. CoreTiming::ScheduleEvent(usToCycles(micro), lwMutexWaitTimer, __KernelGetCurThread()); } diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 6fdc1f51ca..9c13c7d464 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -17,6 +17,7 @@ #include "HLE.h" #include "../MIPS/MIPS.h" +#include "../../Core/CoreTiming.h" #include "sceUmd.h" #include "sceKernelThread.h" @@ -34,6 +35,7 @@ u8 umdActivated = 1; u32 umdStatus = 0; u32 umdErrorStat = 0; static int driveCBId= -1; +int umdStatTimer = 0; #define PSP_UMD_TYPE_GAME 0x10 @@ -171,6 +173,31 @@ u32 sceUmdGetDriveStat() return retVal; } +void __UmdStatTimeout(u64 userdata, int cyclesLate) +{ + SceUID threadID = (SceUID)userdata; + + u32 error; + SceUID waitID = __KernelGetWaitID(threadID, WAITTYPE_UMD, error); + // Assuming it's still waiting. + if (waitID == 1) + __KernelResumeThreadFromWait(threadID, SCE_KERNEL_ERROR_WAIT_TIMEOUT); +} + +void __UmdWaitStat(u32 timeout) +{ + if (umdStatTimer == 0) + umdStatTimer = CoreTiming::RegisterEvent("MutexTimeout", &__UmdStatTimeout); + + // This happens to be how the hardware seems to time things. + if (timeout <= 4) + timeout = 15; + else if (timeout <= 215) + timeout = 250; + + CoreTiming::ScheduleEvent(usToCycles((int) timeout), umdStatTimer, __KernelGetCurThread()); +} + /** * Wait for a drive to reach a certain state * @@ -180,40 +207,51 @@ u32 sceUmdGetDriveStat() */ void sceUmdWaitDriveStat(u32 stat) { - ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStat(stat = %08x)", stat); + DEBUG_LOG(HLE,"0=sceUmdWaitDriveStat(stat = %08x)", stat); RETURN(0); if ((stat & __KernelUmdGetState()) == 0) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0); } void sceUmdWaitDriveStatWithTimer(u32 stat, u32 timeout) { - ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %08x)", stat, timeout); + DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatWithTimer(stat = %08x, timeout = %d)", stat, timeout); RETURN(0); - // TODO: timeout? if ((stat & __KernelUmdGetState()) == 0) - __KernelWaitCurThread(WAITTYPE_UMD, 0, stat, 0, 0); //__KernelWaitCurThread(WAITTYPE_UMD, 0); + { + __UmdWaitStat(timeout); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, 0); + } } void sceUmdWaitDriveStatCB(u32 stat, u32 timeout) { - ERROR_LOG(HLE,"HACK 0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %08x)", stat, timeout); RETURN(0); - // TODO: wait and timeout? - if (driveCBId != -1) { + DEBUG_LOG(HLE,"0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d)", stat, timeout); + bool callbacksProcessed = __KernelForceCallbacks(); if (callbacksProcessed) __KernelExecutePendingMipsCalls(); } else { - ERROR_LOG(HLE, "HACK 0=sceUmdWaitDriveStatCB(stat = %08x) attempting to call unset callback", stat); + WARN_LOG(HLE, "0=sceUmdWaitDriveStatCB(stat = %08x, timeout = %d) without callback", stat, timeout); + } + + if ((stat & __KernelUmdGetState()) == 0) + { + if (timeout == 0) + timeout = 8000; + + __UmdWaitStat(timeout); + __KernelWaitCurThread(WAITTYPE_UMD, 1, stat, 0, true); + __KernelCheckCallbacks(); } } @@ -222,7 +260,9 @@ void sceUmdCancelWaitDriveStat() DEBUG_LOG(HLE,"0=sceUmdCancelWaitDriveStat()"); RETURN(0); - __KernelTriggerWait(WAITTYPE_UMD, 0, SCE_KERNEL_ERROR_WAIT_CANCEL, false); + __KernelTriggerWait(WAITTYPE_UMD, 1, SCE_KERNEL_ERROR_WAIT_CANCEL, false); + // TODO: We should call UnscheduleEvent() event here? + // But it's not often used anyway, and worst-case it will just do nothing unless it waits again. } u32 sceUmdGetErrorStat() From 51a4ed4f755d8d65ff19bb52d159403472fa7517 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 23:19:10 -0800 Subject: [PATCH 10/35] Reschedule when activating/deactivating the UMD. This is what a PSP seems to do. --- Core/HLE/FunctionWrappers.h | 4 ++++ Core/HLE/sceUmd.cpp | 35 ++++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/Core/HLE/FunctionWrappers.h b/Core/HLE/FunctionWrappers.h index 4e6c5c1f04..8cec9e7537 100644 --- a/Core/HLE/FunctionWrappers.h +++ b/Core/HLE/FunctionWrappers.h @@ -108,6 +108,10 @@ template void WrapV_II() { func(PARAM(0), PARAM(1)); } +template void WrapV_UC() { + func(PARAM(0), Memory::GetCharPointer(PARAM(1))); +} + template void WrapU_UU() { u32 retval = func(PARAM(0), PARAM(1)); RETURN(retval); diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 9c13c7d464..310bc3b866 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -100,34 +100,44 @@ void sceUmdGetDiscInfo() RETURN(0); } -u32 sceUmdActivate(u32 unknown, const char *name) +void sceUmdActivate(u32 unknown, const char *name) { if (unknown < 1 || unknown > 2) - return PSP_ERROR_UMD_INVALID_PORT; + { + RETURN(PSP_ERROR_UMD_INVALID_PORT); + return; + } - u32 retVal = 0; + bool changed = umdActivated == 0; __KernelUmdActivate(); if (unknown == 1) { - DEBUG_LOG(HLE, "%i=sceUmdActivate(%d, %s)", retVal, unknown, name); + DEBUG_LOG(HLE, "0=sceUmdActivate(%d, %s)", unknown, name); } else { - ERROR_LOG(HLE, "UNTESTED %i=sceUmdActivate(%d, %s)", retVal, unknown, name); + ERROR_LOG(HLE, "UNTESTED 0=sceUmdActivate(%d, %s)", unknown, name); } u32 notifyArg = UMD_PRESENT | UMD_READABLE; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - return retVal; + RETURN(0); + + if (changed) + __KernelReSchedule("umd activated"); } -u32 sceUmdDeactivate(u32 unknown, const char *name) +void sceUmdDeactivate(u32 unknown, const char *name) { // Why 18? No idea. if (unknown < 0 || unknown > 18) - return PSP_ERROR_UMD_INVALID_PORT; + { + RETURN(PSP_ERROR_UMD_INVALID_PORT); + return; + } + bool changed = umdActivated != 0; __KernelUmdDeactivate(); if (unknown == 1) @@ -141,7 +151,10 @@ u32 sceUmdDeactivate(u32 unknown, const char *name) u32 notifyArg = UMD_PRESENT | UMD_READY; __KernelNotifyCallbackType(THREAD_CALLBACK_UMD, -1, notifyArg); - return 0; + RETURN(0); + + if (changed) + __KernelReSchedule("umd deactivated"); } u32 sceUmdRegisterUMDCallBack(u32 cbId) @@ -274,10 +287,10 @@ u32 sceUmdGetErrorStat() const HLEFunction sceUmdUser[] = { - {0xC6183D47,&WrapU_UC,"sceUmdActivate"}, + {0xC6183D47,WrapV_UC,"sceUmdActivate"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x46EBB729,WrapI_V,"sceUmdCheckMedium"}, - {0xE83742BA,&WrapU_UC,"sceUmdDeactivate"}, + {0xE83742BA,WrapV_UC,"sceUmdDeactivate"}, {0x8EF08FCE,WrapV_U,"sceUmdWaitDriveStat"}, {0x56202973,WrapV_UU,"sceUmdWaitDriveStatWithTimer"}, {0x4A9E5E29,WrapV_UU,"sceUmdWaitDriveStatCB"}, From 9ba9415df45d4d63c5e73ddb717bceb5a1f0745c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 23:48:11 -0800 Subject: [PATCH 11/35] Change the UMD callback on overwrite. --- Core/HLE/sceUmd.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 310bc3b866..8d24ffac7b 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -159,14 +159,15 @@ void sceUmdDeactivate(u32 unknown, const char *name) u32 sceUmdRegisterUMDCallBack(u32 cbId) { - DEBUG_LOG(HLE,"0=sceUmdRegisterUMDCallback(id=%i)",PARAM(0)); if (driveCBId == -1) { + DEBUG_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i)", cbId); driveCBId = cbId; } else { - ERROR_LOG(HLE," 0=sceUmdRegisterUMDCallback(id=%i) callback overwrite attempt",PARAM(0)); + WARN_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i) overwrote callacbk", cbId); + driveCBId = cbId; } return __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId); } From e5f1d701e3d59dcd13bbb785658cd55a48c25b43 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 00:20:28 -0800 Subject: [PATCH 12/35] Don't unregister a different UMD callback, cleanup. --- Core/HLE/sceUmd.cpp | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 8d24ffac7b..fbada80a6a 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -21,7 +21,7 @@ #include "sceUmd.h" #include "sceKernelThread.h" -const int PSP_ERROR_UMD_INVALID_PORT = 0x80010016; +const int PSP_ERROR_UMD_INVALID_PARAM = 0x80010016; #define UMD_NOT_PRESENT 0x01 #define UMD_PRESENT 0x02 @@ -104,7 +104,7 @@ void sceUmdActivate(u32 unknown, const char *name) { if (unknown < 1 || unknown > 2) { - RETURN(PSP_ERROR_UMD_INVALID_PORT); + RETURN(PSP_ERROR_UMD_INVALID_PARAM); return; } @@ -133,7 +133,7 @@ void sceUmdDeactivate(u32 unknown, const char *name) // Why 18? No idea. if (unknown < 0 || unknown > 18) { - RETURN(PSP_ERROR_UMD_INVALID_PORT); + RETURN(PSP_ERROR_UMD_INVALID_PARAM); return; } @@ -159,24 +159,36 @@ void sceUmdDeactivate(u32 unknown, const char *name) u32 sceUmdRegisterUMDCallBack(u32 cbId) { - if (driveCBId == -1) - { - DEBUG_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i)", cbId); - driveCBId = cbId; - } + int retVal; + + // TODO: If the callback is invalid, return PSP_ERROR_UMD_INVALID_PARAM. + if (cbId == 0) + retVal = PSP_ERROR_UMD_INVALID_PARAM; else { - WARN_LOG(HLE, "0=sceUmdRegisterUMDCallback(id=%i) overwrote callacbk", cbId); + retVal = __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId); driveCBId = cbId; } - return __KernelRegisterCallback(THREAD_CALLBACK_UMD, cbId); + + DEBUG_LOG(HLE, "%d=sceUmdRegisterUMDCallback(id=%08x)", retVal, cbId); + return retVal; } u32 sceUmdUnRegisterUMDCallBack(u32 cbId) { - DEBUG_LOG(HLE,"0=sceUmdUnRegisterUMDCallBack(id=%i)",PARAM(0)); - driveCBId = -1; - return __KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId); + u32 retVal; + + if (cbId != driveCBId) + retVal = PSP_ERROR_UMD_INVALID_PARAM; + else + { + retVal = cbId; + driveCBId = -1; + __KernelUnregisterCallback(THREAD_CALLBACK_UMD, cbId); + } + + DEBUG_LOG(HLE, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId); + return retVal; } u32 sceUmdGetDriveStat() From 9e8160c88b4e08246c36fcc5dbe885a6b8892bfe Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 00:33:39 -0800 Subject: [PATCH 13/35] Correct sceUmdGetDiscInfo(). The struct was wrong, also add error handling. --- Core/HLE/sceUmd.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index fbada80a6a..1a2e40afa8 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -43,7 +43,8 @@ int umdStatTimer = 0; #define PSP_UMD_TYPE_AUDIO 0x40 struct PspUmdInfo { - int type; + u32 size; + u32 type; }; @@ -87,17 +88,23 @@ int sceUmdCheckMedium() return 1; //non-zero: disc in drive } -void sceUmdGetDiscInfo() +u32 sceUmdGetDiscInfo(u32 infoAddr) { - u32 infoAddr = PARAM(0); - ERROR_LOG(HLE,"sceUmdGetDiscInfo(%08x)", infoAddr); - PspUmdInfo info; - info.type = PSP_UMD_TYPE_GAME; + DEBUG_LOG(HLE, "sceUmdGetDiscInfo(%08x)", infoAddr); + if (Memory::IsValidAddress(infoAddr)) { + PspUmdInfo info; + Memory::ReadStruct(infoAddr, &info); + if (info.size != 8) + return PSP_ERROR_UMD_INVALID_PARAM; + + info.type = PSP_UMD_TYPE_GAME; Memory::WriteStruct(infoAddr, &info); + return 0; } - RETURN(0); + else + return PSP_ERROR_UMD_INVALID_PARAM; } void sceUmdActivate(u32 unknown, const char *name) @@ -310,7 +317,7 @@ const HLEFunction sceUmdUser[] = {0x6af9b50a,sceUmdCancelWaitDriveStat,"sceUmdCancelWaitDriveStat"}, {0x6B4A146C,&WrapU_V,"sceUmdGetDriveStat"}, {0x20628E6F,&WrapU_V,"sceUmdGetErrorStat"}, - {0x340B7686,sceUmdGetDiscInfo,"sceUmdGetDiscInfo"}, + {0x340B7686,WrapU_U,"sceUmdGetDiscInfo"}, {0xAEE7404D,&WrapU_U,"sceUmdRegisterUMDCallBack"}, {0xBD2BDE07,&WrapU_U,"sceUmdUnRegisterUMDCallBack"}, {0x87533940,0,"sceUmdReplaceProhibit"}, // ??? sounds bogus From bf8abaebe5f81be11fcb34c539b64b059da27551 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 25 Nov 2012 12:05:43 -0800 Subject: [PATCH 14/35] Don't include analog when not enabled in ctrl. Fixes menu, movement in Tales of Eternia. --- Core/HLE/sceCtrl.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 0e255bfdd7..77769a0b5d 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -157,7 +157,13 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) //if (ctrlInited) //{ SampleControls(); - Memory::WriteStruct(ctrlDataPtr, &ctrl); + _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); + memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); + if (!analogEnabled) + { + ctrlData->analog[0] = 128; + ctrlData->analog[1] = 128; + } //} return 1; } From 843d495c5bb7113e0e383841880e0e47ff56f170 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 25 Nov 2012 20:59:52 -0800 Subject: [PATCH 15/35] Don't expect sceCtrlInit ever, minor ctrl funcs. I don't see any indication that you need to call init first. --- Core/HLE/sceCtrl.cpp | 180 ++++++++++++++++++++++++++++--------------- 1 file changed, 120 insertions(+), 60 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 77769a0b5d..65872a2672 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -27,6 +27,7 @@ #define CTRL_MODE_DIGITAL 0 #define CTRL_MODE_ANALOG 1 +const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107; // Returned control data struct _ctrl_data @@ -60,15 +61,13 @@ static std::recursive_mutex ctrlMutex; ////////////////////////////////////////////////////////////////////////// -void SampleControls() { - static int frame = 0; - _ctrl_data &data = ctrl; - data.frame=1;//frame; - frame++; -} +void sceCtrlInit(); +void UpdateLatch() +{ + if (!ctrlInited) + sceCtrlInit(); -void UpdateLatch() { u32 changed = ctrl.buttons ^ oldButtons; latch.btnMake = ctrl.buttons & changed; latch.btnBreak = oldButtons & changed; @@ -81,6 +80,9 @@ void UpdateLatch() { u32 __CtrlPeekButtons() { + if (!ctrlInited) + sceCtrlInit(); + return ctrl.buttons; } @@ -89,61 +91,91 @@ u32 __CtrlPeekButtons() void __CtrlButtonDown(u32 buttonBit) { - std::lock_guard guard(ctrlMutex); - ctrl.buttons |= buttonBit; + if (!ctrlInited) + sceCtrlInit(); + + std::lock_guard guard(ctrlMutex); + ctrl.buttons |= buttonBit; } void __CtrlButtonUp(u32 buttonBit) { - std::lock_guard guard(ctrlMutex); - ctrl.buttons &= ~buttonBit; + if (!ctrlInited) + sceCtrlInit(); + + std::lock_guard guard(ctrlMutex); + ctrl.buttons &= ~buttonBit; } void __CtrlSetAnalog(float x, float y) { - std::lock_guard guard(ctrlMutex); - // TODO: Circle! - if (x > 1.0f) x = 1.0f; - if (y > 1.0f) y = 1.0f; - if (x < -1.0f) x = -1.0f; - if (y < -1.0f) y = -1.0f; - ctrl.analog[0] = (u8)(x * 127.f + 128.f); - ctrl.analog[1] = (u8)(y * 127.f + 128.f); + if (!ctrlInited) + sceCtrlInit(); + + std::lock_guard guard(ctrlMutex); + // TODO: Circle! + if (x > 1.0f) x = 1.0f; + if (y > 1.0f) y = 1.0f; + if (x < -1.0f) x = -1.0f; + if (y < -1.0f) y = -1.0f; + ctrl.analog[0] = (u8)(x * 127.f + 128.f); + ctrl.analog[1] = (u8)(y * 127.f + 128.f); } void sceCtrlInit() { ctrlInited = true; - memset(&ctrl, 0, sizeof(ctrl)); + + std::lock_guard guard(ctrlMutex); + + memset(&ctrl, 0, sizeof(ctrl)); ctrl.analog[0] = 128; ctrl.analog[1] = 128; + // TODO: Make this increment in the correct way. + ctrl.frame = 1; + DEBUG_LOG(HLE,"sceCtrlInit"); RETURN(0); } -void sceCtrlSetSamplingCycle() { - ERROR_LOG(HLE,"UNIMPL sceCtrlSetSamplingCycle"); - RETURN(0); +u32 sceCtrlSetSamplingCycle(u32 cycle) +{ + ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%u)", cycle); + return 0; +} + +int sceCtrlGetSamplingCycle(u32 cyclePtr) +{ + ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%08x)", cyclePtr); + return 0; } u32 sceCtrlSetSamplingMode(u32 mode) { u32 retVal = 0; - DEBUG_LOG(HLE,"sceCtrlSetSamplingMode(%i)", mode); - _assert_msg_(HLE, mode >= 0 && mode <= 1, "sceCtrlSetSamplingMode: mode outside expected range."); + DEBUG_LOG(HLE, "sceCtrlSetSamplingMode(%i)", mode); + if (mode > 1) + return PSP_CTRL_ERROR_INVALID_MODE; - if (ctrlInited) - { - retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL; - analogEnabled = mode == CTRL_MODE_ANALOG ? true : false; - } + retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL; + analogEnabled = mode == CTRL_MODE_ANALOG ? true : false; return retVal; } +int sceCtrlGetSamplingMode(u32 modePtr) +{ + u32 retVal = analogEnabled == true ? CTRL_MODE_ANALOG : CTRL_MODE_DIGITAL; + + if (Memory::IsValidAddress(modePtr)) + Memory::Write_U32(retVal, modePtr); + + return 0; +} + void sceCtrlSetIdleCancelThreshold() { - DEBUG_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold"); + DEBUG_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold"); RETURN(0); } @@ -152,11 +184,13 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); _assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferPositive: trying to read nothing?"); + if (!ctrlInited) + sceCtrlInit(); + std::lock_guard guard(ctrlMutex); - // Let's just ignore if ctrl is inited or not; some games don't init it (Super Fruit Fall) - //if (ctrlInited) - //{ - SampleControls(); + + if (Memory::IsValidAddress(ctrlDataPtr)) + { _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); if (!analogEnabled) @@ -164,11 +198,38 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) ctrlData->analog[0] = 128; ctrlData->analog[1] = 128; } - //} + } + return 1; } -u32 sceCtrlPeekLatch(u32 latchDataPtr) { +u32 sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) +{ + DEBUG_LOG(HLE,"sceCtrlReadBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); + _assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferNegative: trying to read nothing?"); + + if (!ctrlInited) + sceCtrlInit(); + + std::lock_guard guard(ctrlMutex); + + if (Memory::IsValidAddress(ctrlDataPtr)) + { + _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); + memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); + ctrlData->buttons = ~ctrlData->buttons; + if (!analogEnabled) + { + ctrlData->analog[0] = 128; + ctrlData->analog[1] = 128; + } + } + + return 1; +} + +u32 sceCtrlPeekLatch(u32 latchDataPtr) +{ ERROR_LOG(HLE,"FAKE sceCtrlPeekLatch(%08x)", latchDataPtr); if (Memory::IsValidAddress(latchDataPtr)) @@ -176,14 +237,13 @@ u32 sceCtrlPeekLatch(u32 latchDataPtr) { return 1; } -u32 sceCtrlReadLatch(u32 latchDataPtr) { +u32 sceCtrlReadLatch(u32 latchDataPtr) +{ ERROR_LOG(HLE,"FAKE sceCtrlReadLatch(%08x)", latchDataPtr); // Hackery to do it here. - SampleControls(); UpdateLatch(); - if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); @@ -192,26 +252,26 @@ u32 sceCtrlReadLatch(u32 latchDataPtr) { static const HLEFunction sceCtrl[] = { - {0x6a2774f3, sceCtrlInit, "sceCtrlInit"}, //(int unknown), init with 0 - {0x1f4011e6, &WrapU_U, "sceCtrlSetSamplingMode"}, //(int on); - {0x1f803938, &WrapU_UU, "sceCtrlReadBufferPositive"}, //(ctrl_data_t* paddata, int unknown) // unknown should be 1 - {0x6A2774F3, 0, "sceCtrlSetSamplingCycle"}, //? - {0x6A2774F3,sceCtrlSetSamplingCycle,"sceCtrlSetSamplingCycle"}, - {0x02BAAD91,0,"sceCtrlGetSamplingCycle"}, - {0xDA6B76A1,0,"sceCtrlGetSamplingMode"}, - {0x3A622550,&WrapU_UU, "sceCtrlPeekBufferPositive"}, - {0xC152080A,0,"sceCtrlPeekBufferNegative"}, - {0x60B81F86,0,"sceCtrlReadBufferNegative"}, - {0xB1D0E5CD,&WrapU_U,"sceCtrlPeekLatch"}, - {0x0B588501,&WrapU_U,"sceCtrlReadLatch"}, - {0x348D99D4,0,"sceCtrl_348D99D4"}, - {0xAF5960F3,0,"sceCtrl_AF5960F3"}, - {0xA68FD260,0,"sceCtrlClearRapidFire"}, - {0x6841BE1A,0,"sceCtrlSetRapidFire"}, - {0xa7144800,sceCtrlSetIdleCancelThreshold,"sceCtrlSetIdleCancelThreshold"}, - {0x687660fa,0,"sceCtrlGetIdleCancelThreshold"}, + {0x3E65A0EA, WrapV_V, "sceCtrlInit"}, //(int unknown), init with 0 + {0x1f4011e6, WrapU_U, "sceCtrlSetSamplingMode"}, //(int on); + {0x6A2774F3, WrapU_U, "sceCtrlSetSamplingCycle"}, + {0x02BAAD91, WrapI_U,"sceCtrlGetSamplingCycle"}, + {0xDA6B76A1, WrapI_U, "sceCtrlGetSamplingMode"}, + {0x1f803938, WrapU_UU, "sceCtrlReadBufferPositive"}, //(ctrl_data_t* paddata, int unknown) // unknown should be 1 + {0x3A622550, WrapU_UU, "sceCtrlPeekBufferPositive"}, + {0xC152080A, WrapU_UU, "sceCtrlPeekBufferNegative"}, + {0x60B81F86, WrapU_UU, "sceCtrlReadBufferNegative"}, + {0xB1D0E5CD, WrapU_U, "sceCtrlPeekLatch"}, + {0x0B588501, WrapU_U, "sceCtrlReadLatch"}, + {0x348D99D4, 0, "sceCtrl_348D99D4"}, + {0xAF5960F3, 0, "sceCtrl_AF5960F3"}, + {0xA68FD260, 0, "sceCtrlClearRapidFire"}, + {0x6841BE1A, 0, "sceCtrlSetRapidFire"}, + {0xa7144800, WrapV_V, "sceCtrlSetIdleCancelThreshold"}, + {0x687660fa, 0, "sceCtrlGetIdleCancelThreshold"}, }; -void Register_sceCtrl() { - RegisterModule("sceCtrl",ARRAY_SIZE(sceCtrl),sceCtrl); +void Register_sceCtrl() +{ + RegisterModule("sceCtrl", ARRAY_SIZE(sceCtrl), sceCtrl); } From 0dc8e2a420eb1fc65f81a9e72a865316263166fa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 25 Nov 2012 21:44:01 -0800 Subject: [PATCH 16/35] Set the ctrl frame value to something useful. --- Core/HLE/sceCtrl.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 65872a2672..56ba019a7d 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -17,6 +17,7 @@ #include "HLE.h" #include "../MIPS/MIPS.h" +#include "../CoreTiming.h" #include "StdMutex.h" #include "sceCtrl.h" @@ -28,6 +29,7 @@ #define CTRL_MODE_ANALOG 1 const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107; +const int PSP_CTRL_ERROR_INVALID_NUM_BUFFERS = 0x80000104; // Returned control data struct _ctrl_data @@ -131,7 +133,6 @@ void sceCtrlInit() memset(&ctrl, 0, sizeof(ctrl)); ctrl.analog[0] = 128; ctrl.analog[1] = 128; - // TODO: Make this increment in the correct way. ctrl.frame = 1; DEBUG_LOG(HLE,"sceCtrlInit"); @@ -181,9 +182,14 @@ void sceCtrlSetIdleCancelThreshold() u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) { + // TODO: Test rescheduling. DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); _assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferPositive: trying to read nothing?"); + // Pretend we have only 64 of them. + if (nBufs > 64) + return PSP_CTRL_ERROR_INVALID_NUM_BUFFERS; + if (!ctrlInited) sceCtrlInit(); @@ -193,6 +199,8 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) { _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); + + ctrlData->frame = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); if (!analogEnabled) { ctrlData->analog[0] = 128; @@ -205,6 +213,7 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) u32 sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) { + // TODO: Test rescheduling. DEBUG_LOG(HLE,"sceCtrlReadBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); _assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferNegative: trying to read nothing?"); @@ -217,7 +226,9 @@ u32 sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) { _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); + ctrlData->buttons = ~ctrlData->buttons; + ctrlData->frame = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); if (!analogEnabled) { ctrlData->analog[0] = 128; From 754a49dfd7f1af5ed4f27d2a73fe86515f6ca800 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 25 Nov 2012 22:10:25 -0800 Subject: [PATCH 17/35] Make sceCtrlReadLatch work more correctly. It gets changes since last call, makes sense. --- Core/HLE/sceCtrl.cpp | 50 +++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 56ba019a7d..f847eb973a 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -40,7 +40,6 @@ struct _ctrl_data u8 unused[6]; }; -static u32 oldButtons; struct CtrlLatch { u32 btnMake; u32 btnBreak; @@ -53,6 +52,8 @@ struct CtrlLatch { // STATE BEGIN static bool ctrlInited = false; static bool analogEnabled = false; +static int ctrlLatchBufs = 0; +static u32 ctrlOldButtons = 0; static _ctrl_data ctrl; static CtrlLatch latch; @@ -65,20 +66,33 @@ static std::recursive_mutex ctrlMutex; void sceCtrlInit(); -void UpdateLatch() +void __CtrlUpdateLatch() { if (!ctrlInited) sceCtrlInit(); - u32 changed = ctrl.buttons ^ oldButtons; - latch.btnMake = ctrl.buttons & changed; - latch.btnBreak = oldButtons & changed; - latch.btnPress = ctrl.buttons; - latch.btnRelease = (oldButtons & ~ctrl.buttons) & changed; + std::lock_guard guard(ctrlMutex); + + u32 changed = ctrl.buttons ^ ctrlOldButtons; + latch.btnMake |= ctrl.buttons & changed; + latch.btnBreak |= ctrlOldButtons & changed; + latch.btnPress |= ctrl.buttons; + latch.btnRelease |= (ctrlOldButtons & ~ctrl.buttons) & changed; + // TODO: This should really be happening based on the "sampling cycle"... + ctrlLatchBufs++; - oldButtons = ctrl.buttons; + ctrlOldButtons = ctrl.buttons; } +int __CtrlResetLatch() +{ + std::lock_guard guard(ctrlMutex); + + int oldBufs = ctrlLatchBufs; + memset(&latch, 0, sizeof(CtrlLatch)); + ctrlLatchBufs = 0; + return oldBufs; +} u32 __CtrlPeekButtons() { @@ -98,6 +112,7 @@ void __CtrlButtonDown(u32 buttonBit) std::lock_guard guard(ctrlMutex); ctrl.buttons |= buttonBit; + __CtrlUpdateLatch(); } void __CtrlButtonUp(u32 buttonBit) @@ -107,6 +122,7 @@ void __CtrlButtonUp(u32 buttonBit) std::lock_guard guard(ctrlMutex); ctrl.buttons &= ~buttonBit; + __CtrlUpdateLatch(); } void __CtrlSetAnalog(float x, float y) @@ -122,6 +138,8 @@ void __CtrlSetAnalog(float x, float y) if (y < -1.0f) y = -1.0f; ctrl.analog[0] = (u8)(x * 127.f + 128.f); ctrl.analog[1] = (u8)(y * 127.f + 128.f); + + __CtrlUpdateLatch(); } void sceCtrlInit() @@ -130,6 +148,7 @@ void sceCtrlInit() std::lock_guard guard(ctrlMutex); + memset(&latch, 0, sizeof(latch)); memset(&ctrl, 0, sizeof(ctrl)); ctrl.analog[0] = 128; ctrl.analog[1] = 128; @@ -200,7 +219,7 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); - ctrlData->frame = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); + ctrlData->frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz()); if (!analogEnabled) { ctrlData->analog[0] = 128; @@ -228,7 +247,7 @@ u32 sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); ctrlData->buttons = ~ctrlData->buttons; - ctrlData->frame = CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz(); + ctrlData->frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz()); if (!analogEnabled) { ctrlData->analog[0] = 128; @@ -243,22 +262,25 @@ u32 sceCtrlPeekLatch(u32 latchDataPtr) { ERROR_LOG(HLE,"FAKE sceCtrlPeekLatch(%08x)", latchDataPtr); + // TODO: We don't really want to do this here, it should be on an interval. + __CtrlUpdateLatch(); + if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); - return 1; + return ctrlLatchBufs; } u32 sceCtrlReadLatch(u32 latchDataPtr) { ERROR_LOG(HLE,"FAKE sceCtrlReadLatch(%08x)", latchDataPtr); - // Hackery to do it here. - UpdateLatch(); + // TODO: We don't really want to do this here, it should be on an interval. + __CtrlUpdateLatch(); if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); - return 1; + return __CtrlResetLatch(); } static const HLEFunction sceCtrl[] = From b93c4f636cf424d34da3f19f490232c56fa2c497 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 1 Dec 2012 02:08:43 -0800 Subject: [PATCH 18/35] Oops, prevent a possible crash in ctrl. --- Core/HLE/sceCtrl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index f847eb973a..003408a31c 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -214,9 +214,9 @@ u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) std::lock_guard guard(ctrlMutex); - if (Memory::IsValidAddress(ctrlDataPtr)) + _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); + if (Memory::IsValidAddress(ctrlDataPtr) && ctrlData) { - _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); ctrlData->frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz()); @@ -241,9 +241,9 @@ u32 sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) std::lock_guard guard(ctrlMutex); - if (Memory::IsValidAddress(ctrlDataPtr)) + _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); + if (Memory::IsValidAddress(ctrlDataPtr) && ctrlData) { - _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); ctrlData->buttons = ~ctrlData->buttons; From 7edb34057720808fab638643b93a7d6ff5fc33a0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 12:44:33 -0800 Subject: [PATCH 19/35] Start the ctrl latch off all just released. --- Core/HLE/sceCtrl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 003408a31c..3dd877a02e 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -149,6 +149,9 @@ void sceCtrlInit() std::lock_guard guard(ctrlMutex); memset(&latch, 0, sizeof(latch)); + // Start with everything released. + latch.btnRelease = 0xffffffff; + memset(&ctrl, 0, sizeof(ctrl)); ctrl.analog[0] = 128; ctrl.analog[1] = 128; From 83cb8cef6c26b8be6897e3307cc8e02c0f0b946f Mon Sep 17 00:00:00 2001 From: MaXiMu Date: Sun, 2 Dec 2012 22:48:31 +0100 Subject: [PATCH 20/35] Add armeabi on android --- android/jni/Application.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/jni/Application.mk b/android/jni/Application.mk index 0d185744b0..dd83bdcd41 100644 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -1,2 +1,2 @@ APP_STL := stlport_static -APP_ABI := armeabi-v7a +APP_ABI := armeabi armeabi-v7a From fd2d6661917791653664e38156be1760e3d0d6d2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 15:44:23 -0800 Subject: [PATCH 21/35] Add ctrl sampling (vblank). This makes it work like the PSP does with number of buffers, etc. Still doesn't wait yet. --- Core/HLE/sceCtrl.cpp | 208 ++++++++++++++++++++++------------------ Core/HLE/sceCtrl.h | 2 + Core/HLE/sceDisplay.cpp | 19 ++++ Core/HLE/sceDisplay.h | 3 + Core/HLE/sceKernel.cpp | 2 + 5 files changed, 143 insertions(+), 91 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 3dd877a02e..7eb63da4aa 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -20,6 +20,7 @@ #include "../CoreTiming.h" #include "StdMutex.h" #include "sceCtrl.h" +#include "sceDisplay.h" /* Index for the two analog directions */ #define CTRL_ANALOG_X 0 @@ -55,7 +56,10 @@ static bool analogEnabled = false; static int ctrlLatchBufs = 0; static u32 ctrlOldButtons = 0; -static _ctrl_data ctrl; +static _ctrl_data ctrlBufs[64]; +static _ctrl_data ctrlCurrent; +static int ctrlBuf = 0; +static int ctrlBufRead = 0; static CtrlLatch latch; static std::recursive_mutex ctrlMutex; @@ -64,30 +68,39 @@ static std::recursive_mutex ctrlMutex; ////////////////////////////////////////////////////////////////////////// -void sceCtrlInit(); - void __CtrlUpdateLatch() { - if (!ctrlInited) - sceCtrlInit(); - std::lock_guard guard(ctrlMutex); - u32 changed = ctrl.buttons ^ ctrlOldButtons; - latch.btnMake |= ctrl.buttons & changed; + u32 changed = ctrlCurrent.buttons ^ ctrlOldButtons; + latch.btnMake |= ctrlCurrent.buttons & changed; latch.btnBreak |= ctrlOldButtons & changed; - latch.btnPress |= ctrl.buttons; - latch.btnRelease |= (ctrlOldButtons & ~ctrl.buttons) & changed; - // TODO: This should really be happening based on the "sampling cycle"... + latch.btnPress |= ctrlCurrent.buttons; + latch.btnRelease |= (ctrlOldButtons & ~ctrlCurrent.buttons) & changed; ctrlLatchBufs++; - ctrlOldButtons = ctrl.buttons; + ctrlOldButtons = ctrlCurrent.buttons; + + // Copy in the current data to the current buffer. + memcpy(&ctrlBufs[ctrlBuf], &ctrlCurrent, sizeof(_ctrl_data)); + + ctrlBufs[ctrlBuf].frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz()); + if (!analogEnabled) + { + ctrlBufs[ctrlBuf].analog[0] = 128; + ctrlBufs[ctrlBuf].analog[1] = 128; + } + + ctrlBuf = (ctrlBuf + 1) % 64; + + // If we wrapped around, push the read head forward. + // TODO: Is this right? + if (ctrlBufRead == ctrlBuf) + ctrlBufRead = (ctrlBufRead + 1) % 64; } int __CtrlResetLatch() { - std::lock_guard guard(ctrlMutex); - int oldBufs = ctrlLatchBufs; memset(&latch, 0, sizeof(CtrlLatch)); ctrlLatchBufs = 0; @@ -96,10 +109,9 @@ int __CtrlResetLatch() u32 __CtrlPeekButtons() { - if (!ctrlInited) - sceCtrlInit(); + std::lock_guard guard(ctrlMutex); - return ctrl.buttons; + return ctrlCurrent.buttons; } // Functions so that the rest of the emulator can control what the sceCtrl interface should return @@ -107,55 +119,62 @@ u32 __CtrlPeekButtons() void __CtrlButtonDown(u32 buttonBit) { - if (!ctrlInited) - sceCtrlInit(); - std::lock_guard guard(ctrlMutex); - ctrl.buttons |= buttonBit; - __CtrlUpdateLatch(); + ctrlCurrent.buttons |= buttonBit; } void __CtrlButtonUp(u32 buttonBit) { - if (!ctrlInited) - sceCtrlInit(); - std::lock_guard guard(ctrlMutex); - ctrl.buttons &= ~buttonBit; - __CtrlUpdateLatch(); + ctrlCurrent.buttons &= ~buttonBit; } void __CtrlSetAnalog(float x, float y) { - if (!ctrlInited) - sceCtrlInit(); - std::lock_guard guard(ctrlMutex); // TODO: Circle! if (x > 1.0f) x = 1.0f; if (y > 1.0f) y = 1.0f; if (x < -1.0f) x = -1.0f; if (y < -1.0f) y = -1.0f; - ctrl.analog[0] = (u8)(x * 127.f + 128.f); - ctrl.analog[1] = (u8)(y * 127.f + 128.f); + ctrlCurrent.analog[0] = (u8)(x * 127.f + 128.f); + ctrlCurrent.analog[1] = (u8)(y * 127.f + 128.f); +} +void __CtrlVblank() +{ + // When in vblank sampling mode, this samples the ctrl data into the buffers and updates the latch. __CtrlUpdateLatch(); } -void sceCtrlInit() +void __CtrlInit() { - ctrlInited = true; - std::lock_guard guard(ctrlMutex); + if (!ctrlInited) + { + __DisplayListenVblank(__CtrlVblank); + ctrlInited = true; + } + + ctrlBuf = 0; + ctrlBufRead = 0; + ctrlOldButtons = 0; + ctrlLatchBufs = 0; + memset(&latch, 0, sizeof(latch)); // Start with everything released. latch.btnRelease = 0xffffffff; - memset(&ctrl, 0, sizeof(ctrl)); - ctrl.analog[0] = 128; - ctrl.analog[1] = 128; - ctrl.frame = 1; + memset(&ctrlCurrent, 0, sizeof(ctrlCurrent)); + memset(&ctrlBufs, 0, sizeof(ctrlBufs)); + ctrlCurrent.analog[0] = 128; + ctrlCurrent.analog[1] = 128; +} + +void sceCtrlInit() +{ + __CtrlInit(); DEBUG_LOG(HLE,"sceCtrlInit"); RETURN(0); @@ -163,7 +182,15 @@ void sceCtrlInit() u32 sceCtrlSetSamplingCycle(u32 cycle) { - ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%u)", cycle); + if (cycle == 0) + { + // TODO: Change to vblank when we support something else. + DEBUG_LOG(HLE, "sceCtrlSetSamplingCycle(%u)", cycle); + } + else + { + ERROR_LOG(HLE, "UNIMPL sceCtrlSetSamplingCycle(%u)", cycle); + } return 0; } @@ -202,83 +229,82 @@ void sceCtrlSetIdleCancelThreshold() RETURN(0); } -u32 sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) +int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) { - // TODO: Test rescheduling. - DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); - _assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferPositive: trying to read nothing?"); - - // Pretend we have only 64 of them. if (nBufs > 64) return PSP_CTRL_ERROR_INVALID_NUM_BUFFERS; - if (!ctrlInited) - sceCtrlInit(); + int resetRead = ctrlBufRead; - std::lock_guard guard(ctrlMutex); - - _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); - if (Memory::IsValidAddress(ctrlDataPtr) && ctrlData) + int done = 0; + _ctrl_data data; + for (u32 i = 0; i < nBufs; ++i) { - memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); + // Ran out of buffers. + if (ctrlBuf == ctrlBufRead) + break; - ctrlData->frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz()); - if (!analogEnabled) + if (Memory::IsValidAddress(ctrlDataPtr)) { - ctrlData->analog[0] = 128; - ctrlData->analog[1] = 128; + memcpy(&data, &ctrlBufs[ctrlBufRead], sizeof(_ctrl_data)); + ctrlBufRead = (ctrlBufRead + 1) % 64; + + if (negative) + data.buttons = ~data.buttons; + + Memory::WriteStruct(ctrlDataPtr, &data); + done++; } + ctrlDataPtr += sizeof(_ctrl_data); } - return 1; + if (peek) + ctrlBufRead = resetRead; + + return done; } -u32 sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) +void sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) { - // TODO: Test rescheduling. + // TODO: Wait for vblank if there are 0 buffers (resched.) + DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); + + RETURN(__CtrlReadBuffer(ctrlDataPtr, nBufs, false, false)); +} + +void sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) +{ + // TODO: Wait for vblank if there are 0 buffers (resched.) DEBUG_LOG(HLE,"sceCtrlReadBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); - _assert_msg_(HLE, nBufs > 0, "sceCtrlReadBufferNegative: trying to read nothing?"); - if (!ctrlInited) - sceCtrlInit(); + RETURN(__CtrlReadBuffer(ctrlDataPtr, nBufs, true, false)); +} - std::lock_guard guard(ctrlMutex); +int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs) +{ + DEBUG_LOG(HLE,"sceCtrlPeekBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); + return __CtrlReadBuffer(ctrlDataPtr, nBufs, false, true); +} - _ctrl_data *ctrlData = (_ctrl_data*) Memory::GetPointer(ctrlDataPtr); - if (Memory::IsValidAddress(ctrlDataPtr) && ctrlData) - { - memcpy(ctrlData, &ctrl, sizeof(_ctrl_data)); - - ctrlData->buttons = ~ctrlData->buttons; - ctrlData->frame = (u32) (CoreTiming::GetTicks() / CoreTiming::GetClockFrequencyMHz()); - if (!analogEnabled) - { - ctrlData->analog[0] = 128; - ctrlData->analog[1] = 128; - } - } - - return 1; +int sceCtrlPeekBufferNegative(u32 ctrlDataPtr, u32 nBufs) +{ + DEBUG_LOG(HLE,"sceCtrlPeekBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); + return __CtrlReadBuffer(ctrlDataPtr, nBufs, true, true); } u32 sceCtrlPeekLatch(u32 latchDataPtr) { - ERROR_LOG(HLE,"FAKE sceCtrlPeekLatch(%08x)", latchDataPtr); - - // TODO: We don't really want to do this here, it should be on an interval. - __CtrlUpdateLatch(); + ERROR_LOG(HLE, "sceCtrlPeekLatch(%08x)", latchDataPtr); if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); + return ctrlLatchBufs; } u32 sceCtrlReadLatch(u32 latchDataPtr) { - ERROR_LOG(HLE,"FAKE sceCtrlReadLatch(%08x)", latchDataPtr); - - // TODO: We don't really want to do this here, it should be on an interval. - __CtrlUpdateLatch(); + ERROR_LOG(HLE, "sceCtrlReadLatch(%08x)", latchDataPtr); if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); @@ -293,10 +319,10 @@ static const HLEFunction sceCtrl[] = {0x6A2774F3, WrapU_U, "sceCtrlSetSamplingCycle"}, {0x02BAAD91, WrapI_U,"sceCtrlGetSamplingCycle"}, {0xDA6B76A1, WrapI_U, "sceCtrlGetSamplingMode"}, - {0x1f803938, WrapU_UU, "sceCtrlReadBufferPositive"}, //(ctrl_data_t* paddata, int unknown) // unknown should be 1 - {0x3A622550, WrapU_UU, "sceCtrlPeekBufferPositive"}, - {0xC152080A, WrapU_UU, "sceCtrlPeekBufferNegative"}, - {0x60B81F86, WrapU_UU, "sceCtrlReadBufferNegative"}, + {0x1f803938, WrapV_UU, "sceCtrlReadBufferPositive"}, //(ctrl_data_t* paddata, int unknown) // unknown should be 1 + {0x3A622550, WrapI_UU, "sceCtrlPeekBufferPositive"}, + {0xC152080A, WrapI_UU, "sceCtrlPeekBufferNegative"}, + {0x60B81F86, WrapV_UU, "sceCtrlReadBufferNegative"}, {0xB1D0E5CD, WrapU_U, "sceCtrlPeekLatch"}, {0x0B588501, WrapU_U, "sceCtrlReadLatch"}, {0x348D99D4, 0, "sceCtrl_348D99D4"}, diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index 3e02e8feb3..2f658d73c0 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -32,6 +32,8 @@ void Register_sceCtrl(); #define CTRL_LTRIGGER 0x0100 #define CTRL_RTRIGGER 0x0200 +void __CtrlInit(); + void __CtrlButtonDown(u32 buttonBit); void __CtrlButtonUp(u32 buttonBit); // -1 to 1, try to keep it in the circle diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 94e32b2e7c..5e42caebe4 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -72,6 +72,8 @@ double lastFrameTime = 0; // STATE END +std::vector vblankListeners; + // The vblank period is 731.5 us (0.7315 ms) const double vblankMs = 0.7315; const double frameMs = 1000.0 / 60.0; @@ -116,6 +118,20 @@ void __DisplayShutdown() ShutdownGfxState(); } +void __DisplayListenVblank(VblankCallback callback) +{ + vblankListeners.push_back(callback); +} + +void __DisplayFireVblank() +{ + for (std::vector::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter) + { + VblankCallback cb = *iter; + cb(); + } +} + void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; @@ -124,6 +140,9 @@ void hleEnterVblank(u64 userdata, int cyclesLate) isVblank = 1; + // Fire the vblank listeners before we wake threads. + __DisplayFireVblank(); + // Wake up threads waiting for VBlank __KernelTriggerWait(WAITTYPE_VBLANK, 0, true); diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index bcb43f96ef..003b3164b9 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -23,3 +23,6 @@ void Register_sceDisplay(); // will return true once after every end-of-frame. bool __DisplayFrameDone(); + +typedef void (*VblankCallback)(); +void __DisplayListenVblank(VblankCallback callback); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 55ac175c8f..955c89c771 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -29,6 +29,7 @@ #include "__sceAudio.h" #include "sceAudio.h" +#include "sceCtrl.h" #include "sceDisplay.h" #include "sceGe.h" #include "sceIo.h" @@ -80,6 +81,7 @@ void __KernelInit() __PowerInit(); __UtilityInit(); __UmdInit(); + __CtrlInit(); // "Internal" PSP libraries __PPGeInit(); From 958fd29593f13ca2d80424fa213710f91d1bc193 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 16:04:50 -0800 Subject: [PATCH 22/35] On Windows, separate analog and digital arrows. This fixes the Tales of Eternia menu and movement. --- Windows/KeyboardDevice.cpp | 48 +++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/Windows/KeyboardDevice.cpp b/Windows/KeyboardDevice.cpp index c69f97b90c..8d3cf30c37 100644 --- a/Windows/KeyboardDevice.cpp +++ b/Windows/KeyboardDevice.cpp @@ -17,30 +17,46 @@ static const unsigned short key_ctrl_map[] = { VK_LEFT, CTRL_LEFT, VK_RIGHT, CTRL_RIGHT, }; + +static const unsigned short analog_ctrl_map[] = { + 'I', CTRL_UP, + 'K', CTRL_DOWN, + 'J', CTRL_LEFT, + 'L', CTRL_RIGHT, +}; + int KeyboardDevice::UpdateState() { - float analogX = 0; - float analogY = 0; for (int i = 0; i < sizeof(key_ctrl_map)/sizeof(key_ctrl_map[0]); i += 2) { if (!GetAsyncKeyState(key_ctrl_map[i])) __CtrlButtonUp(key_ctrl_map[i+1]); else { __CtrlButtonDown(key_ctrl_map[i+1]); - switch (key_ctrl_map[i]) { - case VK_UP: - analogY -= .8f; - break; - case VK_DOWN: - analogY += .8f; - break; - case VK_LEFT: - analogX -= .8f; - break; - case VK_RIGHT: - analogX += .8f; - break; - } } } + + float analogX = 0; + float analogY = 0; + for (int i = 0; i < sizeof(analog_ctrl_map)/sizeof(analog_ctrl_map[0]); i += 2) { + if (!GetAsyncKeyState(analog_ctrl_map[i])) { + continue; + } + + switch (analog_ctrl_map[i + 1]) { + case CTRL_UP: + analogY -= .8f; + break; + case CTRL_DOWN: + analogY += .8f; + break; + case CTRL_LEFT: + analogX -= .8f; + break; + case CTRL_RIGHT: + analogX += .8f; + break; + } + } + __CtrlSetAnalog(analogX, analogY); return 0; } \ No newline at end of file From ec6c0e9ccd28553fd9c208cacf5a57b0eaaff05c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 16:19:14 -0800 Subject: [PATCH 23/35] The ctrl latch should work now, don't log as error. --- Core/HLE/sceCtrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 7eb63da4aa..0b5ca2e071 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -294,7 +294,7 @@ int sceCtrlPeekBufferNegative(u32 ctrlDataPtr, u32 nBufs) u32 sceCtrlPeekLatch(u32 latchDataPtr) { - ERROR_LOG(HLE, "sceCtrlPeekLatch(%08x)", latchDataPtr); + DEBUG_LOG(HLE, "sceCtrlPeekLatch(%08x)", latchDataPtr); if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); @@ -304,7 +304,7 @@ u32 sceCtrlPeekLatch(u32 latchDataPtr) u32 sceCtrlReadLatch(u32 latchDataPtr) { - ERROR_LOG(HLE, "sceCtrlReadLatch(%08x)", latchDataPtr); + DEBUG_LOG(HLE, "sceCtrlReadLatch(%08x)", latchDataPtr); if (Memory::IsValidAddress(latchDataPtr)) Memory::WriteStruct(latchDataPtr, &latch); From aea9b16a04967b5ae41f7eee4b9515cbf9b08216 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 17:03:13 -0800 Subject: [PATCH 24/35] Add ctrl waits when there are no buffers yet. --- Core/HLE/sceCtrl.cpp | 122 ++++++++++++++++++++++++----------- Core/HLE/sceKernelThread.cpp | 1 + Core/HLE/sceKernelThread.h | 1 + 3 files changed, 87 insertions(+), 37 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 0b5ca2e071..730719816d 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -21,6 +21,8 @@ #include "StdMutex.h" #include "sceCtrl.h" #include "sceDisplay.h" +#include "sceKernel.h" +#include "sceKernelThread.h" /* Index for the two analog directions */ #define CTRL_ANALOG_X 0 @@ -32,6 +34,12 @@ const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107; const int PSP_CTRL_ERROR_INVALID_NUM_BUFFERS = 0x80000104; +enum +{ + CTRL_WAIT_POSITIVE = 1, + CTRL_WAIT_NEGATIVE = 2, +}; + // Returned control data struct _ctrl_data { @@ -62,6 +70,7 @@ static int ctrlBuf = 0; static int ctrlBufRead = 0; static CtrlLatch latch; +static std::vector waitingThreads; static std::recursive_mutex ctrlMutex; // STATE END @@ -141,10 +150,70 @@ void __CtrlSetAnalog(float x, float y) ctrlCurrent.analog[1] = (u8)(y * 127.f + 128.f); } +int __CtrlReadSingleBuffer(u32 ctrlDataPtr, bool negative) +{ + _ctrl_data data; + if (Memory::IsValidAddress(ctrlDataPtr)) + { + memcpy(&data, &ctrlBufs[ctrlBufRead], sizeof(_ctrl_data)); + ctrlBufRead = (ctrlBufRead + 1) % 64; + + if (negative) + data.buttons = ~data.buttons; + + Memory::WriteStruct(ctrlDataPtr, &data); + return 1; + } + + return 0; +} + +int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) +{ + if (nBufs > 64) + return PSP_CTRL_ERROR_INVALID_NUM_BUFFERS; + + int resetRead = ctrlBufRead; + + int done = 0; + for (u32 i = 0; i < nBufs; ++i) + { + // Ran out of buffers. + if (ctrlBuf == ctrlBufRead) + break; + + done += __CtrlReadSingleBuffer(ctrlDataPtr, negative); + ctrlDataPtr += sizeof(_ctrl_data); + } + + if (peek) + ctrlBufRead = resetRead; + + return done; +} + void __CtrlVblank() { // When in vblank sampling mode, this samples the ctrl data into the buffers and updates the latch. __CtrlUpdateLatch(); + + // Wake up a single thread that was waiting for the buffer. +retry: + if (!waitingThreads.empty() && ctrlBuf != ctrlBufRead) + { + SceUID threadID = waitingThreads[0]; + waitingThreads.erase(waitingThreads.begin()); + + u32 error; + SceUID wVal = __KernelGetWaitID(threadID, WAITTYPE_CTRL, error); + // Make sure it didn't get woken or something. + if (wVal == 0) + goto retry; + + u32 ctrlDataPtr = __KernelGetWaitValue(threadID, error); + int retVal = __CtrlReadSingleBuffer(ctrlDataPtr, wVal == CTRL_WAIT_NEGATIVE); + __KernelResumeThreadFromWait(threadID, retVal); + } } void __CtrlInit() @@ -229,47 +298,19 @@ void sceCtrlSetIdleCancelThreshold() RETURN(0); } -int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) -{ - if (nBufs > 64) - return PSP_CTRL_ERROR_INVALID_NUM_BUFFERS; - - int resetRead = ctrlBufRead; - - int done = 0; - _ctrl_data data; - for (u32 i = 0; i < nBufs; ++i) - { - // Ran out of buffers. - if (ctrlBuf == ctrlBufRead) - break; - - if (Memory::IsValidAddress(ctrlDataPtr)) - { - memcpy(&data, &ctrlBufs[ctrlBufRead], sizeof(_ctrl_data)); - ctrlBufRead = (ctrlBufRead + 1) % 64; - - if (negative) - data.buttons = ~data.buttons; - - Memory::WriteStruct(ctrlDataPtr, &data); - done++; - } - ctrlDataPtr += sizeof(_ctrl_data); - } - - if (peek) - ctrlBufRead = resetRead; - - return done; -} - void sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) { // TODO: Wait for vblank if there are 0 buffers (resched.) DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); - RETURN(__CtrlReadBuffer(ctrlDataPtr, nBufs, false, false)); + int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, false); + if (done != 0) + RETURN(done); + else + { + waitingThreads.push_back(__KernelGetCurThread()); + __KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_POSITIVE, ctrlDataPtr, 0, false); + } } void sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) @@ -277,7 +318,14 @@ void sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) // TODO: Wait for vblank if there are 0 buffers (resched.) DEBUG_LOG(HLE,"sceCtrlReadBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); - RETURN(__CtrlReadBuffer(ctrlDataPtr, nBufs, true, false)); + int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, false); + if (done != 0) + RETURN(done); + else + { + waitingThreads.push_back(__KernelGetCurThread()); + __KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_NEGATIVE, ctrlDataPtr, 0, false); + } } int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs) diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index fb623ef17e..d4f2919b64 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -73,6 +73,7 @@ const char *waitTypeStrings[] = "Vblank", "Mutex", "LwMutex", + "Ctrl", }; struct SceKernelSysClock { diff --git a/Core/HLE/sceKernelThread.h b/Core/HLE/sceKernelThread.h index 36ec19c244..8a649b6557 100644 --- a/Core/HLE/sceKernelThread.h +++ b/Core/HLE/sceKernelThread.h @@ -70,6 +70,7 @@ enum WaitType //probably not the real values WAITTYPE_VBLANK = 12, // fake WAITTYPE_MUTEX = 13, WAITTYPE_LWMUTEX = 14, + WAITTYPE_CTRL = 15, // Remember to update sceKernelThread.cpp's waitTypeStrings to match. }; From f6009e477f05c877f3965885559bb545702288c9 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 17:04:57 -0800 Subject: [PATCH 25/35] Start with one free buffer to match things. --- Core/HLE/sceCtrl.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 730719816d..559c75ab11 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -226,7 +226,7 @@ void __CtrlInit() ctrlInited = true; } - ctrlBuf = 0; + ctrlBuf = 1; ctrlBufRead = 0; ctrlOldButtons = 0; ctrlLatchBufs = 0; @@ -239,6 +239,8 @@ void __CtrlInit() memset(&ctrlBufs, 0, sizeof(ctrlBufs)); ctrlCurrent.analog[0] = 128; ctrlCurrent.analog[1] = 128; + ctrlBufs[0].analog[0] = 128; + ctrlBufs[0].analog[1] = 128; } void sceCtrlInit() From 70efb2c3d1d3743cbabbebc811bf8d5423bd5337 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 17:19:57 -0800 Subject: [PATCH 26/35] Test update. --- pspautotests | 2 +- test.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pspautotests b/pspautotests index 3c81649c4b..c725dde370 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 3c81649c4b4056ddabaca293c093ba0d6989502b +Subproject commit c725dde370fac6cb2776a9e1e0a200e0dab11f1e diff --git a/test.py b/test.py index 1378ed3018..3523fd8074 100755 --- a/test.py +++ b/test.py @@ -47,6 +47,8 @@ tests_good = [ "cpu/lsu/lsu", "cpu/fpu/fpu", + "ctrl/ctrl", + "ctrl/sampling/sampling", "display/display", "dmac/dmactest", "loader/bss/bss", @@ -95,7 +97,6 @@ tests_next = [ "threads/vpl/vpl", "threads/vtimers/vtimer", "threads/wakeup/wakeup", - "ctrl/ctrl", "gpu/simple/simple", "gpu/triangle/triangle", "hle/check_not_used_uids", From 8a801ff761856705b2e72c91a2d709832cfd356d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 19:53:20 -0800 Subject: [PATCH 27/35] Send the recent N ctrl buffers, fixing lag. --- Core/HLE/sceCtrl.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 559c75ab11..cf1370460b 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -175,6 +175,11 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) int resetRead = ctrlBufRead; + u32 availBufs = (ctrlBuf - ctrlBufRead + 64) % 64; + if (availBufs > nBufs) + availBufs = nBufs; + ctrlBufRead = (ctrlBuf - availBufs + 64) % 64; + int done = 0; for (u32 i = 0; i < nBufs; ++i) { @@ -296,50 +301,54 @@ int sceCtrlGetSamplingMode(u32 modePtr) void sceCtrlSetIdleCancelThreshold() { - DEBUG_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold"); + ERROR_LOG(HLE,"UNIMPL sceCtrlSetIdleCancelThreshold"); RETURN(0); } void sceCtrlReadBufferPositive(u32 ctrlDataPtr, u32 nBufs) { - // TODO: Wait for vblank if there are 0 buffers (resched.) - DEBUG_LOG(HLE,"sceCtrlReadBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); - int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, false); if (done != 0) + { RETURN(done); + DEBUG_LOG(HLE, "%d=sceCtrlReadBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs); + } else { waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_POSITIVE, ctrlDataPtr, 0, false); + DEBUG_LOG(HLE, "sceCtrlReadBufferPositive(%08x, %i) - waiting", ctrlDataPtr, nBufs); } } void sceCtrlReadBufferNegative(u32 ctrlDataPtr, u32 nBufs) { - // TODO: Wait for vblank if there are 0 buffers (resched.) - DEBUG_LOG(HLE,"sceCtrlReadBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); - int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, false); if (done != 0) + { RETURN(done); + DEBUG_LOG(HLE, "%d=sceCtrlReadBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs); + } else { waitingThreads.push_back(__KernelGetCurThread()); __KernelWaitCurThread(WAITTYPE_CTRL, CTRL_WAIT_NEGATIVE, ctrlDataPtr, 0, false); + DEBUG_LOG(HLE, "sceCtrlReadBufferNegative(%08x, %i) - waiting", ctrlDataPtr, nBufs); } } int sceCtrlPeekBufferPositive(u32 ctrlDataPtr, u32 nBufs) { - DEBUG_LOG(HLE,"sceCtrlPeekBufferPositive(%08x, %i)", ctrlDataPtr, nBufs); - return __CtrlReadBuffer(ctrlDataPtr, nBufs, false, true); + int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, false, true); + DEBUG_LOG(HLE, "%d=sceCtrlPeekBufferPositive(%08x, %i)", done, ctrlDataPtr, nBufs); + return done; } int sceCtrlPeekBufferNegative(u32 ctrlDataPtr, u32 nBufs) { - DEBUG_LOG(HLE,"sceCtrlPeekBufferNegative(%08x, %i)", ctrlDataPtr, nBufs); - return __CtrlReadBuffer(ctrlDataPtr, nBufs, true, true); + int done = __CtrlReadBuffer(ctrlDataPtr, nBufs, true, true); + DEBUG_LOG(HLE, "%d=sceCtrlPeekBufferNegative(%08x, %i)", done, ctrlDataPtr, nBufs); + return done; } u32 sceCtrlPeekLatch(u32 latchDataPtr) From d07e51bff022c4e2fb3349e00ce06b787662325b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 2 Dec 2012 21:07:17 -0800 Subject: [PATCH 28/35] Always allow peeking into ctrl buffers. --- Core/HLE/sceCtrl.cpp | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index cf1370460b..73e03def9d 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -34,6 +34,8 @@ const int PSP_CTRL_ERROR_INVALID_MODE = 0x80000107; const int PSP_CTRL_ERROR_INVALID_NUM_BUFFERS = 0x80000104; +const int NUM_CTRL_BUFFERS = 64; + enum { CTRL_WAIT_POSITIVE = 1, @@ -64,7 +66,7 @@ static bool analogEnabled = false; static int ctrlLatchBufs = 0; static u32 ctrlOldButtons = 0; -static _ctrl_data ctrlBufs[64]; +static _ctrl_data ctrlBufs[NUM_CTRL_BUFFERS]; static _ctrl_data ctrlCurrent; static int ctrlBuf = 0; static int ctrlBufRead = 0; @@ -100,12 +102,12 @@ void __CtrlUpdateLatch() ctrlBufs[ctrlBuf].analog[1] = 128; } - ctrlBuf = (ctrlBuf + 1) % 64; + ctrlBuf = (ctrlBuf + 1) % NUM_CTRL_BUFFERS; // If we wrapped around, push the read head forward. // TODO: Is this right? if (ctrlBufRead == ctrlBuf) - ctrlBufRead = (ctrlBufRead + 1) % 64; + ctrlBufRead = (ctrlBufRead + 1) % NUM_CTRL_BUFFERS; } int __CtrlResetLatch() @@ -156,7 +158,7 @@ int __CtrlReadSingleBuffer(u32 ctrlDataPtr, bool negative) if (Memory::IsValidAddress(ctrlDataPtr)) { memcpy(&data, &ctrlBufs[ctrlBufRead], sizeof(_ctrl_data)); - ctrlBufRead = (ctrlBufRead + 1) % 64; + ctrlBufRead = (ctrlBufRead + 1) % NUM_CTRL_BUFFERS; if (negative) data.buttons = ~data.buttons; @@ -170,23 +172,26 @@ int __CtrlReadSingleBuffer(u32 ctrlDataPtr, bool negative) int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek) { - if (nBufs > 64) + if (nBufs > NUM_CTRL_BUFFERS) return PSP_CTRL_ERROR_INVALID_NUM_BUFFERS; int resetRead = ctrlBufRead; - u32 availBufs = (ctrlBuf - ctrlBufRead + 64) % 64; - if (availBufs > nBufs) + u32 availBufs; + // Peeks always work, they just go go from now X buffers. + if (peek) availBufs = nBufs; - ctrlBufRead = (ctrlBuf - availBufs + 64) % 64; + else + { + availBufs = (ctrlBuf - ctrlBufRead + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS; + if (availBufs > nBufs) + availBufs = nBufs; + } + ctrlBufRead = (ctrlBuf - availBufs + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS; int done = 0; - for (u32 i = 0; i < nBufs; ++i) + for (u32 i = 0; i < availBufs; ++i) { - // Ran out of buffers. - if (ctrlBuf == ctrlBufRead) - break; - done += __CtrlReadSingleBuffer(ctrlDataPtr, negative); ctrlDataPtr += sizeof(_ctrl_data); } @@ -241,11 +246,11 @@ void __CtrlInit() latch.btnRelease = 0xffffffff; memset(&ctrlCurrent, 0, sizeof(ctrlCurrent)); - memset(&ctrlBufs, 0, sizeof(ctrlBufs)); ctrlCurrent.analog[0] = 128; ctrlCurrent.analog[1] = 128; - ctrlBufs[0].analog[0] = 128; - ctrlBufs[0].analog[1] = 128; + + for (int i = 0; i < NUM_CTRL_BUFFERS; i++) + memcpy(&ctrlBufs[i], &ctrlCurrent, sizeof(_ctrl_data)); } void sceCtrlInit() From d91314d906fefdfd7f4bd0909aa88a9b9fd31050 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Mon, 3 Dec 2012 16:44:37 +0800 Subject: [PATCH 29/35] Update Windows/main.cpp Increase windows scheduling resolution --- Windows/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Windows/main.cpp b/Windows/main.cpp index aa2d422de1..7170d7ba2a 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -73,7 +73,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin comm.dwSize = sizeof(comm); comm.dwICC = ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES; InitCommonControlsEx(&comm); - + timeBeginPeriod(1); MainWindow::Init(_hInstance); HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS); @@ -132,6 +132,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin LogManager::Shutdown(); DialogManager::DestroyAll(); + timeEndPeriod(1); g_Config.Save(); delete host; return 0; From ad59c7f46d1301db24d6fcad09f61f9c780d66fd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 3 Dec 2012 07:44:29 -0800 Subject: [PATCH 30/35] Convert the title to wchars to fix non-ASCII. --- Windows/WindowsHost.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 9c56f14567..85b317c6c4 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -40,7 +40,27 @@ void WindowsHost::SetWindowTitle(const char *message) // Really need a better way to deal with versions. std::string title = "PPSSPP v0.4 - "; title += message; - SetWindowText(mainWindow_, title.c_str()); + + int size = MultiByteToWideChar(CP_UTF8, 0, message, title.size(), NULL, 0); + if (size > 0) + { + wchar_t *utf16_title = new wchar_t[size + 1]; + if (utf16_title) + size = MultiByteToWideChar(CP_UTF8, 0, message, title.size(), utf16_title, size); + else + size = 0; + + if (size > 0) + { + utf16_title[size] = 0; + SetWindowTextW(mainWindow_, utf16_title); + delete[] utf16_title; + } + } + + // Something went wrong, fall back to using the local codepage. + if (size <= 0) + SetWindowTextA(mainWindow_, title.c_str()); } void WindowsHost::InitSound(PMixer *mixer) From 346095d5f085984d80b6d9b0589c8afd2931b9cd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 3 Dec 2012 07:57:28 -0800 Subject: [PATCH 31/35] SetWindowText() was doing ANSI conversion. --- Windows/WindowsHost.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 85b317c6c4..7dc6b109ee 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -53,7 +53,8 @@ void WindowsHost::SetWindowTitle(const char *message) if (size > 0) { utf16_title[size] = 0; - SetWindowTextW(mainWindow_, utf16_title); + // Don't use SetWindowTextW because it will internally use DefWindowProcA. + DefWindowProcW(mainWindow_, WM_SETTEXT, 0, (LPARAM) utf16_title); delete[] utf16_title; } } From 742da2cec8114545f8042008e953192d4e6d8927 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 3 Dec 2012 23:03:44 -0800 Subject: [PATCH 32/35] Update tests to tip. --- pspautotests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pspautotests b/pspautotests index c725dde370..494e3592da 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit c725dde370fac6cb2776a9e1e0a200e0dab11f1e +Subproject commit 494e3592da54708e6178a3f6efa1467a4403c2fc From 582b078c2364b69cf0f66d265293c3e8b31455c6 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Wed, 5 Dec 2012 00:04:24 +0800 Subject: [PATCH 33/35] Update Core/Config.cpp --- Core/Config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index aa8fb39afa..e8cf8f1741 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -48,7 +48,7 @@ void CConfig::Load(const char *iniFileName) general->Get("ConfirmOnQuit", &bConfirmOnQuit, false); general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true); general->Get("CurrentDirectory", ¤tDirectory, ""); - + general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false); IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); cpu->Get("Core", &iCpuCore, 0); @@ -79,7 +79,7 @@ void CConfig::Save() general->Set("ConfirmOnQuit", bConfirmOnQuit); general->Set("IgnoreBadMemAccess", bIgnoreBadMemAccess); general->Set("CurrentDirectory", currentDirectory); - + general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad); IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU"); cpu->Set("Core", iCpuCore); From 0b659e20fd6dd752946056dcfcd0a87372150bd0 Mon Sep 17 00:00:00 2001 From: jacky400 Date: Wed, 5 Dec 2012 00:04:55 +0800 Subject: [PATCH 34/35] Update Core/Config.h --- Core/Config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Config.h b/Core/Config.h index f7add3be19..0581bb8c79 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -43,7 +43,7 @@ public: bool bIgnoreBadMemAccess; bool bDisplayFramebuffer; bool bBufferedRendering; - + bool bShowDebuggerOnLoad; bool bShowAnalogStick; bool bShowFPSCounter; bool bShowDebugStats; From a072fff4d47baa45b8a14ec50e28e7a987fb76ef Mon Sep 17 00:00:00 2001 From: jacky400 Date: Wed, 5 Dec 2012 00:05:36 +0800 Subject: [PATCH 35/35] Update Windows/WndMainWindow.cpp --- Windows/WndMainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 51cd5df02a..c0d40527bb 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -580,7 +580,7 @@ namespace MainWindow case WM_USER+1: disasmWindow[0] = new CDisasm(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS); DialogManager::AddDlg(disasmWindow[0]); - disasmWindow[0]->Show(TRUE); + disasmWindow[0]->Show(g_Config.bShowDebuggerOnLoad); memoryWindow[0] = new CMemoryDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS); DialogManager::AddDlg(memoryWindow[0]); if (disasmWindow[0])