mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge branch 'master' of https://github.com/hrydgard/ppsspp into improvedTilControls
This commit is contained in:
commit
b0c7e824be
401 changed files with 28256 additions and 19843 deletions
79
.travis.yml
79
.travis.yml
|
@ -4,33 +4,70 @@ language: cpp
|
|||
|
||||
env:
|
||||
- PPSSPP_BUILD_TYPE=Linux
|
||||
CMAKE=TRUE
|
||||
- PPSSPP_BUILD_TYPE=Android
|
||||
- PPSSPP_BUILD_TYPE=Blackberry
|
||||
CMAKE=TRUE
|
||||
- PPSSPP_BUILD_TYPE=Symbian
|
||||
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:ubuntu-sdk-team/ppa
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install cmake libsdl1.2-dev openjdk-7-jdk ant lib32z1-dev lib32stdc++6
|
||||
- git submodule update --init --recursive
|
||||
- if [ "$PPSSPP_BUILD_TYPE" == "Android" ]; then wget --timeout=30 http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2 -O ndk.tar.bz2 && tar -xf ndk.tar.bz2; fi
|
||||
- if [[ "$CXX" == *clang* ]]; then export NDK_TOOLCHAIN_VERSION=clang; fi
|
||||
- export ANDROID_HOME=$(pwd)/android-ndk-r9 NDK=$(pwd)/android-ndk-r9
|
||||
matrix:
|
||||
include:
|
||||
- compiler: clang
|
||||
env: PPSSPP_BUILD_TYPE=Linux
|
||||
CMAKE=TRUE
|
||||
|
||||
before_script:
|
||||
- mkdir build-travis
|
||||
- cd build-travis
|
||||
- cmake -DHEADLESS=ON ..
|
||||
- cd ..
|
||||
before_install:
|
||||
- git submodule update --init --recursive
|
||||
- sudo apt-get install aria2 -qq
|
||||
- download_extract() { aria2c -x 16 $1 -o $2 && tar -xf $2; }
|
||||
# Travis uses CMake 2.8.7. We require 2.8.8. Grab latest
|
||||
- if [ "$CMAKE" == "TRUE" ]; then
|
||||
sudo apt-get install lib32stdc++6 -qq &&
|
||||
aria2c -x 16 http://www.cmake.org/files/v2.8/cmake-2.8.12.1-Linux-i386.sh &&
|
||||
chmod a+x cmake-2.8.12.1-Linux-i386.sh &&
|
||||
sudo ./cmake-2.8.12.1-Linux-i386.sh --skip-license --prefix=/usr;
|
||||
fi
|
||||
|
||||
install:
|
||||
# Linux Setup
|
||||
- if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then
|
||||
sudo apt-get install libsdl1.2-dev -qq;
|
||||
# Android NDK
|
||||
- elif [ "$PPSSPP_BUILD_TYPE" == "Android" ]; then
|
||||
NDK_VER=android-ndk-r9b &&
|
||||
sudo apt-get install ant -qq &&
|
||||
download_extract http://dl.google.com/android/ndk/${NDK_VER}-linux-x86_64.tar.bz2 ${NDK_VER}-linux-x86_64.tar.bz2 &&
|
||||
export ANDROID_HOME=$(pwd)/${NDK_VER} NDK=$(pwd)/${NDK_VER} &&
|
||||
if [[ "$CXX" == *clang* ]]; then export NDK_TOOLCHAIN_VERSION=clang; fi;
|
||||
# Blackberry NDK: 10.2.0.1155
|
||||
- elif [ "$PPSSPP_BUILD_TYPE" == "Blackberry" ]; then
|
||||
download_extract https://googledrive.com/host/0B5UBD4wjtpZ-QVdzSElobzNTOU0 libs.tar.gz &&
|
||||
download_extract https://googledrive.com/host/0B5UBD4wjtpZ-NV80UzFYMVRkSXM tools.tar.gz &&
|
||||
export QNX_TARGET="$(pwd)/target_10_2_0_1155/qnx6" QNX_HOST="$(pwd)/host_10_2_0_15/linux/x86" && PATH="$QNX_HOST/usr/bin:$PATH";
|
||||
# Symbian NDK: Belle
|
||||
- elif [ "$PPSSPP_BUILD_TYPE" == "Symbian" ]; then
|
||||
sudo apt-get install lib32stdc++6 lib32bz2-1.0 -qq &&
|
||||
download_extract https://googledrive.com/host/0B5UBD4wjtpZ-T0Iwa0F3b2JqREE ndk.tar.bz2 &&
|
||||
sed -i "s!/SDKs!$(pwd)/SDKs!" SDKs/SymbianSR1Qt474/bin/qt.conf &&
|
||||
cp ffmpeg/symbian/armv6/lib/* SDKs/SymbianSR1Qt474/epoc32/release/armv5/urel/ &&
|
||||
export EPOCROOT=$(pwd)/SDKs/SymbianSR1Qt474 SBS_GCCE463BIN=$(pwd)/tools/gcce4/bin &&
|
||||
PATH=$SBS_GCCE463BIN:$(pwd)/tools/sbs/bin:$EPOCROOT/epoc32/tools:$(pwd)/tools:$EPOCROOT/bin:$(pwd)/tools/sbs/linux-x86_64-libc2_15/bin:$PATH;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then cd build-travis && make && cd ..; else cd android && ./ab.sh && cd ..; fi
|
||||
- if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then ./test.py; fi
|
||||
# Compile PPSSPP
|
||||
- if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then
|
||||
./b.sh --headless;
|
||||
- elif [ "$PPSSPP_BUILD_TYPE" == "Android" ]; then
|
||||
pushd android && ./ab.sh && popd;
|
||||
- elif [ "$PPSSPP_BUILD_TYPE" == "Blackberry" ]; then
|
||||
./b.sh --no-package;
|
||||
- elif [ "$PPSSPP_BUILD_TYPE" == "Symbian" ]; then
|
||||
pushd Qt && qmake -spec symbian-sbsv2 PPSSPPQt.pro && make release-gcce -j4 && make sis && popd;
|
||||
fi
|
||||
|
||||
# For now, Android clang seems to be failing to build.
|
||||
matrix:
|
||||
exclude:
|
||||
- compiler: clang
|
||||
env: PPSSPP_BUILD_TYPE=Android
|
||||
after_success:
|
||||
- if [ "$PPSSPP_BUILD_TYPE" == "Linux" ]; then ./test.py; fi
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<id>com.Qtness.PPSSPP</id>
|
||||
<name>PPSSPP</name>
|
||||
<filename>PPSSPPBlackberry</filename>
|
||||
<versionNumber>0.9.5</versionNumber>
|
||||
<versionNumber>0.9.6</versionNumber>
|
||||
<buildId>1</buildId>
|
||||
<description>Playstation portable emulator.</description>
|
||||
<description>Playstation Portable emulator.</description>
|
||||
|
||||
<author>Qtness</author>
|
||||
<authorId>gYAAgGE4qaHzBnzEAu8JKe4G1OI</authorId>
|
||||
|
|
33
Blackberry/bb.toolchain.cmake
Normal file
33
Blackberry/bb.toolchain.cmake
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Standard settings
|
||||
set (CMAKE_SYSTEM_NAME QNX)
|
||||
set (CMAKE_SYSTEM_VERSION 1)
|
||||
set (CMAKE_PREFIX_PATH $ENV{QNX_TARGET}/usr)
|
||||
set (CMAKE_INCLUDE_PATH $ENV{QNX_TARGET}/usr/include)
|
||||
if (SIMULATOR)
|
||||
set (CMAKE_SYSTEM_PROCESSOR x86)
|
||||
set (CMAKE_LIBRARY_PATH $ENV{QNX_TARGET}/x86 $ENV{QNX_TARGET}/x86/usr)
|
||||
else()
|
||||
set (CMAKE_SYSTEM_PROCESSOR armv7)
|
||||
set (CMAKE_LIBRARY_PATH $ENV{QNX_TARGET}/armle-v7 $ENV{QNX_TARGET}/armle-v7/usr)
|
||||
endif()
|
||||
set (UNIX True)
|
||||
|
||||
set (CMAKE_FIND_ROOT_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_LIBRARY_PATH} CACHE string "Blackberry find search path root")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
|
||||
include (CMakeForceCompiler)
|
||||
CMAKE_FORCE_C_COMPILER (nto${CMAKE_SYSTEM_PROCESSOR}-gcc nto${CMAKE_SYSTEM_PROCESSOR}-gcc)
|
||||
CMAKE_FORCE_CXX_COMPILER (nto${CMAKE_SYSTEM_PROCESSOR}-g++ nto${CMAKE_SYSTEM_PROCESSOR}-g++)
|
||||
set (CMAKE_COMPILER_IS_GNUCXX True)
|
||||
execute_process( COMMAND nto${CMAKE_SYSTEM_PROCESSOR}-gcc --version
|
||||
OUTPUT_VARIABLE GCC_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
|
||||
string( REGEX MATCH "[0-9]+.[0-9]+.[0-9]+" GCC_VERSION "${GCC_VERSION}" )
|
||||
set (CMAKE_C_COMPILER_VERSION ${GCC_VERSION})
|
||||
set (CMAKE_CXX_COMPILER_VERSION ${GCC_VERSION})
|
||||
|
||||
# Skip the platform compiler checks for cross compiling
|
||||
set (CMAKE_CROSSCOMPILING TRUE)
|
||||
set (CMAKE_C_COMPILER_WORKS TRUE)
|
||||
set (CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
BB_OS=`cat ${QNX_TARGET}/etc/qversion 2>/dev/null`
|
||||
if [ -z "$BB_OS" ]; then
|
||||
echo "Could not find your Blackberry NDK. Please source bbndk-env.sh"
|
||||
exit 1
|
||||
fi
|
||||
echo "Building for Blackberry ${BB_OS}"
|
||||
|
||||
# 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"
|
||||
make -j4 && blackberry-nativepackager -package PPSSPP.bar bar-descriptor.xml $DEBUG
|
589
CMakeLists.txt
589
CMakeLists.txt
|
@ -10,13 +10,17 @@ if(ANDROID)
|
|||
endif()
|
||||
|
||||
if(BLACKBERRY)
|
||||
set(CMAKE_SYSTEM_NAME "QNX")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS")
|
||||
endif()
|
||||
|
||||
if (IOS OR BLACKBERRY)
|
||||
set(ARM ON)
|
||||
set(USE_FFMPEG ON)
|
||||
if (SIMULATOR)
|
||||
set(X86 ON)
|
||||
else()
|
||||
set(ARM ON)
|
||||
set(ARMEABI_V7A ON)
|
||||
set(USE_FFMPEG ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (MAEMO)
|
||||
|
@ -29,7 +33,7 @@ if(LOONGSON)
|
|||
set(MIPS ON) # MIPS + x86 for now
|
||||
endif()
|
||||
|
||||
if(ARM)
|
||||
if(ARM OR SIMULATOR)
|
||||
set(USING_GLES2 ON)
|
||||
else() # Assume x86
|
||||
set(X86 ON)
|
||||
|
@ -64,26 +68,28 @@ option(IOS "Set to ON if targeting an iOS device" ${IOS})
|
|||
option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2})
|
||||
option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI})
|
||||
option(HEADLESS "Set to OFF to not generate the PPSSPPHeadless target" ${HEADLESS})
|
||||
option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" ${SIMULATOR})
|
||||
option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG})
|
||||
|
||||
if(ANDROID)
|
||||
if(NOT ANDROID_ABI)
|
||||
if(ANDROID OR BLACKBERRY OR IOS)
|
||||
if (NOT CMAKE_TOOLCHAIN_FILE)
|
||||
if (ANDROID)
|
||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/android/android.toolchain.cmake)
|
||||
elseif(BLACKBERRY)
|
||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/Blackberry/bb.toolchain.cmake)
|
||||
elseif(IOS)
|
||||
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_SOURCE_DIR}/ios/ios.toolchain.cmake)
|
||||
endif()
|
||||
message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE was not set!\n"
|
||||
"Delete the CMakeCache.txt file and CMakeFiles directory."
|
||||
"Rerun ${CMAKE_COMMAND} with \"-DCMAKE_TOOLCHAIN_FILE"
|
||||
"=${CMAKE_SOURCE_DIR}/android/android.toolchain.cmake\"")
|
||||
"Delete the CMakeCache.txt file and CMakeFiles directory.\n"
|
||||
"Re-run ${CMAKE_COMMAND} with:\n"
|
||||
"\"-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}\"")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID)
|
||||
set(CoreLibName ppsspp_jni)
|
||||
set(CoreLinkType SHARED)
|
||||
elseif(IOS)
|
||||
if (NOT IOS_PLATFORM)
|
||||
message(FATAL_ERROR "CMAKE_TOOLCHAIN_FILE was not set!\n"
|
||||
"Delete the CMakeCache.txt file and CMakeFiles directory."
|
||||
"Rerun ${CMAKE_COMMAND} with \"-DCMAKE_TOOLCHAIN_FILE"
|
||||
"=${CMAKE_SOURCE_DIR}/ios/ios.toolchain.cmake\"")
|
||||
endif()
|
||||
set(CoreLibName Core)
|
||||
set(CoreLinkType STATIC)
|
||||
else()
|
||||
set(CoreLibName Core)
|
||||
set(CoreLinkType STATIC)
|
||||
|
@ -149,7 +155,7 @@ if(NOT MSVC)
|
|||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -parallel -fopenmp")
|
||||
endif()
|
||||
if(NOT APPLE)
|
||||
if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
|
||||
if (NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND NOT CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
add_definitions(-Wno-psabi)
|
||||
endif()
|
||||
add_definitions(-D_XOPEN_SOURCE=600 -D_XOPEN_SOURCE_EXTENDED -D__BSD_VISIBLE=1)
|
||||
|
@ -160,7 +166,10 @@ if(NOT MSVC)
|
|||
endif()
|
||||
|
||||
if(BLACKBERRY)
|
||||
add_definitions(-D_QNX_SOURCE -DARMV7 -O3 -mfpu=neon -mtune=cortex-a9)
|
||||
add_definitions(-D_QNX_SOURCE)
|
||||
if(ARM)
|
||||
add_definitions(-DARMV7 -O3 -mfpu=neon -mcpu=cortex-a9)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(X86 AND NOT MIPS)
|
||||
|
@ -259,8 +268,6 @@ add_library(Common STATIC
|
|||
Common/KeyMap.h
|
||||
Common/LogManager.cpp
|
||||
Common/LogManager.h
|
||||
Common/MathUtil.cpp
|
||||
Common/MathUtil.h
|
||||
Common/MemArena.cpp
|
||||
Common/MemArena.h
|
||||
Common/MemoryUtil.cpp
|
||||
|
@ -270,8 +277,6 @@ add_library(Common STATIC
|
|||
Common/MsgHandler.h
|
||||
Common/StringUtils.cpp
|
||||
Common/StringUtils.h
|
||||
Common/Thread.cpp
|
||||
Common/Thread.h
|
||||
Common/ThreadPools.cpp
|
||||
Common/ThreadPools.h
|
||||
Common/Timer.cpp
|
||||
|
@ -283,8 +288,175 @@ if(WIN32)
|
|||
target_link_libraries(Common winmm)
|
||||
endif()
|
||||
|
||||
if(BLACKBERRY)
|
||||
set(LIBZIP z)
|
||||
if(NOT USING_GLES2)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
add_library(glew STATIC
|
||||
native/ext/glew/GL/glew.h
|
||||
native/ext/glew/GL/glxew.h
|
||||
native/ext/glew/GL/wglew.h
|
||||
native/ext/glew/glew.c)
|
||||
target_link_libraries(glew ${OPENGL_LIBRARIES})
|
||||
include_directories(native/ext/glew)
|
||||
set(GLEW_LIBRARIES glew)
|
||||
endif()
|
||||
|
||||
add_library(snappy STATIC
|
||||
ext/snappy/snappy-c.cpp
|
||||
ext/snappy/snappy-internal.h
|
||||
ext/snappy/snappy-sinksource.h
|
||||
ext/snappy/snappy-stubs-internal.h
|
||||
ext/snappy/snappy-stubs-public.h
|
||||
ext/snappy/snappy.cpp
|
||||
ext/snappy/snappy.h
|
||||
)
|
||||
include_directories(ext/snappy)
|
||||
|
||||
add_library(vjson STATIC
|
||||
native/ext/vjson/json.cpp
|
||||
native/ext/vjson/json.h
|
||||
native/ext/vjson/block_allocator.cpp
|
||||
native/ext/vjson/block_allocator.h
|
||||
)
|
||||
|
||||
add_library(rg_etc1 STATIC
|
||||
native/ext/rg_etc1/rg_etc1.cpp
|
||||
native/ext/rg_etc1/rg_etc1.h)
|
||||
include_directories(native/ext/rg_etc1)
|
||||
|
||||
add_library(stb_vorbis STATIC
|
||||
native/ext/stb_vorbis/stb_vorbis.c
|
||||
native/ext/stb_vorbis/stb_vorbis.h)
|
||||
include_directories(native/ext/stb_vorbis)
|
||||
|
||||
if(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR)
|
||||
if(BLACKBERRY)
|
||||
set(PLATFORM_ARCH "blackberry/armv7")
|
||||
elseif(IOS)
|
||||
set(PLATFORM_ARCH "ios/universal")
|
||||
elseif(MACOSX)
|
||||
set(PLATFORM_ARCH "macosx/x86_64")
|
||||
elseif(LINUX)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(PLATFORM_ARCH "linux/x86_64")
|
||||
else()
|
||||
set(PLATFORM_ARCH "linux/x86")
|
||||
endif()
|
||||
endif()
|
||||
# Using static libraries
|
||||
if (DEFINED PLATFORM_ARCH)
|
||||
include_directories(ffmpeg/${PLATFORM_ARCH}/include)
|
||||
link_directories(ffmpeg/${PLATFORM_ARCH}/lib)
|
||||
set(FFMPEG_LIBRARIES libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a)
|
||||
else()
|
||||
# Manual definition of system library locations by the user.
|
||||
if (DEFINED FFMPEG_INCLUDE_PATH)
|
||||
include_directories(ffmpeg ${FFMPEG_INCLUDE_PATH})
|
||||
endif()
|
||||
if (DEFINED AVFORMAT_PATH)
|
||||
add_library(libavformat STATIC IMPORTED)
|
||||
set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${AVFORMAT_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavformat)
|
||||
endif()
|
||||
if (DEFINED AVCODEC_PATH)
|
||||
add_library(libavcodec STATIC IMPORTED)
|
||||
set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${AVCODEC_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavcodec)
|
||||
endif()
|
||||
if (DEFINED AVUTIL_PATH)
|
||||
add_library(libavutil STATIC IMPORTED)
|
||||
set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${AVUTIL_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavutil)
|
||||
endif()
|
||||
if (DEFINED SWRESAMPLE_PATH)
|
||||
add_library(libswresample STATIC IMPORTED)
|
||||
set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${SWRESAMPLE_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswresample)
|
||||
endif()
|
||||
if (DEFINED SWSCALE_PATH)
|
||||
add_library(libswscale STATIC IMPORTED)
|
||||
set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${SWSCALE_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswscale)
|
||||
endif()
|
||||
endif(DEFINED PLATFORM_ARCH)
|
||||
endif(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR)
|
||||
|
||||
if(USE_FFMPEG)
|
||||
# Using shared libraries
|
||||
if(DEFINED FFMPEG_BUILDDIR)
|
||||
include_directories(ffmpeg ${FFMPEG_BUILDDIR})
|
||||
|
||||
add_library(libavformat STATIC IMPORTED)
|
||||
set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavformat/libavformat.a)
|
||||
add_library(libavcodec STATIC IMPORTED)
|
||||
set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavcodec/libavcodec.a)
|
||||
add_library(libavutil STATIC IMPORTED)
|
||||
set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavutil/libavutil.a)
|
||||
add_library(libswresample STATIC IMPORTED)
|
||||
set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswresample/libswresample.a)
|
||||
add_library(libswscale STATIC IMPORTED)
|
||||
set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswscale/libswscale.a)
|
||||
|
||||
SET (FFMPEG_LIBRARIES
|
||||
libavformat
|
||||
libavcodec
|
||||
libavutil
|
||||
libswresample
|
||||
libswscale
|
||||
)
|
||||
endif()
|
||||
|
||||
if(IOS OR BLACKBERRY)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} iconv)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} bz2 "-framework CoreVideo")
|
||||
if (NOT IOS)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} "-framework VideoDecodeAcceleration")
|
||||
endif()
|
||||
endif(APPLE)
|
||||
|
||||
set(LinkCommon ${LinkCommon} ${FFMPEG_LIBRARIES})
|
||||
add_definitions(-DUSE_FFMPEG)
|
||||
endif(USE_FFMPEG)
|
||||
|
||||
# Modification to show where we are pulling the ffmpeg libraries from.
|
||||
if(USE_FFMPEG AND DEFINED FFMPEG_LIBRARIES)
|
||||
target_link_libraries(Common ${FFMPEG_LIBRARIES})
|
||||
message(STATUS "FFMPEG library locations:")
|
||||
if(DEFINED PLATFORM_ARCH)
|
||||
set(TEMP ${CMAKE_SOURCE_DIR}/ffmpeg/${PLATFORM_ARCH}/lib)
|
||||
message(STATUS "libavcodec location: ${TEMP}/libavcodec.a")
|
||||
message(STATUS "libavformat location: ${TEMP}/libavformat.a")
|
||||
message(STATUS "libavutil location: ${TEMP}/libavutil.a")
|
||||
message(STATUS "libswresample location: ${TEMP}/libswresample.a")
|
||||
message(STATUS "libswscale location: ${TEMP}/libswscale.a")
|
||||
else()
|
||||
get_target_property(TEMP libavcodec IMPORTED_LOCATION)
|
||||
message(STATUS "libavcodec location: ${TEMP}")
|
||||
get_target_property(TEMP libavformat IMPORTED_LOCATION)
|
||||
message(STATUS "libavformat location: ${TEMP}")
|
||||
get_target_property(TEMP libavutil IMPORTED_LOCATION)
|
||||
message(STATUS "libavutil location: ${TEMP}")
|
||||
get_target_property(TEMP libswresample IMPORTED_LOCATION)
|
||||
message(STATUS "libswresample location: ${TEMP}")
|
||||
get_target_property(TEMP libswscale IMPORTED_LOCATION)
|
||||
message(STATUS "libswscale location: ${TEMP}")
|
||||
endif(DEFINED PLATFORM_ARCH)
|
||||
else()
|
||||
message(STATUS "ERROR: No FFMPEG library locations")
|
||||
endif()
|
||||
|
||||
if(USE_FFMPEG AND NOT DEFINED FFMPEG_LIBRARIES)
|
||||
message(WARNING "FFMPEG_BUILDDIR variable or manual path definition is required to enable FFmpeg. Disabling it.")
|
||||
unset(USE_FFMPEG)
|
||||
endif()
|
||||
|
||||
find_package(ZLIB)
|
||||
if(ZLIB_FOUND)
|
||||
include_directories(${ZLIB_INCLUDE_DIR})
|
||||
else()
|
||||
add_library(zlib STATIC
|
||||
ext/zlib/adler32.c
|
||||
|
@ -316,111 +488,113 @@ else()
|
|||
ext/zlib/zutil.h
|
||||
)
|
||||
include_directories(ext/zlib)
|
||||
set(LIBZIP zlib)
|
||||
set(ZLIB_LIBRARY zlib)
|
||||
endif()
|
||||
|
||||
add_library(snappy STATIC
|
||||
ext/snappy/snappy-c.cpp
|
||||
ext/snappy/snappy-internal.h
|
||||
ext/snappy/snappy-sinksource.h
|
||||
ext/snappy/snappy-stubs-internal.h
|
||||
ext/snappy/snappy-stubs-public.h
|
||||
ext/snappy/snappy.cpp
|
||||
ext/snappy/snappy.h
|
||||
add_library(cityhash STATIC
|
||||
native/ext/cityhash/city.cpp
|
||||
native/ext/cityhash/city.h
|
||||
native/ext/cityhash/citycrc.h
|
||||
)
|
||||
include_directories(ext/snappy)
|
||||
include_directories(ext/cityhash)
|
||||
|
||||
add_library(rg_etc1 STATIC
|
||||
native/ext/rg_etc1/rg_etc1.cpp
|
||||
native/ext/rg_etc1/rg_etc1.h)
|
||||
include_directories(native/ext/rg_etc1)
|
||||
add_library(libzip STATIC
|
||||
native/ext/libzip/zip.h
|
||||
native/ext/libzip/mkstemp.c
|
||||
native/ext/libzip/zip_add.c
|
||||
native/ext/libzip/zip_add_dir.c
|
||||
native/ext/libzip/zip_close.c
|
||||
native/ext/libzip/zip_delete.c
|
||||
native/ext/libzip/zip_dirent.c
|
||||
native/ext/libzip/zip_entry_free.c
|
||||
native/ext/libzip/zip_entry_new.c
|
||||
native/ext/libzip/zip_err_str.c
|
||||
native/ext/libzip/zip_error.c
|
||||
native/ext/libzip/zip_error_clear.c
|
||||
native/ext/libzip/zip_error_get.c
|
||||
native/ext/libzip/zip_error_get_sys_type.c
|
||||
native/ext/libzip/zip_error_strerror.c
|
||||
native/ext/libzip/zip_error_to_str.c
|
||||
native/ext/libzip/zip_fclose.c
|
||||
native/ext/libzip/zip_file_error_clear.c
|
||||
native/ext/libzip/zip_file_error_get.c
|
||||
native/ext/libzip/zip_file_get_offset.c
|
||||
native/ext/libzip/zip_file_strerror.c
|
||||
native/ext/libzip/zip_filerange_crc.c
|
||||
native/ext/libzip/zip_fopen.c
|
||||
native/ext/libzip/zip_fopen_index.c
|
||||
native/ext/libzip/zip_fread.c
|
||||
native/ext/libzip/zip_free.c
|
||||
native/ext/libzip/zip_get_archive_comment.c
|
||||
native/ext/libzip/zip_get_archive_flag.c
|
||||
native/ext/libzip/zip_get_file_comment.c
|
||||
native/ext/libzip/zip_get_name.c
|
||||
native/ext/libzip/zip_get_num_files.c
|
||||
native/ext/libzip/zip_memdup.c
|
||||
native/ext/libzip/zip_name_locate.c
|
||||
native/ext/libzip/zip_new.c
|
||||
native/ext/libzip/zip_open.c
|
||||
native/ext/libzip/zip_rename.c
|
||||
native/ext/libzip/zip_replace.c
|
||||
native/ext/libzip/zip_set_archive_comment.c
|
||||
native/ext/libzip/zip_set_archive_flag.c
|
||||
native/ext/libzip/zip_set_file_comment.c
|
||||
native/ext/libzip/zip_set_name.c
|
||||
native/ext/libzip/zip_source_buffer.c
|
||||
native/ext/libzip/zip_source_file.c
|
||||
native/ext/libzip/zip_source_filep.c
|
||||
native/ext/libzip/zip_source_free.c
|
||||
native/ext/libzip/zip_source_function.c
|
||||
native/ext/libzip/zip_source_zip.c
|
||||
native/ext/libzip/zip_stat.c
|
||||
native/ext/libzip/zip_stat_index.c
|
||||
native/ext/libzip/zip_stat_init.c
|
||||
native/ext/libzip/zip_strerror.c
|
||||
native/ext/libzip/zip_unchange.c
|
||||
native/ext/libzip/zip_unchange_all.c
|
||||
native/ext/libzip/zip_unchange_archive.c
|
||||
native/ext/libzip/zip_unchange_data.c)
|
||||
target_link_libraries(libzip ${ZLIB_LIBRARY})
|
||||
include_directories(native/ext/libzip)
|
||||
set(LIBZIP_LIBRARY libzip)
|
||||
|
||||
if(NOT USING_GLES2)
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
|
||||
add_definitions(-DGLEW_STATIC)
|
||||
add_library(glew STATIC
|
||||
native/ext/glew/GL/glew.h
|
||||
native/ext/glew/GL/glxew.h
|
||||
native/ext/glew/GL/wglew.h
|
||||
native/ext/glew/glew.c)
|
||||
target_link_libraries(glew ${OPENGL_LIBRARIES})
|
||||
include_directories(native/ext/glew)
|
||||
set(GLEW_LIBRARIES glew)
|
||||
# FindPNG does a few things we don't want. So do it ourselves.
|
||||
# Fixed to libpng16, otherwise it can pick up earlier even if newer exists.
|
||||
find_path(PNG_PNG_INCLUDE_DIR NAMES "libpng16/png.h")
|
||||
find_library(PNG_LIBRARY NAMES png16 libpng16 )
|
||||
find_package(PackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(PNG REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR)
|
||||
if (PNG_FOUND)
|
||||
include_directories(${PNG_PNG_INCLUDE_DIR})
|
||||
else()
|
||||
add_library(png16 STATIC
|
||||
native/ext/libpng16/pngconf.h
|
||||
native/ext/libpng16/pngdebug.h
|
||||
native/ext/libpng16/png.c
|
||||
native/ext/libpng16/png.h
|
||||
native/ext/libpng16/pngerror.c
|
||||
native/ext/libpng16/pngget.c
|
||||
native/ext/libpng16/pnginfo.h
|
||||
native/ext/libpng16/pnglibconf.h
|
||||
native/ext/libpng16/pngmem.c
|
||||
native/ext/libpng16/pngpread.c
|
||||
native/ext/libpng16/pngpriv.h
|
||||
native/ext/libpng16/pngread.c
|
||||
native/ext/libpng16/pngrio.c
|
||||
native/ext/libpng16/pngrtran.c
|
||||
native/ext/libpng16/pngrutil.c
|
||||
native/ext/libpng16/pngset.c
|
||||
native/ext/libpng16/pngstruct.h
|
||||
native/ext/libpng16/pngtest.c
|
||||
native/ext/libpng16/pngtrans.c
|
||||
native/ext/libpng16/pngwio.c
|
||||
native/ext/libpng16/pngwrite.c
|
||||
native/ext/libpng16/pngwtran.c
|
||||
native/ext/libpng16/pngwutil.c)
|
||||
set(PNG_LIBRARY png16)
|
||||
include_directories(native/ext)
|
||||
endif()
|
||||
|
||||
add_library(stb_image STATIC
|
||||
native/ext/stb_image/stb_image.c
|
||||
native/ext/stb_image/stb_image.h)
|
||||
include_directories(native/ext/stb_image)
|
||||
|
||||
add_library(stb_vorbis STATIC
|
||||
native/ext/stb_vorbis/stb_vorbis.c
|
||||
native/ext/stb_vorbis/stb_vorbis.h)
|
||||
include_directories(native/ext/stb_vorbis)
|
||||
|
||||
if(ANDROID)
|
||||
add_library(libzip STATIC
|
||||
native/ext/libzip/zip.h
|
||||
native/ext/libzip/mkstemp.c
|
||||
native/ext/libzip/zip_add.c
|
||||
native/ext/libzip/zip_add_dir.c
|
||||
native/ext/libzip/zip_close.c
|
||||
native/ext/libzip/zip_delete.c
|
||||
native/ext/libzip/zip_dirent.c
|
||||
native/ext/libzip/zip_entry_free.c
|
||||
native/ext/libzip/zip_entry_new.c
|
||||
native/ext/libzip/zip_err_str.c
|
||||
native/ext/libzip/zip_error.c
|
||||
native/ext/libzip/zip_error_clear.c
|
||||
native/ext/libzip/zip_error_get.c
|
||||
native/ext/libzip/zip_error_get_sys_type.c
|
||||
native/ext/libzip/zip_error_strerror.c
|
||||
native/ext/libzip/zip_error_to_str.c
|
||||
native/ext/libzip/zip_fclose.c
|
||||
native/ext/libzip/zip_file_error_clear.c
|
||||
native/ext/libzip/zip_file_error_get.c
|
||||
native/ext/libzip/zip_file_get_offset.c
|
||||
native/ext/libzip/zip_file_strerror.c
|
||||
native/ext/libzip/zip_filerange_crc.c
|
||||
native/ext/libzip/zip_fopen.c
|
||||
native/ext/libzip/zip_fopen_index.c
|
||||
native/ext/libzip/zip_fread.c
|
||||
native/ext/libzip/zip_free.c
|
||||
native/ext/libzip/zip_get_archive_comment.c
|
||||
native/ext/libzip/zip_get_archive_flag.c
|
||||
native/ext/libzip/zip_get_file_comment.c
|
||||
native/ext/libzip/zip_get_name.c
|
||||
native/ext/libzip/zip_get_num_files.c
|
||||
native/ext/libzip/zip_memdup.c
|
||||
native/ext/libzip/zip_name_locate.c
|
||||
native/ext/libzip/zip_new.c
|
||||
native/ext/libzip/zip_open.c
|
||||
native/ext/libzip/zip_rename.c
|
||||
native/ext/libzip/zip_replace.c
|
||||
native/ext/libzip/zip_set_archive_comment.c
|
||||
native/ext/libzip/zip_set_archive_flag.c
|
||||
native/ext/libzip/zip_set_file_comment.c
|
||||
native/ext/libzip/zip_set_name.c
|
||||
native/ext/libzip/zip_source_buffer.c
|
||||
native/ext/libzip/zip_source_file.c
|
||||
native/ext/libzip/zip_source_filep.c
|
||||
native/ext/libzip/zip_source_free.c
|
||||
native/ext/libzip/zip_source_function.c
|
||||
native/ext/libzip/zip_source_zip.c
|
||||
native/ext/libzip/zip_stat.c
|
||||
native/ext/libzip/zip_stat_index.c
|
||||
native/ext/libzip/zip_stat_init.c
|
||||
native/ext/libzip/zip_strerror.c
|
||||
native/ext/libzip/zip_unchange.c
|
||||
native/ext/libzip/zip_unchange_all.c
|
||||
native/ext/libzip/zip_unchange_archive.c
|
||||
native/ext/libzip/zip_unchange_data.c)
|
||||
target_link_libraries(libzip zlib)
|
||||
include_directories(native/ext/libzip)
|
||||
set(LIBZIP libzip zlib)
|
||||
endif()
|
||||
|
||||
|
||||
set(nativeExtra)
|
||||
set(nativeExtraLibs)
|
||||
if(ANDROID)
|
||||
|
@ -468,7 +642,10 @@ elseif(SDL_FOUND)
|
|||
set(TargetBin PPSSPPSDL)
|
||||
# Require SDL
|
||||
include_directories(${SDL_INCLUDE_DIR})
|
||||
set(nativeExtra ${nativeExtra} native/base/PCMain.cpp)
|
||||
set(nativeExtra ${nativeExtra}
|
||||
SDL/SDLJoystick.h
|
||||
SDL/SDLJoystick.cpp
|
||||
native/base/PCMain.cpp)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} ${SDL_LIBRARY})
|
||||
if(APPLE)
|
||||
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm)
|
||||
|
@ -517,6 +694,10 @@ add_library(native STATIC
|
|||
native/base/timeutil.h
|
||||
native/data/compression.cpp
|
||||
native/data/compression.h
|
||||
native/ext/vjson/json.cpp
|
||||
native/ext/vjson/json.h
|
||||
native/ext/vjson/block_allocator.cpp
|
||||
native/ext/vjson/block_allocator.h
|
||||
native/file/chunk_file.cpp
|
||||
native/file/chunk_file.h
|
||||
native/file/dialog.cpp
|
||||
|
@ -529,6 +710,8 @@ add_library(native STATIC
|
|||
native/file/file_util.h
|
||||
native/file/ini_file.cpp
|
||||
native/file/ini_file.h
|
||||
native/file/path.cpp
|
||||
native/file/path.h
|
||||
native/file/vfs.h
|
||||
native/file/zip_read.cpp
|
||||
native/file/zip_read.h
|
||||
|
@ -630,13 +813,15 @@ add_library(native STATIC
|
|||
native/util/random/rng.h
|
||||
native/util/text/utf8.h
|
||||
native/util/text/utf8.cpp
|
||||
native/util/text/parsers.h
|
||||
native/util/text/parsers.cpp
|
||||
native/util/const_map.h
|
||||
native/ext/jpge/jpgd.cpp
|
||||
native/ext/jpge/jpgd.h
|
||||
native/ext/jpge/jpge.cpp
|
||||
native/ext/jpge/jpge.h)
|
||||
include_directories(native)
|
||||
target_link_libraries(native ${LIBZIP} rg_etc1 stb_image stb_vorbis snappy ${GLEW_LIBRARIES})
|
||||
target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARY} rg_etc1 vjson stb_vorbis snappy ${GLEW_LIBRARIES})
|
||||
|
||||
if(ANDROID)
|
||||
target_link_libraries(native log)
|
||||
|
@ -681,12 +866,15 @@ if(ARM)
|
|||
Core/MIPS/ARM/ArmCompFPU.cpp
|
||||
Core/MIPS/ARM/ArmCompLoadStore.cpp
|
||||
Core/MIPS/ARM/ArmCompVFPU.cpp
|
||||
Core/MIPS/ARM/ArmCompVFPUNEON.cpp
|
||||
Core/MIPS/ARM/ArmJit.cpp
|
||||
Core/MIPS/ARM/ArmJit.h
|
||||
Core/MIPS/ARM/ArmRegCache.cpp
|
||||
Core/MIPS/ARM/ArmRegCache.h
|
||||
Core/MIPS/ARM/ArmRegCacheFPU.cpp
|
||||
Core/MIPS/ARM/ArmRegCacheFPU.h
|
||||
GPU/GLES/VertexDecoderArm.cpp
|
||||
GPU/GLES/VertexDecoder.h
|
||||
ext/disarm.cpp)
|
||||
elseif(X86)
|
||||
set(CoreExtra ${CoreExtra}
|
||||
|
@ -703,6 +891,8 @@ elseif(X86)
|
|||
Core/MIPS/x86/RegCache.h
|
||||
Core/MIPS/x86/RegCacheFPU.cpp
|
||||
Core/MIPS/x86/RegCacheFPU.h
|
||||
GPU/GLES/VertexDecoderX86.cpp
|
||||
GPU/GLES/VertexDecoder.h
|
||||
ext/disarm.cpp)
|
||||
endif()
|
||||
|
||||
|
@ -849,6 +1039,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
|||
Core/HLE/sceNet.h
|
||||
Core/HLE/sceNetAdhoc.cpp
|
||||
Core/HLE/sceNetAdhoc.h
|
||||
Core/HLE/proAdhoc.h
|
||||
Core/HLE/proAdhoc.cpp
|
||||
Core/HLE/sceOpenPSID.cpp
|
||||
Core/HLE/sceOpenPSID.h
|
||||
Core/HLE/sceP3da.cpp
|
||||
|
@ -946,6 +1138,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
|||
Core/SaveState.h
|
||||
Core/System.cpp
|
||||
Core/System.h
|
||||
Core/Util/GameManager.cpp
|
||||
Core/Util/GameManager.h
|
||||
Core/Util/BlockAllocator.cpp
|
||||
Core/Util/BlockAllocator.h
|
||||
Core/Util/PPGeDraw.cpp
|
||||
|
@ -955,7 +1149,7 @@ add_library(${CoreLibName} ${CoreLinkType}
|
|||
$<TARGET_OBJECTS:GPU>
|
||||
Globals.h
|
||||
git-version.cpp)
|
||||
target_link_libraries(${CoreLibName} Common native kirk xbrz xxhash
|
||||
target_link_libraries(${CoreLibName} Common native kirk cityhash xbrz xxhash
|
||||
${CoreExtraLibs} ${GLEW_LIBRARIES} ${OPENGL_LIBRARIES})
|
||||
setup_target_project(${CoreLibName} Core)
|
||||
|
||||
|
@ -970,7 +1164,7 @@ set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/git-version.cpp
|
|||
PROPERTIES GENERATED TRUE)
|
||||
add_dependencies(${CoreLibName} GitVersion)
|
||||
|
||||
if(BLACKBERRY OR IOS OR ARMEABI_V7A)
|
||||
if(ARMEABI_V7A)
|
||||
set(GPU_NEON GPU/Common/TextureDecoderNEON.cpp)
|
||||
endif()
|
||||
add_library(GPU OBJECT
|
||||
|
@ -1006,6 +1200,7 @@ add_library(GPU OBJECT
|
|||
GPU/GLES/TextureScaler.h
|
||||
GPU/GLES/TransformPipeline.cpp
|
||||
GPU/GLES/TransformPipeline.h
|
||||
GPU/GLES/SoftwareTransform.cpp
|
||||
GPU/GLES/VertexDecoder.cpp
|
||||
GPU/GLES/VertexDecoder.h
|
||||
GPU/GLES/VertexShaderGenerator.cpp
|
||||
|
@ -1126,7 +1321,9 @@ set(NativeAppSource
|
|||
UI/UIShader.cpp
|
||||
UI/OnScreenDisplay.cpp
|
||||
UI/ControlMappingScreen.cpp
|
||||
UI/Store.cpp
|
||||
UI/CwCheatScreen.cpp
|
||||
UI/InstallZipScreen.cpp
|
||||
UI/ui_atlas.cpp)
|
||||
if(ANDROID AND ARM)
|
||||
set(NativeAppSource ${NativeAppSource} android/jni/ArmEmitterTest.cpp)
|
||||
|
@ -1135,129 +1332,10 @@ set(NativeAssets
|
|||
android/assets/ui_atlas.zim
|
||||
assets/shaders
|
||||
assets/ppge_atlas.zim
|
||||
assets/langregion.ini)
|
||||
assets/langregion.ini
|
||||
assets/unknown.png)
|
||||
set(LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT} ${nativeExtraLibs})
|
||||
|
||||
if(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR)
|
||||
if(BLACKBERRY)
|
||||
set(PLATFORM_ARCH "blackberry/armv7")
|
||||
elseif(IOS)
|
||||
set(PLATFORM_ARCH "ios/universal")
|
||||
elseif(MACOSX)
|
||||
set(PLATFORM_ARCH "macosx/x86_64")
|
||||
elseif(LINUX)
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
set(PLATFORM_ARCH "linux/x86_64")
|
||||
else()
|
||||
set(PLATFORM_ARCH "linux/x86")
|
||||
endif()
|
||||
endif()
|
||||
# Using static libraries
|
||||
if (DEFINED PLATFORM_ARCH)
|
||||
include_directories(ffmpeg/${PLATFORM_ARCH}/include)
|
||||
link_directories(ffmpeg/${PLATFORM_ARCH}/lib)
|
||||
set(FFMPEG_LIBRARIES libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a)
|
||||
else()
|
||||
# Manual definition of system library locations by the user.
|
||||
if (DEFINED FFMPEG_INCLUDE_PATH)
|
||||
include_directories(ffmpeg ${FFMPEG_INCLUDE_PATH})
|
||||
endif()
|
||||
if (DEFINED AVFORMAT_PATH)
|
||||
add_library(libavformat STATIC IMPORTED)
|
||||
set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${AVFORMAT_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavformat)
|
||||
endif()
|
||||
if (DEFINED AVCODEC_PATH)
|
||||
add_library(libavcodec STATIC IMPORTED)
|
||||
set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${AVCODEC_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavcodec)
|
||||
endif()
|
||||
if (DEFINED AVUTIL_PATH)
|
||||
add_library(libavutil STATIC IMPORTED)
|
||||
set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${AVUTIL_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libavutil)
|
||||
endif()
|
||||
if (DEFINED SWRESAMPLE_PATH)
|
||||
add_library(libswresample STATIC IMPORTED)
|
||||
set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${SWRESAMPLE_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswresample)
|
||||
endif()
|
||||
if (DEFINED SWSCALE_PATH)
|
||||
add_library(libswscale STATIC IMPORTED)
|
||||
set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${SWSCALE_PATH})
|
||||
SET (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} libswscale)
|
||||
endif()
|
||||
endif(DEFINED PLATFORM_ARCH)
|
||||
endif(USE_FFMPEG AND NOT DEFINED FFMPEG_BUILDDIR)
|
||||
|
||||
if(USE_FFMPEG)
|
||||
# Using shared libraries
|
||||
if(DEFINED FFMPEG_BUILDDIR)
|
||||
include_directories(ffmpeg ${FFMPEG_BUILDDIR})
|
||||
|
||||
add_library(libavformat STATIC IMPORTED)
|
||||
set_target_properties(libavformat PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavformat/libavformat.a)
|
||||
add_library(libavcodec STATIC IMPORTED)
|
||||
set_target_properties(libavcodec PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavcodec/libavcodec.a)
|
||||
add_library(libavutil STATIC IMPORTED)
|
||||
set_target_properties(libavutil PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libavutil/libavutil.a)
|
||||
add_library(libswresample STATIC IMPORTED)
|
||||
set_target_properties(libswresample PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswresample/libswresample.a)
|
||||
add_library(libswscale STATIC IMPORTED)
|
||||
set_target_properties(libswscale PROPERTIES IMPORTED_LOCATION ${FFMPEG_BUILDDIR}/libswscale/libswscale.a)
|
||||
|
||||
SET (FFMPEG_LIBRARIES
|
||||
libavformat
|
||||
libavcodec
|
||||
libavutil
|
||||
libswresample
|
||||
libswscale
|
||||
)
|
||||
endif()
|
||||
|
||||
if(IOS OR BLACKBERRY)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} iconv)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} bz2 "-framework CoreVideo")
|
||||
if (NOT IOS)
|
||||
set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} "-framework VideoDecodeAcceleration")
|
||||
endif()
|
||||
endif(APPLE)
|
||||
|
||||
set(LinkCommon ${LinkCommon} ${FFMPEG_LIBRARIES})
|
||||
add_definitions(-DUSE_FFMPEG)
|
||||
endif(USE_FFMPEG)
|
||||
|
||||
# Modification to show where we are pulling the ffmpeg libraries from.
|
||||
if(USE_FFMPEG AND DEFINED FFMPEG_LIBRARIES)
|
||||
target_link_libraries(Common ${FFMPEG_LIBRARIES})
|
||||
message(STATUS "FFMPEG library locations:")
|
||||
if(DEFINED PLATFORM_ARCH)
|
||||
set(TEMP ${CMAKE_SOURCE_DIR}/ffmpeg/${PLATFORM_ARCH}/lib)
|
||||
message(STATUS "libavcodec location: ${TEMP}/libavcodec.a")
|
||||
message(STATUS "libavformat location: ${TEMP}/libavformat.a")
|
||||
message(STATUS "libavutil location: ${TEMP}/libavutil.a")
|
||||
message(STATUS "libswresample location: ${TEMP}/libswresample.a")
|
||||
message(STATUS "libswscale location: ${TEMP}/libswscale.a")
|
||||
else()
|
||||
get_target_property(TEMP libavcodec IMPORTED_LOCATION)
|
||||
message(STATUS "libavcodec location: ${TEMP}")
|
||||
get_target_property(TEMP libavformat IMPORTED_LOCATION)
|
||||
message(STATUS "libavformat location: ${TEMP}")
|
||||
get_target_property(TEMP libavutil IMPORTED_LOCATION)
|
||||
message(STATUS "libavutil location: ${TEMP}")
|
||||
get_target_property(TEMP libswresample IMPORTED_LOCATION)
|
||||
message(STATUS "libswresample location: ${TEMP}")
|
||||
get_target_property(TEMP libswscale IMPORTED_LOCATION)
|
||||
message(STATUS "libswscale location: ${TEMP}")
|
||||
endif(DEFINED PLATFORM_ARCH)
|
||||
endif()
|
||||
if(USE_FFMPEG AND NOT DEFINED FFMPEG_LIBRARIES)
|
||||
message(WARNING "FFMPEG_BUILDDIR variable or manual path definition is required to enable FFmpeg. Disabling it.")
|
||||
unset(USE_FFMPEG)
|
||||
endif()
|
||||
|
||||
if(HEADLESS)
|
||||
add_executable(PPSSPPHeadless
|
||||
|
@ -1282,7 +1360,7 @@ endif()
|
|||
|
||||
# installs
|
||||
file(INSTALL ${NativeAssets} DESTINATION assets)
|
||||
file(INSTALL flash0 lang DESTINATION .)
|
||||
file(INSTALL flash0 lang DESTINATION assets)
|
||||
|
||||
# Fix CMake some Xcode settings.
|
||||
if(APPLE)
|
||||
|
@ -1297,8 +1375,11 @@ if(APPLE)
|
|||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g -D_NDEBUG")
|
||||
|
||||
# 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")
|
||||
if(NOT ZLIB_FOUND)
|
||||
set_target_properties(zlib PROPERTIES COMPILE_FLAGS "-O3")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(APPLE AND NOT IOS)
|
||||
|
@ -1311,10 +1392,6 @@ if(IOS)
|
|||
|
||||
file(GLOB IOSAssets ios/assets/*.png)
|
||||
file(INSTALL ${IOSAssets} DESTINATION assets)
|
||||
file(INSTALL assets/langregion.ini DESTINATION assets)
|
||||
file(INSTALL assets/shaders DESTINATION assets)
|
||||
file(INSTALL flash0 DESTINATION assets)
|
||||
file(INSTALL lang DESTINATION assets)
|
||||
if (IOS_DEBUG)
|
||||
file(INSTALL pspautotests DESTINATION assets)
|
||||
endif()
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#endif
|
||||
|
||||
// Only Linux platforms have /proc/cpuinfo
|
||||
#if !defined(BLACKBERRY) && !defined(IOS) && !defined(__SYMBIAN32__)
|
||||
#if defined(__linux__)
|
||||
const char procfile[] = "/proc/cpuinfo";
|
||||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu
|
||||
const char syscpupresentfile[] = "/sys/devices/system/cpu/present";
|
||||
|
@ -200,7 +200,7 @@ void CPUInfo::Detect()
|
|||
vendor = VENDOR_ARM;
|
||||
|
||||
// Get the information about the CPU
|
||||
#if defined(__SYMBIAN32__) || defined(BLACKBERRY) || defined(IOS)
|
||||
#if !defined(__linux__)
|
||||
bool isVFP3 = false;
|
||||
bool isVFP4 = false;
|
||||
#ifdef IOS
|
||||
|
@ -209,7 +209,7 @@ void CPUInfo::Detect()
|
|||
#ifdef __ARM_ARCH_7S__
|
||||
isVFP4 = true;
|
||||
#endif
|
||||
strcpy(brand_string, "Apple");
|
||||
strcpy(brand_string, "Apple A");
|
||||
num_cores = 2;
|
||||
#elif defined(BLACKBERRY)
|
||||
isVFP3 = true;
|
||||
|
@ -220,10 +220,14 @@ void CPUInfo::Detect()
|
|||
if (!strncmp(brand_string, "MSM", 3))
|
||||
isVFP4 = true;
|
||||
deviceinfo_free_details(&details);
|
||||
#elif defined(SYMBIAN)
|
||||
#elif defined(__SYMBIAN32__)
|
||||
strcpy(brand_string, "Samsung ARMv6");
|
||||
num_cores = 1;
|
||||
#else
|
||||
strcpy(brand_string, "Unknown");
|
||||
num_cores = 1;
|
||||
#endif
|
||||
strncpy(cpu_string, brand_string, sizeof(cpu_string));
|
||||
// Hardcode this for now
|
||||
bSwp = true;
|
||||
bHalf = true;
|
||||
|
@ -240,7 +244,7 @@ void CPUInfo::Detect()
|
|||
bIDIVt = isVFP4;
|
||||
bFP = false;
|
||||
bASIMD = false;
|
||||
#else
|
||||
#else // __linux__
|
||||
strncpy(cpu_string, GetCPUString(), sizeof(cpu_string));
|
||||
bSwp = CheckCPUFeature("swp");
|
||||
bHalf = CheckCPUFeature("half");
|
||||
|
@ -255,46 +259,36 @@ void CPUInfo::Detect()
|
|||
bVFPv4 = CheckCPUFeature("vfpv4");
|
||||
bIDIVa = CheckCPUFeature("idiva");
|
||||
bIDIVt = CheckCPUFeature("idivt");
|
||||
// Qualcomm Krait supports IDIVA but it doesn't report it. Check for krait.
|
||||
if (GetCPUImplementer() == 0x51 && GetCPUPart() == 0x6F) // Krait(300) is 0x6F, Scorpion is 0x4D
|
||||
// Qualcomm Krait supports IDIVA but it doesn't report it. Check for krait (0x4D = Plus, 0x6F = Pro).
|
||||
unsigned short CPUPart = GetCPUPart();
|
||||
if (GetCPUImplementer() == 0x51 && (CPUPart == 0x4D || CPUPart == 0x6F))
|
||||
bIDIVa = bIDIVt = true;
|
||||
// These two require ARMv8 or higher
|
||||
bFP = CheckCPUFeature("fp");
|
||||
bASIMD = CheckCPUFeature("asimd");
|
||||
num_cores = GetCoreCount();
|
||||
#endif
|
||||
// On android, we build a separate library for ARMv7 so this is fine.
|
||||
// TODO: Check for ARMv7 on other platforms.
|
||||
#if defined(__ARM_ARCH_7A__)
|
||||
bArmV7 = true;
|
||||
#else
|
||||
bArmV7 = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize()
|
||||
{
|
||||
std::string sum;
|
||||
#if defined(BLACKBERRY) || defined(IOS) || defined(__SYMBIAN32__)
|
||||
sum = StringFromFormat("%i cores", num_cores);
|
||||
#else
|
||||
if (num_cores == 1)
|
||||
sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
|
||||
else
|
||||
sum = StringFromFormat("%s, %i cores", cpu_string, num_cores);
|
||||
#endif
|
||||
if (bSwp) sum += ", SWP";
|
||||
if (bHalf) sum += ", Half";
|
||||
if (bThumb) sum += ", Thumb";
|
||||
if (bFastMult) sum += ", FastMult";
|
||||
if (bVFP) sum += ", VFP";
|
||||
if (bEDSP) sum += ", EDSP";
|
||||
if (bThumbEE) sum += ", ThumbEE";
|
||||
if (bNEON) sum += ", NEON";
|
||||
if (bVFPv3) sum += ", VFPv3";
|
||||
if (bTLS) sum += ", TLS";
|
||||
if (bVFP) sum += ", VFP";
|
||||
if (bVFPv3) sum += ", VFPv3";
|
||||
if (bVFPv4) sum += ", VFPv4";
|
||||
if (bNEON) sum += ", NEON";
|
||||
if (bIDIVa) sum += ", IDIVa";
|
||||
if (bIDIVt) sum += ", IDIVt";
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -70,6 +70,9 @@ enum ARMReg
|
|||
// ASIMD Quad-Word registers
|
||||
Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7,
|
||||
Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15,
|
||||
|
||||
// for NEON VLD/VST instructions
|
||||
REG_UPDATE = R13,
|
||||
INVALID_REG = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
|
@ -346,9 +349,44 @@ struct LiteralPool
|
|||
|
||||
typedef const u8* JumpTarget;
|
||||
|
||||
// XXX: Stop polluting the global namespace
|
||||
const u32 I_8 = (1 << 0);
|
||||
const u32 I_16 = (1 << 1);
|
||||
const u32 I_32 = (1 << 2);
|
||||
const u32 I_64 = (1 << 3);
|
||||
const u32 I_SIGNED = (1 << 4);
|
||||
const u32 I_UNSIGNED = (1 << 5);
|
||||
const u32 F_32 = (1 << 6);
|
||||
const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL
|
||||
|
||||
u32 EncodeVd(ARMReg Vd);
|
||||
u32 EncodeVn(ARMReg Vn);
|
||||
u32 EncodeVm(ARMReg Vm);
|
||||
|
||||
u32 encodedSize(u32 value);
|
||||
|
||||
// Subtracts the base from the register to give us the real one
|
||||
ARMReg SubBase(ARMReg Reg);
|
||||
|
||||
// See A.7.1 in the ARMv7-A
|
||||
// VMUL F32 scalars can only be up to D15[0], D15[1] - higher scalars cannot be individually addressed
|
||||
ARMReg DScalar(ARMReg dreg, int subScalar);
|
||||
ARMReg QScalar(ARMReg qreg, int subScalar);
|
||||
|
||||
enum NEONAlignment {
|
||||
ALIGN_NONE = 0,
|
||||
ALIGN_64 = 1,
|
||||
ALIGN_128 = 2,
|
||||
ALIGN_256 = 3
|
||||
};
|
||||
|
||||
|
||||
class NEONXEmitter;
|
||||
|
||||
class ARMXEmitter
|
||||
{
|
||||
friend struct OpArg; // for Write8 etc
|
||||
friend class NEONXEmitter;
|
||||
private:
|
||||
u8 *code, *startcode;
|
||||
u8 *lastCacheFlushEnd;
|
||||
|
@ -361,9 +399,6 @@ private:
|
|||
void WriteShiftedDataOp(u32 op, bool SetFlags, ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void WriteSignedMultiply(u32 Op, u32 Op2, u32 Op3, ARMReg dest, ARMReg r1, ARMReg r2);
|
||||
|
||||
u32 EncodeVd(ARMReg Vd);
|
||||
u32 EncodeVn(ARMReg Vn);
|
||||
u32 EncodeVm(ARMReg Vm);
|
||||
void WriteVFPDataOp(u32 Op, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
|
||||
void Write4OpMultiply(u32 op, ARMReg destLo, ARMReg destHi, ARMReg rn, ARMReg rm);
|
||||
|
@ -371,6 +406,9 @@ private:
|
|||
// New Ops
|
||||
void WriteInstruction(u32 op, ARMReg Rd, ARMReg Rn, Operand2 Rm, bool SetFlags = false);
|
||||
|
||||
void WriteVLDST1(bool load, u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align, ARMReg Rm);
|
||||
void WriteVLDST1_lane(bool load, u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm);
|
||||
|
||||
protected:
|
||||
inline void Write32(u32 value) {*(u32*)code = value; code+=4;}
|
||||
|
||||
|
@ -449,7 +487,6 @@ public:
|
|||
void ADDS(ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void ADC (ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void ADCS(ARMReg dest, ARMReg src, Operand2 op2);
|
||||
|
||||
void LSL (ARMReg dest, ARMReg src, Operand2 op2);
|
||||
void LSL (ARMReg dest, ARMReg src, ARMReg op2);
|
||||
void LSLS(ARMReg dest, ARMReg src, Operand2 op2);
|
||||
|
@ -505,6 +542,7 @@ public:
|
|||
void BFI(ARMReg rd, ARMReg rn, u8 lsb, u8 width);
|
||||
void UBFX(ARMReg dest, ARMReg op2, u8 lsb, u8 width);
|
||||
void CLZ(ARMReg rd, ARMReg rm);
|
||||
void PLD(ARMReg rd, int offset, bool forWrite = false);
|
||||
|
||||
// Using just MSR here messes with our defines on the PPC side of stuff (when this code was in dolphin...)
|
||||
// Just need to put an underscore here, bit annoying.
|
||||
|
@ -543,12 +581,10 @@ public:
|
|||
// is deprecating conditional execution of ASIMD instructions.
|
||||
// ASIMD instructions don't even have a conditional encoding.
|
||||
|
||||
// Subtracts the base from the register to give us the real one
|
||||
ARMReg SubBase(ARMReg Reg);
|
||||
// NEON Only
|
||||
void VABD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VADD(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUB(IntegerSize Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VABD(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VADD(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUB(IntegerSize size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
|
||||
// VFP Only
|
||||
void VLDR(ARMReg Dest, ARMReg Base, s16 offset);
|
||||
|
@ -582,6 +618,163 @@ public:
|
|||
void VCVTF32F16(ARMReg Dest, ARMReg Src);
|
||||
void VCVTF16F32(ARMReg Dest, ARMReg Src);
|
||||
|
||||
void VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VABS(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VCEQ(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VCGE(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VCGT(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VCLE(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCLS(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VCLT(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCLZ(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VCNT(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index);
|
||||
void VDUP(u32 Size, ARMReg Vd, ARMReg Rt);
|
||||
void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index);
|
||||
void VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
|
||||
// Three registers
|
||||
void VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
|
||||
// Two registers and a scalar
|
||||
// These two are super useful for matrix multiplication
|
||||
void VMUL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMLA_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
|
||||
// TODO:
|
||||
/*
|
||||
void VMLS_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMLAL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMLSL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VMULL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMLAL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMLSL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMULH_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQDMULL_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQRDMULH_scalar(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
*/
|
||||
|
||||
void VNEG(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VPADAL(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VPADDL(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQABS(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQNEG(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VRECPE(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VSWP(ARMReg Vd, ARMReg Vm);
|
||||
void VTRN(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm);
|
||||
void VUZP(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VZIP(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VREV64(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VREV32(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VREV16(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
|
||||
|
||||
// Widening and narrowing moves
|
||||
void VMOVL(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
void VMOVN(u32 Size, ARMReg Vd, ARMReg Vm);
|
||||
|
||||
// Vector VCVT
|
||||
void VCVT(u32 DestSize, ARMReg Dest, ARMReg Src);
|
||||
|
||||
|
||||
// Notes:
|
||||
// Rm == _PC is interpreted as no offset, otherwise, effective address is sum of Rn and Rm
|
||||
// Rm == R13 is interpreted as VLD1, .... [Rn]! Added a REG_UPDATE pseudo register.
|
||||
|
||||
// Load/store multiple registers full of elements (a register is a D register)
|
||||
// Specifying alignment when it can be guaranteed is documented to improve load/store performance.
|
||||
// For example, when loading a set of four 64-bit registers that we know is 32-byte aligned, we should specify ALIGN_256.
|
||||
void VLD1(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
void VST1(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
|
||||
// Load/store single lanes of D registers
|
||||
void VLD1_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm = _PC);
|
||||
void VST1_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, bool aligned, ARMReg Rm = _PC);
|
||||
|
||||
// Load one value into all lanes of a D or a Q register (either supported, all formats should work).
|
||||
void VLD1_all_lanes(u32 Size, ARMReg Vd, ARMReg Rn, bool aligned, ARMReg Rm = _PC);
|
||||
|
||||
/*
|
||||
// Deinterleave two loads... or something. TODO
|
||||
void VLD2(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
void VST2(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
|
||||
void VLD2_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC);
|
||||
void VST2_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC);
|
||||
|
||||
void VLD3(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
void VST3(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
|
||||
void VLD3_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC);
|
||||
void VST3_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC);
|
||||
|
||||
void VLD4(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
void VST4(u32 Size, ARMReg Vd, ARMReg Rn, int regCount, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC);
|
||||
|
||||
void VLD4_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC);
|
||||
void VST4_lane(u32 Size, ARMReg Vd, ARMReg Rn, int lane, ARMReg Rm = _PC);
|
||||
*/
|
||||
|
||||
void VMRS_APSR();
|
||||
void VMRS(ARMReg Rt);
|
||||
void VMSR(ARMReg Rt);
|
||||
|
@ -592,13 +785,16 @@ public:
|
|||
void MOVI2R(ARMReg reg, u32 val, bool optimize = true);
|
||||
void MOVI2F(ARMReg dest, float val, ARMReg tempReg, bool negate = false);
|
||||
|
||||
// Load pointers without casting
|
||||
template <class T> void MOVP2R(ARMReg reg, T *val) {
|
||||
MOVI2R(reg, (u32)(intptr_t)(void *)val);
|
||||
}
|
||||
|
||||
void ADDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||
void ANDI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||
void CMPI2R(ARMReg rs, u32 val, ARMReg scratch);
|
||||
void TSTI2R(ARMReg rs, u32 val, ARMReg scratch);
|
||||
void ORI2R(ARMReg rd, ARMReg rs, u32 val, ARMReg scratch);
|
||||
|
||||
|
||||
}; // class ARMXEmitter
|
||||
|
||||
|
||||
|
@ -635,14 +831,16 @@ public:
|
|||
// Call this when shutting down. Don't rely on the destructor, even though it'll do the job.
|
||||
void FreeCodeSpace()
|
||||
{
|
||||
#ifndef __SYMBIAN32__
|
||||
#ifdef __SYMBIAN32__
|
||||
ResetExecutableMemory(region);
|
||||
#else
|
||||
FreeMemoryPages(region, region_size);
|
||||
#endif
|
||||
region = NULL;
|
||||
region_size = 0;
|
||||
}
|
||||
|
||||
bool IsInSpace(u8 *ptr)
|
||||
bool IsInSpace(const u8 *ptr) const
|
||||
{
|
||||
return ptr >= region && ptr < region + region_size;
|
||||
}
|
||||
|
@ -672,7 +870,7 @@ public:
|
|||
return region;
|
||||
}
|
||||
|
||||
size_t GetOffset(u8 *ptr) {
|
||||
size_t GetOffset(const u8 *ptr) const {
|
||||
return ptr - region;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#ifdef BLACKBERRY
|
||||
#include <atomic.h>
|
||||
#elif defined(__SYMBIAN32__)
|
||||
#include <glib/gatomic.h>
|
||||
#include <e32atomics.h>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
|
@ -63,12 +63,16 @@ inline u32 AtomicLoad(volatile u32& src) {
|
|||
return src; // 32-bit reads are always atomic.
|
||||
}
|
||||
inline u32 AtomicLoadAcquire(volatile u32& src) {
|
||||
#ifdef __SYMBIAN32__
|
||||
return __e32_atomic_load_acq32(&src);
|
||||
#else
|
||||
//keep the compiler from caching any memory references
|
||||
u32 result = src; // 32-bit reads are always atomic.
|
||||
//__sync_synchronize(); // TODO: May not be necessary.
|
||||
// Compiler instruction only. x86 loads always have acquire semantics.
|
||||
__asm__ __volatile__ ( "":::"memory" );
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void AtomicOr(volatile u32& target, u32 value) {
|
||||
|
@ -82,57 +86,12 @@ inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
|
|||
#ifdef BLACKBERRY
|
||||
atomic_set(&dest, value);
|
||||
#elif defined(__SYMBIAN32__)
|
||||
g_atomic_int_set(&dest, value);
|
||||
__e32_atomic_store_rel32(&dest, value);
|
||||
#else
|
||||
__sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics.
|
||||
__sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function has acquire semantics.
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Old code kept here for reference in case we need the parts with __asm__ __volatile__.
|
||||
#if 0
|
||||
LONG SyncInterlockedIncrement(LONG *Dest)
|
||||
{
|
||||
#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__))
|
||||
return __sync_add_and_fetch(Dest, 1);
|
||||
#else
|
||||
register int result;
|
||||
__asm__ __volatile__("lock; xadd %0,%1"
|
||||
: "=r" (result), "=m" (*Dest)
|
||||
: "0" (1), "m" (*Dest)
|
||||
: "memory");
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
LONG SyncInterlockedExchangeAdd(LONG *Dest, LONG Val)
|
||||
{
|
||||
#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__))
|
||||
return __sync_add_and_fetch(Dest, Val);
|
||||
#else
|
||||
register int result;
|
||||
__asm__ __volatile__("lock; xadd %0,%1"
|
||||
: "=r" (result), "=m" (*Dest)
|
||||
: "0" (Val), "m" (*Dest)
|
||||
: "memory");
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
LONG SyncInterlockedExchange(LONG *Dest, LONG Val)
|
||||
{
|
||||
#if defined(__GNUC__) && defined (__GNUC_MINOR__) && ((4 < __GNUC__) || (4 == __GNUC__ && 1 <= __GNUC_MINOR__))
|
||||
return __sync_lock_test_and_set(Dest, Val);
|
||||
#else
|
||||
register int result;
|
||||
__asm__ __volatile__("lock; xchg %0,%1"
|
||||
: "=r" (result), "=m" (*Dest)
|
||||
: "0" (Val), "m" (*Dest)
|
||||
: "memory");
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#undef _interlockedbittestandreset64
|
||||
#else
|
||||
|
||||
#if !defined(_M_GENERIC) && !defined(MIPS)
|
||||
#ifdef _M_SSE
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
|
@ -45,8 +45,7 @@
|
|||
#include <machine/cpufunc.h>
|
||||
#elif !defined(MIPS)
|
||||
|
||||
void __cpuidex(int regs[4], int cpuid_leaf, int ecxval)
|
||||
{
|
||||
void __cpuidex(int regs[4], int cpuid_leaf, int ecxval) {
|
||||
#ifdef ANDROID
|
||||
// Use the /dev/cpu/%i/cpuid interface
|
||||
int f = open("/dev/cpu/0/cpuid", O_RDONLY);
|
||||
|
@ -90,8 +89,7 @@ CPUInfo::CPUInfo() {
|
|||
}
|
||||
|
||||
// Detects the various cpu features
|
||||
void CPUInfo::Detect()
|
||||
{
|
||||
void CPUInfo::Detect() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
#ifdef _M_IX86
|
||||
Mode64bit = false;
|
||||
|
@ -154,7 +152,11 @@ void CPUInfo::Detect()
|
|||
if ((cpu_id[2] >> 9) & 1) bSSSE3 = true;
|
||||
if ((cpu_id[2] >> 19) & 1) bSSE4_1 = true;
|
||||
if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true;
|
||||
if ((cpu_id[2] >> 28) & 1) bAVX = true;
|
||||
if ((cpu_id[2] >> 28) & 1) {
|
||||
bAVX = true;
|
||||
if ((cpu_id[2] >> 12) & 1)
|
||||
bFMA = true;
|
||||
}
|
||||
if ((cpu_id[2] >> 25) & 1) bAES = true;
|
||||
}
|
||||
if (max_ex_fn >= 0x80000004) {
|
||||
|
@ -231,6 +233,7 @@ std::string CPUInfo::Summarize()
|
|||
if (bSSE4_2) sum += ", SSE4.2";
|
||||
if (HTT) sum += ", HTT";
|
||||
if (bAVX) sum += ", AVX";
|
||||
if (bAVX) sum += ", FMA";
|
||||
if (bAES) sum += ", AES";
|
||||
if (bLongMode) sum += ", 64-bit support";
|
||||
return sum;
|
||||
|
|
|
@ -19,26 +19,29 @@
|
|||
#ifndef _CPUDETECT_H_
|
||||
#define _CPUDETECT_H_
|
||||
|
||||
// Every architecture has its own define. This needs to be added to.
|
||||
#if defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__)
|
||||
#define HAVE_ARMV7 1
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
|
||||
enum CPUVendor
|
||||
{
|
||||
enum CPUVendor {
|
||||
VENDOR_INTEL = 0,
|
||||
VENDOR_AMD = 1,
|
||||
VENDOR_ARM = 2,
|
||||
VENDOR_OTHER = 3,
|
||||
};
|
||||
|
||||
struct CPUInfo
|
||||
{
|
||||
struct CPUInfo {
|
||||
CPUVendor vendor;
|
||||
|
||||
|
||||
char cpu_string[0x21];
|
||||
char brand_string[0x41];
|
||||
bool OS64bit;
|
||||
bool CPU64bit;
|
||||
bool Mode64bit;
|
||||
|
||||
|
||||
bool HTT;
|
||||
int num_cores;
|
||||
int logical_cpu_count;
|
||||
|
@ -53,10 +56,11 @@ struct CPUInfo
|
|||
bool bLZCNT;
|
||||
bool bSSE4A;
|
||||
bool bAVX;
|
||||
bool bFMA;
|
||||
bool bAES;
|
||||
bool bLAHFSAHF64;
|
||||
bool bLongMode;
|
||||
|
||||
|
||||
// ARM specific CPUInfo
|
||||
bool bSwp;
|
||||
bool bHalf;
|
||||
|
@ -71,7 +75,6 @@ struct CPUInfo
|
|||
bool bVFPv4;
|
||||
bool bIDIVa;
|
||||
bool bIDIVt;
|
||||
bool bArmV7; // enable MOVT, MOVW etc
|
||||
|
||||
// ARMv8 specific
|
||||
bool bFP;
|
||||
|
@ -79,7 +82,7 @@ struct CPUInfo
|
|||
|
||||
// Call Detect()
|
||||
explicit CPUInfo();
|
||||
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string Summarize();
|
||||
|
||||
|
|
|
@ -146,6 +146,8 @@ private:
|
|||
# define _M_SSE 0x301
|
||||
# elif defined __SSE3__
|
||||
# define _M_SSE 0x300
|
||||
# elif defined __SSE2__
|
||||
# define _M_SSE 0x200
|
||||
# endif
|
||||
#elif ((_MSC_VER >= 1500) || __INTEL_COMPILER) // Visual Studio 2008
|
||||
# define _M_SSE 0x402
|
||||
|
|
|
@ -183,16 +183,13 @@
|
|||
<ClInclude Include="KeyMap.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="LogManager.h" />
|
||||
<ClInclude Include="MathUtil.h" />
|
||||
<ClInclude Include="MemArena.h" />
|
||||
<ClInclude Include="MemoryUtil.h" />
|
||||
<ClInclude Include="MsgHandler.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
<ClInclude Include="StdConditionVariable.h" />
|
||||
<ClInclude Include="StdMutex.h" />
|
||||
<ClInclude Include="StringUtils.h" />
|
||||
<ClInclude Include="Swap.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="ThreadPools.h" />
|
||||
<ClInclude Include="Thunk.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
|
@ -216,7 +213,6 @@
|
|||
<ClCompile Include="FileUtil.cpp" />
|
||||
<ClCompile Include="KeyMap.cpp" />
|
||||
<ClCompile Include="LogManager.cpp" />
|
||||
<ClCompile Include="MathUtil.cpp" />
|
||||
<ClCompile Include="MemArena.cpp" />
|
||||
<ClCompile Include="MemoryUtil.cpp" />
|
||||
<ClCompile Include="Misc.cpp" />
|
||||
|
@ -228,7 +224,6 @@
|
|||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringUtils.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="ThreadPools.cpp" />
|
||||
<ClCompile Include="Thunk.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
|
|
|
@ -16,14 +16,11 @@
|
|||
<ClInclude Include="FixedSizeQueue.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="LogManager.h" />
|
||||
<ClInclude Include="MathUtil.h" />
|
||||
<ClInclude Include="MemArena.h" />
|
||||
<ClInclude Include="MemoryUtil.h" />
|
||||
<ClInclude Include="MsgHandler.h" />
|
||||
<ClInclude Include="StdConditionVariable.h" />
|
||||
<ClInclude Include="StdMutex.h" />
|
||||
<ClInclude Include="StringUtils.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Thunk.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="x64Analyzer.h" />
|
||||
|
@ -47,13 +44,11 @@
|
|||
<ClCompile Include="CPUDetect.cpp" />
|
||||
<ClCompile Include="FileUtil.cpp" />
|
||||
<ClCompile Include="LogManager.cpp" />
|
||||
<ClCompile Include="MathUtil.cpp" />
|
||||
<ClCompile Include="MemArena.cpp" />
|
||||
<ClCompile Include="MemoryUtil.cpp" />
|
||||
<ClCompile Include="Misc.cpp" />
|
||||
<ClCompile Include="MsgHandler.cpp" />
|
||||
<ClCompile Include="StringUtils.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Thunk.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="x64Analyzer.cpp" />
|
||||
|
|
|
@ -37,7 +37,10 @@
|
|||
#include <CoreFoundation/CFString.h>
|
||||
#include <CoreFoundation/CFURL.h>
|
||||
#include <CoreFoundation/CFBundle.h>
|
||||
#endif
|
||||
#if !defined(IOS)
|
||||
#include <mach-o/dyld.h>
|
||||
#endif // !defined(IOS)
|
||||
#endif // __APPLE__
|
||||
|
||||
#include "util/text/utf8.h"
|
||||
|
||||
|
@ -254,11 +257,11 @@ bool CreateDir(const std::string &path)
|
|||
bool CreateFullPath(const std::string &fullPath)
|
||||
{
|
||||
int panicCounter = 100;
|
||||
INFO_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
|
||||
DEBUG_LOG(COMMON, "CreateFullPath: path %s", fullPath.c_str());
|
||||
|
||||
if (File::Exists(fullPath))
|
||||
{
|
||||
INFO_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
|
||||
DEBUG_LOG(COMMON, "CreateFullPath: path exists %s", fullPath.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -641,21 +644,50 @@ bool SetCurrentDir(const std::string &directory)
|
|||
return __chdir(directory.c_str()) == 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::wstring &GetExeDirectory()
|
||||
const std::string &GetExeDirectory()
|
||||
{
|
||||
static std::wstring DolphinPath;
|
||||
if (DolphinPath.empty())
|
||||
static std::string ExePath;
|
||||
|
||||
if (ExePath.empty())
|
||||
{
|
||||
wchar_t Dolphin_exe_Path[2048];
|
||||
GetModuleFileName(NULL, Dolphin_exe_Path, 2048);
|
||||
DolphinPath = Dolphin_exe_Path;
|
||||
DolphinPath = DolphinPath.substr(0, DolphinPath.find_last_of('\\'));
|
||||
}
|
||||
return DolphinPath;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
TCHAR program_path[4096] = {0};
|
||||
GetModuleFileName(NULL, program_path, ARRAY_SIZE(program_path) - 1);
|
||||
program_path[ARRAY_SIZE(program_path) - 1] = '\0';
|
||||
TCHAR *last_slash = _tcsrchr(program_path, '\\');
|
||||
if (last_slash != NULL)
|
||||
*(last_slash + 1) = '\0';
|
||||
#ifdef UNICODE
|
||||
ExePath = ConvertWStringToUTF8(program_path);
|
||||
#else
|
||||
ExePath = program_path;
|
||||
#endif
|
||||
|
||||
#elif (defined(__APPLE__) && !defined(IOS)) || defined(__linux__)
|
||||
char program_path[4096];
|
||||
uint32_t program_path_size = sizeof(program_path) - 1;
|
||||
|
||||
#if defined(__linux__)
|
||||
if (readlink("/proc/self/exe", program_path, 4095) > 0)
|
||||
#elif defined(__APPLE__) && !defined(IOS)
|
||||
if (_NSGetExecutablePath(program_path, &program_path_size) == 0)
|
||||
#else
|
||||
#error Unmatched ifdef.
|
||||
#endif
|
||||
{
|
||||
program_path[sizeof(program_path) - 1] = '\0';
|
||||
char *last_slash = strrchr(program_path, '/');
|
||||
if (last_slash != NULL)
|
||||
*(last_slash + 1) = '\0';
|
||||
ExePath = program_path;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return ExePath;
|
||||
}
|
||||
|
||||
|
||||
IOFile::IOFile()
|
||||
: m_file(NULL), m_good(true)
|
||||
{}
|
||||
|
|
|
@ -102,9 +102,7 @@ void CopyDir(const std::string &source_path, const std::string &dest_path);
|
|||
// Set the current directory to given directory
|
||||
bool SetCurrentDir(const std::string &directory);
|
||||
|
||||
#ifdef _WIN32
|
||||
std::wstring &GetExeDirectory();
|
||||
#endif
|
||||
const std::string &GetExeDirectory();
|
||||
|
||||
// simple wrapper for cstdlib file functions to
|
||||
// hopefully will make error checking easier
|
||||
|
|
|
@ -67,6 +67,7 @@ static const DefMappingStruct defaultQwertyKeyboardKeyMap[] = {
|
|||
{VIRTKEY_UNTHROTTLE , NKCODE_TAB},
|
||||
{VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE},
|
||||
{VIRTKEY_PAUSE , NKCODE_ESCAPE},
|
||||
{VIRTKEY_REWIND , NKCODE_DEL},
|
||||
};
|
||||
|
||||
static const DefMappingStruct defaultAzertyKeyboardKeyMap[] = {
|
||||
|
@ -95,6 +96,7 @@ static const DefMappingStruct defaultAzertyKeyboardKeyMap[] = {
|
|||
{VIRTKEY_UNTHROTTLE , NKCODE_TAB},
|
||||
{VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE},
|
||||
{VIRTKEY_PAUSE , NKCODE_ESCAPE},
|
||||
{VIRTKEY_REWIND , NKCODE_DEL},
|
||||
};
|
||||
|
||||
static const DefMappingStruct defaultQwertzKeyboardKeyMap[] = {
|
||||
|
@ -123,6 +125,7 @@ static const DefMappingStruct defaultQwertzKeyboardKeyMap[] = {
|
|||
{VIRTKEY_UNTHROTTLE , NKCODE_TAB},
|
||||
{VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE},
|
||||
{VIRTKEY_PAUSE , NKCODE_ESCAPE},
|
||||
{VIRTKEY_REWIND , NKCODE_DEL},
|
||||
};
|
||||
|
||||
static const DefMappingStruct default360KeyMap[] = {
|
||||
|
@ -190,6 +193,7 @@ static const DefMappingStruct defaultBlackberryQWERTYKeyMap[] = {
|
|||
{VIRTKEY_UNTHROTTLE , NKCODE_TAB},
|
||||
{VIRTKEY_SPEED_TOGGLE, NKCODE_GRAVE},
|
||||
{VIRTKEY_PAUSE , NKCODE_ESCAPE},
|
||||
{VIRTKEY_REWIND , NKCODE_DEL},
|
||||
};
|
||||
|
||||
static const DefMappingStruct defaultPadMap[] = {
|
||||
|
@ -279,17 +283,17 @@ void UpdateConfirmCancelKeys() {
|
|||
int confirmKey = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CROSS : CTRL_CIRCLE;
|
||||
int cancelKey = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CIRCLE : CTRL_CROSS;
|
||||
|
||||
for(auto i = g_controllerMap[confirmKey].begin(); i != g_controllerMap[confirmKey].end(); ++i) {
|
||||
for (auto i = g_controllerMap[confirmKey].begin(); i != g_controllerMap[confirmKey].end(); ++i) {
|
||||
confirmKeys.push_back((keycode_t)i->keyCode);
|
||||
}
|
||||
|
||||
for(auto i = g_controllerMap[cancelKey].begin(); i != g_controllerMap[cancelKey].end(); ++i) {
|
||||
for (auto i = g_controllerMap[cancelKey].begin(); i != g_controllerMap[cancelKey].end(); ++i) {
|
||||
cancelKeys.push_back((keycode_t)i->keyCode);
|
||||
}
|
||||
|
||||
// Push several hard-coded keys before submitting to native.
|
||||
const keycode_t hardcodedConfirmKeys[] = {
|
||||
NKCODE_SPACE,
|
||||
const keycode_t hardcodedConfirmKeys[] = {
|
||||
NKCODE_SPACE,
|
||||
NKCODE_ENTER,
|
||||
};
|
||||
|
||||
|
@ -299,9 +303,9 @@ void UpdateConfirmCancelKeys() {
|
|||
confirmKeys.push_back(hardcodedConfirmKeys[i]);
|
||||
}
|
||||
|
||||
const keycode_t hardcodedCancelKeys[] = {
|
||||
NKCODE_ESCAPE,
|
||||
NKCODE_BACK,
|
||||
const keycode_t hardcodedCancelKeys[] = {
|
||||
NKCODE_ESCAPE,
|
||||
NKCODE_BACK,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(hardcodedCancelKeys); i++) {
|
||||
|
@ -329,7 +333,6 @@ void SetDefaultKeyMap(DefaultMaps dmap, bool replace) {
|
|||
bool qwertz = false;
|
||||
#ifdef _WIN32
|
||||
HKL localeId = GetKeyboardLayout(0);
|
||||
|
||||
// TODO: Is this list complete enough?
|
||||
switch ((int)localeId & 0xFFFF) {
|
||||
case 0x407:
|
||||
|
@ -360,7 +363,8 @@ void SetDefaultKeyMap(DefaultMaps dmap, bool replace) {
|
|||
SetDefaultKeyMap(DEVICE_ID_PAD_0, defaultShieldKeyMap, ARRAY_SIZE(defaultShieldKeyMap), replace);
|
||||
break;
|
||||
case DEFAULT_MAPPING_BLACKBERRY_QWERTY:
|
||||
SetDefaultKeyMap(DEVICE_ID_PAD_0, defaultBlackberryQWERTYKeyMap, ARRAY_SIZE(defaultBlackberryQWERTYKeyMap), replace);
|
||||
SetDefaultKeyMap(DEVICE_ID_KEYBOARD, defaultBlackberryQWERTYKeyMap, ARRAY_SIZE(defaultBlackberryQWERTYKeyMap), replace);
|
||||
replace = false;
|
||||
case DEFAULT_MAPPING_PAD:
|
||||
SetDefaultKeyMap(DEVICE_ID_PAD_0, defaultPadMap, ARRAY_SIZE(defaultPadMap), replace);
|
||||
break;
|
||||
|
@ -426,7 +430,7 @@ const KeyMap_IntStrPair key_names[] = {
|
|||
{NKCODE_F10, "F10"},
|
||||
{NKCODE_F11, "F11"},
|
||||
{NKCODE_F12, "F12"},
|
||||
|
||||
|
||||
{NKCODE_GRAVE, "`"},
|
||||
{NKCODE_SLASH, "/"},
|
||||
{NKCODE_BACKSLASH, "\\"},
|
||||
|
@ -453,7 +457,8 @@ const KeyMap_IntStrPair key_names[] = {
|
|||
{NKCODE_ALT_RIGHT, "RAlt"},
|
||||
{NKCODE_SPACE, "Space"},
|
||||
{NKCODE_WINDOW, "Windows"},
|
||||
{NKCODE_DEL, "Del"},
|
||||
{NKCODE_DEL, "Backspace"},
|
||||
{NKCODE_FORWARD_DEL, "Delete"},
|
||||
{NKCODE_MOVE_HOME, "Home"},
|
||||
{NKCODE_MOVE_END, "End"},
|
||||
{NKCODE_ESCAPE, "Esc"},
|
||||
|
@ -601,6 +606,11 @@ const KeyMap_IntStrPair psp_button_names[] = {
|
|||
{VIRTKEY_UNTHROTTLE, "Unthrottle"},
|
||||
{VIRTKEY_SPEED_TOGGLE, "SpeedToggle"},
|
||||
{VIRTKEY_PAUSE, "Pause"},
|
||||
#ifndef USING_GLES2
|
||||
{VIRTKEY_REWIND, "Rewind"},
|
||||
#endif
|
||||
{VIRTKEY_SAVE_STATE, "Save State"},
|
||||
{VIRTKEY_LOAD_STATE, "Load State"},
|
||||
|
||||
{VIRTKEY_AXIS_RIGHT_Y_MAX, "RightAn.Up"},
|
||||
{VIRTKEY_AXIS_RIGHT_Y_MIN, "RightAn.Down"},
|
||||
|
@ -671,27 +681,20 @@ KeyDef AxisDef(int deviceId, int axisId, int direction) {
|
|||
return KeyDef(deviceId, TranslateKeyCodeFromAxis(axisId, direction));
|
||||
}
|
||||
|
||||
static bool FindKeyMapping(int deviceId, int key, int *psp_button) {
|
||||
static bool FindKeyMapping(int deviceId, int key, std::vector<int> *psp_button) {
|
||||
// Brute force, let's optimize later
|
||||
for (auto iter = g_controllerMap.begin(); iter != g_controllerMap.end(); ++iter) {
|
||||
for (auto iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2) {
|
||||
if (*iter2 == KeyDef(deviceId, key)) {
|
||||
*psp_button = iter->first;
|
||||
return true;
|
||||
psp_button->push_back(iter->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return psp_button->size() > 0;
|
||||
}
|
||||
|
||||
int KeyToPspButton(int deviceId, int key) {
|
||||
int search_start_layer = 0;
|
||||
int psp_button;
|
||||
|
||||
if (FindKeyMapping(deviceId, key, &psp_button))
|
||||
return psp_button;
|
||||
|
||||
return KEYMAP_ERROR_UNKNOWN_KEY;
|
||||
bool KeyToPspButton(int deviceId, int key, std::vector<int> *pspKeys) {
|
||||
return FindKeyMapping(deviceId, key, pspKeys);
|
||||
}
|
||||
|
||||
// TODO: vector output
|
||||
|
@ -708,9 +711,9 @@ bool KeyFromPspButton(int btn, std::vector<KeyDef> *keys) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int AxisToPspButton(int deviceId, int axisId, int direction) {
|
||||
bool AxisToPspButton(int deviceId, int axisId, int direction, std::vector<int> *pspKeys) {
|
||||
int key = TranslateKeyCodeFromAxis(axisId, direction);
|
||||
return KeyToPspButton(deviceId, key);
|
||||
return KeyToPspButton(deviceId, key, pspKeys);
|
||||
}
|
||||
|
||||
bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction) {
|
||||
|
|
|
@ -40,6 +40,9 @@ enum {
|
|||
VIRTKEY_AXIS_RIGHT_Y_MIN = 0x10009,
|
||||
VIRTKEY_AXIS_RIGHT_X_MAX = 0x1000a,
|
||||
VIRTKEY_AXIS_RIGHT_Y_MAX = 0x1000b,
|
||||
VIRTKEY_REWIND = 0x1000c,
|
||||
VIRTKEY_SAVE_STATE = 0x1000d,
|
||||
VIRTKEY_LOAD_STATE = 0x1000e,
|
||||
VIRTKEY_LAST,
|
||||
VIRTKEY_COUNT = VIRTKEY_LAST - VIRTKEY_FIRST
|
||||
};
|
||||
|
@ -95,9 +98,9 @@ typedef std::map<int, std::vector<KeyDef>> KeyMapping;
|
|||
// KeyMap
|
||||
// A translation layer for key assignment. Provides
|
||||
// integration with Core's config state.
|
||||
//
|
||||
//
|
||||
// Does not handle input state managment.
|
||||
//
|
||||
//
|
||||
// Platform ports should map their platform's keys to KeyMap's keys (NKCODE_*).
|
||||
//
|
||||
// Then have KeyMap transform those into psp buttons.
|
||||
|
@ -113,7 +116,7 @@ namespace KeyMap {
|
|||
std::string name;
|
||||
};
|
||||
|
||||
// Use if you need to display the textual name
|
||||
// Use if you need to display the textual name
|
||||
std::string GetKeyName(int keyCode);
|
||||
std::string GetKeyOrAxisName(int keyCode);
|
||||
std::string GetAxisName(int axisId);
|
||||
|
@ -124,10 +127,7 @@ namespace KeyMap {
|
|||
// Use if to translate KeyMap Keys to PSP
|
||||
// buttons. You should have already translated
|
||||
// your platform's keys to KeyMap keys.
|
||||
//
|
||||
// Returns KEYMAP_ERROR_UNKNOWN_KEY
|
||||
// for any unmapped key
|
||||
int KeyToPspButton(int deviceId, int key);
|
||||
bool KeyToPspButton(int deviceId, int key, std::vector<int> *pspKeys);
|
||||
bool KeyFromPspButton(int btn, std::vector<KeyDef> *keys);
|
||||
|
||||
int TranslateKeyCodeToAxis(int keyCode, int &direction);
|
||||
|
@ -141,7 +141,7 @@ namespace KeyMap {
|
|||
// Direction is negative or positive.
|
||||
void SetAxisMapping(int btn, int deviceId, int axisId, int direction, bool replace);
|
||||
|
||||
int AxisToPspButton(int deviceId, int axisId, int direction);
|
||||
bool AxisToPspButton(int deviceId, int axisId, int direction, std::vector<int> *pspKeys);
|
||||
bool AxisFromPspButton(int btn, int *deviceId, int *axisId, int *direction);
|
||||
std::string NamePspButtonFromAxis(int deviceId, int axisId, int direction);
|
||||
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
|
||||
#include "Log.h"
|
||||
#include "StringUtils.h"
|
||||
#include "Thread.h"
|
||||
#include "FileUtil.h"
|
||||
#include "file/ini_file.h"
|
||||
|
||||
#include <set>
|
||||
#include "StdMutex.h"
|
||||
|
||||
#define MAX_MESSAGES 8000
|
||||
#define MAX_MSGLEN 1024
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
int GetPow2(int x)
|
||||
{
|
||||
int ret = 0;
|
||||
int val = 1;
|
||||
while(x > val)
|
||||
{
|
||||
ret++;
|
||||
val *= 2;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _MATH_UTIL_H_
|
||||
#define _MATH_UTIL_H_
|
||||
|
||||
int GetPow2(int x);
|
||||
|
||||
#endif // _MATH_UTIL_H_
|
|
@ -175,6 +175,12 @@ void *MemArena::CreateView(s64 offset, size_t size, void *base)
|
|||
return ptr;
|
||||
#else
|
||||
void *retval = mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED |
|
||||
// Do not sync memory to underlying file. Linux has this by default.
|
||||
#ifdef BLACKBERRY
|
||||
MAP_NOSYNCFILE |
|
||||
#elif defined(__FreeBSD__)
|
||||
MAP_NOSYNC |
|
||||
#endif
|
||||
((base == 0) ? 0 : MAP_FIXED), fd, offset);
|
||||
|
||||
if (retval == MAP_FAILED)
|
||||
|
@ -216,7 +222,6 @@ u8* MemArena::Find4GBBase()
|
|||
#else // 32 bit
|
||||
|
||||
#ifdef _WIN32
|
||||
// The highest thing in any 1GB section of memory space is the locked cache. We only need to fit it.
|
||||
u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
if (base) {
|
||||
VirtualFree(base, 0, MEM_RELEASE);
|
||||
|
@ -244,8 +249,6 @@ u8* MemArena::Find4GBBase()
|
|||
// if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM))
|
||||
// continue;
|
||||
|
||||
|
||||
|
||||
static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) {
|
||||
// OK, we know where to find free space. Now grab it!
|
||||
// We just mimic the popular BAT setup.
|
||||
|
@ -265,6 +268,8 @@ static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32
|
|||
for (i = 0; i < num_views; i++)
|
||||
{
|
||||
const MemoryView &view = views[i];
|
||||
if (view.size == 0)
|
||||
continue;
|
||||
SKIP(flags, view.flags);
|
||||
if (view.flags & MV_MIRROR_PREVIOUS) {
|
||||
position = last_position;
|
||||
|
@ -305,6 +310,8 @@ bail:
|
|||
// Argh! ERROR! Free what we grabbed so far so we can try again.
|
||||
for (int j = 0; j <= i; j++)
|
||||
{
|
||||
if (views[i].size == 0)
|
||||
continue;
|
||||
SKIP(flags, views[i].flags);
|
||||
if (views[j].out_ptr_low && *views[j].out_ptr_low)
|
||||
{
|
||||
|
@ -334,6 +341,8 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||
|
||||
for (int i = 0; i < num_views; i++)
|
||||
{
|
||||
if (views[i].size == 0)
|
||||
continue;
|
||||
SKIP(flags, views[i].flags);
|
||||
if ((views[i].flags & MV_MIRROR_PREVIOUS) == 0)
|
||||
total_mem += roundup(views[i].size);
|
||||
|
@ -384,6 +393,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena
|
|||
u8 *base = MemArena::Find4GBBase();
|
||||
if (!Memory_TryBase(base, views, num_views, flags, arena))
|
||||
{
|
||||
ERROR_LOG(MEMMAP, "MemoryMap_Setup: Failed finding a memory base.");
|
||||
PanicAlert("MemoryMap_Setup: Failed finding a memory base.");
|
||||
return 0;
|
||||
}
|
||||
|
@ -399,6 +409,8 @@ void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemAr
|
|||
{
|
||||
for (int i = 0; i < num_views; i++)
|
||||
{
|
||||
if (views[i].size == 0)
|
||||
continue;
|
||||
SKIP(flags, views[i].flags);
|
||||
if (views[i].out_ptr_low && *views[i].out_ptr_low)
|
||||
arena->ReleaseView(*views[i].out_ptr_low, views[i].size);
|
||||
|
|
|
@ -60,6 +60,8 @@ enum {
|
|||
// MV_FAKE_VMEM = 2,
|
||||
// MV_WII_ONLY = 4,
|
||||
MV_IS_PRIMARY_RAM = 0x100,
|
||||
MV_IS_EXTRA1_RAM = 0x200,
|
||||
MV_IS_EXTRA2_RAM = 0x400,
|
||||
};
|
||||
|
||||
struct MemoryView
|
||||
|
|
|
@ -45,10 +45,17 @@
|
|||
|
||||
#ifdef __SYMBIAN32__
|
||||
#include <e32std.h>
|
||||
#define SYMBIAN_CODECHUNK_SIZE 1024*1024*20;
|
||||
#define CODECHUNK_SIZE 1024*1024*20
|
||||
static RChunk* g_code_chunk = NULL;
|
||||
static RHeap* g_code_heap = NULL;
|
||||
static void* g_next_ptr = NULL;
|
||||
static u8* g_next_ptr = NULL;
|
||||
static u8* g_orig_ptr = NULL;
|
||||
|
||||
void ResetExecutableMemory(void* ptr)
|
||||
{
|
||||
// Just reset the ptr to the base
|
||||
g_next_ptr = g_orig_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This is purposely not a full wrapper for virtualalloc/mmap, but it
|
||||
|
@ -63,14 +70,13 @@ void* AllocateExecutableMemory(size_t size, bool low)
|
|||
//memory chunk for all the executable code for the JIT
|
||||
if( g_code_chunk == NULL && g_code_heap == NULL)
|
||||
{
|
||||
TInt minsize = SYMBIAN_CODECHUNK_SIZE;
|
||||
TInt maxsize = SYMBIAN_CODECHUNK_SIZE + 3*GetPageSize(); //some offsets
|
||||
g_code_chunk = new RChunk();
|
||||
g_code_chunk->CreateLocalCode(minsize, maxsize);
|
||||
g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, minsize, 1, maxsize);
|
||||
g_next_ptr = (void*) g_code_heap->Alloc( minsize );
|
||||
g_code_chunk->CreateLocalCode(CODECHUNK_SIZE, CODECHUNK_SIZE + 3*GetPageSize());
|
||||
g_code_heap = UserHeap::ChunkHeap(*g_code_chunk, CODECHUNK_SIZE, 1, CODECHUNK_SIZE + 3*GetPageSize());
|
||||
g_next_ptr = reinterpret_cast<u8*>(g_code_heap->AllocZ(CODECHUNK_SIZE));
|
||||
g_orig_ptr = g_next_ptr;
|
||||
}
|
||||
void* ptr = g_next_ptr;
|
||||
void* ptr = (void*)g_next_ptr;
|
||||
g_next_ptr += size;
|
||||
#else
|
||||
static char *map_hint = 0;
|
||||
|
@ -123,7 +129,7 @@ void* AllocateMemoryPages(size_t size)
|
|||
#ifdef _WIN32
|
||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
#elif defined(__SYMBIAN32__)
|
||||
void* ptr = new u8[size];
|
||||
void* ptr = malloc(size);
|
||||
#else
|
||||
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
#endif
|
||||
|
@ -173,7 +179,7 @@ void FreeMemoryPages(void* ptr, size_t size)
|
|||
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
|
||||
ptr = NULL; // Is this our responsibility?
|
||||
#elif defined(__SYMBIAN32__)
|
||||
delete [] ptr;
|
||||
free(ptr);
|
||||
#else
|
||||
munmap(ptr, size);
|
||||
#endif
|
||||
|
|
|
@ -30,6 +30,9 @@ void* AllocateAlignedMemory(size_t size,size_t alignment);
|
|||
void FreeAlignedMemory(void* ptr);
|
||||
void WriteProtectMemory(void* ptr, size_t size, bool executable = false);
|
||||
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute = false);
|
||||
#ifdef __SYMBIAN32__
|
||||
void ResetExecutableMemory(void* ptr);
|
||||
#endif
|
||||
|
||||
inline int GetPageSize() { return 4096; }
|
||||
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
|
||||
#ifndef CONDITION_VARIABLE_H_
|
||||
#define CONDITION_VARIABLE_H_
|
||||
|
||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
|
||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
|
||||
|
||||
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !defined(ANDROID) && !defined(__SYMBIAN32__)
|
||||
// GCC 4.4 provides <condition_variable>
|
||||
#include <condition_variable>
|
||||
#else
|
||||
|
||||
// partial std::condition_variable implementation for win32/pthread
|
||||
|
||||
#include "StdMutex.h"
|
||||
|
||||
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__)
|
||||
#define USE_RVALUE_REFERENCES
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_X64)
|
||||
#define USE_CONDITION_VARIABLES
|
||||
#elif defined(_WIN32)
|
||||
#define USE_EVENTS
|
||||
#endif
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
class condition_variable
|
||||
{
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||
typedef CONDITION_VARIABLE native_type;
|
||||
#elif defined(_WIN32)
|
||||
typedef HANDLE native_type;
|
||||
#else
|
||||
typedef pthread_cond_t native_type;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
#ifdef USE_EVENTS
|
||||
typedef native_type native_handle_type;
|
||||
#else
|
||||
typedef native_type* native_handle_type;
|
||||
#endif
|
||||
|
||||
condition_variable()
|
||||
{
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||
InitializeConditionVariable(&m_handle);
|
||||
#elif defined(_WIN32)
|
||||
m_handle = CreateEvent(NULL, false, false, NULL);
|
||||
#else
|
||||
pthread_cond_init(&m_handle, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
~condition_variable()
|
||||
{
|
||||
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
|
||||
CloseHandle(m_handle);
|
||||
#elif !defined(_WIN32)
|
||||
pthread_cond_destroy(&m_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
condition_variable(const condition_variable&) /*= delete*/;
|
||||
condition_variable& operator=(const condition_variable&) /*= delete*/;
|
||||
|
||||
void notify_one()
|
||||
{
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||
WakeConditionVariable(&m_handle);
|
||||
#elif defined(_WIN32)
|
||||
SetEvent(m_handle);
|
||||
#else
|
||||
pthread_cond_signal(&m_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
void notify_all()
|
||||
{
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
|
||||
WakeAllConditionVariable(&m_handle);
|
||||
#elif defined(_WIN32)
|
||||
// TODO: broken
|
||||
SetEvent(m_handle);
|
||||
#else
|
||||
pthread_cond_broadcast(&m_handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
void wait(unique_lock<mutex>& lock)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#ifdef USE_SRWLOCKS
|
||||
SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
|
||||
#elif defined(USE_CONDITION_VARIABLES)
|
||||
SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
|
||||
#else
|
||||
// TODO: broken, the unlock and wait need to be atomic
|
||||
lock.unlock();
|
||||
WaitForSingleObject(m_handle, INFINITE);
|
||||
lock.lock();
|
||||
#endif
|
||||
#else
|
||||
pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class Predicate>
|
||||
void wait(unique_lock<mutex>& lock, Predicate pred)
|
||||
{
|
||||
while (!pred())
|
||||
wait(lock);
|
||||
}
|
||||
|
||||
//template <class Clock, class Duration>
|
||||
//cv_status wait_until(unique_lock<mutex>& lock,
|
||||
// const chrono::time_point<Clock, Duration>& abs_time);
|
||||
|
||||
//template <class Clock, class Duration, class Predicate>
|
||||
// bool wait_until(unique_lock<mutex>& lock,
|
||||
// const chrono::time_point<Clock, Duration>& abs_time,
|
||||
// Predicate pred);
|
||||
|
||||
//template <class Rep, class Period>
|
||||
//cv_status wait_for(unique_lock<mutex>& lock,
|
||||
// const chrono::duration<Rep, Period>& rel_time);
|
||||
|
||||
//template <class Rep, class Period, class Predicate>
|
||||
// bool wait_for(unique_lock<mutex>& lock,
|
||||
// const chrono::duration<Rep, Period>& rel_time,
|
||||
// Predicate pred);
|
||||
|
||||
native_handle_type native_handle()
|
||||
{
|
||||
#ifdef USE_EVENTS
|
||||
return m_handle;
|
||||
#else
|
||||
return &m_handle;
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
native_type m_handle;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
|
@ -1,212 +0,0 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Common.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/mach.h>
|
||||
#elif defined(ANDROID)
|
||||
#include <sys/syscall.h>
|
||||
#elif defined BSD4_4
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
|
||||
#ifdef BLACKBERRY
|
||||
#include <sys/neutrino.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_BEGINTHREADEX
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
namespace Common
|
||||
{
|
||||
|
||||
int CurrentThreadId()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return GetCurrentThreadId();
|
||||
#elif defined __APPLE__
|
||||
return mach_thread_self();
|
||||
#else
|
||||
return pthread_self();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
bool SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
|
||||
{
|
||||
return SetThreadAffinityMask(thread, mask) != 0;
|
||||
}
|
||||
|
||||
bool SetCurrentThreadAffinity(u32 mask)
|
||||
{
|
||||
return SetThreadAffinityMask(GetCurrentThread(), mask) != 0;
|
||||
}
|
||||
|
||||
// Supporting functions
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
void SwitchCurrentThread()
|
||||
{
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
// Sets the debugger-visible name of the current thread.
|
||||
// Uses undocumented (actually, it is now documented) trick.
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
|
||||
|
||||
// This is implemented much nicer in upcoming msvc++, see:
|
||||
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
|
||||
void SetCurrentThreadName(const char* szThreadName)
|
||||
{
|
||||
static const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
|
||||
#pragma pack(push,8)
|
||||
struct THREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
LPCSTR szName; // pointer to name (in user addr space)
|
||||
DWORD dwThreadID; // thread ID (-1=caller thread)
|
||||
DWORD dwFlags; // reserved for future use, must be zero
|
||||
} info;
|
||||
#pragma pack(pop)
|
||||
|
||||
info.dwType = 0x1000;
|
||||
info.szName = szThreadName;
|
||||
info.dwThreadID = -1; //dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{}
|
||||
}
|
||||
|
||||
void EnableCrashingOnCrashes()
|
||||
{
|
||||
typedef BOOL (WINAPI *tGetPolicy)(LPDWORD lpFlags);
|
||||
typedef BOOL (WINAPI *tSetPolicy)(DWORD dwFlags);
|
||||
const DWORD EXCEPTION_SWALLOWING = 0x1;
|
||||
|
||||
HMODULE kernel32 = LoadLibraryA("kernel32.dll");
|
||||
tGetPolicy pGetPolicy = (tGetPolicy)GetProcAddress(kernel32,
|
||||
"GetProcessUserModeExceptionPolicy");
|
||||
tSetPolicy pSetPolicy = (tSetPolicy)GetProcAddress(kernel32,
|
||||
"SetProcessUserModeExceptionPolicy");
|
||||
if (pGetPolicy && pSetPolicy)
|
||||
{
|
||||
DWORD dwFlags;
|
||||
if (pGetPolicy(&dwFlags))
|
||||
{
|
||||
// Turn off the filter
|
||||
pSetPolicy(dwFlags & ~EXCEPTION_SWALLOWING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#else // !WIN32, so must be POSIX threads
|
||||
|
||||
bool SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
return thread_policy_set(pthread_mach_thread_np(thread),
|
||||
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1) == 0;
|
||||
#elif defined(ANDROID) || defined(BLACKBERRY)
|
||||
return false;
|
||||
#elif (defined __linux__ || defined BSD4_4)
|
||||
cpu_set_t cpu_set;
|
||||
CPU_ZERO(&cpu_set);
|
||||
|
||||
for (int i = 0; i != sizeof(mask) * 8; ++i) {
|
||||
if ((mask >> i) & 1)
|
||||
CPU_SET(i, &cpu_set);
|
||||
}
|
||||
|
||||
return pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set) == 0;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SetCurrentThreadAffinity(u32 mask)
|
||||
{
|
||||
#ifdef BLACKBERRY
|
||||
return ThreadCtl(_NTO_TCTL_RUNMASK, &mask) != -1;
|
||||
#elif defined(ANDROID)
|
||||
return syscall(__NR_sched_setaffinity, gettid(), sizeof(mask), &mask) == 0;
|
||||
#else
|
||||
return SetThreadAffinity(pthread_self(), mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
static pthread_key_t threadname_key;
|
||||
static pthread_once_t threadname_key_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
usleep(1000 * ms);
|
||||
}
|
||||
|
||||
void SwitchCurrentThread()
|
||||
{
|
||||
usleep(1000 * 1);
|
||||
}
|
||||
|
||||
static void FreeThreadName(void* threadname)
|
||||
{
|
||||
free(threadname);
|
||||
}
|
||||
|
||||
static void ThreadnameKeyAlloc()
|
||||
{
|
||||
pthread_key_create(&threadname_key, FreeThreadName);
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char* szThreadName)
|
||||
{
|
||||
#ifdef BLACKBERRY
|
||||
pthread_setname_np(pthread_self(), szThreadName);
|
||||
#else
|
||||
pthread_once(&threadname_key_once, ThreadnameKeyAlloc);
|
||||
|
||||
void* threadname;
|
||||
if ((threadname = pthread_getspecific(threadname_key)) != NULL)
|
||||
free(threadname);
|
||||
|
||||
pthread_setspecific(threadname_key, strdup(szThreadName));
|
||||
#endif
|
||||
|
||||
INFO_LOG(COMMON, "%s(%s)\n", __FUNCTION__, szThreadName);
|
||||
}
|
||||
|
||||
void EnableCrashingOnCrashes()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Common
|
176
Common/Thread.h
176
Common/Thread.h
|
@ -1,176 +0,0 @@
|
|||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _THREAD_H_
|
||||
#define _THREAD_H_
|
||||
|
||||
#include "thread/thread.h"
|
||||
#include "StdConditionVariable.h"
|
||||
|
||||
// Don't include common.h here as it will break LogManager
|
||||
#include "CommonTypes.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
// This may not be defined outside _WIN32
|
||||
#ifndef _WIN32
|
||||
#ifndef INFINITE
|
||||
#define INFINITE 0xffffffff
|
||||
#endif
|
||||
|
||||
// Assume !ARM && !MIPS = x86
|
||||
#if !defined(ARM) && !defined(MIPS)
|
||||
#include <xmmintrin.h>
|
||||
#endif
|
||||
|
||||
//for gettimeofday and struct time(spec|val)
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
namespace Common
|
||||
{
|
||||
|
||||
int CurrentThreadId();
|
||||
|
||||
// In Windows 7 SP1 or later, stops Windows from swallowing crashes in WndProcs and other callbacks.
|
||||
void EnableCrashingOnCrashes();
|
||||
|
||||
bool SetThreadAffinity(std::thread::native_handle_type thread, u32 mask);
|
||||
bool SetCurrentThreadAffinity(u32 mask);
|
||||
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
Event()
|
||||
: is_set(false)
|
||||
{};
|
||||
|
||||
void Set()
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(m_mutex);
|
||||
if (!is_set)
|
||||
{
|
||||
is_set = true;
|
||||
m_condvar.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
void Wait()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m_mutex);
|
||||
m_condvar.wait(lk, IsSet(this));
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m_mutex);
|
||||
// no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
private:
|
||||
class IsSet
|
||||
{
|
||||
public:
|
||||
IsSet(const Event* ev)
|
||||
: m_event(ev)
|
||||
{}
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
return m_event->is_set;
|
||||
}
|
||||
|
||||
private:
|
||||
const Event* const m_event;
|
||||
};
|
||||
|
||||
volatile bool is_set;
|
||||
std::condition_variable m_condvar;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
|
||||
// TODO: doesn't work on windows with (count > 2)
|
||||
class Barrier
|
||||
{
|
||||
public:
|
||||
Barrier(size_t count)
|
||||
: m_count(count), m_waiting(0)
|
||||
{}
|
||||
|
||||
// block until "count" threads call Sync()
|
||||
bool Sync()
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(m_mutex);
|
||||
|
||||
// TODO: broken when next round of Sync()s
|
||||
// is entered before all waiting threads return from the notify_all
|
||||
|
||||
if (m_count == ++m_waiting)
|
||||
{
|
||||
m_waiting = 0;
|
||||
m_condvar.notify_all();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_condvar.wait(lk, IsDoneWating(this));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
class IsDoneWating
|
||||
{
|
||||
public:
|
||||
IsDoneWating(const Barrier* bar)
|
||||
: m_bar(bar)
|
||||
{}
|
||||
|
||||
bool operator()()
|
||||
{
|
||||
return (0 == m_bar->m_waiting);
|
||||
}
|
||||
|
||||
private:
|
||||
const Barrier* const m_bar;
|
||||
};
|
||||
|
||||
std::condition_variable m_condvar;
|
||||
std::mutex m_mutex;
|
||||
const size_t m_count;
|
||||
volatile size_t m_waiting;
|
||||
};
|
||||
|
||||
void SleepCurrentThread(int ms);
|
||||
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
|
||||
|
||||
// Use this function during a spin-wait to make the current thread
|
||||
// relax while another thread is working. This may be more efficient
|
||||
// than using events because event functions use kernel calls.
|
||||
inline void YieldCPU()
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const char *name);
|
||||
|
||||
} // namespace Common
|
||||
|
||||
#endif // _THREAD_H_
|
|
@ -463,7 +463,7 @@ namespace PpcGen
|
|||
region_size = 0;
|
||||
}
|
||||
|
||||
bool IsInSpace(u8 *ptr)
|
||||
bool IsInSpace(const u8 *ptr) const
|
||||
{
|
||||
return ptr >= region && ptr < region + region_size;
|
||||
}
|
||||
|
@ -493,7 +493,7 @@ namespace PpcGen
|
|||
return region;
|
||||
}
|
||||
|
||||
size_t GetOffset(u8 *ptr) {
|
||||
size_t GetOffset(const u8 *ptr) const {
|
||||
return ptr - region;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1371,6 +1371,12 @@ void XEmitter::PSLLQ(X64Reg reg, int shift) {
|
|||
Write8(shift);
|
||||
}
|
||||
|
||||
void XEmitter::PSLLDQ(X64Reg reg, int shift) {
|
||||
WriteSSEOp(64, 0x73, true, (X64Reg)7, R(reg));
|
||||
Write8(shift);
|
||||
}
|
||||
|
||||
|
||||
// WARNING not REX compatible
|
||||
void XEmitter::PSRAW(X64Reg reg, int shift) {
|
||||
if (reg > 7)
|
||||
|
|
|
@ -126,7 +126,6 @@ enum
|
|||
|
||||
class XEmitter;
|
||||
|
||||
// RIP addressing does not benefit from micro op fusion on Core arch
|
||||
struct OpArg
|
||||
{
|
||||
OpArg() {} // dummy op arg, used for storage
|
||||
|
@ -658,6 +657,8 @@ public:
|
|||
void PSLLD(X64Reg reg, int shift);
|
||||
void PSLLQ(X64Reg reg, int shift);
|
||||
|
||||
void PSLLDQ(X64Reg reg, int shift);
|
||||
|
||||
void PSRAW(X64Reg reg, int shift);
|
||||
void PSRAD(X64Reg reg, int shift);
|
||||
|
||||
|
@ -755,7 +756,7 @@ public:
|
|||
region_size = 0;
|
||||
}
|
||||
|
||||
bool IsInSpace(u8 *ptr)
|
||||
bool IsInSpace(const u8 *ptr) const
|
||||
{
|
||||
return ptr >= region && ptr < region + region_size;
|
||||
}
|
||||
|
@ -781,7 +782,7 @@ public:
|
|||
return region;
|
||||
}
|
||||
|
||||
size_t GetOffset(u8 *ptr) {
|
||||
size_t GetOffset(const u8 *ptr) const {
|
||||
return ptr - region;
|
||||
}
|
||||
};
|
||||
|
|
307
Core/Config.cpp
307
Core/Config.cpp
|
@ -17,20 +17,31 @@
|
|||
|
||||
#include "base/display.h"
|
||||
#include "base/NativeApp.h"
|
||||
#include "ext/vjson/json.h"
|
||||
#include "file/ini_file.h"
|
||||
#include "i18n/i18n.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "net/http_client.h"
|
||||
#include "util/text/parsers.h"
|
||||
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Common/KeyMap.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Config.h"
|
||||
#include "file/ini_file.h"
|
||||
#include "i18n/i18n.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
#include "HLE/sceUtility.h"
|
||||
#include "Common/CPUDetect.h"
|
||||
|
||||
#ifndef USING_QT_UI
|
||||
extern const char *PPSSPP_GIT_VERSION;
|
||||
#endif
|
||||
|
||||
// TODO: Find a better place for this.
|
||||
http::Downloader g_DownloadManager;
|
||||
|
||||
Config g_Config;
|
||||
|
||||
#ifdef IOS
|
||||
extern bool isJailed;
|
||||
extern bool iosCanUseJit;
|
||||
#endif
|
||||
|
||||
Config::Config() { }
|
||||
|
@ -52,12 +63,16 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
IniFile::Section *general = iniFile.GetOrCreateSection("General");
|
||||
|
||||
general->Get("FirstRun", &bFirstRun, true);
|
||||
general->Get("RunCount", &iRunCount, 0);
|
||||
iRunCount++;
|
||||
general->Get("Enable Logging", &bEnableLogging, true);
|
||||
general->Get("AutoRun", &bAutoRun, true);
|
||||
general->Get("Browse", &bBrowse, false);
|
||||
general->Get("IgnoreBadMemAccess", &bIgnoreBadMemAccess, true);
|
||||
general->Get("CurrentDirectory", ¤tDirectory, "");
|
||||
general->Get("ShowDebuggerOnLoad", &bShowDebuggerOnLoad, false);
|
||||
general->Get("HomebrewStore", &bHomebrewStore, false);
|
||||
general->Get("CheckForNewVersion", &bCheckForNewVersion, true);
|
||||
|
||||
if (!File::Exists(currentDirectory))
|
||||
currentDirectory = "";
|
||||
|
@ -79,13 +94,13 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
general->Get("RewindFlipFrequency", &iRewindFlipFrequency, 0);
|
||||
general->Get("GridView1", &bGridView1, true);
|
||||
general->Get("GridView2", &bGridView2, true);
|
||||
general->Get("GridView3", &bGridView3, true);
|
||||
general->Get("GridView3", &bGridView3, false);
|
||||
|
||||
// "default" means let emulator decide, "" means disable.
|
||||
general->Get("ReportingHost", &sReportHost, "default");
|
||||
general->Get("Recent", recentIsos);
|
||||
general->Get("AutoSaveSymbolMap", &bAutoSaveSymbolMap, false);
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
general->Get("TopMost", &bTopMost);
|
||||
general->Get("WindowX", &iWindowX, -1); // -1 tells us to center the window.
|
||||
general->Get("WindowY", &iWindowY, -1);
|
||||
|
@ -118,19 +133,15 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
#ifdef IOS
|
||||
cpu->Get("Jit", &bJit, !isJailed);
|
||||
cpu->Get("Jit", &bJit, iosCanUseJit);
|
||||
#else
|
||||
cpu->Get("Jit", &bJit, true);
|
||||
#endif
|
||||
cpu->Get("SeparateCPUThread", &bSeparateCPUThread, false);
|
||||
cpu->Get("AtomicAudioLocks", &bAtomicAudioLocks, false);
|
||||
|
||||
#ifdef __SYMBIAN32__
|
||||
cpu->Get("SeparateIOThread", &bSeparateIOThread, false);
|
||||
#else
|
||||
cpu->Get("SeparateIOThread", &bSeparateIOThread, true);
|
||||
#endif
|
||||
cpu->Get("FastMemory", &bFastMemory, false);
|
||||
cpu->Get("FastMemoryAccess", &bFastMemory, true);
|
||||
cpu->Get("CPUSpeed", &iLockedCPUSpeed, 0);
|
||||
|
||||
IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics");
|
||||
|
@ -144,12 +155,13 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
graphics->Get("RenderingMode", &iRenderingMode, renderingModeDefault);
|
||||
graphics->Get("SoftwareRendering", &bSoftwareRendering, false);
|
||||
graphics->Get("HardwareTransform", &bHardwareTransform, true);
|
||||
graphics->Get("SoftwareSkinning", &bSoftwareSkinning, true);
|
||||
graphics->Get("TextureFiltering", &iTexFiltering, 1);
|
||||
// Auto on Windows, 1x elsewhere. Maybe change to 2x on large screens?
|
||||
#ifdef _WIN32
|
||||
// Auto on Windows, 2x on large screens, 1x elsewhere.
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
graphics->Get("InternalResolution", &iInternalResolution, 0);
|
||||
#else
|
||||
graphics->Get("InternalResolution", &iInternalResolution, 1);
|
||||
graphics->Get("InternalResolution", &iInternalResolution, pixel_xres >= 1024 ? 2 : 1);
|
||||
#endif
|
||||
|
||||
graphics->Get("FrameSkip", &iFrameSkip, 0);
|
||||
|
@ -169,25 +181,38 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
iAnisotropyLevel = 4;
|
||||
}
|
||||
graphics->Get("VertexCache", &bVertexCache, true);
|
||||
graphics->Get("VertexDecoderJit", &bVertexDecoderJit, true);
|
||||
#ifdef IOS
|
||||
graphics->Get("VertexDecJit", &bVertexDecoderJit, iosCanUseJit);
|
||||
#else
|
||||
graphics->Get("VertexDecJit", &bVertexDecoderJit, true);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
graphics->Get("FullScreen", &bFullScreen, false);
|
||||
#endif
|
||||
bool partialStretchDefault = false;
|
||||
#ifdef BLACKBERRY
|
||||
graphics->Get("PartialStretch", &bPartialStretch, pixel_xres == pixel_yres);
|
||||
partialStretchDefault = pixel_xres < 1.3 * pixel_yres;
|
||||
#endif
|
||||
graphics->Get("PartialStretch", &bPartialStretch, partialStretchDefault);
|
||||
graphics->Get("StretchToDisplay", &bStretchToDisplay, false);
|
||||
graphics->Get("TrueColor", &bTrueColor, true);
|
||||
graphics->Get("MipMap", &bMipMap, true);
|
||||
|
||||
graphics->Get("MipMap", &bMipMap, false);
|
||||
|
||||
graphics->Get("TexScalingLevel", &iTexScalingLevel, 1);
|
||||
graphics->Get("TexScalingType", &iTexScalingType, 0);
|
||||
graphics->Get("TexDeposterize", &bTexDeposterize, false);
|
||||
graphics->Get("VSyncInterval", &bVSync, false);
|
||||
graphics->Get("DisableStencilTest", &bDisableStencilTest, false);
|
||||
graphics->Get("AlwaysDepthWrite", &bAlwaysDepthWrite, false);
|
||||
// Has been in use on Symbian since v0.7. Preferred option.
|
||||
#ifdef __SYMBIAN32__
|
||||
graphics->Get("TimerHack", &bTimerHack, true);
|
||||
#else
|
||||
graphics->Get("TimerHack", &bTimerHack, false);
|
||||
#endif
|
||||
graphics->Get("LowQualitySplineBezier", &bLowQualitySplineBezier, false);
|
||||
graphics->Get("WipeFramebufferAlpha", &bWipeFramebufferAlpha, false);
|
||||
graphics->Get("PostShader", &sPostShaderName, "Off");
|
||||
|
||||
IniFile::Section *sound = iniFile.GetOrCreateSection("Sound");
|
||||
|
@ -233,29 +258,47 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
control->Get("TiltInputType", &iTiltInputType, 0);
|
||||
|
||||
#endif
|
||||
control->Get("DisableDpadDiagonals", &bDisableDpadDiagonals, false);
|
||||
control->Get("TouchButtonStyle", &iTouchButtonStyle, 1);
|
||||
control->Get("TouchButtonOpacity", &iTouchButtonOpacity, 65);
|
||||
control->Get("ButtonScale", &fButtonScale, 1.15);
|
||||
//set these to -1 if not initialized. initializing these
|
||||
//requires pixel coordinates which is not known right now.
|
||||
//will be initialized in GamepadEmu::CreatePadLayout
|
||||
control->Get("ActionButtonSpacing", &iActionButtonSpacing, -1);
|
||||
float defaultScale = 1.15f;
|
||||
control->Get("ActionButtonSpacing2", &fActionButtonSpacing, 1.0f);
|
||||
control->Get("ActionButtonCenterX", &fActionButtonCenterX, -1.0);
|
||||
control->Get("ActionButtonCenterY", &fActionButtonCenterY, -1.0);
|
||||
control->Get("DPadRadius", &iDpadRadius, -1);
|
||||
control->Get("ActionButtonScale", &fActionButtonScale, defaultScale);
|
||||
control->Get("DPadX", &fDpadX, -1.0);
|
||||
control->Get("DPadY", &fDpadY, -1.0);
|
||||
control->Get("StartKeyX", &fStartKeyX, -1.0);
|
||||
control->Get("StartKeyY", &fStartKeyY, -1.0);
|
||||
control->Get("SelectKeyX", &fSelectKeyX, -1.0);
|
||||
control->Get("SelectKeyY", &fSelectKeyY, -1.0);
|
||||
control->Get("UnthrottleKeyX", &fUnthrottleKeyX, -1.0);
|
||||
control->Get("UnthrottleKeyY", &fUnthrottleKeyY, -1.0);
|
||||
control->Get("LKeyX", &fLKeyX, -1.0);
|
||||
control->Get("LKeyY", &fLKeyY, -1.0);
|
||||
control->Get("RKeyX", &fRKeyX, -1.0);
|
||||
control->Get("RKeyY", &fRKeyY, -1.0);
|
||||
control->Get("AnalogStickX", &fAnalogStickX, -1.0);
|
||||
control->Get("AnalogStickY", &fAnalogStickY, -1.0);
|
||||
|
||||
// Check for an old dpad setting
|
||||
float f;
|
||||
control->Get("DPadRadius", &f, 0.0f);
|
||||
if (f > 0.0f) {
|
||||
ResetControlLayout();
|
||||
} else {
|
||||
control->Get("DPadScale", &fDpadScale, defaultScale);
|
||||
control->Get("DPadSpacing", &fDpadSpacing, 1.0f);
|
||||
control->Get("StartKeyX", &fStartKeyX, -1.0);
|
||||
control->Get("StartKeyY", &fStartKeyY, -1.0);
|
||||
control->Get("StartKeyScale", &fStartKeyScale, defaultScale);
|
||||
control->Get("SelectKeyX", &fSelectKeyX, -1.0);
|
||||
control->Get("SelectKeyY", &fSelectKeyY, -1.0);
|
||||
control->Get("SelectKeyScale", &fSelectKeyScale, defaultScale);
|
||||
control->Get("UnthrottleKeyX", &fUnthrottleKeyX, -1.0);
|
||||
control->Get("UnthrottleKeyY", &fUnthrottleKeyY, -1.0);
|
||||
control->Get("UnthrottleKeyScale", &fUnthrottleKeyScale, defaultScale);
|
||||
control->Get("LKeyX", &fLKeyX, -1.0);
|
||||
control->Get("LKeyY", &fLKeyY, -1.0);
|
||||
control->Get("LKeyScale", &fLKeyScale, defaultScale);
|
||||
control->Get("RKeyX", &fRKeyX, -1.0);
|
||||
control->Get("RKeyY", &fRKeyY, -1.0);
|
||||
control->Get("RKeyScale", &fRKeyScale, defaultScale);
|
||||
control->Get("AnalogStickX", &fAnalogStickX, -1.0);
|
||||
control->Get("AnalogStickY", &fAnalogStickY, -1.0);
|
||||
control->Get("AnalogStickScale", &fAnalogStickScale, defaultScale);
|
||||
}
|
||||
|
||||
// MIGRATION: For users who had the old static touch layout, aren't I nice?
|
||||
if (fDpadX > 1.0 || fDpadY > 1.0) // Likely the rest are too!
|
||||
|
@ -277,9 +320,20 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
fAnalogStickX /= dp_xres;
|
||||
fAnalogStickY /= dp_yres;
|
||||
}
|
||||
|
||||
|
||||
IniFile::Section *network = iniFile.GetOrCreateSection("Network");
|
||||
network->Get("EnableWlan", &bEnableWlan, false);
|
||||
|
||||
IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam");
|
||||
pspConfig->Get("PSPModel", &iPSPModel, PSP_MODEL_SLIM);
|
||||
pspConfig->Get("PSPFirmwareVersion", &iFirmwareVersion, PSP_DEFAULT_FIRMWARE);
|
||||
#if !defined(_M_X64) && !defined(_WIN32) && !defined(__SYMBIAN32__)
|
||||
// 32-bit mmap cannot map more than 32MB contiguous
|
||||
iPSPModel = PSP_MODEL_FAT;
|
||||
#endif
|
||||
pspConfig->Get("NickName", &sNickName, "PPSSPP");
|
||||
pspConfig->Get("proAdhocServer", &proAdhocServer, "localhost");
|
||||
pspConfig->Get("MacAddress", &localMacAddress, "01:02:03:04:05:06");
|
||||
pspConfig->Get("Language", &iLanguage, PSP_SYSTEMPARAM_LANGUAGE_ENGLISH);
|
||||
pspConfig->Get("TimeFormat", &iTimeFormat, PSP_SYSTEMPARAM_TIME_FORMAT_24HR);
|
||||
pspConfig->Get("DateFormat", &iDateFormat, PSP_SYSTEMPARAM_DATE_FORMAT_YYYYMMDD);
|
||||
|
@ -288,7 +342,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
pspConfig->Get("ButtonPreference", &iButtonPreference, PSP_SYSTEMPARAM_BUTTON_CROSS);
|
||||
pspConfig->Get("LockParentalLevel", &iLockParentalLevel, 0);
|
||||
pspConfig->Get("WlanAdhocChannel", &iWlanAdhocChannel, PSP_SYSTEMPARAM_ADHOC_CHANNEL_AUTOMATIC);
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
pspConfig->Get("BypassOSKWithKeyboard", &bBypassOSKWithKeyboard, false);
|
||||
#endif
|
||||
pspConfig->Get("WlanPowerSave", &bWlanPowerSave, PSP_SYSTEMPARAM_WLAN_POWERSAVE_OFF);
|
||||
|
@ -311,6 +365,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
debugConfig->Get("ShowBottomTabTitles",&bShowBottomTabTitles,true);
|
||||
debugConfig->Get("ShowDeveloperMenu", &bShowDeveloperMenu, false);
|
||||
debugConfig->Get("SkipDeadbeefFilling", &bSkipDeadbeefFilling, false);
|
||||
debugConfig->Get("FuncHashMap", &bFuncHashMap, false);
|
||||
|
||||
IniFile::Section *speedhacks = iniFile.GetOrCreateSection("SpeedHacks");
|
||||
speedhacks->Get("PrescaleUV", &bPrescaleUV, false);
|
||||
|
@ -319,6 +374,25 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
IniFile::Section *jitConfig = iniFile.GetOrCreateSection("JIT");
|
||||
jitConfig->Get("DiscardRegsOnJRRA", &bDiscardRegsOnJRRA, false);
|
||||
|
||||
IniFile::Section *upgrade = iniFile.GetOrCreateSection("Upgrade");
|
||||
upgrade->Get("UpgradeMessage", &upgradeMessage, "");
|
||||
upgrade->Get("UpgradeVersion", &upgradeVersion, "");
|
||||
upgrade->Get("DismissedVersion", &dismissedVersion, "");
|
||||
|
||||
if (dismissedVersion == upgradeVersion) {
|
||||
upgradeMessage = "";
|
||||
}
|
||||
|
||||
// Check for new version on every 5 runs.
|
||||
// Sometimes the download may not be finished when the main screen shows (if the user dismisses the
|
||||
// splash screen quickly), but then we'll just show the notification next time instead, we store the
|
||||
// upgrade number in the ini.
|
||||
if (iRunCount % 10 == 0 && bCheckForNewVersion) {
|
||||
std::shared_ptr<http::Download> dl = g_DownloadManager.StartDownloadWithCallback(
|
||||
"http://www.ppsspp.org/version.json", "", &DownloadCompletedCallback);
|
||||
dl->SetHidden(true);
|
||||
}
|
||||
|
||||
INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename_.c_str());
|
||||
bSaveSettings = true;
|
||||
|
||||
|
@ -343,10 +417,11 @@ void Config::Save() {
|
|||
}
|
||||
|
||||
IniFile::Section *general = iniFile.GetOrCreateSection("General");
|
||||
|
||||
|
||||
// Need to do this somewhere...
|
||||
bFirstRun = false;
|
||||
general->Set("FirstRun", bFirstRun);
|
||||
general->Set("RunCount", iRunCount);
|
||||
general->Set("Enable Logging", bEnableLogging);
|
||||
general->Set("AutoRun", bAutoRun);
|
||||
general->Set("Browse", bBrowse);
|
||||
|
@ -355,7 +430,7 @@ void Config::Save() {
|
|||
general->Set("ShowDebuggerOnLoad", bShowDebuggerOnLoad);
|
||||
general->Set("ReportingHost", sReportHost);
|
||||
general->Set("AutoSaveSymbolMap", bAutoSaveSymbolMap);
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
general->Set("TopMost", bTopMost);
|
||||
general->Set("WindowX", iWindowX);
|
||||
general->Set("WindowY", iWindowY);
|
||||
|
@ -373,10 +448,11 @@ void Config::Save() {
|
|||
general->Set("GridView1", bGridView1);
|
||||
general->Set("GridView2", bGridView2);
|
||||
general->Set("GridView3", bGridView3);
|
||||
|
||||
general->Set("CheckForNewVersion", bCheckForNewVersion);
|
||||
|
||||
IniFile::Section *recent = iniFile.GetOrCreateSection("Recent");
|
||||
recent->Set("MaxRecent", iMaxRecent);
|
||||
|
||||
|
||||
for (int i = 0; i < iMaxRecent; i++) {
|
||||
char keyName[64];
|
||||
sprintf(keyName,"FileName%d",i);
|
||||
|
@ -384,15 +460,15 @@ void Config::Save() {
|
|||
recent->Set(keyName, recentIsos[i]);
|
||||
} else {
|
||||
recent->Delete(keyName); // delete the nonexisting FileName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IniFile::Section *cpu = iniFile.GetOrCreateSection("CPU");
|
||||
cpu->Set("Jit", bJit);
|
||||
cpu->Set("SeparateCPUThread", bSeparateCPUThread);
|
||||
cpu->Set("AtomicAudioLocks", bAtomicAudioLocks);
|
||||
cpu->Set("AtomicAudioLocks", bAtomicAudioLocks);
|
||||
cpu->Set("SeparateIOThread", bSeparateIOThread);
|
||||
cpu->Set("FastMemory", bFastMemory);
|
||||
cpu->Set("FastMemoryAccess", bFastMemory);
|
||||
cpu->Set("CPUSpeed", iLockedCPUSpeed);
|
||||
|
||||
IniFile::Section *graphics = iniFile.GetOrCreateSection("Graphics");
|
||||
|
@ -400,6 +476,7 @@ void Config::Save() {
|
|||
graphics->Set("RenderingMode", iRenderingMode);
|
||||
graphics->Set("SoftwareRendering", bSoftwareRendering);
|
||||
graphics->Set("HardwareTransform", bHardwareTransform);
|
||||
graphics->Set("SoftwareSkinning", bSoftwareSkinning);
|
||||
graphics->Set("TextureFiltering", iTexFiltering);
|
||||
graphics->Set("InternalResolution", iInternalResolution);
|
||||
graphics->Set("FrameSkip", iFrameSkip);
|
||||
|
@ -408,13 +485,10 @@ void Config::Save() {
|
|||
graphics->Set("ForceMaxEmulatedFPS", iForceMaxEmulatedFPS);
|
||||
graphics->Set("AnisotropyLevel", iAnisotropyLevel);
|
||||
graphics->Set("VertexCache", bVertexCache);
|
||||
graphics->Set("VertexDecoderJit", bVertexDecoderJit);
|
||||
#ifdef _WIN32
|
||||
graphics->Set("FullScreen", bFullScreen);
|
||||
#endif
|
||||
#ifdef BLACKBERRY
|
||||
graphics->Set("PartialStretch", bPartialStretch);
|
||||
#endif
|
||||
graphics->Set("PartialStretch", bPartialStretch);
|
||||
graphics->Set("StretchToDisplay", bStretchToDisplay);
|
||||
graphics->Set("TrueColor", bTrueColor);
|
||||
graphics->Set("MipMap", bMipMap);
|
||||
|
@ -424,6 +498,7 @@ void Config::Save() {
|
|||
graphics->Set("VSyncInterval", bVSync);
|
||||
graphics->Set("DisableStencilTest", bDisableStencilTest);
|
||||
graphics->Set("AlwaysDepthWrite", bAlwaysDepthWrite);
|
||||
graphics->Set("TimerHack", bTimerHack);
|
||||
graphics->Set("LowQualitySplineBezier", bLowQualitySplineBezier);
|
||||
graphics->Set("PostShader", sPostShaderName);
|
||||
|
||||
|
@ -448,7 +523,6 @@ void Config::Save() {
|
|||
control->Set("ShowTouchUnthrottle", bShowTouchUnthrottle);
|
||||
control->Set("ShowTouchDpad", bShowTouchDpad);
|
||||
|
||||
// control->Set("KeyMapping",iMappingMap);
|
||||
#ifdef USING_GLES2
|
||||
control->Set("TiltBaseX", fTiltBaseX);
|
||||
control->Set("TiltBaseY", fTiltBaseY);
|
||||
|
@ -459,30 +533,46 @@ void Config::Save() {
|
|||
control->Set("DeadzoneRadius", fDeadzoneRadius);
|
||||
control->Set("TiltInputType", iTiltInputType);
|
||||
#endif
|
||||
control->Set("DisableDpadDiagonals", bDisableDpadDiagonals);
|
||||
control->Set("TouchButtonStyle", iTouchButtonStyle);
|
||||
control->Set("TouchButtonOpacity", iTouchButtonOpacity);
|
||||
control->Set("ButtonScale", fButtonScale);
|
||||
control->Set("ActionButtonSpacing", iActionButtonSpacing);
|
||||
control->Set("ActionButtonScale", fActionButtonScale);
|
||||
control->Set("ActionButtonSpacing2", fActionButtonSpacing);
|
||||
control->Set("ActionButtonCenterX", fActionButtonCenterX);
|
||||
control->Set("ActionButtonCenterY", fActionButtonCenterY);
|
||||
control->Set("DPadRadius", iDpadRadius);
|
||||
control->Set("DPadX", fDpadX);
|
||||
control->Set("DPadY", fDpadY);
|
||||
control->Set("DPadScale", fDpadScale);
|
||||
control->Set("DPadSpacing", fDpadSpacing);
|
||||
control->Set("StartKeyX", fStartKeyX);
|
||||
control->Set("StartKeyY", fStartKeyY);
|
||||
control->Set("StartKeyScale", fStartKeyScale);
|
||||
control->Set("SelectKeyX", fSelectKeyX);
|
||||
control->Set("SelectKeyY", fSelectKeyY);
|
||||
control->Set("SelectKeyScale", fSelectKeyScale);
|
||||
control->Set("UnthrottleKeyX", fUnthrottleKeyX);
|
||||
control->Set("UnthrottleKeyY", fUnthrottleKeyY);
|
||||
control->Set("UnthrottleKeyScale", fUnthrottleKeyScale);
|
||||
control->Set("LKeyX", fLKeyX);
|
||||
control->Set("LKeyY", fLKeyY);
|
||||
control->Set("LKeyScale", fLKeyScale);
|
||||
control->Set("RKeyX", fRKeyX);
|
||||
control->Set("RKeyY", fRKeyY);
|
||||
control->Set("RKeyScale", fRKeyScale);
|
||||
control->Set("AnalogStickX", fAnalogStickX);
|
||||
control->Set("AnalogStickY", fAnalogStickY);
|
||||
control->Set("AnalogStickScale", fAnalogStickScale);
|
||||
control->Delete("DPadRadius");
|
||||
|
||||
IniFile::Section *network = iniFile.GetOrCreateSection("Network");
|
||||
network->Set("EnableWlan", bEnableWlan);
|
||||
|
||||
IniFile::Section *pspConfig = iniFile.GetOrCreateSection("SystemParam");
|
||||
pspConfig->Set("PSPModel", iPSPModel);
|
||||
pspConfig->Set("PSPFirmwareVersion", iFirmwareVersion);
|
||||
pspConfig->Set("NickName", sNickName.c_str());
|
||||
pspConfig->Set("proAdhocServer", proAdhocServer.c_str());
|
||||
pspConfig->Set("MacAddress", localMacAddress.c_str());
|
||||
pspConfig->Set("Language", iLanguage);
|
||||
pspConfig->Set("TimeFormat", iTimeFormat);
|
||||
pspConfig->Set("DateFormat", iDateFormat);
|
||||
|
@ -493,7 +583,7 @@ void Config::Save() {
|
|||
pspConfig->Set("WlanAdhocChannel", iWlanAdhocChannel);
|
||||
pspConfig->Set("WlanPowerSave", bWlanPowerSave);
|
||||
pspConfig->Set("EncryptSave", bEncryptSave);
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
pspConfig->Set("BypassOSKWithKeyboard", bBypassOSKWithKeyboard);
|
||||
#endif
|
||||
|
||||
|
@ -514,11 +604,18 @@ void Config::Save() {
|
|||
debugConfig->Set("ShowBottomTabTitles",bShowBottomTabTitles);
|
||||
debugConfig->Set("ShowDeveloperMenu", bShowDeveloperMenu);
|
||||
debugConfig->Set("SkipDeadbeefFilling", bSkipDeadbeefFilling);
|
||||
debugConfig->Set("FuncHashMap", bFuncHashMap);
|
||||
|
||||
IniFile::Section *speedhacks = iniFile.GetOrCreateSection("SpeedHacks");
|
||||
speedhacks->Set("PrescaleUV", bPrescaleUV);
|
||||
speedhacks->Set("DisableAlphaTest", bDisableAlphaTest);
|
||||
|
||||
// Save upgrade check state
|
||||
IniFile::Section *upgrade = iniFile.GetOrCreateSection("Upgrade");
|
||||
upgrade->Set("UpgradeMessage", upgradeMessage);
|
||||
upgrade->Set("UpgradeVersion", upgradeVersion);
|
||||
upgrade->Set("DismissedVersion", dismissedVersion);
|
||||
|
||||
if (!iniFile.Save(iniFilename_.c_str())) {
|
||||
ERROR_LOG(LOADER, "Error saving config - can't write ini %s", iniFilename_.c_str());
|
||||
return;
|
||||
|
@ -542,9 +639,67 @@ void Config::Save() {
|
|||
}
|
||||
}
|
||||
|
||||
// Use for debugging the version check without messing with the server
|
||||
#if 0
|
||||
#define PPSSPP_GIT_VERSION "v0.0.1-gaaaaaaaaa"
|
||||
#endif
|
||||
|
||||
void Config::DownloadCompletedCallback(http::Download &download) {
|
||||
if (download.ResultCode() != 200) {
|
||||
ERROR_LOG(LOADER, "Failed to download version.json");
|
||||
return;
|
||||
}
|
||||
std::string data;
|
||||
download.buffer().TakeAll(&data);
|
||||
if (data.empty()) {
|
||||
ERROR_LOG(LOADER, "Version check: Empty data from server!");
|
||||
return;
|
||||
}
|
||||
|
||||
JsonReader reader(data.c_str(), data.size());
|
||||
const json_value *root = reader.root();
|
||||
std::string version = root->getString("version", "");
|
||||
|
||||
const char *gitVer = PPSSPP_GIT_VERSION;
|
||||
Version installed(gitVer);
|
||||
Version upgrade(version);
|
||||
Version dismissed(g_Config.dismissedVersion);
|
||||
|
||||
if (!installed.IsValid()) {
|
||||
ERROR_LOG(LOADER, "Version check: Local version string invalid. Build problems? %s", PPSSPP_GIT_VERSION);
|
||||
return;
|
||||
}
|
||||
if (!upgrade.IsValid()) {
|
||||
ERROR_LOG(LOADER, "Version check: Invalid server version: %s", version.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (installed >= upgrade) {
|
||||
INFO_LOG(LOADER, "Version check: Already up to date, erasing any upgrade message");
|
||||
g_Config.upgradeMessage = "";
|
||||
g_Config.upgradeVersion = upgrade.ToString();
|
||||
g_Config.dismissedVersion = "";
|
||||
return;
|
||||
}
|
||||
|
||||
if (installed < upgrade && dismissed != upgrade) {
|
||||
g_Config.upgradeMessage = "New version of PPSSPP available!";
|
||||
g_Config.upgradeVersion = upgrade.ToString();
|
||||
g_Config.dismissedVersion = "";
|
||||
}
|
||||
}
|
||||
|
||||
void Config::DismissUpgrade() {
|
||||
g_Config.dismissedVersion = g_Config.upgradeVersion;
|
||||
}
|
||||
|
||||
void Config::AddRecent(const std::string &file) {
|
||||
for (auto str = recentIsos.begin(); str != recentIsos.end(); str++) {
|
||||
if (*str == file) {
|
||||
for (auto str = recentIsos.begin(); str != recentIsos.end(); ++str) {
|
||||
#ifdef _WIN32
|
||||
if (!strcmpIgnore((*str).c_str(), file.c_str(), "\\", "/")) {
|
||||
#else
|
||||
if (!strcmp((*str).c_str(), file.c_str())) {
|
||||
#endif
|
||||
recentIsos.erase(str);
|
||||
recentIsos.insert(recentIsos.begin(), file);
|
||||
if ((int)recentIsos.size() > iMaxRecent)
|
||||
|
@ -560,15 +715,15 @@ void Config::AddRecent(const std::string &file) {
|
|||
void Config::CleanRecent() {
|
||||
std::vector<std::string> cleanedRecent;
|
||||
for (size_t i = 0; i < recentIsos.size(); i++) {
|
||||
if (File::Exists(recentIsos[i])){
|
||||
if (File::Exists(recentIsos[i])) {
|
||||
// clean the redundant recent games' list.
|
||||
if (cleanedRecent.size()==0){ // add first one
|
||||
cleanedRecent.push_back(recentIsos[i]);
|
||||
if (cleanedRecent.size()==0) { // add first one
|
||||
cleanedRecent.push_back(recentIsos[i]);
|
||||
}
|
||||
for (size_t j=0; j<cleanedRecent.size();j++){
|
||||
if (cleanedRecent[j]==recentIsos[i])
|
||||
for (size_t j = 0; j < cleanedRecent.size();j++) {
|
||||
if (cleanedRecent[j] == recentIsos[i])
|
||||
break; // skip if found redundant
|
||||
if (j==cleanedRecent.size()-1){ // add if no redundant found
|
||||
if (j == cleanedRecent.size() - 1){ // add if no redundant found
|
||||
cleanedRecent.push_back(recentIsos[i]);
|
||||
}
|
||||
}
|
||||
|
@ -619,3 +774,33 @@ void Config::RestoreDefaults() {
|
|||
currentDirectory = "";
|
||||
Load();
|
||||
}
|
||||
|
||||
void Config::ResetControlLayout() {
|
||||
float defaultScale = 1.15f;
|
||||
g_Config.fActionButtonScale = defaultScale;
|
||||
g_Config.fActionButtonSpacing = 1.0f;
|
||||
g_Config.fActionButtonCenterX = -1.0;
|
||||
g_Config.fActionButtonCenterY = -1.0;
|
||||
g_Config.fDpadScale = defaultScale;
|
||||
g_Config.fDpadSpacing = 1.0f;
|
||||
g_Config.fDpadX = -1.0;
|
||||
g_Config.fDpadY = -1.0;
|
||||
g_Config.fStartKeyX = -1.0;
|
||||
g_Config.fStartKeyY = -1.0;
|
||||
g_Config.fStartKeyScale = defaultScale;
|
||||
g_Config.fSelectKeyX = -1.0;
|
||||
g_Config.fSelectKeyY = -1.0;
|
||||
g_Config.fSelectKeyScale = defaultScale;
|
||||
g_Config.fUnthrottleKeyX = -1.0;
|
||||
g_Config.fUnthrottleKeyY = -1.0;
|
||||
g_Config.fUnthrottleKeyScale = defaultScale;
|
||||
g_Config.fLKeyX = -1.0;
|
||||
g_Config.fLKeyY = -1.0;
|
||||
g_Config.fLKeyScale = defaultScale;
|
||||
g_Config.fRKeyX = -1.0;
|
||||
g_Config.fRKeyY = -1.0;
|
||||
g_Config.fRKeyScale = defaultScale;
|
||||
g_Config.fAnalogStickX = -1.0;
|
||||
g_Config.fAnalogStickY = -1.0;
|
||||
g_Config.fAnalogStickScale = defaultScale;
|
||||
}
|
||||
|
|
|
@ -22,9 +22,19 @@
|
|||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
#if !defined(USING_QT_UI)
|
||||
extern const char *PPSSPP_GIT_VERSION;
|
||||
#endif
|
||||
|
||||
const int MAX_CONFIG_VOLUME = 8;
|
||||
const int PSP_MODEL_FAT = 0;
|
||||
const int PSP_MODEL_SLIM = 1;
|
||||
const int PSP_DEFAULT_FIRMWARE = 150;
|
||||
|
||||
namespace http {
|
||||
class Download;
|
||||
class Downloader;
|
||||
}
|
||||
|
||||
struct Config {
|
||||
public:
|
||||
|
@ -35,14 +45,17 @@ public:
|
|||
bool bSaveSettings;
|
||||
bool bFirstRun;
|
||||
|
||||
int iRunCount; // To be used to for example check for updates every 10 runs and things like that.
|
||||
|
||||
bool bAutoRun; // start immediately
|
||||
bool bBrowse; // when opening the emulator, immediately show a file browser
|
||||
bool bHomebrewStore;
|
||||
|
||||
// General
|
||||
int iNumWorkerThreads;
|
||||
bool bScreenshotsAsPNG;
|
||||
bool bEnableLogging;
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
bool bPauseOnLostFocus;
|
||||
bool bTopMost;
|
||||
std::string sFont;
|
||||
|
@ -51,6 +64,8 @@ public:
|
|||
bool bIgnoreBadMemAccess;
|
||||
bool bFastMemory;
|
||||
bool bJit;
|
||||
bool bCheckForNewVersion;
|
||||
|
||||
// Definitely cannot be changed while game is running.
|
||||
bool bSeparateCPUThread;
|
||||
bool bSeparateIOThread;
|
||||
|
@ -61,14 +76,15 @@ public:
|
|||
std::vector<std::string> recentIsos;
|
||||
std::string sLanguageIni;
|
||||
|
||||
|
||||
// GFX
|
||||
bool bSoftwareRendering;
|
||||
bool bHardwareTransform; // only used in the GLES backend
|
||||
bool bSoftwareSkinning; // may speed up some games
|
||||
|
||||
int iRenderingMode; // 0 = non-buffered rendering 1 = buffered rendering 2 = Read Framebuffer to memory (CPU) 3 = Read Framebuffer to memory (GPU)
|
||||
int iTexFiltering; // 1 = off , 2 = nearest , 3 = linear , 4 = linear(CG)
|
||||
#ifdef BLACKBERRY
|
||||
bool bPartialStretch;
|
||||
#endif
|
||||
bool bStretchToDisplay;
|
||||
bool bVSync;
|
||||
int iFrameSkip;
|
||||
|
@ -99,8 +115,8 @@ public:
|
|||
bool bReloadCheats;
|
||||
bool bDisableStencilTest;
|
||||
bool bAlwaysDepthWrite;
|
||||
bool bTimerHack;
|
||||
bool bLowQualitySplineBezier;
|
||||
bool bWipeFramebufferAlpha; // this was meant to be CopyStencilToAlpha but not done yet.
|
||||
std::string sPostShaderName; // Off for off.
|
||||
|
||||
// Sound
|
||||
|
@ -135,26 +151,42 @@ public:
|
|||
bool bGridView2;
|
||||
bool bGridView3;
|
||||
|
||||
// Disable diagonals
|
||||
bool bDisableDpadDiagonals;
|
||||
// Control Style
|
||||
int iTouchButtonStyle;
|
||||
// Control Positions
|
||||
int iTouchButtonOpacity;
|
||||
float fButtonScale;
|
||||
//space between PSP buttons
|
||||
int iActionButtonSpacing;
|
||||
//the PSP button's center (triangle, circle, square, cross)
|
||||
float fActionButtonCenterX, fActionButtonCenterY;
|
||||
float fActionButtonScale;
|
||||
float fActionButtonSpacing;
|
||||
//radius of the D-pad (PSP cross)
|
||||
int iDpadRadius;
|
||||
// int iDpadRadius;
|
||||
//the D-pad (PSP cross) position
|
||||
float fDpadX, fDpadY;
|
||||
float fDpadScale;
|
||||
float fDpadSpacing;
|
||||
//the start key position
|
||||
float fStartKeyX, fStartKeyY;
|
||||
//the select key position;
|
||||
float fStartKeyScale;
|
||||
//the select key position;
|
||||
float fSelectKeyX, fSelectKeyY;
|
||||
float fSelectKeyScale;
|
||||
|
||||
float fUnthrottleKeyX, fUnthrottleKeyY;
|
||||
float fUnthrottleKeyScale;
|
||||
|
||||
float fLKeyX, fLKeyY;
|
||||
float fLKeyScale;
|
||||
|
||||
float fRKeyX, fRKeyY;
|
||||
float fRKeyScale;
|
||||
|
||||
//position of the analog stick
|
||||
float fAnalogStickX, fAnalogStickY;
|
||||
float fAnalogStickScale;
|
||||
|
||||
// Controls Visibility
|
||||
bool bShowTouchControls;
|
||||
|
@ -170,10 +202,10 @@ public:
|
|||
|
||||
bool bShowTouchLTrigger;
|
||||
bool bShowTouchRTrigger;
|
||||
|
||||
|
||||
bool bShowTouchAnalogStick;
|
||||
bool bShowTouchDpad;
|
||||
|
||||
|
||||
bool bHapticFeedback;
|
||||
|
||||
// GLES backend-specific hacks. Not saved to the ini file, do not add checkboxes. Will be made into
|
||||
|
@ -193,6 +225,8 @@ public:
|
|||
|
||||
// SystemParam
|
||||
std::string sNickName;
|
||||
std::string proAdhocServer;
|
||||
std::string localMacAddress;
|
||||
int iLanguage;
|
||||
int iTimeFormat;
|
||||
int iDateFormat;
|
||||
|
@ -201,10 +235,16 @@ public:
|
|||
int iButtonPreference;
|
||||
int iLockParentalLevel;
|
||||
bool bEncryptSave;
|
||||
|
||||
// Networking
|
||||
bool bEnableWlan;
|
||||
int iWlanAdhocChannel;
|
||||
bool bWlanPowerSave;
|
||||
|
||||
int iPSPModel;
|
||||
int iFirmwareVersion;
|
||||
// TODO: Make this work with your platform, too!
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
bool bBypassOSKWithKeyboard;
|
||||
#endif
|
||||
|
||||
|
@ -226,6 +266,7 @@ public:
|
|||
bool bShowDeveloperMenu;
|
||||
// Double edged sword: much easier debugging, but not accurate.
|
||||
bool bSkipDeadbeefFilling;
|
||||
bool bFuncHashMap;
|
||||
|
||||
std::string currentDirectory;
|
||||
std::string externalDirectory;
|
||||
|
@ -233,6 +274,11 @@ public:
|
|||
std::string flash0Directory;
|
||||
std::string internalDataDirectory;
|
||||
|
||||
// Data for upgrade prompt
|
||||
std::string upgradeMessage; // The actual message from the server is currently not used, need a translation mechanism. So this just acts as a flag.
|
||||
std::string upgradeVersion;
|
||||
std::string dismissedVersion;
|
||||
|
||||
void Load(const char *iniFileName = "ppsspp.ini", const char *controllerIniFilename = "controls.ini");
|
||||
void Save();
|
||||
void RestoreDefaults();
|
||||
|
@ -247,6 +293,11 @@ public:
|
|||
void AddRecent(const std::string &file);
|
||||
void CleanRecent();
|
||||
|
||||
static void DownloadCompletedCallback(http::Download &download);
|
||||
void DismissUpgrade();
|
||||
|
||||
void ResetControlLayout();
|
||||
|
||||
private:
|
||||
std::string iniFilename_;
|
||||
std::string controllerIniFilename_;
|
||||
|
@ -254,4 +305,7 @@ private:
|
|||
std::string defaultPath_;
|
||||
};
|
||||
|
||||
// TODO: Find a better place for this.
|
||||
extern http::Downloader g_DownloadManager;
|
||||
extern Config g_Config;
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ void Core_RunLoop() {
|
|||
while (globalUIState != UISTATE_INGAME && globalUIState != UISTATE_EXIT) {
|
||||
time_update();
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
double startTime = time_now_d();
|
||||
UpdateRunLoop();
|
||||
|
||||
|
@ -164,7 +164,7 @@ void Core_RunLoop() {
|
|||
while (!coreState && globalUIState == UISTATE_INGAME) {
|
||||
time_update();
|
||||
UpdateRunLoop();
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
if (!Core_IsStepping()) {
|
||||
GL_SwapBuffers();
|
||||
}
|
||||
|
|
|
@ -171,6 +171,7 @@
|
|||
<ClCompile Include="CPU.cpp" />
|
||||
<ClCompile Include="Cwcheat.cpp" />
|
||||
<ClCompile Include="Debugger\Breakpoints.cpp" />
|
||||
<ClCompile Include="Debugger\DisassemblyManager.cpp" />
|
||||
<ClCompile Include="Debugger\SymbolMap.cpp" />
|
||||
<ClCompile Include="Dialog\PSPGamedataInstallDialog.cpp" />
|
||||
<ClCompile Include="Dialog\PSPDialog.cpp" />
|
||||
|
@ -194,6 +195,7 @@
|
|||
<ClCompile Include="HDRemaster.cpp" />
|
||||
<ClCompile Include="HLE\HLE.cpp" />
|
||||
<ClCompile Include="HLE\HLETables.cpp" />
|
||||
<ClCompile Include="HLE\proAdhoc.cpp" />
|
||||
<ClCompile Include="HLE\sceAtrac.cpp" />
|
||||
<ClCompile Include="HLE\sceAudio.cpp" />
|
||||
<ClCompile Include="HLE\sceAudiocodec.cpp" />
|
||||
|
@ -390,6 +392,7 @@
|
|||
<ClCompile Include="MIPS\MIPSStackWalk.cpp" />
|
||||
<ClCompile Include="System.cpp" />
|
||||
<ClCompile Include="Util\BlockAllocator.cpp" />
|
||||
<ClCompile Include="Util\GameManager.cpp" />
|
||||
<ClCompile Include="Util\PPGeDraw.cpp" />
|
||||
<ClCompile Include="Util\ppge_atlas.cpp" />
|
||||
<ClCompile Include="..\ext\xxhash.c">
|
||||
|
@ -423,6 +426,7 @@
|
|||
<ClInclude Include="Cwcheat.h" />
|
||||
<ClInclude Include="Debugger\Breakpoints.h" />
|
||||
<ClInclude Include="Debugger\DebugInterface.h" />
|
||||
<ClInclude Include="Debugger\DisassemblyManager.h" />
|
||||
<ClInclude Include="Debugger\SymbolMap.h" />
|
||||
<ClInclude Include="Dialog\PSPGamedataInstallDialog.h" />
|
||||
<ClInclude Include="Dialog\PSPDialog.h" />
|
||||
|
@ -449,6 +453,7 @@
|
|||
<ClInclude Include="HLE\HLE.h" />
|
||||
<ClInclude Include="HLE\HLETables.h" />
|
||||
<ClInclude Include="HLE\KernelWaitHelpers.h" />
|
||||
<ClInclude Include="HLE\proAdhoc.h" />
|
||||
<ClInclude Include="HLE\sceAtrac.h" />
|
||||
<ClInclude Include="HLE\sceAudio.h" />
|
||||
<ClInclude Include="HLE\sceAudiocodec.h" />
|
||||
|
@ -518,6 +523,12 @@
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmCompVFPUNEON.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmJit.h">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||
|
@ -575,6 +586,7 @@
|
|||
<ClInclude Include="System.h" />
|
||||
<ClInclude Include="ThreadEventQueue.h" />
|
||||
<ClInclude Include="Util\BlockAllocator.h" />
|
||||
<ClInclude Include="Util\GameManager.h" />
|
||||
<ClInclude Include="Util\PPGeDraw.h" />
|
||||
<ClInclude Include="Util\ppge_atlas.h" />
|
||||
<ClInclude Include="..\ext\xxhash.h" />
|
||||
|
|
|
@ -496,6 +496,15 @@
|
|||
<ClCompile Include="Dialog\PSPNetconfDialog.cpp">
|
||||
<Filter>Dialog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\DisassemblyManager.cpp">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HLE\proAdhoc.cpp">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Util\GameManager.cpp">
|
||||
<Filter>Util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
|
@ -915,6 +924,18 @@
|
|||
<ClInclude Include="MIPS\JitCommon\JitState.h">
|
||||
<Filter>MIPS\JitCommon</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MIPS\ARM\ArmCompVFPUNEON.cpp">
|
||||
<Filter>MIPS\ARM</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\DisassemblyManager.h">
|
||||
<Filter>Debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HLE\proAdhoc.h">
|
||||
<Filter>HLE\Libraries</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Util\GameManager.h">
|
||||
<Filter>Util</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -922,4 +943,4 @@
|
|||
<None Include="..\android\jni\Android.mk" />
|
||||
<None Include="GameLogNotes.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -33,7 +33,7 @@ enum GPUCore {
|
|||
|
||||
// PSP_CoreParameter()
|
||||
struct CoreParameter {
|
||||
CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true) {}
|
||||
CoreParameter() : collectEmuLog(0), unthrottle(false), fpsLimit(0), updateRecent(true), freezeNext(false), frozen(false) {}
|
||||
CPUCore cpuCore;
|
||||
GPUCore gpuCore;
|
||||
bool enableSound; // there aren't multiple sound cores.
|
||||
|
@ -64,4 +64,8 @@ struct CoreParameter {
|
|||
int fpsLimit;
|
||||
|
||||
bool updateRecent;
|
||||
|
||||
// Freeze-frame. For nvidia perfhud profiling. Developers only.
|
||||
bool freezeNext;
|
||||
bool frozen;
|
||||
};
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
#include "Atomics.h"
|
||||
#include "CoreTiming.h"
|
||||
#include "Core.h"
|
||||
#include "Config.h"
|
||||
#include "HLE/sceKernelThread.h"
|
||||
#include "../Common/ChunkFile.h"
|
||||
#include "HLE/sceDisplay.h"
|
||||
|
||||
int CPU_HZ = 222000000;
|
||||
|
||||
|
@ -100,14 +102,29 @@ int GetClockFrequencyMHz()
|
|||
return CPU_HZ / 1000000;
|
||||
}
|
||||
|
||||
u64 GetGlobalTimeUsScaled()
|
||||
{
|
||||
s64 ticksSinceLast = GetTicks() - lastGlobalTimeTicks;
|
||||
int freq = GetClockFrequencyMHz();
|
||||
if (g_Config.bTimerHack) {
|
||||
float vps;
|
||||
__DisplayGetVPS(&vps);
|
||||
if (vps > 4.0f)
|
||||
freq *= (vps / 60.0f);
|
||||
}
|
||||
s64 usSinceLast = ticksSinceLast / freq;
|
||||
return lastGlobalTimeUs + usSinceLast;
|
||||
|
||||
}
|
||||
|
||||
u64 GetGlobalTimeUs()
|
||||
{
|
||||
s64 ticksSinceLast = GetTicks() - lastGlobalTimeTicks;
|
||||
s64 usSinceLast = ticksSinceLast / GetClockFrequencyMHz();
|
||||
int freq = GetClockFrequencyMHz();
|
||||
s64 usSinceLast = ticksSinceLast / freq;
|
||||
return lastGlobalTimeUs + usSinceLast;
|
||||
}
|
||||
|
||||
|
||||
Event* GetNewEvent()
|
||||
{
|
||||
if(!eventPool)
|
||||
|
|
|
@ -80,6 +80,7 @@ namespace CoreTiming
|
|||
u64 GetTicks();
|
||||
u64 GetIdleTicks();
|
||||
u64 GetGlobalTimeUs();
|
||||
u64 GetGlobalTimeUsScaled();
|
||||
|
||||
// Returns the event_type identifier.
|
||||
int RegisterEvent(const char *name, TimedCallback callback);
|
||||
|
|
|
@ -114,7 +114,10 @@ void CWCheatEngine::CreateCodeList() { //Creates code list to be used in functio
|
|||
continue; //Line indicates Disc ID, not needed for cheats
|
||||
}
|
||||
if (initialCodesList[i].substr(0,2) == "_G") {
|
||||
continue; //Line indicates game Title, also not needed for cheats.
|
||||
continue; //Line indicates game Title, also not needed for cheats
|
||||
}
|
||||
if (initialCodesList[i].substr(0,2) == "//") {
|
||||
continue; //Line indicates comment, also not needed for cheats.
|
||||
}
|
||||
if (initialCodesList[i].substr(0,3) == "_C1") {
|
||||
cheatEnabled = true;
|
||||
|
@ -231,7 +234,7 @@ std::vector<std::string> CWCheatEngine::GetCodesList() { //Reads the entire chea
|
|||
}
|
||||
for (int i = 0; !list.eof(); i ++) {
|
||||
getline(list, line, '\n');
|
||||
if (line.length() > 3 && line.substr(0,1) == "_"){
|
||||
if (line.length() > 3 && (line.substr(0,1) == "_"||line.substr(0,2) == "//")){
|
||||
codesList.push_back(line);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,13 +324,24 @@ const std::vector<BreakPoint> CBreakPoints::GetBreakpoints()
|
|||
|
||||
void CBreakPoints::Update(u32 addr)
|
||||
{
|
||||
if (MIPSComp::jit && Core_IsInactive())
|
||||
if (MIPSComp::jit)
|
||||
{
|
||||
bool resume = false;
|
||||
if (Core_IsStepping() == false)
|
||||
{
|
||||
Core_EnableStepping(true);
|
||||
Core_WaitInactive();
|
||||
resume = true;
|
||||
}
|
||||
|
||||
// In case this is a delay slot, clear the previous instruction too.
|
||||
if (addr != 0)
|
||||
MIPSComp::jit->ClearCacheAt(addr - 4, 8);
|
||||
else
|
||||
MIPSComp::jit->ClearCache();
|
||||
|
||||
if (resume)
|
||||
Core_EnableStepping(false);
|
||||
}
|
||||
|
||||
// Redraw in order to show the breakpoint.
|
||||
|
|
|
@ -41,8 +41,6 @@ public:
|
|||
virtual void runToBreakpoint() {}
|
||||
virtual int getColor(unsigned int address){return 0xFFFFFFFF;}
|
||||
virtual const char *getDescription(unsigned int address) {return "";}
|
||||
virtual const char *findSymbolForAddress(unsigned int address) { return NULL; };
|
||||
virtual bool getSymbolValue(char* symbol, u32& dest) { return false; };
|
||||
virtual bool initExpression(const char* exp, PostfixExpression& dest) { return false; };
|
||||
virtual bool parseExpression(PostfixExpression& exp, u32& dest) { return false; };
|
||||
|
||||
|
|
1004
Core/Debugger/DisassemblyManager.cpp
Normal file
1004
Core/Debugger/DisassemblyManager.cpp
Normal file
File diff suppressed because it is too large
Load diff
207
Core/Debugger/DisassemblyManager.h
Normal file
207
Core/Debugger/DisassemblyManager.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
// Copyright (c) 2012- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
#include "Globals.h"
|
||||
#include "Core/MIPS/MIPSAnalyst.h"
|
||||
|
||||
enum DisassemblyLineType { DISTYPE_OPCODE, DISTYPE_MACRO, DISTYPE_DATA, DISTYPE_OTHER };
|
||||
|
||||
struct DisassemblyLineInfo
|
||||
{
|
||||
DisassemblyLineType type;
|
||||
MIPSAnalyst::MipsOpcodeInfo info;
|
||||
std::string name;
|
||||
std::string params;
|
||||
u32 totalSize;
|
||||
};
|
||||
|
||||
enum LineType { LINE_UP, LINE_DOWN, LINE_RIGHT };
|
||||
|
||||
struct BranchLine
|
||||
{
|
||||
u32 first;
|
||||
u32 second;
|
||||
LineType type;
|
||||
int laneIndex;
|
||||
|
||||
bool operator<(const BranchLine& other) const
|
||||
{
|
||||
return first < other.first;
|
||||
}
|
||||
};
|
||||
|
||||
class DisassemblyEntry
|
||||
{
|
||||
public:
|
||||
virtual ~DisassemblyEntry() { };
|
||||
virtual void recheck() = 0;
|
||||
virtual int getNumLines() = 0;
|
||||
virtual int getLineNum(u32 address, bool findStart) = 0;
|
||||
virtual u32 getLineAddress(int line) = 0;
|
||||
virtual u32 getTotalSize() = 0;
|
||||
virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) = 0;
|
||||
virtual void getBranchLines(u32 start, u32 size, std::vector<BranchLine>& dest) { };
|
||||
};
|
||||
|
||||
class DisassemblyFunction: public DisassemblyEntry
|
||||
{
|
||||
public:
|
||||
DisassemblyFunction(u32 _address, u32 _size);
|
||||
virtual void recheck();
|
||||
virtual int getNumLines();
|
||||
virtual int getLineNum(u32 address, bool findStart);
|
||||
virtual u32 getLineAddress(int line);
|
||||
virtual u32 getTotalSize() { return size; };
|
||||
virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols);
|
||||
virtual void getBranchLines(u32 start, u32 size, std::vector<BranchLine>& dest);
|
||||
private:
|
||||
void generateBranchLines();
|
||||
void load();
|
||||
void clear();
|
||||
void addOpcodeSequence(u32 start, u32 end);
|
||||
|
||||
u32 address;
|
||||
u32 size;
|
||||
u32 hash;
|
||||
std::vector<BranchLine> lines;
|
||||
std::map<u32,DisassemblyEntry*> entries;
|
||||
std::vector<u32> lineAddresses;
|
||||
};
|
||||
|
||||
class DisassemblyOpcode: public DisassemblyEntry
|
||||
{
|
||||
public:
|
||||
DisassemblyOpcode(u32 _address, int _num): address(_address), num(_num) { };
|
||||
virtual ~DisassemblyOpcode() { };
|
||||
virtual void recheck() { };
|
||||
virtual int getNumLines() { return num; };
|
||||
virtual int getLineNum(u32 address, bool findStart) { return (address-this->address)/4; };
|
||||
virtual u32 getLineAddress(int line) { return address+line*4; };
|
||||
virtual u32 getTotalSize() { return num*4; };
|
||||
virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols);
|
||||
virtual void getBranchLines(u32 start, u32 size, std::vector<BranchLine>& dest);
|
||||
private:
|
||||
u32 address;
|
||||
int num;
|
||||
};
|
||||
|
||||
|
||||
class DisassemblyMacro: public DisassemblyEntry
|
||||
{
|
||||
public:
|
||||
DisassemblyMacro(u32 _address): address(_address) { };
|
||||
virtual ~DisassemblyMacro() { };
|
||||
|
||||
void setMacroLi(u32 _immediate, u8 _rt);
|
||||
void setMacroMemory(std::string _name, u32 _immediate, u8 _rt, int _dataSize);
|
||||
|
||||
virtual void recheck() { };
|
||||
virtual int getNumLines() { return 1; };
|
||||
virtual int getLineNum(u32 address, bool findStart) { return 0; };
|
||||
virtual u32 getLineAddress(int line) { return address; };
|
||||
virtual u32 getTotalSize() { return numOpcodes*4; };
|
||||
virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols) ;
|
||||
private:
|
||||
enum MacroType { MACRO_LI, MACRO_MEMORYIMM };
|
||||
|
||||
MacroType type;
|
||||
std::string name;
|
||||
u32 immediate;
|
||||
u32 address;
|
||||
u32 numOpcodes;
|
||||
u8 rt;
|
||||
int dataSize;
|
||||
};
|
||||
|
||||
|
||||
class DisassemblyData: public DisassemblyEntry
|
||||
{
|
||||
public:
|
||||
DisassemblyData(u32 _address, u32 _size, DataType _type);
|
||||
virtual ~DisassemblyData() { };
|
||||
|
||||
virtual void recheck();
|
||||
virtual int getNumLines() { return (int)lines.size(); };
|
||||
virtual int getLineNum(u32 address, bool findStart);
|
||||
virtual u32 getLineAddress(int line) { return lineAddresses[line]; };
|
||||
virtual u32 getTotalSize() { return size; };
|
||||
virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols);
|
||||
private:
|
||||
void createLines();
|
||||
|
||||
struct DataEntry
|
||||
{
|
||||
std::string text;
|
||||
u32 size;
|
||||
int lineNum;
|
||||
};
|
||||
|
||||
u32 address;
|
||||
u32 size;
|
||||
u32 hash;
|
||||
DataType type;
|
||||
std::map<u32,DataEntry> lines;
|
||||
std::vector<u32> lineAddresses;
|
||||
};
|
||||
|
||||
class DisassemblyComment: public DisassemblyEntry
|
||||
{
|
||||
public:
|
||||
DisassemblyComment(u32 _address, u32 _size, std::string name, std::string param);
|
||||
virtual ~DisassemblyComment() { };
|
||||
|
||||
virtual void recheck() { };
|
||||
virtual int getNumLines() { return 1; };
|
||||
virtual int getLineNum(u32 address, bool findStart) { return 0; };
|
||||
virtual u32 getLineAddress(int line) { return address; };
|
||||
virtual u32 getTotalSize() { return size; };
|
||||
virtual bool disassemble(u32 address, DisassemblyLineInfo& dest, bool insertSymbols);
|
||||
private:
|
||||
u32 address;
|
||||
u32 size;
|
||||
std::string name;
|
||||
std::string param;
|
||||
};
|
||||
|
||||
class DebugInterface;
|
||||
|
||||
class DisassemblyManager
|
||||
{
|
||||
public:
|
||||
void clear();
|
||||
|
||||
void setCpu(DebugInterface* _cpu) { cpu = _cpu; };
|
||||
void setMaxParamChars(int num) { maxParamChars = num; clear(); };
|
||||
void getLine(u32 address, bool insertSymbols, DisassemblyLineInfo& dest);
|
||||
void analyze(u32 address, u32 size);
|
||||
std::vector<BranchLine> getBranchLines(u32 start, u32 size);
|
||||
|
||||
u32 getStartAddress(u32 address);
|
||||
u32 getNthPreviousAddress(u32 address, int n = 1);
|
||||
u32 getNthNextAddress(u32 address, int n = 1);
|
||||
|
||||
static DebugInterface* getCpu() { return cpu; };
|
||||
static int getMaxParamChars() { return maxParamChars; };
|
||||
private:
|
||||
DisassemblyEntry* getEntry(u32 address);
|
||||
static std::map<u32,DisassemblyEntry*> entries;
|
||||
static DebugInterface* cpu;
|
||||
static int maxParamChars;
|
||||
};
|
||||
|
||||
bool isInInterval(u32 start, u32 size, u32 value);
|
File diff suppressed because it is too large
Load diff
|
@ -24,15 +24,28 @@
|
|||
#include <map>
|
||||
|
||||
enum SymbolType {
|
||||
ST_FUNCTION=1,
|
||||
ST_DATA=2
|
||||
ST_NONE = 0,
|
||||
ST_FUNCTION = 1,
|
||||
ST_DATA = 2,
|
||||
ST_ALL = 3,
|
||||
};
|
||||
|
||||
struct SymbolInfo {
|
||||
SymbolType type;
|
||||
u32 address;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct SymbolEntry {
|
||||
std::string name;
|
||||
u32 address;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
enum DataType {
|
||||
DATATYPE_NONE, DATATYPE_BYTE, DATATYPE_HALFWORD, DATATYPE_WORD, DATATYPE_ASCII
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
struct HWND__;
|
||||
typedef struct HWND__ *HWND;
|
||||
|
@ -41,68 +54,64 @@ typedef struct HWND__ *HWND;
|
|||
class SymbolMap {
|
||||
public:
|
||||
SymbolMap() {}
|
||||
void Clear();
|
||||
void SortSymbols();
|
||||
|
||||
bool LoadSymbolMap(const char *filename);
|
||||
void SaveSymbolMap(const char *filename) const;
|
||||
bool LoadNocashSym(const char *ilename);
|
||||
void AddSymbol(const char *symbolname, unsigned int vaddress, size_t size, SymbolType symbol);
|
||||
void RemoveSymbolNum(int symbolnum);
|
||||
void Clear();
|
||||
void AnalyzeBackwards();
|
||||
int GetSymbolNum(unsigned int address, SymbolType symmask=ST_FUNCTION) const;
|
||||
|
||||
SymbolType GetSymbolType(u32 address) const;
|
||||
bool GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask = ST_FUNCTION) const;
|
||||
u32 GetNextSymbolAddress(u32 address, SymbolType symmask);
|
||||
const char *GetDescription(unsigned int address) const;
|
||||
std::vector<SymbolEntry> GetAllSymbols(SymbolType symmask);
|
||||
|
||||
#ifdef _WIN32
|
||||
void FillSymbolListBox(HWND listbox, SymbolType symmask=ST_FUNCTION) const;
|
||||
void FillSymbolComboBox(HWND listbox,SymbolType symmask=ST_FUNCTION) const;
|
||||
void FillListBoxBLinks(HWND listbox, int num) const;
|
||||
void FillSymbolListBox(HWND listbox, SymbolType symType) const;
|
||||
#endif
|
||||
int GetNumSymbols() const;
|
||||
const char *GetSymbolName(int i) const;
|
||||
void SetSymbolName(int i, const char *newname);
|
||||
void SetSymbolSize(int i, int newSize);
|
||||
u32 GetSymbolSize(int i) const;
|
||||
u32 GetSymbolAddr(int i) const;
|
||||
SymbolType GetSymbolType(int i) const;
|
||||
int FindSymbol(const char *name) const;
|
||||
u32 GetAddress(int num) const;
|
||||
void IncreaseRunCount(int num);
|
||||
unsigned int GetRunCount(int num) const;
|
||||
void SortSymbols();
|
||||
const char* getDirectSymbol(u32 address);
|
||||
bool getSymbolValue(char* symbol, u32& dest);
|
||||
|
||||
void UseFuncSignaturesFile(const char *filename, u32 maxAddress);
|
||||
void CompileFuncSignaturesFile(const char *filename) const;
|
||||
void AddFunction(const char* name, u32 address, u32 size);
|
||||
u32 GetFunctionStart(u32 address) const;
|
||||
int GetFunctionNum(u32 address) const;
|
||||
u32 GetFunctionSize(u32 startAddress) const;
|
||||
bool SetFunctionSize(u32 startAddress, u32 newSize);
|
||||
bool RemoveFunction(u32 startAddress, bool removeName);
|
||||
|
||||
void AddLabel(const char* name, u32 address);
|
||||
void SetLabelName(const char* name, u32 address);
|
||||
const char* GetLabelName(u32 address) const;
|
||||
bool GetLabelValue(const char* name, u32& dest);
|
||||
|
||||
void AddData(u32 address, u32 size, DataType type);
|
||||
u32 GetDataStart(u32 address) const;
|
||||
u32 GetDataSize(u32 startAddress) const;
|
||||
DataType GetDataType(u32 startAddress) const;
|
||||
|
||||
static const u32 INVALID_ADDRESS = (u32)-1;
|
||||
private:
|
||||
struct MapEntryUniqueInfo {
|
||||
u32 address;
|
||||
u32 vaddress;
|
||||
void AssignFunctionIndices();
|
||||
|
||||
struct FunctionEntry {
|
||||
u32 size;
|
||||
SymbolType type;
|
||||
|
||||
bool operator < (const MapEntryUniqueInfo &other) const {
|
||||
return vaddress < other.vaddress;
|
||||
}
|
||||
int index;
|
||||
};
|
||||
|
||||
struct MapEntry : public MapEntryUniqueInfo {
|
||||
struct LabelEntry {
|
||||
char name[128];
|
||||
u32 unknown;
|
||||
u32 runCount;
|
||||
|
||||
#ifdef BWLINKS
|
||||
std::vector <u32> backwardLinks;
|
||||
#endif
|
||||
void UndecorateName() {
|
||||
// TODO
|
||||
}
|
||||
};
|
||||
|
||||
std::set<MapEntryUniqueInfo> uniqueEntries;
|
||||
std::vector<MapEntry> entries;
|
||||
std::map<u32, u32> entryRanges;
|
||||
struct DataEntry {
|
||||
DataType type;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
std::map<u32, FunctionEntry> functions;
|
||||
std::map<u32, LabelEntry> labels;
|
||||
std::map<u32, DataEntry> data;
|
||||
|
||||
mutable recursive_mutex lock_;
|
||||
};
|
||||
|
||||
extern SymbolMap symbolMap;
|
||||
|
||||
|
|
|
@ -128,6 +128,25 @@ bool PSPDialog::IsButtonPressed(int checkButton)
|
|||
return !isFading && !(lastButtons & checkButton) && (buttons & checkButton);
|
||||
}
|
||||
|
||||
bool PSPDialog::IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold, int framesHeldRepeatRate)
|
||||
{
|
||||
bool btnWasHeldLastFrame = (lastButtons & checkButton) && (buttons & checkButton);
|
||||
if (!isFading && btnWasHeldLastFrame) {
|
||||
framesHeld++;
|
||||
}
|
||||
else {
|
||||
framesHeld = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's considered held for dialog purposes after 30 frames (~0.5 seconds),
|
||||
// and set to repeat every 10 frames, by default.
|
||||
if (framesHeld >= framesHeldThreshold && ((framesHeld % framesHeldRepeatRate) == 0))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void PSPDialog::DisplayButtons(int flags)
|
||||
{
|
||||
I18NCategory *d = GetI18NCategory("Dialog");
|
||||
|
|
|
@ -79,6 +79,7 @@ public:
|
|||
void EndDraw();
|
||||
protected:
|
||||
bool IsButtonPressed(int checkButton);
|
||||
bool IsButtonHeld(int checkButton, int &framesHeld, int framesHeldThreshold = 30, int framesHeldRepeatRate = 10);
|
||||
void DisplayButtons(int flags);
|
||||
|
||||
void StartFade(bool fadeIn_);
|
||||
|
|
|
@ -147,7 +147,10 @@ void PSPGamedataInstallDialog::updateProgress() {
|
|||
// Update progress bar(if there is).
|
||||
// progress value is progress[3] << 24 | progress[2] << 16 | progress[1] << 8 | progress[0].
|
||||
// We only should update progress[0] here as the max progress value is 100.
|
||||
progressValue = (int)(allReadSize / allFilesSize) * 100;
|
||||
if (allFilesSize != 0)
|
||||
progressValue = (int)(allReadSize / allFilesSize) * 100;
|
||||
else
|
||||
progressValue = 100;
|
||||
request.progress[0] = progressValue;
|
||||
Memory::WriteStruct(paramAddr,&request);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
#include "PSPNetconfDialog.h"
|
||||
#include "ChunkFile.h"
|
||||
#include "../Core/MemMap.h"
|
||||
#include "../Core/HLE/sceNetAdhoc.h"
|
||||
|
||||
#define NETCONF_CONNECT_ADHOC 2
|
||||
#define NETCONF_CREATE_ADHOC 4
|
||||
#define NETCONF_JOIN_ADHOC 5
|
||||
|
||||
PSPNetconfDialog::PSPNetconfDialog() {
|
||||
}
|
||||
|
@ -40,6 +45,19 @@ int PSPNetconfDialog::Init(u32 paramAddr) {
|
|||
}
|
||||
|
||||
int PSPNetconfDialog::Update(int animSpeed) {
|
||||
if(request.netAction == NETCONF_CONNECT_ADHOC ||
|
||||
request.netAction == NETCONF_CREATE_ADHOC ||
|
||||
request.netAction == NETCONF_JOIN_ADHOC){
|
||||
if(request.NetconfData != NULL){
|
||||
Shutdown(true);
|
||||
if(sceNetAdhocctlCreate(request.NetconfData->groupName) == 0)
|
||||
{
|
||||
status = SCE_UTILITY_STATUS_FINISHED;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -58,4 +76,4 @@ void PSPNetconfDialog::DoState(PointerWrap &p) {
|
|||
return;
|
||||
|
||||
p.Do(request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,4 +46,4 @@ public:
|
|||
|
||||
private:
|
||||
SceUtilityNetconfParam request;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#include "i18n/i18n.h"
|
||||
#include "math/math_util.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "Core/Dialog/PSPOskDialog.h"
|
||||
#include "Core/Util/PPGeDraw.h"
|
||||
|
@ -27,8 +28,8 @@
|
|||
#include "Common/ChunkFile.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "Core/Host.h"
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
#include "base/NativeApp.h"
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
|
@ -705,12 +706,14 @@ void PSPOskDialog::RenderKeyboard()
|
|||
|
||||
std::string buffer;
|
||||
|
||||
u32 FIELDDRAWMAX = 15;
|
||||
u32 limit = FieldMaxLength();
|
||||
u32 drawLimit = std::min(FIELDDRAWMAX, limit); // Field drew length limit.
|
||||
|
||||
const float keyboardLeftSide = (480.0f - (24.0f * numKeyCols[currentKeyboard])) / 2.0f;
|
||||
const float characterWidth = 12.0f;
|
||||
float previewLeftSide = (480.0f - (12.0f * limit)) / 2.0f;
|
||||
float title = (480.0f - (0.5f * limit)) / 2.0f;
|
||||
float previewLeftSide = (480.0f - (12.0f * drawLimit)) / 2.0f;
|
||||
float title = (480.0f - (0.5f * drawLimit)) / 2.0f;
|
||||
|
||||
|
||||
PPGeDrawText(oskDesc.c_str(), title , 20, PPGE_ALIGN_CENTER, 0.5f, CalcFadedColor(0xFFFFFFFF));
|
||||
|
@ -719,20 +722,22 @@ void PSPOskDialog::RenderKeyboard()
|
|||
|
||||
result = CombinationString(false);
|
||||
|
||||
for (u32 i = 0; i < limit; ++i)
|
||||
u32 drawIndex = (u32)(result.size() > drawLimit ? result.size() - drawLimit : 0);
|
||||
drawIndex = result.size() == limit + 1 ? drawIndex - 1 : drawIndex; // When the length reached limit, the last character don't fade in and out.
|
||||
for (u32 i = 0; i < drawLimit; ++i, ++drawIndex)
|
||||
{
|
||||
u32 color = CalcFadedColor(0xFFFFFFFF);
|
||||
if (i + 1 < result.size())
|
||||
if (drawIndex + 1 < result.size())
|
||||
{
|
||||
temp[0] = result[i];
|
||||
temp[0] = result[drawIndex];
|
||||
ConvertUCS2ToUTF8(buffer, temp);
|
||||
PPGeDrawText(buffer.c_str(), previewLeftSide + (i * characterWidth), 40.0f, PPGE_ALIGN_HCENTER, 0.5f, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i + 1 == result.size())
|
||||
if (drawIndex + 1 == result.size())
|
||||
{
|
||||
temp[0] = result[i];
|
||||
temp[0] = result[drawIndex];
|
||||
|
||||
if(isCombinated == true)
|
||||
{
|
||||
|
@ -781,7 +786,7 @@ void PSPOskDialog::RenderKeyboard()
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
// TODO: Why does this have a 2 button press lag/delay when
|
||||
// re-opening the dialog box? I don't get it.
|
||||
int PSPOskDialog::NativeKeyboard()
|
||||
|
@ -803,7 +808,7 @@ int PSPOskDialog::NativeKeyboard()
|
|||
if(defaultText.empty())
|
||||
defaultText.assign(L"VALUE");
|
||||
|
||||
if(host->InputBoxGetWString(titleText.c_str(), defaultText, inputChars))
|
||||
if(System_InputBoxGetWString(titleText.c_str(), defaultText, inputChars))
|
||||
{
|
||||
u32 maxLength = FieldMaxLength();
|
||||
if (inputChars.length() > maxLength)
|
||||
|
@ -844,15 +849,26 @@ int PSPOskDialog::NativeKeyboard()
|
|||
|
||||
int PSPOskDialog::Update(int animSpeed)
|
||||
{
|
||||
buttons = __CtrlReadLatch();
|
||||
int cancelButton = g_Config.iButtonPreference == PSP_SYSTEMPARAM_BUTTON_CROSS ? CTRL_CIRCLE : CTRL_CROSS;
|
||||
int confirmButton = cancelButton == CTRL_CROSS ? CTRL_CIRCLE : CTRL_CROSS;
|
||||
static int cancelBtnFramesHeld = 0;
|
||||
static int confirmBtnFramesHeld = 0;
|
||||
static int leftBtnFramesHeld = 0;
|
||||
static int upBtnFramesHeld = 0;
|
||||
static int downBtnFramesHeld = 0;
|
||||
static int rightBtnFramesHeld = 0;
|
||||
const int framesHeldThreshold = 10;
|
||||
const int framesHeldRepeatRate = 5;
|
||||
|
||||
buttons = __CtrlPeekButtons();
|
||||
int selectedRow = selectedChar / numKeyCols[currentKeyboard];
|
||||
int selectedExtra = selectedChar % numKeyCols[currentKeyboard];
|
||||
|
||||
// TODO: Add your platforms here when you have a NativeKeyboard func.
|
||||
|
||||
#ifdef _WIN32
|
||||
// Fall back to the OSK/continue normally if we're in fullscreen. The dialog box
|
||||
// doesn't work right if in fullscreen.
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
// Windows: Fall back to the OSK/continue normally if we're in fullscreen.
|
||||
// The dialog box doesn't work right if in fullscreen.
|
||||
if(g_Config.bBypassOSKWithKeyboard && !g_Config.bFullScreen)
|
||||
return NativeKeyboard();
|
||||
#endif
|
||||
|
@ -920,21 +936,21 @@ int PSPOskDialog::Update(int animSpeed)
|
|||
PPGeDrawText("R", 300, 245, PPGE_ALIGN_LEFT, 0.6f, CalcFadedColor(0xFFFFFFFF));
|
||||
PPGeDrawText(language, 315, 247, PPGE_ALIGN_LEFT, 0.5f, CalcFadedColor(0xFFFFFFFF));
|
||||
|
||||
if (IsButtonPressed(CTRL_UP))
|
||||
if (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate))
|
||||
{
|
||||
selectedChar -= numKeyCols[currentKeyboard];
|
||||
}
|
||||
else if (IsButtonPressed(CTRL_DOWN))
|
||||
else if (IsButtonPressed(CTRL_DOWN) || IsButtonHeld(CTRL_DOWN, downBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate))
|
||||
{
|
||||
selectedChar += numKeyCols[currentKeyboard];
|
||||
}
|
||||
else if (IsButtonPressed(CTRL_LEFT))
|
||||
else if (IsButtonPressed(CTRL_LEFT) || IsButtonHeld(CTRL_LEFT, leftBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate))
|
||||
{
|
||||
selectedChar--;
|
||||
if (((selectedChar + numKeyCols[currentKeyboard]) % numKeyCols[currentKeyboard]) == numKeyCols[currentKeyboard] - 1)
|
||||
selectedChar += numKeyCols[currentKeyboard];
|
||||
}
|
||||
else if (IsButtonPressed(CTRL_RIGHT))
|
||||
else if (IsButtonPressed(CTRL_RIGHT) || IsButtonHeld(CTRL_RIGHT, rightBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate))
|
||||
{
|
||||
selectedChar++;
|
||||
if ((selectedChar % numKeyCols[currentKeyboard]) == 0)
|
||||
|
@ -943,7 +959,7 @@ int PSPOskDialog::Update(int animSpeed)
|
|||
|
||||
selectedChar = (selectedChar + (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard])) % (numKeyCols[currentKeyboard] * numKeyRows[currentKeyboard]);
|
||||
|
||||
if (IsButtonPressed(g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE ? CTRL_CROSS : CTRL_CIRCLE))
|
||||
if (IsButtonPressed(confirmButton) || IsButtonHeld(confirmButton, confirmBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate))
|
||||
{
|
||||
inputChars = CombinationString(true);
|
||||
}
|
||||
|
@ -1009,7 +1025,7 @@ int PSPOskDialog::Update(int animSpeed)
|
|||
|
||||
selectedChar = selectedRow * numKeyCols[currentKeyboard] + selectedExtra;
|
||||
}
|
||||
else if (IsButtonPressed(g_Config.iButtonPreference != PSP_SYSTEMPARAM_BUTTON_CIRCLE ? CTRL_CIRCLE : CTRL_CROSS))
|
||||
else if (IsButtonPressed(cancelButton) || IsButtonHeld(cancelButton, cancelBtnFramesHeld, framesHeldThreshold, framesHeldRepeatRate))
|
||||
{
|
||||
if (inputChars.size() > 0)
|
||||
{
|
||||
|
@ -1046,7 +1062,7 @@ int PSPOskDialog::Update(int animSpeed)
|
|||
|
||||
oskParams->base.result = 0;
|
||||
oskParams->fields[0].result = PSP_UTILITY_OSK_RESULT_CHANGED;
|
||||
|
||||
lastButtons = buttons;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ private:
|
|||
void ConvertUCS2ToUTF8(std::string& _string, const PSPPointer<u16_le> em_address);
|
||||
void ConvertUCS2ToUTF8(std::string& _string, const wchar_t *input);
|
||||
void RenderKeyboard();
|
||||
#ifdef _WIN32
|
||||
#if defined(_WIN32) && !defined(USING_QT_UI)
|
||||
int NativeKeyboard();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -61,8 +61,7 @@ int PSPSaveDialog::Init(int paramAddr)
|
|||
switch ((SceUtilitySavedataFocus)(u32)param.GetPspParam()->focus)
|
||||
{
|
||||
case SCE_UTILITY_SAVEDATA_FOCUS_NAME:
|
||||
// TODO: This should probably force not using the list?
|
||||
currentSelectedSave = 0;
|
||||
currentSelectedSave = param.GetSaveNameIndex(param.GetPspParam());
|
||||
break;
|
||||
case SCE_UTILITY_SAVEDATA_FOCUS_FIRSTLIST:
|
||||
currentSelectedSave = param.GetFirstListSave();
|
||||
|
@ -270,11 +269,15 @@ void PSPSaveDialog::DisplayBanner(int which)
|
|||
void PSPSaveDialog::DisplaySaveList(bool canMove)
|
||||
{
|
||||
int displayCount = 0;
|
||||
static int upFramesHeld = 0;
|
||||
static int downFramesHeld = 0;
|
||||
|
||||
for (int i = 0; i < param.GetFilenameCount(); i++)
|
||||
{
|
||||
int textureColor = 0xFFFFFFFF;
|
||||
auto fileInfo = param.GetFileInfo(i);
|
||||
|
||||
if (param.GetFileInfo(i).size == 0 && param.GetFileInfo(i).textureData == 0)
|
||||
if (fileInfo.size == 0 && fileInfo.texture != NULL)
|
||||
textureColor = 0xFF777777;
|
||||
|
||||
// Calc save image position on screen
|
||||
|
@ -301,21 +304,21 @@ void PSPSaveDialog::DisplaySaveList(bool canMove)
|
|||
|
||||
int tw = 256;
|
||||
int th = 256;
|
||||
if (param.GetFileInfo(i).textureData != 0) {
|
||||
tw = param.GetFileInfo(i).textureWidth;
|
||||
th = param.GetFileInfo(i).textureHeight;
|
||||
PPGeSetTexture(param.GetFileInfo(i).textureData, param.GetFileInfo(i).textureWidth, param.GetFileInfo(i).textureHeight);
|
||||
if (fileInfo.texture != NULL) {
|
||||
fileInfo.texture->SetTexture();
|
||||
tw = fileInfo.texture->Width();
|
||||
th = fileInfo.texture->Height();
|
||||
PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor);
|
||||
} else
|
||||
PPGeDisableTexture();
|
||||
}
|
||||
PPGeSetDefaultTexture();
|
||||
displayCount++;
|
||||
}
|
||||
|
||||
if (canMove) {
|
||||
if (IsButtonPressed(CTRL_UP) && currentSelectedSave > 0)
|
||||
if ( (IsButtonPressed(CTRL_UP) || IsButtonHeld(CTRL_UP, upFramesHeld)) && currentSelectedSave > 0)
|
||||
currentSelectedSave--;
|
||||
else if (IsButtonPressed(CTRL_DOWN) && currentSelectedSave < (param.GetFilenameCount()-1))
|
||||
|
||||
else if ( (IsButtonPressed(CTRL_DOWN) || IsButtonHeld(CTRL_DOWN, downFramesHeld)) && currentSelectedSave < (param.GetFilenameCount() - 1))
|
||||
currentSelectedSave++;
|
||||
}
|
||||
}
|
||||
|
@ -323,8 +326,9 @@ void PSPSaveDialog::DisplaySaveList(bool canMove)
|
|||
void PSPSaveDialog::DisplaySaveIcon()
|
||||
{
|
||||
int textureColor = CalcFadedColor(0xFFFFFFFF);
|
||||
auto curSave = param.GetFileInfo(currentSelectedSave);
|
||||
|
||||
if (param.GetFileInfo(currentSelectedSave).size == 0)
|
||||
if (curSave.size == 0)
|
||||
textureColor = CalcFadedColor(0xFF777777);
|
||||
|
||||
// Calc save image position on screen
|
||||
|
@ -335,14 +339,15 @@ void PSPSaveDialog::DisplaySaveIcon()
|
|||
|
||||
int tw = 256;
|
||||
int th = 256;
|
||||
if (param.GetFileInfo(currentSelectedSave).textureData != 0) {
|
||||
tw = param.GetFileInfo(currentSelectedSave).textureWidth;
|
||||
th = param.GetFileInfo(currentSelectedSave).textureHeight;
|
||||
PPGeSetTexture(param.GetFileInfo(currentSelectedSave).textureData, param.GetFileInfo(currentSelectedSave).textureWidth, param.GetFileInfo(currentSelectedSave).textureHeight);
|
||||
} else
|
||||
if (curSave.texture != NULL) {
|
||||
curSave.texture->SetTexture();
|
||||
tw = curSave.texture->Width();
|
||||
th = curSave.texture->Height();
|
||||
} else {
|
||||
PPGeDisableTexture();
|
||||
PPGeDrawImage(x, y, w, h, 0, 0 ,1 ,1 ,tw, th, textureColor);
|
||||
if (param.GetFileInfo(currentSelectedSave).textureData != 0)
|
||||
}
|
||||
PPGeDrawImage(x, y, w, h, 0, 0, 1, 1, tw, th, textureColor);
|
||||
if (curSave.texture != NULL)
|
||||
PPGeSetDefaultTexture();
|
||||
}
|
||||
|
||||
|
@ -956,6 +961,10 @@ int PSPSaveDialog::Update(int animSpeed)
|
|||
case SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE:
|
||||
if (param.Load(param.GetPspParam(), GetSelectedSaveDirName(), currentSelectedSave, param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE))
|
||||
param.GetPspParam()->common.result = 0;
|
||||
else if (param.secureCanSkip(param.GetPspParam(),param.GetPspParam()->mode == SCE_UTILITY_SAVEDATA_TYPE_READDATASECURE)) {
|
||||
INFO_LOG(SCEUTILITY,"Has not been saved yet, just skip.");
|
||||
param.GetPspParam()->common.result = 0;
|
||||
}
|
||||
else
|
||||
param.GetPspParam()->common.result = SCE_UTILITY_SAVEDATA_ERROR_RW_NO_DATA; // not sure if correct code
|
||||
status = SCE_UTILITY_STATUS_FINISHED;
|
||||
|
|
|
@ -166,10 +166,9 @@ void SavedataParam::Init()
|
|||
#ifdef ANDROID
|
||||
int handle = pspFileSystem.OpenFile(savePath + ".nomedia", (FileAccess)(FILEACCESS_CREATE | FILEACCESS_WRITE), 0);
|
||||
if (handle) {
|
||||
ILOG("Created .nomedia file");
|
||||
pspFileSystem.CloseFile(handle);
|
||||
} else {
|
||||
ILOG("Failed to create .nomedia file");
|
||||
ELOG("Failed to create .nomedia file");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -324,15 +323,11 @@ bool SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &save
|
|||
ParamSFOData sfoFile;
|
||||
std::string sfopath = dirPath+"/" + SFO_FILENAME;
|
||||
PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
|
||||
if(sfoInfo.exists) // Read old sfo if exist
|
||||
if (sfoInfo.exists) // Read old sfo if exist
|
||||
{
|
||||
u8 *sfoData = new u8[(size_t)sfoInfo.size];
|
||||
size_t sfoSize = (size_t)sfoInfo.size;
|
||||
if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL))
|
||||
{
|
||||
sfoFile.ReadSFO(sfoData,sfoSize);
|
||||
delete[] sfoData;
|
||||
}
|
||||
std::vector<u8> sfoData;
|
||||
if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0)
|
||||
sfoFile.ReadSFO(sfoData);
|
||||
}
|
||||
|
||||
// Update values
|
||||
|
@ -567,12 +562,11 @@ void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string di
|
|||
ParamSFOData sfoFile;
|
||||
std::string sfopath = dirPath+"/" + SFO_FILENAME;
|
||||
PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
|
||||
if(sfoInfo.exists) {
|
||||
// Read sfo
|
||||
u8 *sfoData = new u8[(size_t)sfoInfo.size];
|
||||
size_t sfoSize = (size_t)sfoInfo.size;
|
||||
if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL)) {
|
||||
sfoFile.ReadSFO(sfoData,sfoSize);
|
||||
if (sfoInfo.exists) {
|
||||
// Read sfo
|
||||
std::vector<u8> sfoData;
|
||||
if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0) {
|
||||
sfoFile.ReadSFO(sfoData);
|
||||
|
||||
// copy back info in request
|
||||
strncpy(param->sfoParam.title,sfoFile.GetValueString("TITLE").c_str(),128);
|
||||
|
@ -580,10 +574,42 @@ void SavedataParam::LoadSFO(SceUtilitySavedataParam *param, const std::string di
|
|||
strncpy(param->sfoParam.detail,sfoFile.GetValueString("SAVEDATA_DETAIL").c_str(),1024);
|
||||
param->sfoParam.parentalLevel = sfoFile.GetValueInt("PARENTAL_LEVEL");
|
||||
}
|
||||
delete[] sfoData;
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::string> SavedataParam::getSecureFileNames(std::string dirPath) {
|
||||
PSPFileInfo sfoFileInfo = pspFileSystem.GetFileInfo(dirPath + "/" + SFO_FILENAME);
|
||||
std::set<std::string> secureFileNames;
|
||||
if (!sfoFileInfo.exists)
|
||||
return secureFileNames;
|
||||
|
||||
ParamSFOData sfoFile;
|
||||
std::vector<u8> sfoData;
|
||||
if (pspFileSystem.ReadEntireFile(dirPath + "/" + SFO_FILENAME, sfoData) >= 0) {
|
||||
sfoFile.ReadSFO(sfoData);
|
||||
}
|
||||
|
||||
u32 sfoFileListSize = 0;
|
||||
char *sfoFileList = (char *)sfoFile.GetValueData("SAVEDATA_FILE_LIST", &sfoFileListSize);
|
||||
const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3;
|
||||
const u32 FILE_LIST_COUNT_MAX = 99;
|
||||
|
||||
// Filenames are 13 bytes long at most. Add a NULL so there's no surprises.
|
||||
char temp[14];
|
||||
temp[13] = '\0';
|
||||
|
||||
for (u32 i = 0; i < FILE_LIST_COUNT_MAX; ++i) {
|
||||
// Ends at a NULL filename.
|
||||
if (i * FILE_LIST_ITEM_SIZE >= sfoFileListSize || sfoFileList[i * FILE_LIST_ITEM_SIZE] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(temp, &sfoFileList[i * FILE_LIST_ITEM_SIZE], 13);
|
||||
secureFileNames.insert(temp);
|
||||
}
|
||||
return secureFileNames;
|
||||
}
|
||||
|
||||
void SavedataParam::LoadFile(const std::string dirPath, const std::string filename, PspUtilitySavedataFileData *fileData) {
|
||||
std::string filePath = dirPath + "/" + filename;
|
||||
s64 readSize = -1;
|
||||
|
@ -959,32 +985,7 @@ int SavedataParam::GetFilesList(SceUtilitySavedataParam *param)
|
|||
std::set<std::string> secureFilenames;
|
||||
// TODO: Error code if not?
|
||||
if (sfoFileInfo.exists) {
|
||||
ParamSFOData sfoFile;
|
||||
size_t sfoSize = (size_t)sfoFileInfo.size;
|
||||
u8 *sfoData = new u8[sfoSize];
|
||||
if (ReadPSPFile(dirPath + "/" + SFO_FILENAME, &sfoData, sfoSize, NULL)){
|
||||
sfoFile.ReadSFO(sfoData, sfoSize);
|
||||
}
|
||||
delete[] sfoData;
|
||||
|
||||
u32 sfoFileListSize = 0;
|
||||
char *sfoFileList = (char *)sfoFile.GetValueData("SAVEDATA_FILE_LIST", &sfoFileListSize);
|
||||
const int FILE_LIST_ITEM_SIZE = 13 + 16 + 3;
|
||||
const u32 FILE_LIST_COUNT_MAX = 99;
|
||||
|
||||
// Filenames are 13 bytes long at most. Add a NULL so there's no surprises.
|
||||
char temp[14];
|
||||
temp[13] = '\0';
|
||||
|
||||
for (u32 i = 0; i < FILE_LIST_COUNT_MAX; ++i) {
|
||||
// Ends at a NULL filename.
|
||||
if (i * FILE_LIST_ITEM_SIZE >= sfoFileListSize || sfoFileList[i * FILE_LIST_ITEM_SIZE] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(temp, &sfoFileList[i * FILE_LIST_ITEM_SIZE], 13);
|
||||
secureFilenames.insert(temp);
|
||||
}
|
||||
secureFilenames = getSecureFileNames(dirPath);
|
||||
}
|
||||
|
||||
// Does not list directories, nor recurse into them, and ignores files not ALL UPPERCASE.
|
||||
|
@ -1085,20 +1086,20 @@ void SavedataParam::Clear()
|
|||
{
|
||||
for (int i = 0; i < saveNameListDataCount; i++)
|
||||
{
|
||||
if (saveDataList[i].textureData != 0 && saveDataList[i].size != 0)
|
||||
kernelMemory.Free(saveDataList[i].textureData);
|
||||
saveDataList[i].textureData = 0;
|
||||
if (saveDataList[i].texture != NULL && (!noSaveIcon || saveDataList[i].texture != noSaveIcon->texture))
|
||||
delete saveDataList[i].texture;
|
||||
saveDataList[i].texture = NULL;
|
||||
}
|
||||
|
||||
delete[] saveDataList;
|
||||
delete [] saveDataList;
|
||||
saveDataList = 0;
|
||||
saveDataListCount = 0;
|
||||
}
|
||||
if (noSaveIcon)
|
||||
{
|
||||
if(noSaveIcon->textureData != 0)
|
||||
kernelMemory.Free(noSaveIcon->textureData);
|
||||
noSaveIcon->textureData = 0;
|
||||
if (noSaveIcon->texture != NULL)
|
||||
delete noSaveIcon->texture;
|
||||
noSaveIcon->texture = NULL;
|
||||
delete noSaveIcon;
|
||||
noSaveIcon = 0;
|
||||
}
|
||||
|
@ -1233,33 +1234,6 @@ int SavedataParam::SetPspParam(SceUtilitySavedataParam *param)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool SavedataParam::CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info)
|
||||
{
|
||||
unsigned char *textureData;
|
||||
int w,h;
|
||||
|
||||
int success = pngLoadPtr(pngData, (int)pngSize, &w, &h, &textureData, false);
|
||||
|
||||
u32 texSize = w*h*4;
|
||||
u32 atlasPtr;
|
||||
if (success)
|
||||
atlasPtr = kernelMemory.Alloc(texSize, true, "SaveData Icon");
|
||||
if (success && atlasPtr != (u32)-1)
|
||||
{
|
||||
info.textureData = atlasPtr;
|
||||
Memory::Memcpy(atlasPtr, textureData, texSize);
|
||||
free(textureData);
|
||||
info.textureWidth = w;
|
||||
info.textureHeight = h;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN_LOG(SCEUTILITY, "Unable to load PNG data for savedata.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName)
|
||||
{
|
||||
saveInfo.size = info.size;
|
||||
|
@ -1268,7 +1242,12 @@ void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::
|
|||
saveInfo.modif_time = info.mtime;
|
||||
|
||||
// Start with a blank slate.
|
||||
saveInfo.textureData = 0;
|
||||
if (saveInfo.texture != NULL) {
|
||||
if (!noSaveIcon || saveInfo.texture != noSaveIcon->texture) {
|
||||
delete saveInfo.texture;
|
||||
}
|
||||
saveInfo.texture = NULL;
|
||||
}
|
||||
saveInfo.title[0] = 0;
|
||||
saveInfo.saveTitle[0] = 0;
|
||||
saveInfo.saveDetail[0] = 0;
|
||||
|
@ -1278,28 +1257,22 @@ void SavedataParam::SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::
|
|||
std::string fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + ICON0_FILENAME;
|
||||
PSPFileInfo info2 = pspFileSystem.GetFileInfo(fileDataPath2);
|
||||
if (info2.exists)
|
||||
{
|
||||
u8 *textureDataPNG = new u8[(size_t)info2.size];
|
||||
ReadPSPFile(fileDataPath2, &textureDataPNG, info2.size, NULL);
|
||||
CreatePNGIcon(textureDataPNG, (int)info2.size, saveInfo);
|
||||
delete[] textureDataPNG;
|
||||
}
|
||||
saveInfo.texture = new PPGeImage(fileDataPath2);
|
||||
|
||||
// Load info in PARAM.SFO
|
||||
fileDataPath2 = savePath + GetGameName(pspParam) + saveName + "/" + SFO_FILENAME;
|
||||
info2 = pspFileSystem.GetFileInfo(fileDataPath2);
|
||||
if (info2.exists)
|
||||
{
|
||||
u8 *sfoParam = new u8[(size_t)info2.size];
|
||||
ReadPSPFile(fileDataPath2, &sfoParam, info2.size, NULL);
|
||||
std::vector<u8> sfoData;
|
||||
pspFileSystem.ReadEntireFile(fileDataPath2, sfoData);
|
||||
ParamSFOData sfoFile;
|
||||
if (sfoFile.ReadSFO(sfoParam,(size_t)info2.size))
|
||||
if (sfoFile.ReadSFO(sfoData))
|
||||
{
|
||||
SetStringFromSFO(sfoFile, "TITLE", saveInfo.title, sizeof(saveInfo.title));
|
||||
SetStringFromSFO(sfoFile, "SAVEDATA_TITLE", saveInfo.saveTitle, sizeof(saveInfo.saveTitle));
|
||||
SetStringFromSFO(sfoFile, "SAVEDATA_DETAIL", saveInfo.saveDetail, sizeof(saveInfo.saveDetail));
|
||||
}
|
||||
delete [] sfoParam;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1314,7 +1287,12 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName)
|
|||
saveInfo.size = 0;
|
||||
saveInfo.saveName = saveName;
|
||||
saveInfo.idx = 0;
|
||||
saveInfo.textureData = 0;
|
||||
if (saveInfo.texture != NULL) {
|
||||
if (!noSaveIcon || saveInfo.texture != noSaveIcon->texture) {
|
||||
delete saveInfo.texture;
|
||||
}
|
||||
saveInfo.texture = NULL;
|
||||
}
|
||||
|
||||
if (GetPspParam()->newData.IsValid() && GetPspParam()->newData->buf.IsValid())
|
||||
{
|
||||
|
@ -1323,11 +1301,9 @@ void SavedataParam::ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName)
|
|||
{
|
||||
noSaveIcon = new SaveFileInfo();
|
||||
PspUtilitySavedataFileData *newData = GetPspParam()->newData;
|
||||
CreatePNGIcon(newData->buf, (int)newData->size, *noSaveIcon);
|
||||
noSaveIcon->texture = new PPGeImage(newData->buf.ptr, (SceSize)newData->size);
|
||||
}
|
||||
saveInfo.textureData = noSaveIcon->textureData;
|
||||
saveInfo.textureWidth = noSaveIcon->textureWidth;
|
||||
saveInfo.textureHeight = noSaveIcon->textureHeight;
|
||||
saveInfo.texture = noSaveIcon->texture;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1465,6 +1441,21 @@ int SavedataParam::GetLastEmptySave()
|
|||
return idx;
|
||||
}
|
||||
|
||||
int SavedataParam::GetSaveNameIndex(SceUtilitySavedataParam* param)
|
||||
{
|
||||
std::string saveName = GetSaveName(param);
|
||||
for (int i = 0; i < saveNameListDataCount; i++)
|
||||
{
|
||||
// TODO: saveName may contain wildcards
|
||||
if (saveDataList[i].saveName == saveName)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SavedataParam::DoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("SavedataParam", 1);
|
||||
|
@ -1501,11 +1492,10 @@ bool SavedataParam::IsSaveEncrypted(SceUtilitySavedataParam* param, const std::s
|
|||
PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfopath);
|
||||
if(sfoInfo.exists) // Read sfo
|
||||
{
|
||||
u8 *sfoData = new u8[(size_t)sfoInfo.size];
|
||||
size_t sfoSize = (size_t)sfoInfo.size;
|
||||
if(ReadPSPFile(sfopath,&sfoData,sfoSize, NULL))
|
||||
std::vector<u8> sfoData;
|
||||
if (pspFileSystem.ReadEntireFile(sfopath, sfoData) >= 0)
|
||||
{
|
||||
sfoFile.ReadSFO(sfoData,sfoSize);
|
||||
sfoFile.ReadSFO(sfoData);
|
||||
|
||||
// save created in PPSSPP and not encrypted has '0' in SAVEDATA_PARAMS
|
||||
u32 tmpDataSize = 0;
|
||||
|
@ -1519,7 +1509,6 @@ bool SavedataParam::IsSaveEncrypted(SceUtilitySavedataParam* param, const std::s
|
|||
}
|
||||
}
|
||||
}
|
||||
delete[] sfoData;
|
||||
}
|
||||
return isCrypted;
|
||||
}
|
||||
|
@ -1531,3 +1520,25 @@ bool SavedataParam::IsInSaveDataList(std::string saveName, int count) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SavedataParam::secureCanSkip(SceUtilitySavedataParam* param, bool secureMode) {
|
||||
if (!secureMode) // Only check in secure mode.
|
||||
return false;
|
||||
std::string dirPath = savePath + GetGameName(param) + GetSaveName(param);
|
||||
std::string sfoPath = dirPath + "/" + SFO_FILENAME;
|
||||
std::string secureFileName = GetFileName(param);
|
||||
std::set<std::string> secureFileNames;
|
||||
PSPFileInfo sfoInfo = pspFileSystem.GetFileInfo(sfoPath);
|
||||
// If sfo doesn't exist,shouldn't skip.
|
||||
if (!sfoInfo.exists)
|
||||
return false;
|
||||
|
||||
// Get secure file names from PARAM.SFO.
|
||||
secureFileNames = getSecureFileNames(dirPath);
|
||||
// Secure file name should be saved in PARAM.SFO
|
||||
// Cannot find name in PARAM.SFO, could skip.
|
||||
if (secureFileNames.find(secureFileName) == secureFileNames.end())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "Core/HLE/sceRtc.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Dialog/PSPDialog.h"
|
||||
#include "Core/Util/PPGeDraw.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#undef st_ctime
|
||||
|
@ -250,12 +251,9 @@ struct SaveFileInfo
|
|||
|
||||
tm modif_time;
|
||||
|
||||
u32 textureData;
|
||||
int textureWidth;
|
||||
int textureHeight;
|
||||
PPGeImage *texture;
|
||||
|
||||
SaveFileInfo() : size(0), saveName(""), idx(0),
|
||||
textureData(0), textureWidth(0), textureHeight(0)
|
||||
SaveFileInfo() : size(0), saveName(""), idx(0), texture(NULL)
|
||||
{
|
||||
memset(title, 0, 128);
|
||||
memset(saveTitle, 0, 128);
|
||||
|
@ -265,7 +263,7 @@ struct SaveFileInfo
|
|||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("SaveFileInfo", 1);
|
||||
auto s = p.Section("SaveFileInfo", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -278,9 +276,30 @@ struct SaveFileInfo
|
|||
p.DoArray(saveDetail, sizeof(saveDetail));
|
||||
|
||||
p.Do(modif_time);
|
||||
p.Do(textureData);
|
||||
p.Do(textureWidth);
|
||||
p.Do(textureHeight);
|
||||
|
||||
if (s <= 1) {
|
||||
u32 textureData;
|
||||
int textureWidth;
|
||||
int textureHeight;
|
||||
p.Do(textureData);
|
||||
p.Do(textureWidth);
|
||||
p.Do(textureHeight);
|
||||
|
||||
if (textureData != 0) {
|
||||
// Must be MODE_READ.
|
||||
texture = new PPGeImage("");
|
||||
texture->CompatLoad(textureData, textureWidth, textureHeight);
|
||||
}
|
||||
} else {
|
||||
bool hasTexture = texture != NULL;
|
||||
p.Do(hasTexture);
|
||||
if (hasTexture) {
|
||||
if (p.mode == p.MODE_READ) {
|
||||
texture = new PPGeImage("");
|
||||
}
|
||||
texture->DoState(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -305,6 +324,7 @@ public:
|
|||
bool GetSize(SceUtilitySavedataParam* param);
|
||||
bool IsSaveEncrypted(SceUtilitySavedataParam* param, const std::string &saveDirName);
|
||||
bool IsInSaveDataList(std::string saveName, int count);
|
||||
bool secureCanSkip(SceUtilitySavedataParam* param, bool secureMode);
|
||||
|
||||
std::string GetGameName(SceUtilitySavedataParam* param);
|
||||
std::string GetSaveName(SceUtilitySavedataParam* param);
|
||||
|
@ -330,12 +350,12 @@ public:
|
|||
int GetLastDataSave();
|
||||
int GetFirstEmptySave();
|
||||
int GetLastEmptySave();
|
||||
int GetSaveNameIndex(SceUtilitySavedataParam* param);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
private:
|
||||
void Clear();
|
||||
bool CreatePNGIcon(u8* pngData, int pngSize, SaveFileInfo& info);
|
||||
void SetFileInfo(int idx, PSPFileInfo &info, std::string saveName);
|
||||
void SetFileInfo(SaveFileInfo &saveInfo, PSPFileInfo &info, std::string saveName);
|
||||
void ClearFileInfo(SaveFileInfo &saveInfo, std::string saveName);
|
||||
|
@ -351,6 +371,8 @@ private:
|
|||
int UpdateHash(u8* sfoData, int sfoSize, int sfoDataParamsOffset, int encryptmode);
|
||||
int BuildHash(unsigned char *output, unsigned char *data, unsigned int len, unsigned int alignedLen, int mode, unsigned char *cryptkey);
|
||||
|
||||
std::set<std::string> getSecureFileNames(std::string dirPath);
|
||||
|
||||
SceUtilitySavedataParam* pspParam;
|
||||
int selectedSave;
|
||||
SaveFileInfo *saveDataList;
|
||||
|
|
|
@ -29,7 +29,7 @@ const char *ElfReader::GetSectionName(int section)
|
|||
return 0;
|
||||
|
||||
int nameOffset = sections[section].sh_name;
|
||||
char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
|
||||
const char *ptr = (const char *)GetSectionDataPtr(header->e_shstrndx);
|
||||
|
||||
if (ptr)
|
||||
return ptr + nameOffset;
|
||||
|
@ -51,10 +51,13 @@ void addrToHiLo(u32 addr, u16 &hi, s16 &lo)
|
|||
}
|
||||
}
|
||||
|
||||
void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
||||
bool ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
||||
{
|
||||
int numErrors = 0;
|
||||
DEBUG_LOG(LOADER, "Loading %i relocations...", numRelocs);
|
||||
for (int r = 0; r < numRelocs; r++)
|
||||
{
|
||||
// INFO_LOG(LOADER, "Loading reloc %i (%p)...", r, rels + r);
|
||||
u32 info = rels[r].r_info;
|
||||
u32 addr = rels[r].r_offset;
|
||||
|
||||
|
@ -66,15 +69,35 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
|||
//0 = code
|
||||
//1 = data
|
||||
|
||||
if (readwrite >= (int)ARRAY_SIZE(segmentVAddr)) {
|
||||
if (numErrors < 10) {
|
||||
ERROR_LOG_REPORT(LOADER, "Bad segment number %i", readwrite);
|
||||
}
|
||||
numErrors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
addr += segmentVAddr[readwrite];
|
||||
|
||||
// It appears that misaligned relocations are allowed.
|
||||
// Will they work correctly on big-endian?
|
||||
|
||||
if (((addr & 3) && type != R_MIPS_32) || !Memory::IsValidAddress(addr)) {
|
||||
if (numErrors < 10) {
|
||||
WARN_LOG_REPORT(LOADER, "Suspicious address %08x, skipping reloc, type = %d", addr, type);
|
||||
} else if (numErrors == 10) {
|
||||
WARN_LOG(LOADER, "Too many bad relocations, skipping logging");
|
||||
}
|
||||
numErrors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 op = Memory::Read_Instruction(addr).encoding;
|
||||
|
||||
const bool log = false;
|
||||
//log=true;
|
||||
if (log)
|
||||
{
|
||||
DEBUG_LOG(LOADER,"rel at: %08x type: %08x",addr,info);
|
||||
if (log) {
|
||||
DEBUG_LOG(LOADER,"rel at: %08x info: %08x type: %i",addr, info, type);
|
||||
}
|
||||
u32 relocateTo = segmentVAddr[relative];
|
||||
|
||||
|
@ -107,22 +130,24 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
|||
if ((rels[t].r_info & 0xF) == R_MIPS_LO16)
|
||||
{
|
||||
u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite];
|
||||
if (log)
|
||||
{
|
||||
if (log) {
|
||||
DEBUG_LOG(LOADER,"Corresponding lo found at %08x", corrLoAddr);
|
||||
}
|
||||
|
||||
s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed??
|
||||
cur += lo;
|
||||
cur += relocateTo;
|
||||
addrToHiLo(cur, hi, lo);
|
||||
found = true;
|
||||
break;
|
||||
if (Memory::IsValidAddress(corrLoAddr)) {
|
||||
s16 lo = (s32)(s16)(u16)(Memory::ReadUnchecked_U32(corrLoAddr) & 0xFFFF); //signed??
|
||||
cur += lo;
|
||||
cur += relocateTo;
|
||||
addrToHiLo(cur, hi, lo);
|
||||
found = true;
|
||||
break;
|
||||
} else {
|
||||
ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
if (!found) {
|
||||
ERROR_LOG_REPORT(LOADER, "R_MIPS_HI16: could not find R_MIPS_LO16");
|
||||
|
||||
}
|
||||
op = (op & 0xFFFF0000) | (hi);
|
||||
}
|
||||
break;
|
||||
|
@ -164,6 +189,10 @@ void ElfReader::LoadRelocations(Elf32_Rel *rels, int numRelocs)
|
|||
}
|
||||
Memory::Write_U32(op, addr);
|
||||
}
|
||||
if (numErrors) {
|
||||
WARN_LOG(LOADER, "%i bad relocations found!!!", numErrors);
|
||||
}
|
||||
return numErrors == 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -276,8 +305,8 @@ void ElfReader::LoadRelocations2(int rel_seg)
|
|||
ERROR_LOG_REPORT(LOADER, "Rel2: invalid lo16 type! %x", flag);
|
||||
}
|
||||
|
||||
op = Memory::ReadUnchecked_U32(rel_offset);
|
||||
DEBUG_LOG(LOADER, "Rel2: %5d: CMD=0x%04X type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, type, off_seg, rel_base, addr_seg, op);
|
||||
op = Memory::Read_Instruction(rel_offset).encoding;
|
||||
DEBUG_LOG(LOADER, "Rel2: %5d: CMD=0x%04X flag=%x type=%d off_seg=%d offset=%08x addr_seg=%d op=%08x\n", rcount, cmd, flag, type, off_seg, rel_base, addr_seg, op);
|
||||
|
||||
switch(type){
|
||||
case 0:
|
||||
|
@ -289,6 +318,11 @@ void ElfReader::LoadRelocations2(int rel_seg)
|
|||
case 6: // R_MIPS_J26
|
||||
case 7: // R_MIPS_JAL26
|
||||
op = (op&0xFC000000) | (((op&0x03FFFFFF)+(relocate_to>>2))&0x03FFFFFF);
|
||||
// To be safe, let's force it to the specified jump.
|
||||
if (type == 6)
|
||||
op = (op & ~0xFC000000) | 0x08000000;
|
||||
else if (type == 7)
|
||||
op = (op & ~0xFC000000) | 0x0C000000;
|
||||
break;
|
||||
case 4: // R_MIPS_HI16
|
||||
addr = ((op<<16)+lo16)+relocate_to;
|
||||
|
@ -301,6 +335,7 @@ void ElfReader::LoadRelocations2(int rel_seg)
|
|||
op = (op&0xffff0000) | (((op&0xffff)+relocate_to)&0xffff);
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG_REPORT(LOADER, "Rel2: unexpected relocation type! %x", type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -436,7 +471,7 @@ int ElfReader::LoadInto(u32 loadAddress)
|
|||
DEBUG_LOG(LOADER,"Relocations:");
|
||||
|
||||
// Second pass: Do necessary relocations
|
||||
for (int i=0; i<GetNumSections(); i++)
|
||||
for (int i = 0; i < GetNumSections(); i++)
|
||||
{
|
||||
Elf32_Shdr *s = §ions[i];
|
||||
const char *name = GetSectionName(i);
|
||||
|
@ -445,7 +480,6 @@ int ElfReader::LoadInto(u32 loadAddress)
|
|||
{
|
||||
//We have a relocation table!
|
||||
int sectionToModify = s->sh_info;
|
||||
|
||||
if (sectionToModify >= 0)
|
||||
{
|
||||
if (!(sections[sectionToModify].sh_flags & SHF_ALLOC))
|
||||
|
@ -458,8 +492,10 @@ int ElfReader::LoadInto(u32 loadAddress)
|
|||
|
||||
Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i);
|
||||
|
||||
DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify));
|
||||
LoadRelocations(rels, numRelocs);
|
||||
DEBUG_LOG(LOADER,"%s: Performing %i relocations on %s : offset = %08x", name, numRelocs, GetSectionName(sectionToModify), sections[i].sh_offset);
|
||||
if (!LoadRelocations(rels, numRelocs)) {
|
||||
WARN_LOG(LOADER, "LoadInto: Relocs failed, trying anyway");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -495,28 +531,25 @@ int ElfReader::LoadInto(u32 loadAddress)
|
|||
}
|
||||
|
||||
// Segment relocations (a few games use them)
|
||||
if (GetNumSections() == 0)
|
||||
{
|
||||
for (int i=0; i<header->e_phnum; i++)
|
||||
if (GetNumSections() == 0) {
|
||||
for (int i = 0; i < header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr *p = &segments[i];
|
||||
if (p->p_type == 0x700000A0)
|
||||
{
|
||||
if (p->p_type == PT_PSPREL1) {
|
||||
INFO_LOG(LOADER,"Loading segment relocations");
|
||||
|
||||
int numRelocs = p->p_filesz / sizeof(Elf32_Rel);
|
||||
|
||||
Elf32_Rel *rels = (Elf32_Rel *)GetSegmentPtr(i);
|
||||
LoadRelocations(rels, numRelocs);
|
||||
} else if (p->p_type == 0x700000A1)
|
||||
{
|
||||
if (!LoadRelocations(rels, numRelocs)) {
|
||||
ERROR_LOG(LOADER, "LoadInto: Relocs failed, trying anyway (2)");
|
||||
}
|
||||
} else if (p->p_type == PT_PSPREL2) {
|
||||
INFO_LOG(LOADER,"Loading segment relocations2");
|
||||
LoadRelocations2(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NOTICE_LOG(LOADER,"ELF loading completed successfully.");
|
||||
return SCE_KERNEL_ERROR_OK;
|
||||
}
|
||||
|
||||
|
@ -564,18 +597,18 @@ bool ElfReader::LoadSymbols()
|
|||
|
||||
if (bRelocate)
|
||||
value += sectionAddrs[sectionIndex];
|
||||
SymbolType symtype = ST_DATA;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case STT_OBJECT:
|
||||
symtype = ST_DATA; break;
|
||||
symbolMap.AddData(value,size,DATATYPE_BYTE);
|
||||
break;
|
||||
case STT_FUNC:
|
||||
symtype = ST_FUNCTION; break;
|
||||
symbolMap.AddFunction(name,value,size);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
symbolMap.AddSymbol(name, value, size, symtype);
|
||||
hasSymbols = true;
|
||||
//...
|
||||
}
|
||||
|
|
|
@ -55,7 +55,6 @@ public:
|
|||
bRelocate(false),
|
||||
entryPoint(0),
|
||||
vaddr(0) {
|
||||
INFO_LOG(LOADER, "ElfReader: %p", ptr);
|
||||
base = (char*)ptr;
|
||||
base32 = (u32 *)ptr;
|
||||
header = (Elf32_Ehdr*)ptr;
|
||||
|
@ -117,6 +116,10 @@ public:
|
|||
{
|
||||
return segmentVAddr[segment];
|
||||
}
|
||||
u32 GetSegmentDataSize(int segment)
|
||||
{
|
||||
return segments[segment].p_filesz;
|
||||
}
|
||||
|
||||
bool DidRelocate() {
|
||||
return bRelocate;
|
||||
|
@ -135,7 +138,7 @@ public:
|
|||
// More indepth stuff:)
|
||||
int LoadInto(u32 vaddr);
|
||||
bool LoadSymbols();
|
||||
void LoadRelocations(Elf32_Rel *rels, int numRelocs);
|
||||
bool LoadRelocations(Elf32_Rel *rels, int numRelocs);
|
||||
void LoadRelocations2(int rel_seg);
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ enum ElfType
|
|||
ET_CORE =4,
|
||||
ET_LOPROC =0xFF00,
|
||||
ET_HIPROC =0xFFFF,
|
||||
ET_PSP_PRX=0xFFA0,
|
||||
};
|
||||
|
||||
// Machine/Architecture
|
||||
|
@ -78,6 +79,34 @@ enum ElfMachine
|
|||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
// MIPS-specific header flags.
|
||||
#define EF_MIPS_NOREORDER 0x00000001
|
||||
#define EF_MIPS_PIC 0x00000002
|
||||
#define EF_MIPS_CPIC 0x00000004
|
||||
#define EF_MIPS_XGOT 0x00000008
|
||||
#define EF_MIPS_UCODE 0x00000010
|
||||
#define EF_MIPS_ABI2 0x00000020
|
||||
#define EF_MIPS_DYNAMIC 0x00000040
|
||||
#define EF_MIPS_32BITMODE 0x00000100
|
||||
#define EF_MIPS_ABI_MASK 0x0000f000
|
||||
#define EF_MIPS_ABI_O32 0x00001000
|
||||
#define EF_MIPS_ABI_O64 0x00002000
|
||||
#define E_MIPS_ABI_EABI32 0x00003000
|
||||
#define E_MIPS_ABI_EABI64 0x00004000
|
||||
#define EF_MIPS_MACH_MASK 0x00ff0000
|
||||
#define EF_MIPS_MACH_PSP 0x00a20000
|
||||
#define EF_MIPS_ARCH_MASK 0xf0000000
|
||||
#define EF_MIPS_ARCH_1 0x00000000
|
||||
#define EF_MIPS_ARCH_2 0x10000000
|
||||
#define EF_MIPS_ARCH_3 0x20000000
|
||||
#define EF_MIPS_ARCH_4 0x30000000
|
||||
#define EF_MIPS_ARCH_5 0x40000000
|
||||
#define EF_MIPS_ARCH_32 0x50000000
|
||||
#define EF_MIPS_ARCH_64 0x60000000
|
||||
#define EF_MIPS_ARCH_32R2 0x70000000
|
||||
#define EF_MIPS_ARCH_64R2 0x80000000
|
||||
|
||||
|
||||
|
||||
/////////////////////
|
||||
// Sections constants
|
||||
|
@ -165,6 +194,10 @@ enum ElfSectionFlags
|
|||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7FFFFFFF
|
||||
|
||||
// Custom segment types
|
||||
#define PT_PSPREL1 0x700000a0
|
||||
#define PT_PSPREL2 0x700000a1
|
||||
|
||||
// Segment flags
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
|
|
|
@ -23,9 +23,10 @@
|
|||
#include "Common/FileUtil.h"
|
||||
#include "Core/ELF/PBPReader.h"
|
||||
|
||||
PBPReader::PBPReader(const char *filename) : header_() {
|
||||
PBPReader::PBPReader(const char *filename) : header_(), isELF_(false) {
|
||||
file_ = File::OpenCFile(filename, "rb");
|
||||
if (!file_) {
|
||||
ERROR_LOG(LOADER, "Failed to open PBP file %s", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -34,6 +35,12 @@ PBPReader::PBPReader(const char *filename) : header_() {
|
|||
fseek(file_, 0, SEEK_SET);
|
||||
fread((char *)&header_, 1, sizeof(header_), file_);
|
||||
if (memcmp(header_.magic, "\0PBP", 4) != 0) {
|
||||
if (memcmp(header_.magic, "\nFLE", 4) != 0) {
|
||||
DEBUG_LOG(LOADER, "%s: File actually an ELF, not a PBP", filename);
|
||||
isELF_ = true;
|
||||
} else {
|
||||
ERROR_LOG(LOADER, "Magic number in %s indicated no PBP: %s", filename, header_.magic);
|
||||
}
|
||||
fclose(file_);
|
||||
file_ = 0;
|
||||
return;
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
~PBPReader();
|
||||
|
||||
bool IsValid() const { return file_ != 0; }
|
||||
bool IsELF() const { return file_ == 0 && isELF_; }
|
||||
|
||||
// Delete the returned buffer with delete [].
|
||||
u8 *GetSubFile(PBPSubFile file, size_t *outSize);
|
||||
|
@ -61,4 +62,5 @@ private:
|
|||
FILE *file_;
|
||||
size_t fileSize_;
|
||||
const PBPHeader header_;
|
||||
};
|
||||
bool isELF_;
|
||||
};
|
||||
|
|
|
@ -37,6 +37,10 @@ public:
|
|||
bool ReadSFO(const u8 *paramsfo, size_t size);
|
||||
bool WriteSFO(u8 **paramsfo, size_t *size);
|
||||
|
||||
bool ReadSFO(const std::vector<u8> ¶msfo) {
|
||||
return ReadSFO(¶msfo[0], paramsfo.size());
|
||||
}
|
||||
|
||||
int GetDataOffset(const u8 *paramsfo, std::string dataName);
|
||||
|
||||
private:
|
||||
|
|
|
@ -382,11 +382,15 @@ u32 ISOFileSystem::OpenFile(std::string filename, FileAccess access, const char
|
|||
{
|
||||
u32 sectorStart = 0xFFFFFFFF, readSize = 0xFFFFFFFF;
|
||||
parseLBN(filename, §orStart, &readSize);
|
||||
if (sectorStart >= blockDevice->GetNumBlocks())
|
||||
if (sectorStart > blockDevice->GetNumBlocks())
|
||||
{
|
||||
WARN_LOG(FILESYS, "Unable to open raw sector: %s, sector %08x, max %08x", filename.c_str(), sectorStart, blockDevice->GetNumBlocks());
|
||||
WARN_LOG(FILESYS, "Unable to open raw sector, out of range: %s, sector %08x, max %08x", filename.c_str(), sectorStart, blockDevice->GetNumBlocks());
|
||||
return 0;
|
||||
}
|
||||
else if (sectorStart == blockDevice->GetNumBlocks())
|
||||
{
|
||||
ERROR_LOG(FILESYS, "Should not be able to open the block after the last on disc! %08x", sectorStart);
|
||||
}
|
||||
|
||||
DEBUG_LOG(FILESYS, "Got a raw sector open: %s, sector %08x, size %08x", filename.c_str(), sectorStart, readSize);
|
||||
u32 newHandle = hAlloc->GetNewHandle();
|
||||
|
|
|
@ -255,6 +255,22 @@ void MetaFileSystem::Unmount(std::string prefix, IFileSystem *system)
|
|||
fileSystems.erase(std::remove(fileSystems.begin(), fileSystems.end(), x), fileSystems.end());
|
||||
}
|
||||
|
||||
void MetaFileSystem::Remount(IFileSystem *oldSystem, IFileSystem *newSystem) {
|
||||
for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) {
|
||||
if (it->system == oldSystem) {
|
||||
it->system = newSystem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IFileSystem *MetaFileSystem::GetSystem(const std::string &prefix) {
|
||||
for (auto it = fileSystems.begin(); it != fileSystems.end(); ++it) {
|
||||
if (it->prefix == prefix)
|
||||
return it->system;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MetaFileSystem::Shutdown()
|
||||
{
|
||||
lock_guard guard(lock);
|
||||
|
@ -501,6 +517,23 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int MetaFileSystem::ReadEntireFile(const std::string &filename, std::vector<u8> &data) {
|
||||
int error = 0;
|
||||
u32 handle = pspFileSystem.OpenWithError(error, filename, FILEACCESS_READ);
|
||||
if (handle == 0)
|
||||
return error;
|
||||
|
||||
size_t dataSize = (size_t)pspFileSystem.GetFileInfo(filename).size;
|
||||
data.resize(dataSize);
|
||||
|
||||
size_t result = pspFileSystem.ReadFile(handle, (u8 *)&data[0], dataSize);
|
||||
pspFileSystem.CloseFile(handle);
|
||||
|
||||
if (result != dataSize)
|
||||
return SCE_KERNEL_ERROR_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MetaFileSystem::DoState(PointerWrap &p)
|
||||
{
|
||||
lock_guard guard(lock);
|
||||
|
|
|
@ -51,6 +51,9 @@ public:
|
|||
|
||||
void Mount(std::string prefix, IFileSystem *system);
|
||||
void Unmount(std::string prefix, IFileSystem *system);
|
||||
void Remount(IFileSystem *oldSystem, IFileSystem *newSystem);
|
||||
|
||||
IFileSystem *GetSystem(const std::string &prefix);
|
||||
|
||||
void ThreadEnded(int threadID);
|
||||
|
||||
|
@ -102,6 +105,9 @@ public:
|
|||
|
||||
// TODO: void IoCtl(...)
|
||||
|
||||
// Convenience helper - returns < 0 on failure.
|
||||
int ReadEntireFile(const std::string &filename, std::vector<u8> &data);
|
||||
|
||||
void SetStartingDirectory(const std::string &dir) {
|
||||
lock_guard guard(lock);
|
||||
startingDirectory = dir;
|
||||
|
|
|
@ -30,17 +30,35 @@
|
|||
|
||||
// These fonts, created by ttf2pgf, don't have complete glyph info and need to be identified.
|
||||
static bool isJPCSPFont(const char *fontName) {
|
||||
return !strcmp(fontName, "Liberation") || !strcmp(fontName, "Sazanami") || !strcmp(fontName, "UnDotum");
|
||||
return !strcmp(fontName, "Liberation Sans") || !strcmp(fontName, "Liberation Serif") || !strcmp(fontName, "Sazanami") || !strcmp(fontName, "UnDotum") || !strcmp(fontName, "Microsoft YaHei");
|
||||
}
|
||||
|
||||
// Gets a number of bits from an offset.
|
||||
// TODO: Make more efficient.
|
||||
static int getBits(int numBits, const u8 *buf, size_t pos) {
|
||||
int v = 0;
|
||||
for (int i = 0; i < numBits; i++) {
|
||||
v = v | (((buf[pos >> 3] >> (pos & 7)) & 1) << i);
|
||||
pos++;
|
||||
_dbg_assert_msg_(SCEFONT, numBits <= 32, "Unable to return more than 32 bits, %d requested", numBits);
|
||||
|
||||
const size_t wordpos = pos >> 5;
|
||||
const u32 *wordbuf = (const u32 *)buf;
|
||||
const u8 bitoff = pos & 31;
|
||||
|
||||
// Might just be in one, has to be within two.
|
||||
if (bitoff + numBits < 32) {
|
||||
const u32 mask = (1 << numBits) - 1;
|
||||
return (wordbuf[wordpos] >> bitoff) & mask;
|
||||
} else {
|
||||
int v = wordbuf[wordpos] >> bitoff;
|
||||
|
||||
const u8 done = 32 - bitoff;
|
||||
const u8 remaining = numBits - done;
|
||||
const u32 mask = (1 << remaining) - 1;
|
||||
v |= (wordbuf[wordpos + 1] & mask) << done;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int consumeBits(int numBits, const u8 *buf, size_t &pos) {
|
||||
int v = getBits(numBits, buf, pos);
|
||||
pos += numBits;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
@ -64,8 +82,47 @@ PGF::~PGF() {
|
|||
}
|
||||
}
|
||||
|
||||
struct GlyphFromPGF1State {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
int left;
|
||||
int top;
|
||||
int flags;
|
||||
int shadowID;
|
||||
int advanceH;
|
||||
int advanceV;
|
||||
int dimensionWidth, dimensionHeight;
|
||||
int xAdjustH, xAdjustV;
|
||||
int yAdjustH, yAdjustV;
|
||||
u32 ptr;
|
||||
|
||||
operator Glyph() {
|
||||
Glyph ret;
|
||||
ret.w = w;
|
||||
ret.h = h;
|
||||
ret.left = left;
|
||||
ret.top = top;
|
||||
ret.flags = flags;
|
||||
// Wasn't read before.
|
||||
ret.shadowFlags = 0;
|
||||
ret.shadowID = shadowID;
|
||||
ret.advanceH = advanceH;
|
||||
ret.advanceV = advanceV;
|
||||
ret.dimensionWidth = dimensionWidth;
|
||||
ret.dimensionHeight = dimensionHeight;
|
||||
ret.xAdjustH = xAdjustH;
|
||||
ret.xAdjustV = xAdjustV;
|
||||
ret.yAdjustH = yAdjustH;
|
||||
ret.yAdjustV = yAdjustV;
|
||||
ret.ptr = ptr;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
void PGF::DoState(PointerWrap &p) {
|
||||
auto s = p.Section("PGF", 1);
|
||||
auto s = p.Section("PGF", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -98,8 +155,22 @@ void PGF::DoState(PointerWrap &p) {
|
|||
|
||||
p.Do(charmap_compr);
|
||||
p.Do(charmap);
|
||||
p.Do(glyphs);
|
||||
p.Do(shadowGlyphs);
|
||||
if (s == 1) {
|
||||
std::vector<GlyphFromPGF1State> oldGlyphs;
|
||||
p.Do(oldGlyphs);
|
||||
glyphs.resize(oldGlyphs.size());
|
||||
for (size_t i = 0; i < oldGlyphs.size(); ++i) {
|
||||
glyphs[i] = oldGlyphs[i];
|
||||
}
|
||||
p.Do(oldGlyphs);
|
||||
shadowGlyphs.resize(oldGlyphs.size());
|
||||
for (size_t i = 0; i < oldGlyphs.size(); ++i) {
|
||||
shadowGlyphs[i] = oldGlyphs[i];
|
||||
}
|
||||
} else {
|
||||
p.Do(glyphs);
|
||||
p.Do(shadowGlyphs);
|
||||
}
|
||||
p.Do(firstGlyph);
|
||||
}
|
||||
|
||||
|
@ -110,6 +181,8 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
memcpy(&header, ptr, sizeof(header));
|
||||
ptr += sizeof(header);
|
||||
|
||||
fileName = header.fontName;
|
||||
|
||||
if (header.revision == 3) {
|
||||
memcpy(&rev3extra, ptr, sizeof(rev3extra));
|
||||
rev3extra.compCharMapLength1 &= 0xFFFF;
|
||||
|
@ -149,10 +222,8 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
const u8 *uptr = (const u8 *)wptr;
|
||||
|
||||
int shadowCharMapSize = ((header.shadowMapLength * header.shadowMapBpe + 31) & ~31) / 8;
|
||||
u8 *shadowCharMap = new u8[shadowCharMapSize];
|
||||
for (int i = 0; i < shadowCharMapSize; i++) {
|
||||
shadowCharMap[i] = *uptr++;
|
||||
}
|
||||
const u8 *shadowCharMap = uptr;
|
||||
uptr += shadowCharMapSize;
|
||||
|
||||
const u16_le *sptr = (const u16_le *)uptr;
|
||||
if (header.revision == 3) {
|
||||
|
@ -174,17 +245,12 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
uptr = (const u8 *)sptr;
|
||||
|
||||
int charMapSize = ((header.charMapLength * header.charMapBpe + 31) & ~31) / 8;
|
||||
|
||||
u8 *charMap = new u8[charMapSize];
|
||||
for (int i = 0; i < charMapSize; i++) {
|
||||
charMap[i] = *uptr++;
|
||||
}
|
||||
const u8 *charMap = uptr;
|
||||
uptr += charMapSize;
|
||||
|
||||
int charPointerSize = (((header.charPointerLength * header.charPointerBpe + 31) & ~31) / 8);
|
||||
u8 *charPointerTable = new u8[charPointerSize];
|
||||
for (int i = 0; i < charPointerSize; i++) {
|
||||
charPointerTable[i] = *uptr++;
|
||||
}
|
||||
const u8 *charPointerTable = uptr;
|
||||
uptr += charPointerSize;
|
||||
|
||||
// PGF Fontdata.
|
||||
u32 fontDataOffset = (u32)(uptr - startPtr);
|
||||
|
@ -213,10 +279,6 @@ void PGF::ReadPtr(const u8 *ptr, size_t dataSize) {
|
|||
std::vector<int> charPointers = getTable(charPointerTable, header.charPointerBpe, glyphs.size());
|
||||
std::vector<int> shadowMap = getTable(shadowCharMap, header.shadowMapBpe, shadowGlyphs.size());
|
||||
|
||||
delete [] charMap;
|
||||
delete [] shadowCharMap;
|
||||
delete [] charPointerTable;
|
||||
|
||||
// Pregenerate glyphs.
|
||||
for (size_t i = 0; i < glyphs.size(); i++) {
|
||||
GetGlyph(fontData, charPointers[i] * 4 * 8 /* ??? */, FONT_PGF_CHARGLYPH, glyphs[i]);
|
||||
|
@ -247,13 +309,18 @@ int PGF::GetCharIndex(int charCode, const std::vector<int> &charmapCompressed) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo) {
|
||||
bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo, int altCharCode) {
|
||||
Glyph glyph;
|
||||
memset(charInfo, 0, sizeof(*charInfo));
|
||||
|
||||
if (!GetCharGlyph(charCode, FONT_PGF_CHARGLYPH, glyph)) {
|
||||
// Character not in font, return zeroed charInfo as on real PSP.
|
||||
return false;
|
||||
if (charCode < firstGlyph) {
|
||||
// Character not in font, return zeroed charInfo as on real PSP.
|
||||
return false;
|
||||
}
|
||||
if (!GetCharGlyph(altCharCode, FONT_PGF_CHARGLYPH, glyph)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
charInfo->bitmapWidth = glyph.w;
|
||||
|
@ -262,14 +329,17 @@ bool PGF::GetCharInfo(int charCode, PGFCharInfo *charInfo) {
|
|||
charInfo->bitmapTop = glyph.top;
|
||||
charInfo->sfp26Width = glyph.dimensionWidth;
|
||||
charInfo->sfp26Height = glyph.dimensionHeight;
|
||||
charInfo->sfp26Ascender = glyph.top << 6;
|
||||
charInfo->sfp26Descender = (glyph.h - glyph.top) << 6;
|
||||
charInfo->sfp26Ascender = glyph.yAdjustH;
|
||||
// Font y goes upwards. If top is 10 and height is 11, the descender is approx. -1 (below 0.)
|
||||
charInfo->sfp26Descender = charInfo->sfp26Ascender - charInfo->sfp26Height;
|
||||
charInfo->sfp26BearingHX = glyph.xAdjustH;
|
||||
charInfo->sfp26BearingHY = glyph.yAdjustH;
|
||||
charInfo->sfp26BearingVX = glyph.xAdjustV;
|
||||
charInfo->sfp26BearingVY = glyph.yAdjustV;
|
||||
charInfo->sfp26AdvanceH = glyph.advanceH;
|
||||
charInfo->sfp26AdvanceV = glyph.advanceV;
|
||||
charInfo->shadowFlags = glyph.shadowFlags;
|
||||
charInfo->shadowId = glyph.shadowID;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -297,7 +367,7 @@ void PGF::GetFontInfo(PGFFontInfo *fi) {
|
|||
|
||||
fi->maxGlyphWidth = header.maxGlyphWidth;
|
||||
fi->maxGlyphHeight = header.maxGlyphHeight;
|
||||
fi->charMapLength = header.charMapLength;
|
||||
fi->numGlyphs = header.charPointerLength;
|
||||
fi->shadowMapLength = 0; // header.shadowMapLength; TODO
|
||||
|
||||
fi->BPP = header.bpp;
|
||||
|
@ -311,40 +381,34 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
if (charPtr + 96 > fontDataSize * 8)
|
||||
return false;
|
||||
}
|
||||
// Skip size.
|
||||
charPtr += 14;
|
||||
|
||||
glyph.w = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
glyph.w = consumeBits(7, fontdata, charPtr);
|
||||
glyph.h = consumeBits(7, fontdata, charPtr);
|
||||
|
||||
glyph.h = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
|
||||
glyph.left = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
glyph.left = consumeBits(7, fontdata, charPtr);
|
||||
if (glyph.left >= 64) {
|
||||
glyph.left -= 128;
|
||||
}
|
||||
|
||||
glyph.top = getBits(7, fontdata, charPtr);
|
||||
charPtr += 7;
|
||||
glyph.top = consumeBits(7, fontdata, charPtr);
|
||||
if (glyph.top >= 64) {
|
||||
glyph.top -= 128;
|
||||
}
|
||||
|
||||
glyph.flags = getBits(6, fontdata, charPtr);
|
||||
charPtr += 6;
|
||||
glyph.flags = consumeBits(6, fontdata, charPtr);
|
||||
|
||||
if (glyph.flags & FONT_PGF_CHARGLYPH) {
|
||||
// Skip magic number
|
||||
charPtr += 7;
|
||||
if (glyphType == FONT_PGF_CHARGLYPH) {
|
||||
glyph.shadowFlags = consumeBits(2, fontdata, charPtr) << (2 + 3);
|
||||
glyph.shadowFlags |= consumeBits(2, fontdata, charPtr) << 3;
|
||||
glyph.shadowFlags |= consumeBits(3, fontdata, charPtr);
|
||||
|
||||
glyph.shadowID = getBits(9, fontdata, charPtr);
|
||||
charPtr += 9;
|
||||
glyph.shadowID = consumeBits(9, fontdata, charPtr);
|
||||
|
||||
if ((glyph.flags & FONT_PGF_METRIC_DIMENSION_INDEX) == FONT_PGF_METRIC_DIMENSION_INDEX)
|
||||
{
|
||||
int dimensionIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
int dimensionIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (dimensionIndex < header.dimTableLength) {
|
||||
glyph.dimensionWidth = dimensionTable[0][dimensionIndex];
|
||||
|
@ -360,16 +424,13 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
}
|
||||
else
|
||||
{
|
||||
glyph.dimensionWidth = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.dimensionHeight = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.dimensionWidth = consumeBits(32, fontdata, charPtr);
|
||||
glyph.dimensionHeight = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
|
||||
if ((glyph.flags & FONT_PGF_METRIC_BEARING_X_INDEX) == FONT_PGF_METRIC_BEARING_X_INDEX)
|
||||
{
|
||||
int xAdjustIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
int xAdjustIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (xAdjustIndex < header.xAdjustTableLength) {
|
||||
glyph.xAdjustH = xAdjustTable[0][xAdjustIndex];
|
||||
|
@ -386,16 +447,13 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
}
|
||||
else
|
||||
{
|
||||
glyph.xAdjustH = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.xAdjustV = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.xAdjustH = consumeBits(32, fontdata, charPtr);
|
||||
glyph.xAdjustV = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
|
||||
if ((glyph.flags & FONT_PGF_METRIC_BEARING_Y_INDEX) == FONT_PGF_METRIC_BEARING_Y_INDEX)
|
||||
{
|
||||
int yAdjustIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
int yAdjustIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (yAdjustIndex < header.xAdjustTableLength) {
|
||||
glyph.yAdjustH = yAdjustTable[0][yAdjustIndex];
|
||||
|
@ -412,18 +470,23 @@ bool PGF::GetGlyph(const u8 *fontdata, size_t charPtr, int glyphType, Glyph &gly
|
|||
}
|
||||
else
|
||||
{
|
||||
glyph.yAdjustH = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.yAdjustV = getBits(32, fontdata, charPtr);
|
||||
charPtr += 32;
|
||||
glyph.yAdjustH = consumeBits(32, fontdata, charPtr);
|
||||
glyph.yAdjustV = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
|
||||
int advanceIndex = getBits(8, fontdata, charPtr);
|
||||
charPtr += 8;
|
||||
if ((glyph.flags & FONT_PGF_METRIC_ADVANCE_INDEX) == FONT_PGF_METRIC_ADVANCE_INDEX)
|
||||
{
|
||||
int advanceIndex = consumeBits(8, fontdata, charPtr);
|
||||
|
||||
if (advanceIndex < header.advanceTableLength) {
|
||||
glyph.advanceH = advanceTable[0][advanceIndex];
|
||||
glyph.advanceV = advanceTable[1][advanceIndex];
|
||||
if (advanceIndex < header.advanceTableLength) {
|
||||
glyph.advanceH = advanceTable[0][advanceIndex];
|
||||
glyph.advanceV = advanceTable[1][advanceIndex];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph.advanceH = consumeBits(32, fontdata, charPtr);
|
||||
glyph.advanceV = consumeBits(32, fontdata, charPtr);
|
||||
}
|
||||
} else {
|
||||
glyph.shadowID = 65535;
|
||||
|
@ -453,7 +516,7 @@ bool PGF::GetCharGlyph(int charCode, int glyphType, Glyph &glyph) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType, bool packagedFont) {
|
||||
void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType) {
|
||||
Glyph glyph;
|
||||
if (!GetCharGlyph(charCode, glyphType, glyph)) {
|
||||
// No Glyph available for this charCode, try to use the alternate char.
|
||||
|
@ -472,7 +535,7 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW
|
|||
return;
|
||||
}
|
||||
|
||||
u32 bitPtr = glyph.ptr * 8;
|
||||
size_t bitPtr = glyph.ptr * 8;
|
||||
int numberPixels = glyph.w * glyph.h;
|
||||
int pixelIndex = 0;
|
||||
|
||||
|
@ -481,14 +544,12 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW
|
|||
|
||||
while (pixelIndex < numberPixels && bitPtr + 8 < fontDataSize * 8) {
|
||||
// This is some kind of nibble based RLE compression.
|
||||
int nibble = getBits(4, fontData, bitPtr);
|
||||
bitPtr += 4;
|
||||
int nibble = consumeBits(4, fontData, bitPtr);
|
||||
|
||||
int count;
|
||||
int value = 0;
|
||||
if (nibble < 8) {
|
||||
value = getBits(4, fontData, bitPtr);
|
||||
bitPtr += 4;
|
||||
value = consumeBits(4, fontData, bitPtr);
|
||||
count = nibble + 1;
|
||||
} else {
|
||||
count = 16 - nibble;
|
||||
|
@ -496,8 +557,7 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW
|
|||
|
||||
for (int i = 0; i < count && pixelIndex < numberPixels; i++) {
|
||||
if (nibble >= 8) {
|
||||
value = getBits(4, fontData, bitPtr);
|
||||
bitPtr += 4;
|
||||
value = consumeBits(4, fontData, bitPtr);
|
||||
}
|
||||
|
||||
int xx, yy;
|
||||
|
@ -512,10 +572,6 @@ void PGF::DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipW
|
|||
int pixelX = x + xx;
|
||||
int pixelY = y + yy;
|
||||
|
||||
// Apply offset by 1px for our packaged PSP fonts
|
||||
if (packagedFont)
|
||||
pixelX += 1;
|
||||
|
||||
if (pixelX >= clipX && pixelX < clipX + clipWidth && pixelY >= clipY && pixelY < clipY + clipHeight) {
|
||||
// 4-bit color value
|
||||
int pixelColor = value;
|
||||
|
|
|
@ -39,6 +39,7 @@ enum {
|
|||
FONT_PGF_METRIC_DIMENSION_INDEX = 0x04,
|
||||
FONT_PGF_METRIC_BEARING_X_INDEX = 0x08,
|
||||
FONT_PGF_METRIC_BEARING_Y_INDEX = 0x10,
|
||||
FONT_PGF_METRIC_ADVANCE_INDEX = 0x20,
|
||||
FONT_PGF_CHARGLYPH = 0x20,
|
||||
FONT_PGF_SHADOWGLYPH = 0x40,
|
||||
};
|
||||
|
@ -93,13 +94,12 @@ struct PGFFontStyle {
|
|||
|
||||
|
||||
struct Glyph {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
int left;
|
||||
int top;
|
||||
int flags;
|
||||
int shadowFlags;
|
||||
int shadowID;
|
||||
int advanceH;
|
||||
int advanceV;
|
||||
|
@ -142,6 +142,7 @@ struct PGFHeader
|
|||
s32_le charMapBpe;
|
||||
s32_le charPointerBpe;
|
||||
|
||||
// TODO: This has values in it (0404)...
|
||||
u8 pad1[2];
|
||||
u8 bpp;
|
||||
u8 pad2[1];
|
||||
|
@ -159,6 +160,7 @@ struct PGFHeader
|
|||
u16_le firstGlyph;
|
||||
u16_le lastGlyph;
|
||||
|
||||
// TODO: This has a few 01s in it in the official fonts.
|
||||
u8 pad5[26];
|
||||
|
||||
s32_le maxAscender;
|
||||
|
@ -211,7 +213,8 @@ struct PGFCharInfo {
|
|||
s32_le sfp26BearingVY;
|
||||
s32_le sfp26AdvanceH;
|
||||
s32_le sfp26AdvanceV;
|
||||
u8 pad[4];
|
||||
s16_le shadowFlags;
|
||||
s16_le shadowId;
|
||||
};
|
||||
|
||||
struct PGFFontInfo {
|
||||
|
@ -242,13 +245,14 @@ struct PGFFontInfo {
|
|||
// Bitmap dimensions.
|
||||
s16_le maxGlyphWidth;
|
||||
s16_le maxGlyphHeight;
|
||||
s32_le charMapLength; // Number of elements in the font's charmap.
|
||||
s32_le numGlyphs;
|
||||
s32_le shadowMapLength; // Number of elements in the font's shadow charmap.
|
||||
|
||||
// Font style (used by font comparison functions).
|
||||
PGFFontStyle fontStyle;
|
||||
|
||||
s32_le BPP; // Font's BPP.
|
||||
u8 BPP; // Font's BPP.
|
||||
u8 pad[3];
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
@ -260,9 +264,9 @@ public:
|
|||
|
||||
void ReadPtr(const u8 *ptr, size_t dataSize);
|
||||
|
||||
bool GetCharInfo(int charCode, PGFCharInfo *ci);
|
||||
bool GetCharInfo(int charCode, PGFCharInfo *ci, int altCharCode);
|
||||
void GetFontInfo(PGFFontInfo *fi);
|
||||
void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType, bool packagedFont);
|
||||
void DrawCharacter(const GlyphImage *image, int clipX, int clipY, int clipWidth, int clipHeight, int charCode, int altCharCode, int glyphType);
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
||||
|
|
|
@ -806,3 +806,13 @@ template <int func(int, const char *, int)> void WrapI_ICI() {
|
|||
int retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){
|
||||
u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){
|
||||
u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "../Config.h"
|
||||
#include "ChunkFile.h"
|
||||
#include "FixedSizeQueue.h"
|
||||
#include "Common/Thread.h"
|
||||
#include "Common/Atomics.h"
|
||||
#include "../../native/base/mutex.h"
|
||||
|
||||
|
|
710
Core/HLE/proAdhoc.cpp
Normal file
710
Core/HLE/proAdhoc.cpp
Normal file
|
@ -0,0 +1,710 @@
|
|||
// TODO: Add license
|
||||
|
||||
#include "util/text/parsers.h"
|
||||
#include "proAdhoc.h"
|
||||
|
||||
uint32_t fakePoolSize = 0;
|
||||
SceNetAdhocMatchingContext * contexts = NULL;
|
||||
int one = 1;
|
||||
bool friendFinderRunning = false;
|
||||
SceNetAdhocctlPeerInfo * friends = NULL;
|
||||
SceNetAdhocctlScanInfo * networks = NULL;
|
||||
int eventHandlerUpdate = -1;
|
||||
int threadStatus = ADHOCCTL_STATE_DISCONNECTED;
|
||||
|
||||
int metasocket;
|
||||
SceNetAdhocctlParameter parameter;
|
||||
std::thread friendFinderThread;
|
||||
recursive_mutex peerlock;
|
||||
SceNetAdhocPdpStat * pdp[255];
|
||||
SceNetAdhocPtpStat * ptp[255];
|
||||
|
||||
int isLocalMAC(const SceNetEtherAddr * addr) {
|
||||
SceNetEtherAddr saddr;
|
||||
getLocalMac(&saddr);
|
||||
|
||||
// Compare MAC Addresses
|
||||
int match = memcmp((const void *)addr, (const void *)&saddr, ETHER_ADDR_LEN);
|
||||
|
||||
// Return Result
|
||||
return (match == 0);
|
||||
}
|
||||
|
||||
int isPDPPortInUse(uint16_t port) {
|
||||
// Iterate Elements
|
||||
int i = 0; for(; i < 255; i++) if(pdp[i] != NULL && pdp[i]->lport == port) return 1;
|
||||
|
||||
// Unused Port
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isPTPPortInUse(uint16_t port) {
|
||||
// Iterate Sockets
|
||||
int i = 0; for(; i < 255; i++) if(ptp[i] != NULL && ptp[i]->lport == port) return 1;
|
||||
|
||||
// Unused Port
|
||||
return 0;
|
||||
}
|
||||
|
||||
void addFriend(SceNetAdhocctlConnectPacketS2C * packet) {
|
||||
// Allocate Structure
|
||||
SceNetAdhocctlPeerInfo * peer = (SceNetAdhocctlPeerInfo *)malloc(sizeof(SceNetAdhocctlPeerInfo));
|
||||
// Allocated Structure
|
||||
if(peer != NULL) {
|
||||
// Clear Memory
|
||||
memset(peer, 0, sizeof(SceNetAdhocctlPeerInfo));
|
||||
|
||||
// Link to existing Peers
|
||||
peer->next = friends;
|
||||
|
||||
// Save Nickname
|
||||
peer->nickname = packet->name;
|
||||
|
||||
// Save MAC Address
|
||||
peer->mac_addr = packet->mac;
|
||||
|
||||
// Save IP Address
|
||||
peer->ip_addr = packet->ip;
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Link into Peerlist
|
||||
friends = peer;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void changeBlockingMode(int fd, int nonblocking) {
|
||||
unsigned long on = 1;
|
||||
unsigned long off = 0;
|
||||
#ifdef _MSC_VER
|
||||
if(nonblocking){
|
||||
// Change to Non-Blocking Mode
|
||||
ioctlsocket(fd,FIONBIO,&on);
|
||||
}else {
|
||||
// Change to Blocking Mode
|
||||
ioctlsocket(fd, FIONBIO, &off);
|
||||
}
|
||||
#else
|
||||
if(nonblocking == 1) fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
else {
|
||||
// Get Flags
|
||||
int flags = fcntl(fd, F_GETFL);
|
||||
// Remove Non-Blocking Flag
|
||||
fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int countAvailableNetworks(void) {
|
||||
// Network Count
|
||||
int count = 0;
|
||||
|
||||
// Group Reference
|
||||
SceNetAdhocctlScanInfo * group = networks;
|
||||
|
||||
// Count Groups
|
||||
for(; group != NULL; group = group->next) count++;
|
||||
|
||||
// Return Network Count
|
||||
return count;
|
||||
}
|
||||
|
||||
void deleteAllPDP(void) {
|
||||
// Iterate Element
|
||||
int i = 0; for(; i < 255; i++) {
|
||||
// Active Socket
|
||||
if(pdp[i] != NULL) {
|
||||
// Close Socket
|
||||
closesocket(pdp[i]->id);
|
||||
|
||||
// Free Memory
|
||||
free(pdp[i]);
|
||||
|
||||
// Delete Reference
|
||||
pdp[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteAllPTP(void) {
|
||||
// Iterate Element
|
||||
int i = 0; for(; i < 255; i++) {
|
||||
// Active Socket
|
||||
if(ptp[i] != NULL) {
|
||||
// Close Socket
|
||||
closesocket(ptp[i]->id);
|
||||
|
||||
// Free Memory
|
||||
free(ptp[i]);
|
||||
|
||||
// Delete Reference
|
||||
ptp[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteFriendByIP(uint32_t ip) {
|
||||
// Previous Peer Reference
|
||||
SceNetAdhocctlPeerInfo * prev = NULL;
|
||||
|
||||
// Peer Pointer
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Found Peer
|
||||
if(peer->ip_addr == ip) {
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Unlink Left (Beginning)
|
||||
if(prev == NULL)friends = peer->next;
|
||||
|
||||
// Unlink Left (Other)
|
||||
else prev->next = peer->next;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Free Memory
|
||||
free(peer);
|
||||
|
||||
// Stop Search
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Previous Reference
|
||||
prev = peer;
|
||||
}
|
||||
}
|
||||
|
||||
int findFreeMatchingID(void) {
|
||||
// Minimum Matching ID
|
||||
int min = 1;
|
||||
|
||||
// Maximum Matching ID
|
||||
int max = 0;
|
||||
|
||||
// Find highest Matching ID
|
||||
SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) {
|
||||
// New Maximum
|
||||
if(max < item->id) max = item->id;
|
||||
}
|
||||
|
||||
// Find unoccupied ID
|
||||
int i = min; for(; i < max; i++) {
|
||||
// Found unoccupied ID
|
||||
if(findMatchingContext(i) == NULL) return i;
|
||||
}
|
||||
|
||||
// Append at virtual end
|
||||
return max + 1;
|
||||
}
|
||||
|
||||
SceNetAdhocMatchingContext * findMatchingContext(int id) {
|
||||
// Iterate Matching Context List
|
||||
SceNetAdhocMatchingContext * item = contexts; for(; item != NULL; item = item->next) { // Found Matching ID
|
||||
if(item->id == id) return item;
|
||||
}
|
||||
|
||||
// Context not found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node) {
|
||||
// End of List
|
||||
if(node == NULL) return;
|
||||
|
||||
// Increase Recursion Depth
|
||||
freeFriendsRecursive(node->next);
|
||||
|
||||
// Free Memory
|
||||
free(node);
|
||||
}
|
||||
|
||||
int friendFinder(){
|
||||
// Receive Buffer
|
||||
int rxpos = 0;
|
||||
uint8_t rx[1024];
|
||||
|
||||
// Chat Packet
|
||||
SceNetAdhocctlChatPacketC2S chat;
|
||||
chat.base.opcode = OPCODE_CHAT;
|
||||
|
||||
// Last Ping Time
|
||||
uint64_t lastping = 0;
|
||||
|
||||
// Last Time Reception got updated
|
||||
uint64_t lastreceptionupdate = 0;
|
||||
|
||||
uint64_t now;
|
||||
|
||||
// Finder Loop
|
||||
while(friendFinderRunning) {
|
||||
// Acquire Network Lock
|
||||
//_acquireNetworkLock();
|
||||
|
||||
// Ping Server
|
||||
now = real_time_now()*1000.0;
|
||||
if(now - lastping >= 100) {
|
||||
// Update Ping Time
|
||||
lastping = now;
|
||||
|
||||
// Prepare Packet
|
||||
uint8_t opcode = OPCODE_PING;
|
||||
|
||||
// Send Ping to Server
|
||||
send(metasocket, (const char *)&opcode, 1,0);
|
||||
}
|
||||
|
||||
// Send Chat Messages
|
||||
//while(popFromOutbox(chat.message))
|
||||
//{
|
||||
// // Send Chat to Server
|
||||
// sceNetInetSend(metasocket, (const char *)&chat, sizeof(chat), 0);
|
||||
//}
|
||||
|
||||
// Wait for Incoming Data
|
||||
int received = recv(metasocket, (char *)(rx + rxpos), sizeof(rx) - rxpos,0);
|
||||
|
||||
// Free Network Lock
|
||||
//_freeNetworkLock();
|
||||
|
||||
// Received Data
|
||||
if(received > 0) {
|
||||
// Fix Position
|
||||
rxpos += received;
|
||||
|
||||
// Log Incoming Traffic
|
||||
//printf("Received %d Bytes of Data from Server\n", received);
|
||||
INFO_LOG(SCENET, "Received %d Bytes of Data from Adhoc Server", received);
|
||||
}
|
||||
|
||||
// Handle Packets
|
||||
if(rxpos > 0) {
|
||||
// BSSID Packet
|
||||
if(rx[0] == OPCODE_CONNECT_BSSID) {
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlConnectBSSIDPacketS2C)) {
|
||||
// Cast Packet
|
||||
SceNetAdhocctlConnectBSSIDPacketS2C * packet = (SceNetAdhocctlConnectBSSIDPacketS2C *)rx;
|
||||
// Update BSSID
|
||||
parameter.bssid.mac_addr = packet->mac;
|
||||
// Change State
|
||||
threadStatus = ADHOCCTL_STATE_CONNECTED;
|
||||
// Notify Event Handlers
|
||||
CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate, join32(ADHOCCTL_EVENT_CONNECT, 0));
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlConnectBSSIDPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectBSSIDPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlConnectBSSIDPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Chat Packet
|
||||
else if(rx[0] == OPCODE_CHAT) {
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlChatPacketS2C)) {
|
||||
// Cast Packet
|
||||
SceNetAdhocctlChatPacketS2C * packet = (SceNetAdhocctlChatPacketS2C *)rx;
|
||||
|
||||
// Fix for Idiots that try to troll the "ME" Nametag
|
||||
if(strcasecmp((char *)packet->name.data, "ME") == 0) strcpy((char *)packet->name.data, "NOT ME");
|
||||
|
||||
// Add Incoming Chat to HUD
|
||||
//printf("Receive chat message %s", packet->base.message);
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlChatPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlChatPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlChatPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Connect Packet
|
||||
else if(rx[0] == OPCODE_CONNECT) {
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlConnectPacketS2C)) {
|
||||
// Log Incoming Peer
|
||||
INFO_LOG(SCENET,"Incoming Peer Data...");
|
||||
|
||||
// Cast Packet
|
||||
SceNetAdhocctlConnectPacketS2C * packet = (SceNetAdhocctlConnectPacketS2C *)rx;
|
||||
|
||||
// Add User
|
||||
addFriend(packet);
|
||||
|
||||
// Update HUD User Count
|
||||
#ifdef LOCALHOST_AS_PEER
|
||||
setUserCount(getActivePeerCount());
|
||||
#else
|
||||
// setUserCount(getActivePeerCount()+1);
|
||||
#endif
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlConnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlConnectPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlConnectPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Disconnect Packet
|
||||
else if(rx[0] == OPCODE_DISCONNECT) {
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlDisconnectPacketS2C)) {
|
||||
// Log Incoming Peer Delete Request
|
||||
INFO_LOG(SCENET,"FriendFinder: Incoming Peer Data Delete Request...");
|
||||
|
||||
// Cast Packet
|
||||
SceNetAdhocctlDisconnectPacketS2C * packet = (SceNetAdhocctlDisconnectPacketS2C *)rx;
|
||||
|
||||
// Delete User by IP
|
||||
deleteFriendByIP(packet->ip);
|
||||
|
||||
// Update HUD User Count
|
||||
#ifdef LOCALHOST_AS_PEER
|
||||
setUserCount(_getActivePeerCount());
|
||||
#else
|
||||
//setUserCount(_getActivePeerCount()+1);
|
||||
#endif
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlDisconnectPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlDisconnectPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlDisconnectPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Packet
|
||||
else if(rx[0] == OPCODE_SCAN) {
|
||||
// Enough Data available
|
||||
if(rxpos >= (int)sizeof(SceNetAdhocctlScanPacketS2C)) {
|
||||
// Log Incoming Network Information
|
||||
INFO_LOG(SCENET,"Incoming Group Information...");
|
||||
// Cast Packet
|
||||
SceNetAdhocctlScanPacketS2C * packet = (SceNetAdhocctlScanPacketS2C *)rx;
|
||||
|
||||
// Allocate Structure Data
|
||||
SceNetAdhocctlScanInfo * group = (SceNetAdhocctlScanInfo *)malloc(sizeof(SceNetAdhocctlScanInfo));
|
||||
|
||||
// Allocated Structure Data
|
||||
if(group != NULL)
|
||||
{
|
||||
// Clear Memory
|
||||
memset(group, 0, sizeof(SceNetAdhocctlScanInfo));
|
||||
|
||||
// Link to existing Groups
|
||||
group->next = networks;
|
||||
|
||||
// Copy Group Name
|
||||
group->group_name = packet->group;
|
||||
|
||||
// Set Group Host
|
||||
group->bssid.mac_addr = packet->mac;
|
||||
|
||||
// Link into Group List
|
||||
networks = group;
|
||||
}
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + sizeof(SceNetAdhocctlScanPacketS2C), sizeof(rx) - sizeof(SceNetAdhocctlScanPacketS2C));
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= sizeof(SceNetAdhocctlScanPacketS2C);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan Complete Packet
|
||||
else if(rx[0] == OPCODE_SCAN_COMPLETE) {
|
||||
// Log Scan Completion
|
||||
INFO_LOG(SCENET,"FriendFinder: Incoming Scan complete response...");
|
||||
|
||||
// Change State
|
||||
threadStatus = ADHOCCTL_STATE_DISCONNECTED;
|
||||
|
||||
// Notify Event Handlers
|
||||
CoreTiming::ScheduleEvent_Threadsafe_Immediate(eventHandlerUpdate,join32(ADHOCCTL_EVENT_SCAN, 0));
|
||||
//int i = 0; for(; i < ADHOCCTL_MAX_HANDLER; i++)
|
||||
//{
|
||||
// // Active Handler
|
||||
// if(_event_handler[i] != NULL) _event_handler[i](ADHOCCTL_EVENT_SCAN, 0, _event_args[i]);
|
||||
//}
|
||||
|
||||
// Move RX Buffer
|
||||
memmove(rx, rx + 1, sizeof(rx) - 1);
|
||||
|
||||
// Fix RX Buffer Length
|
||||
rxpos -= 1;
|
||||
}
|
||||
}
|
||||
// Original value was 10 ms, I think 100 is just fine
|
||||
sleep_ms(100);
|
||||
}
|
||||
|
||||
// Log Shutdown
|
||||
INFO_LOG(SCENET, "FriendFinder: End of Friend Finder Thread");
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getActivePeerCount(void) {
|
||||
// Counter
|
||||
int count = 0;
|
||||
|
||||
// #ifdef LOCALHOST_AS_PEER
|
||||
// // Increase for Localhost
|
||||
// count++;
|
||||
// #endif
|
||||
|
||||
// Peer Reference
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Increase Counter
|
||||
count++;
|
||||
}
|
||||
|
||||
// Return Result
|
||||
return count;
|
||||
}
|
||||
|
||||
int getLocalIp(sockaddr_in * SocketAddress){
|
||||
#ifdef _MSC_VER
|
||||
// Get local host name
|
||||
char szHostName[128] = "";
|
||||
|
||||
if(::gethostname(szHostName, sizeof(szHostName))) {
|
||||
// Error handling
|
||||
}
|
||||
// Get local IP addresses
|
||||
struct hostent *pHost = 0;
|
||||
pHost = ::gethostbyname(szHostName);
|
||||
if(pHost) {
|
||||
memcpy(&SocketAddress->sin_addr, pHost->h_addr_list[0], pHost->h_length);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
#else
|
||||
SocketAddress->sin_addr.s_addr = inet_addr("192.168.12.1");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void getLocalMac(SceNetEtherAddr * addr){
|
||||
// Read MAC Address from config
|
||||
uint8_t mac[ETHER_ADDR_LEN] = {0};
|
||||
if (!ParseMacAddress(g_Config.localMacAddress.c_str(), mac)) {
|
||||
ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.localMacAddress.c_str());
|
||||
}
|
||||
memcpy(addr, mac, ETHER_ADDR_LEN);
|
||||
}
|
||||
|
||||
int getPTPSocketCount(void) {
|
||||
// Socket Counter
|
||||
int counter = 0;
|
||||
|
||||
// Count Sockets
|
||||
int i = 0; for(; i < 255; i++) if(ptp[i] != NULL) counter++;
|
||||
|
||||
// Return Socket Count
|
||||
return counter;
|
||||
}
|
||||
|
||||
int initNetwork(SceNetAdhocctlAdhocId *adhoc_id){
|
||||
int iResult = 0;
|
||||
#ifdef _MSC_VER
|
||||
WSADATA data;
|
||||
iResult = WSAStartup(MAKEWORD(2,2),&data);
|
||||
if(iResult != NOERROR){
|
||||
ERROR_LOG(SCENET, "Wsa failed");
|
||||
return iResult;
|
||||
}
|
||||
#endif
|
||||
metasocket = (int)INVALID_SOCKET;
|
||||
metasocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
|
||||
if(metasocket == INVALID_SOCKET){
|
||||
ERROR_LOG(SCENET,"invalid socket");
|
||||
return -1;
|
||||
}
|
||||
struct sockaddr_in server_addr;
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(27312); // Maybe read this from config too
|
||||
|
||||
// Resolve dns
|
||||
addrinfo * resultAddr;
|
||||
addrinfo * ptr;
|
||||
in_addr serverIp;
|
||||
iResult = getaddrinfo(g_Config.proAdhocServer.c_str(),0,NULL,&resultAddr);
|
||||
if(iResult != 0){
|
||||
ERROR_LOG(SCENET, "Dns error\n");
|
||||
return iResult;
|
||||
}
|
||||
for(ptr = resultAddr; ptr != NULL; ptr = ptr->ai_next){
|
||||
switch(ptr->ai_family){
|
||||
case AF_INET:
|
||||
serverIp = ((sockaddr_in *)ptr->ai_addr)->sin_addr;
|
||||
}
|
||||
}
|
||||
server_addr.sin_addr = serverIp;
|
||||
iResult = connect(metasocket,(sockaddr *)&server_addr,sizeof(server_addr));
|
||||
if(iResult == SOCKET_ERROR){
|
||||
ERROR_LOG(SCENET,"Socket error");
|
||||
return iResult;
|
||||
}
|
||||
memset(¶meter,0,sizeof(parameter));
|
||||
strcpy((char *)¶meter.nickname.data, g_Config.sNickName.c_str());
|
||||
parameter.channel = 1; // Fake Channel 1
|
||||
|
||||
// Prepare Login Packet
|
||||
getLocalMac(¶meter.bssid.mac_addr);
|
||||
SceNetAdhocctlLoginPacketC2S packet;
|
||||
packet.base.opcode = OPCODE_LOGIN;
|
||||
SceNetEtherAddr addres;
|
||||
getLocalMac(&addres);
|
||||
packet.mac = addres;
|
||||
strcpy((char *)packet.name.data, g_Config.sNickName.c_str());
|
||||
memcpy(packet.game.data, adhoc_id->data, ADHOCCTL_ADHOCID_LEN);
|
||||
int sent = send(metasocket, (char*)&packet, sizeof(packet), 0);
|
||||
changeBlockingMode(metasocket,1); // Change to non-blocking
|
||||
if(sent > 0){
|
||||
return 0;
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int isBroadcastMAC(const SceNetEtherAddr * addr) {
|
||||
// Broadcast MAC
|
||||
if(memcmp(addr->data, "\xFF\xFF\xFF\xFF\xFF\xFF", ETHER_ADDR_LEN) == 0) return 1;
|
||||
// Normal MAC
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resolveIP(uint32_t ip, SceNetEtherAddr * mac) {
|
||||
sockaddr_in addr;
|
||||
getLocalIp(&addr);
|
||||
uint32 localIp = addr.sin_addr.s_addr;
|
||||
|
||||
if(ip == localIp){
|
||||
getLocalMac(mac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Peer Reference
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Found Matching Peer
|
||||
if(peer->ip_addr == ip) {
|
||||
// Copy Data
|
||||
*mac = peer->mac_addr;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Peer not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip) {
|
||||
// Get Local MAC Address
|
||||
SceNetEtherAddr localMac;
|
||||
getLocalMac(&localMac);
|
||||
// Local MAC Requested
|
||||
if(memcmp(&localMac, mac, sizeof(SceNetEtherAddr)) == 0) {
|
||||
// Get Local IP Address
|
||||
sockaddr_in sockAddr;
|
||||
getLocalIp(&sockAddr);
|
||||
*ip = sockAddr.sin_addr.s_addr;
|
||||
return 0; // return succes
|
||||
}
|
||||
|
||||
// Multithreading Lock
|
||||
peerlock.lock();
|
||||
|
||||
// Peer Reference
|
||||
SceNetAdhocctlPeerInfo * peer = friends;
|
||||
|
||||
// Iterate Peers
|
||||
for(; peer != NULL; peer = peer->next) {
|
||||
// Found Matching Peer
|
||||
if(memcmp(&peer->mac_addr, mac, sizeof(SceNetEtherAddr)) == 0) {
|
||||
// Copy Data
|
||||
*ip = peer->ip_addr;
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Return Success
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Multithreading Unlock
|
||||
peerlock.unlock();
|
||||
|
||||
// Peer not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
int validNetworkName(const SceNetAdhocctlGroupName * group_name) {
|
||||
// Result
|
||||
int valid = 1;
|
||||
|
||||
// Name given
|
||||
if(group_name != NULL) {
|
||||
// Iterate Name Characters
|
||||
int i = 0; for(; i < ADHOCCTL_GROUPNAME_LEN && valid; i++) {
|
||||
// End of Name
|
||||
if(group_name->data[i] == 0) break;
|
||||
|
||||
// Not a digit
|
||||
if(group_name->data[i] < '0' || group_name->data[i] > '9') {
|
||||
// Not 'A' to 'Z'
|
||||
if(group_name->data[i] < 'A' || group_name->data[i] > 'Z') {
|
||||
// Not 'a' to 'z'
|
||||
if(group_name->data[i] < 'a' || group_name->data[i] > 'z') {
|
||||
// Invalid Name
|
||||
valid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return Result
|
||||
return valid;
|
||||
}
|
||||
|
||||
u64 join32(u32 num1, u32 num2){
|
||||
return (u64)num2 << 32 | num1;
|
||||
}
|
||||
|
||||
void split64(u64 num, int buff[]){
|
||||
int num1 = (int)(num&firstMask);
|
||||
int num2 = (int)((num&secondMask)>>32);
|
||||
buff[0] = num1;
|
||||
buff[1] = num2;
|
||||
}
|
594
Core/HLE/proAdhoc.h
Normal file
594
Core/HLE/proAdhoc.h
Normal file
|
@ -0,0 +1,594 @@
|
|||
#pragma once
|
||||
|
||||
#include "base/timeutil.h"
|
||||
#include "base/mutex.h"
|
||||
#include "thread/thread.h"
|
||||
#include "net/resolve.h"
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HLE/sceNetAdhoc.h"
|
||||
#include "Core/HLE/sceKernel.h"
|
||||
#include "Core/HLE/sceKernelThread.h"
|
||||
#include "Core/HLE/sceKernelMutex.h"
|
||||
#include "Core/HLE/sceUtility.h"
|
||||
|
||||
// Net stuff
|
||||
#ifdef _MSC_VER
|
||||
#include <WS2tcpip.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
#define PACK
|
||||
#undef errno
|
||||
#undef EAGAIN
|
||||
#undef EINPROGRESS
|
||||
#undef EISCONN
|
||||
#define errno WSAGetLastError()
|
||||
#define EAGAIN WSAEWOULDBLOCK
|
||||
#define EINPROGRESS WSAEWOULDBLOCK
|
||||
#define EISCONN WSAEISCONN
|
||||
#else
|
||||
#define INVALID_SOCKET -1
|
||||
#define SOCKET_ERROR -1
|
||||
#define closesocket close
|
||||
#define PACK __attribute__((packed))
|
||||
#endif
|
||||
|
||||
// psp strutcs and definitions
|
||||
#define ADHOCCTL_MODE_ADHOC 0
|
||||
#define ADHOCCTL_MODE_GAMEMODE 1
|
||||
|
||||
// Event Types for Event Handler
|
||||
#define ADHOCCTL_EVENT_CONNECT 1
|
||||
#define ADHOCCTL_EVENT_DISCONNECT 2
|
||||
#define ADHOCCTL_EVENT_SCAN 3
|
||||
|
||||
// Internal Thread States
|
||||
#define ADHOCCTL_STATE_DISCONNECTED 0
|
||||
#define ADHOCCTL_STATE_CONNECTED 1
|
||||
#define ADHOCCTL_STATE_SCANNING 2
|
||||
#define ADHOCCTL_STATE_GAMEMODE 3
|
||||
|
||||
// Kernel Utility Netconf Adhoc Types
|
||||
#define UTILITY_NETCONF_TYPE_CONNECT_ADHOC 2
|
||||
#define UTILITY_NETCONF_TYPE_CREATE_ADHOC 4
|
||||
#define UTILITY_NETCONF_TYPE_JOIN_ADHOC 5
|
||||
|
||||
// Kernel Utility States
|
||||
#define UTILITY_NETCONF_STATUS_NONE 0
|
||||
#define UTILITY_NETCONF_STATUS_INITIALIZE 1
|
||||
#define UTILITY_NETCONF_STATUS_RUNNING 2
|
||||
#define UTILITY_NETCONF_STATUS_FINISHED 3
|
||||
#define UTILITY_NETCONF_STATUS_SHUTDOWN 4
|
||||
|
||||
// PTP Connection States
|
||||
#define PTP_STATE_CLOSED 0
|
||||
#define PTP_STATE_LISTEN 1
|
||||
#define PTP_STATE_ESTABLISHED 4
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
// Ethernet Address
|
||||
#define ETHER_ADDR_LEN 6
|
||||
typedef struct SceNetEtherAddr {
|
||||
uint8_t data[ETHER_ADDR_LEN];
|
||||
} PACK SceNetEtherAddr;
|
||||
|
||||
|
||||
// Adhoc Virtual Network Name
|
||||
#define ADHOCCTL_GROUPNAME_LEN 8
|
||||
typedef struct SceNetAdhocctlGroupName {
|
||||
uint8_t data[ADHOCCTL_GROUPNAME_LEN];
|
||||
} PACK SceNetAdhocctlGroupName;
|
||||
|
||||
// Virtual Network Host Information
|
||||
typedef struct SceNetAdhocctlBSSId {
|
||||
SceNetEtherAddr mac_addr;
|
||||
uint8_t padding[2];
|
||||
} PACK SceNetAdhocctlBSSId;
|
||||
|
||||
// Virtual Network Information
|
||||
typedef struct SceNetAdhocctlScanInfo {
|
||||
struct SceNetAdhocctlScanInfo * next;
|
||||
s32_le channel;
|
||||
SceNetAdhocctlGroupName group_name;
|
||||
SceNetAdhocctlBSSId bssid;
|
||||
s32_le mode;
|
||||
} PACK SceNetAdhocctlScanInfo;
|
||||
|
||||
// Player Nickname
|
||||
#define ADHOCCTL_NICKNAME_LEN 128
|
||||
typedef struct SceNetAdhocctlNickname {
|
||||
uint8_t data[ADHOCCTL_NICKNAME_LEN];
|
||||
} PACK SceNetAdhocctlNickname;
|
||||
|
||||
// Active Virtual Network Information
|
||||
typedef struct SceNetAdhocctlParameter {
|
||||
s32_le channel;
|
||||
SceNetAdhocctlGroupName group_name;
|
||||
SceNetAdhocctlBSSId bssid;
|
||||
SceNetAdhocctlNickname nickname;
|
||||
} PACK SceNetAdhocctlParameter;
|
||||
|
||||
// Peer Information
|
||||
typedef struct SceNetAdhocctlPeerInfo {
|
||||
SceNetAdhocctlPeerInfo * next;
|
||||
SceNetAdhocctlNickname nickname;
|
||||
SceNetEtherAddr mac_addr;
|
||||
u32_le ip_addr;
|
||||
uint8_t padding[2];
|
||||
u64_le last_recv;
|
||||
} PACK SceNetAdhocctlPeerInfo;
|
||||
|
||||
// Peer Information with u32 pointers
|
||||
typedef struct SceNetAdhocctlPeerInfoEmu {
|
||||
u32_le next; // Changed the pointer to u32
|
||||
SceNetAdhocctlNickname nickname;
|
||||
SceNetEtherAddr mac_addr;
|
||||
u32_le ip_addr;
|
||||
u32 padding; // Changed the pointer to u32
|
||||
u64_le last_recv;
|
||||
} SceNetAdhocctlPeerInfoEmu;
|
||||
|
||||
// Game Mode Peer List
|
||||
#define ADHOCCTL_GAMEMODE_MAX_MEMBERS 16
|
||||
typedef struct SceNetAdhocctlGameModeInfo {
|
||||
s32_le num;
|
||||
SceNetEtherAddr member[ADHOCCTL_GAMEMODE_MAX_MEMBERS];
|
||||
} PACK SceNetAdhocctlGameModeInfo;
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Adhoc ID (Game Product Key)
|
||||
#define ADHOCCTL_ADHOCID_LEN 9
|
||||
typedef struct SceNetAdhocctlAdhocId {
|
||||
s32_le type;
|
||||
uint8_t data[ADHOCCTL_ADHOCID_LEN];
|
||||
uint8_t padding[3];
|
||||
} SceNetAdhocctlAdhocId;
|
||||
|
||||
// Socket Polling Event Listener
|
||||
struct SceNetAdhocPollSd {
|
||||
s32_le id;
|
||||
s32_le events;
|
||||
s32_le revents;
|
||||
};
|
||||
|
||||
// PDP Socket Status
|
||||
struct SceNetAdhocPdpStat {
|
||||
struct SceNetAdhocPdpStat * next;
|
||||
s32_le id;
|
||||
SceNetEtherAddr laddr;
|
||||
u16_le lport;
|
||||
u32_le rcv_sb_cc;
|
||||
};
|
||||
|
||||
// PTP Socket Status
|
||||
struct SceNetAdhocPtpStat {
|
||||
u32_le next; // Changed the pointer to u32
|
||||
s32_le id;
|
||||
SceNetEtherAddr laddr;
|
||||
SceNetEtherAddr paddr;
|
||||
u16_le lport;
|
||||
u16_le pport;
|
||||
u32_le snd_sb_cc;
|
||||
u32_le rcv_sb_cc;
|
||||
s32_le state;
|
||||
};
|
||||
|
||||
// Gamemode Optional Peer Buffer Data
|
||||
struct SceNetAdhocGameModeOptData {
|
||||
u32_le size;
|
||||
u32_le flag;
|
||||
u64_le last_recv;
|
||||
};
|
||||
|
||||
// Gamemode Buffer Status
|
||||
struct SceNetAdhocGameModeBufferStat {
|
||||
struct SceNetAdhocGameModeBufferStat * next;
|
||||
s32_le id;
|
||||
void * ptr;
|
||||
u32_le size;
|
||||
u32_le master;
|
||||
SceNetAdhocGameModeOptData opt;
|
||||
};
|
||||
|
||||
|
||||
// Internal Matching Peer Information
|
||||
typedef struct SceNetAdhocMatchingMemberInternal {
|
||||
// Next Peer
|
||||
struct SceNetAdhocMatchingMemberInternal * next;
|
||||
|
||||
// MAC Address
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// State Variable
|
||||
s32_le state;
|
||||
|
||||
// Send in Progress
|
||||
s32_le sending;
|
||||
|
||||
// Last Heartbeat
|
||||
u64_le lastping;
|
||||
} SceNetAdhocMatchingMemberInternal;
|
||||
|
||||
|
||||
// Matching handler
|
||||
struct SceNetAdhocMatchingHandlerArgs {
|
||||
s32_le id;
|
||||
s32_le event;
|
||||
SceNetEtherAddr * peer;
|
||||
s32_le optlen;
|
||||
void * opt;
|
||||
};
|
||||
|
||||
struct SceNetAdhocMatchingHandler {
|
||||
u32_le entryPoint;
|
||||
};
|
||||
|
||||
// Thread Message Stack Item
|
||||
typedef struct ThreadMessage {
|
||||
// Next Thread Message
|
||||
struct ThreadMessage * next;
|
||||
|
||||
// Stack Event Opcode
|
||||
u32_le opcode;
|
||||
|
||||
// Target MAC Address
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// Optional Data Length
|
||||
s32_le optlen;
|
||||
} ThreadMessage;
|
||||
|
||||
// Established Peer
|
||||
|
||||
// Context Information
|
||||
typedef struct SceNetAdhocMatchingContext {
|
||||
// Next Context
|
||||
struct SceNetAdhocMatchingContext * next;
|
||||
|
||||
// Externally Visible ID
|
||||
s32_le id;
|
||||
|
||||
// Matching Mode (HOST, CLIENT, P2P)
|
||||
s32_le mode;
|
||||
|
||||
// Running Flag (1 = running, 0 = created)
|
||||
s32_le running;
|
||||
|
||||
// Maximum Number of Peers (for HOST, P2P)
|
||||
s32_le maxpeers;
|
||||
|
||||
// Local MAC Address
|
||||
SceNetEtherAddr mac;
|
||||
|
||||
// Peer List for Connectees
|
||||
SceNetAdhocMatchingMemberInternal * peerlist;
|
||||
|
||||
// Local PDP Port
|
||||
u16_le port;
|
||||
|
||||
// Local PDP Socket
|
||||
s32_le socket;
|
||||
|
||||
// Receive Buffer Length
|
||||
s32_le rxbuflen;
|
||||
|
||||
// Receive Buffer
|
||||
uint8_t * rxbuf;
|
||||
|
||||
// Hello Broadcast Interval (Microseconds)
|
||||
u32_le hello_int;
|
||||
|
||||
// Keep-Alive Broadcast Interval (Microseconds)
|
||||
u32_le keepalive_int;
|
||||
|
||||
// Resend Interval (Microseconds)
|
||||
u32_le resend_int;
|
||||
|
||||
// Resend-Counter
|
||||
s32_le resendcounter;
|
||||
|
||||
// Keep-Alive Counter
|
||||
s32_le keepalivecounter;
|
||||
|
||||
// Event Handler
|
||||
SceNetAdhocMatchingHandler handler;
|
||||
|
||||
// Hello Data Length
|
||||
u32_le hellolen;
|
||||
|
||||
// Hello Data
|
||||
void * hello;
|
||||
|
||||
// Event Caller Thread
|
||||
s32_le event_thid;
|
||||
|
||||
// IO Handler Thread
|
||||
s32_le input_thid;
|
||||
|
||||
// Event Caller Thread Message Stack
|
||||
s32_le event_stack_lock;
|
||||
ThreadMessage * event_stack;
|
||||
|
||||
// IO Handler Thread Message Stack
|
||||
s32_le input_stack_lock;
|
||||
ThreadMessage * input_stack;
|
||||
} SceNetAdhocMatchingContext;
|
||||
|
||||
// End of psp definitions
|
||||
|
||||
#define OPCODE_PING 0
|
||||
#define OPCODE_LOGIN 1
|
||||
#define OPCODE_CONNECT 2
|
||||
#define OPCODE_DISCONNECT 3
|
||||
#define OPCODE_SCAN 4
|
||||
#define OPCODE_SCAN_COMPLETE 5
|
||||
#define OPCODE_CONNECT_BSSID 6
|
||||
#define OPCODE_CHAT 7
|
||||
|
||||
// PSP Product Code
|
||||
#define PRODUCT_CODE_LENGTH 9
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
// Game Product Code (ex. ULUS12345)
|
||||
char data[PRODUCT_CODE_LENGTH];
|
||||
} PACK SceNetAdhocctlProductCode;
|
||||
|
||||
// Basic Packet
|
||||
typedef struct {
|
||||
uint8_t opcode;
|
||||
} PACK SceNetAdhocctlPacketBase;
|
||||
|
||||
// C2S Login Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetEtherAddr mac;
|
||||
SceNetAdhocctlNickname name;
|
||||
SceNetAdhocctlProductCode game;
|
||||
} PACK SceNetAdhocctlLoginPacketC2S;
|
||||
|
||||
// C2S Connect Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetAdhocctlGroupName group;
|
||||
} PACK SceNetAdhocctlConnectPacketC2S;
|
||||
|
||||
// C2S Chat Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
char message[64];
|
||||
} PACK SceNetAdhocctlChatPacketC2S;
|
||||
|
||||
// S2C Connect Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetAdhocctlNickname name;
|
||||
SceNetEtherAddr mac;
|
||||
uint32_t ip;
|
||||
} PACK SceNetAdhocctlConnectPacketS2C;
|
||||
|
||||
// S2C Disconnect Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
uint32_t ip;
|
||||
} PACK SceNetAdhocctlDisconnectPacketS2C;
|
||||
|
||||
// S2C Scan Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetAdhocctlGroupName group;
|
||||
SceNetEtherAddr mac;
|
||||
} PACK SceNetAdhocctlScanPacketS2C;
|
||||
|
||||
// S2C Connect BSSID Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlPacketBase base;
|
||||
SceNetEtherAddr mac;
|
||||
} PACK SceNetAdhocctlConnectBSSIDPacketS2C;
|
||||
|
||||
// S2C Chat Packet
|
||||
typedef struct {
|
||||
SceNetAdhocctlChatPacketC2S base;
|
||||
SceNetAdhocctlNickname name;
|
||||
} PACK SceNetAdhocctlChatPacketS2C;
|
||||
#ifdef _MSC_VER
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Aux vars
|
||||
extern int metasocket;
|
||||
extern SceNetAdhocctlParameter parameter;
|
||||
extern std::thread friendFinderThread;
|
||||
extern recursive_mutex peerlock;
|
||||
extern SceNetAdhocPdpStat * pdp[255];
|
||||
extern SceNetAdhocPtpStat * ptp[255];
|
||||
|
||||
extern uint32_t fakePoolSize;
|
||||
extern SceNetAdhocMatchingContext * contexts;
|
||||
extern int one;
|
||||
extern bool friendFinderRunning;
|
||||
extern SceNetAdhocctlPeerInfo * friends;
|
||||
extern SceNetAdhocctlScanInfo * networks;
|
||||
extern int eventHandlerUpdate;
|
||||
extern int threadStatus;
|
||||
// End of Aux vars
|
||||
|
||||
/**
|
||||
* Local MAC Check
|
||||
* @param saddr To-be-checked MAC Address
|
||||
* @return 1 if valid or... 0
|
||||
*/
|
||||
int isLocalMAC(const SceNetEtherAddr * addr);
|
||||
|
||||
/**
|
||||
* PDP Port Check
|
||||
* @param port To-be-checked Port
|
||||
* @return 1 if in use or... 0
|
||||
*/
|
||||
int isPDPPortInUse(uint16_t port);
|
||||
|
||||
/**
|
||||
* Check whether PTP Port is in use or not
|
||||
* @param port To-be-checked Port Number
|
||||
* @return 1 if in use or... 0
|
||||
*/
|
||||
int isPTPPortInUse(uint16_t port);
|
||||
|
||||
/**
|
||||
* Add Friend to Local List
|
||||
* @param packet Friend Information
|
||||
*/
|
||||
void addFriend(SceNetAdhocctlConnectPacketS2C * packet);
|
||||
|
||||
/**
|
||||
* Changes the Blocking Mode of the socket
|
||||
* @param fd File Descriptor of the socket
|
||||
* @param nonblocking 1 to set to nonblock and 0 to set blocking
|
||||
*/
|
||||
void changeBlockingMode(int fd, int nonblocking);
|
||||
|
||||
/**
|
||||
* Count Virtual Networks by analyzing the Friend List
|
||||
* @return Number of Virtual Networks
|
||||
*/
|
||||
int countAvailableNetworks();
|
||||
|
||||
/**
|
||||
* Closes & Deletes all PDP Sockets
|
||||
*/
|
||||
void deleteAllPDP(void);
|
||||
|
||||
/**
|
||||
* Closes & Deletes all PTP sockets
|
||||
*/
|
||||
void deleteAllPTP(void);
|
||||
|
||||
/**
|
||||
* Delete Friend from Local List
|
||||
* @param ip Friend IP
|
||||
*/
|
||||
void deleteFriendByIP(uint32_t ip);
|
||||
|
||||
/**
|
||||
* Find Free Matching ID
|
||||
* @return First unoccupied Matching ID
|
||||
*/
|
||||
int findFreeMatchingID(void);
|
||||
|
||||
/**
|
||||
* Find Internal Matching Context for Matching ID
|
||||
* @param id Matching ID
|
||||
* @return Matching Context Pointer or... NULL
|
||||
*/
|
||||
SceNetAdhocMatchingContext * findMatchingContext(int id);
|
||||
|
||||
/**
|
||||
* Recursive Memory Freeing-Helper for Friend-Structures
|
||||
* @param node Current Node in List
|
||||
*/
|
||||
void freeFriendsRecursive(SceNetAdhocctlPeerInfo * node);
|
||||
|
||||
/**
|
||||
* Friend Finder Thread (Receives Peer Information)
|
||||
* @param args Length of argp in Bytes (Unused)
|
||||
* @param argp Argument (Unused)
|
||||
* @return Unused Value - Return 0
|
||||
*/
|
||||
int friendFinder();
|
||||
|
||||
/**
|
||||
* Return Number of active Peers in the same Network as the Local Player
|
||||
* @return Number of active Peers
|
||||
*/
|
||||
int getActivePeerCount(void);
|
||||
|
||||
/**
|
||||
* Returns the locall Ip of this machine, TODO: Implement the linux version
|
||||
* @param SocketAddres OUT: local ip
|
||||
*/
|
||||
int getLocalIp(sockaddr_in * SocketAddress);
|
||||
|
||||
/**
|
||||
* Joins two 32 bits number into a 64 bit one
|
||||
* @param num1: first number
|
||||
* @param num2: second number
|
||||
* @return Single 64 bit number
|
||||
*/
|
||||
#define firstMask 0x00000000FFFFFFFF
|
||||
#define secondMask 0xFFFFFFFF00000000
|
||||
u64 join32(u32 num1, u32 num2);
|
||||
|
||||
/**
|
||||
* Splits a 64 bit number into two 32 bit ones
|
||||
* @param num: The number to be split
|
||||
* @param buf OUT: Array containing the split numbers
|
||||
*/
|
||||
void split64(u64 num, int buff[]);
|
||||
|
||||
/**
|
||||
* Returns the local mac, TODO: Read from Config file
|
||||
* @param addr OUT: Local Mac
|
||||
*/
|
||||
void getLocalMac(SceNetEtherAddr * addr);
|
||||
|
||||
/**
|
||||
* PTP Socket Counter
|
||||
* @return Number of internal PTP Sockets
|
||||
*/
|
||||
int getPTPSocketCount(void);
|
||||
|
||||
/**
|
||||
* Initialize Networking Components for Adhocctl Emulator
|
||||
* @param adhoc_id Game Product Code
|
||||
* @param server_ip Server IP
|
||||
* @return 0 on success or... -1
|
||||
*/
|
||||
int initNetwork(SceNetAdhocctlAdhocId *adhocid);
|
||||
|
||||
/**
|
||||
* Broadcast MAC Check
|
||||
* @param addr To-be-checked MAC Address
|
||||
* @return 1 if Broadcast MAC or... 0
|
||||
*/
|
||||
int isBroadcastMAC(const SceNetEtherAddr * addr);
|
||||
|
||||
/**
|
||||
* Resolve IP to MAC
|
||||
* @param ip Peer IP Address
|
||||
* @param mac OUT: Peer MAC
|
||||
* @return 0 on success or... ADHOC_NO_ENTRY
|
||||
*/
|
||||
int resolveIP(uint32_t ip, SceNetEtherAddr * mac);
|
||||
|
||||
/**
|
||||
* Resolve MAC to IP
|
||||
* @param mac Peer MAC Address
|
||||
* @param ip OUT: Peer IP
|
||||
* @return 0 on success or... ADHOC_NO_ENTRY
|
||||
*/
|
||||
int resolveMAC(SceNetEtherAddr * mac, uint32_t * ip);
|
||||
|
||||
/**
|
||||
* Check whether Network Name contains only valid symbols
|
||||
* @param group_name To-be-checked Network Name
|
||||
* @return 1 if valid or... 0
|
||||
*/
|
||||
int validNetworkName(const SceNetAdhocctlGroupName * groupname);
|
|
@ -722,6 +722,10 @@ u32 sceAtracGetBufferInfoForResetting(int atracID, int sample, u32 bufferInfoAdd
|
|||
// minWritebytes should not be bigger than writeablebytes
|
||||
minWritebytes = std::min(minWritebytes, (int)atrac->first.writableBytes);
|
||||
|
||||
if (atrac->first.fileoffset <= 2*atrac->atracBufSize){
|
||||
Sampleoffset = atrac->first.fileoffset;
|
||||
}
|
||||
|
||||
// If we've already loaded everything, the answer is 0.
|
||||
if (atrac->first.size >= atrac->first.filesize) {
|
||||
Sampleoffset = 0;
|
||||
|
@ -1871,7 +1875,6 @@ const HLEFunction sceAtrac3plus[] = {
|
|||
{0x0C116E1B,WrapI_IUUUU<sceAtracLowLevelDecode>,"sceAtracLowLevelDecode"},
|
||||
};
|
||||
|
||||
|
||||
void Register_sceAtrac3plus() {
|
||||
// Two names
|
||||
RegisterModule("sceATRAC3plus_Library", ARRAY_SIZE(sceAtrac3plus), sceAtrac3plus);
|
||||
|
|
|
@ -141,7 +141,7 @@ u32 sceAudioOutput(u32 chan, int vol, u32 samplePtr) {
|
|||
|
||||
u32 sceAudioOutputPanned(u32 chan, int leftvol, int rightvol, u32 samplePtr) {
|
||||
if (leftvol > 0xFFFF || rightvol > 0xFFFF) {
|
||||
ERROR_LOG(SCEAUDIO, "sceAudioOutputPannedBlocking() - invalid volume");
|
||||
ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned() - invalid volume");
|
||||
return SCE_ERROR_AUDIO_INVALID_VOLUME;
|
||||
} else if (chan >= PSP_AUDIO_CHANNEL_MAX) {
|
||||
ERROR_LOG(SCEAUDIO, "sceAudioOutputPanned() - bad channel");
|
||||
|
@ -167,8 +167,9 @@ int sceAudioGetChannelRestLen(u32 chan) {
|
|||
ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLen(%08x) - bad channel", chan);
|
||||
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
|
||||
}
|
||||
DEBUG_LOG(SCEAUDIO, "sceAudioGetChannelRestLen(%08x)", chan);
|
||||
return (int)chans[chan].sampleQueue.size() / 2;
|
||||
int remainingSamples = (int)chans[chan].sampleQueue.size() / 2;
|
||||
DEBUG_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLen(%08x)", remainingSamples, chan);
|
||||
return remainingSamples;
|
||||
}
|
||||
|
||||
int sceAudioGetChannelRestLength(u32 chan) {
|
||||
|
@ -176,8 +177,9 @@ int sceAudioGetChannelRestLength(u32 chan) {
|
|||
ERROR_LOG(SCEAUDIO, "sceAudioGetChannelRestLength(%08x) - bad channel", chan);
|
||||
return SCE_ERROR_AUDIO_INVALID_CHANNEL;
|
||||
}
|
||||
DEBUG_LOG(SCEAUDIO, "sceAudioGetChannelRestLength(%08x)", chan);
|
||||
return (int)chans[chan].sampleQueue.size() / 2;
|
||||
int remainingSamples = (int)chans[chan].sampleQueue.size() / 2;
|
||||
DEBUG_LOG(SCEAUDIO, "%d=sceAudioGetChannelRestLength(%08x)", remainingSamples, chan);
|
||||
return remainingSamples;
|
||||
}
|
||||
|
||||
static u32 GetFreeChannel() {
|
||||
|
@ -438,7 +440,7 @@ const HLEFunction sceAudio[] =
|
|||
{0x5EC81C55, WrapU_IUU<sceAudioChReserve>, "sceAudioChReserve"},
|
||||
{0x6FC46853, WrapU_U<sceAudioChRelease>, "sceAudioChRelease"},
|
||||
{0xE9D97901, WrapI_U<sceAudioGetChannelRestLen>, "sceAudioGetChannelRestLen"},
|
||||
{0xB011922F, WrapI_U<sceAudioGetChannelRestLen>, "sceAudioGetChannelRestLength"},
|
||||
{0xB011922F, WrapI_U<sceAudioGetChannelRestLength>, "sceAudioGetChannelRestLength"},
|
||||
{0xCB2E439E, WrapU_UU<sceAudioSetChannelDataLen>, "sceAudioSetChannelDataLen"},
|
||||
{0x95FD0C2D, WrapU_UU<sceAudioChangeChannelConfig>, "sceAudioChangeChannelConfig"},
|
||||
{0xB7E1D8E7, WrapU_UUU<sceAudioChangeChannelVolume>, "sceAudioChangeChannelVolume"},
|
||||
|
|
|
@ -114,7 +114,7 @@ void __CtrlUpdateLatch()
|
|||
latch.btnMake |= buttons & changed;
|
||||
latch.btnBreak |= ctrlOldButtons & changed;
|
||||
latch.btnPress |= buttons;
|
||||
latch.btnRelease |= (ctrlOldButtons & ~buttons) & changed;
|
||||
latch.btnRelease |= ~buttons;
|
||||
dialogBtnMake |= buttons & changed;
|
||||
ctrlLatchBufs++;
|
||||
|
||||
|
@ -195,10 +195,8 @@ void __CtrlSetRapidFire(bool state)
|
|||
emuRapidFire = state;
|
||||
}
|
||||
|
||||
int __CtrlReadSingleBuffer(u32 ctrlDataPtr, bool negative)
|
||||
int __CtrlReadSingleBuffer(PSPPointer<_ctrl_data> data, bool negative)
|
||||
{
|
||||
PSPPointer<_ctrl_data> data;
|
||||
data = ctrlDataPtr;
|
||||
if (data.IsValid())
|
||||
{
|
||||
*data = ctrlBufs[ctrlBufRead];
|
||||
|
@ -238,11 +236,10 @@ int __CtrlReadBuffer(u32 ctrlDataPtr, u32 nBufs, bool negative, bool peek)
|
|||
ctrlBufRead = (ctrlBuf - availBufs + NUM_CTRL_BUFFERS) % NUM_CTRL_BUFFERS;
|
||||
|
||||
int done = 0;
|
||||
PSPPointer<_ctrl_data> data;
|
||||
data = ctrlDataPtr;
|
||||
for (u32 i = 0; i < availBufs; ++i)
|
||||
{
|
||||
done += __CtrlReadSingleBuffer(ctrlDataPtr, negative);
|
||||
ctrlDataPtr += sizeof(_ctrl_data);
|
||||
}
|
||||
done += __CtrlReadSingleBuffer(data++, negative);
|
||||
|
||||
if (peek)
|
||||
ctrlBufRead = resetRead;
|
||||
|
@ -268,7 +265,8 @@ retry:
|
|||
if (wVal == 0)
|
||||
goto retry;
|
||||
|
||||
u32 ctrlDataPtr = __KernelGetWaitValue(threadID, error);
|
||||
PSPPointer<_ctrl_data> ctrlDataPtr;
|
||||
ctrlDataPtr = __KernelGetWaitValue(threadID, error);
|
||||
int retVal = __CtrlReadSingleBuffer(ctrlDataPtr, wVal == CTRL_WAIT_NEGATIVE);
|
||||
__KernelResumeThreadFromWait(threadID, retVal);
|
||||
}
|
||||
|
@ -325,7 +323,7 @@ void __CtrlDoState(PointerWrap &p)
|
|||
{
|
||||
std::lock_guard<std::recursive_mutex> guard(ctrlMutex);
|
||||
|
||||
auto s = p.Section("sceCtrl", 1, 2);
|
||||
auto s = p.Section("sceCtrl", 1, 3);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -334,7 +332,10 @@ void __CtrlDoState(PointerWrap &p)
|
|||
p.Do(ctrlOldButtons);
|
||||
|
||||
p.DoVoid(ctrlBufs, sizeof(ctrlBufs));
|
||||
p.Do(ctrlCurrent);
|
||||
if (s <= 2) {
|
||||
_ctrl_data dummy = {0};
|
||||
p.Do(dummy);
|
||||
}
|
||||
p.Do(ctrlBuf);
|
||||
p.Do(ctrlBufRead);
|
||||
p.Do(latch);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
// TODO: Move the relevant parts into common. Don't want the core
|
||||
// to be dependent on "native", I think. Or maybe should get rid of common
|
||||
|
@ -29,7 +30,6 @@
|
|||
#include "gfx_es2/gl_state.h"
|
||||
#endif
|
||||
|
||||
#include "Common/Thread.h"
|
||||
#include "Core/CoreTiming.h"
|
||||
#include "Core/CoreParameter.h"
|
||||
#include "Core/Reporting.h"
|
||||
|
@ -81,7 +81,7 @@ static int afterFlipEvent = -1;
|
|||
// hCount is computed now.
|
||||
static int vCount;
|
||||
// The "AccumulatedHcount" can be adjusted, this is the base.
|
||||
static double hCountBase;
|
||||
static u32 hCountBase;
|
||||
static int isVblank;
|
||||
static int numSkippedFrames;
|
||||
static bool hasSetMode;
|
||||
|
@ -96,7 +96,7 @@ static double nextFrameTime;
|
|||
static int numVBlanksSinceFlip;
|
||||
|
||||
static u64 frameStartTicks;
|
||||
const float hCountPerVblank = 285.72f; // insprired by jpcsp
|
||||
const int hCountPerVblank = 286;
|
||||
|
||||
|
||||
std::vector<WaitVBlankInfo> vblankWaitingThreads;
|
||||
|
@ -111,7 +111,7 @@ std::vector<VblankCallback> vblankListeners;
|
|||
|
||||
// The vblank period is 731.5 us (0.7315 ms)
|
||||
const double vblankMs = 0.7315;
|
||||
const double frameMs = 1000.0 / 60.0;
|
||||
const double frameMs = 1001.0 / 60.0;
|
||||
|
||||
enum {
|
||||
PSP_DISPLAY_SETBUF_IMMEDIATE = 0,
|
||||
|
@ -139,6 +139,8 @@ void hleAfterFlip(u64 userdata, int cyclesLate);
|
|||
|
||||
void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId);
|
||||
void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId);
|
||||
int __DisplayGetFlipCount() { return actualFlips; }
|
||||
int __DisplayGetVCount() { return vCount; }
|
||||
|
||||
void __DisplayInit() {
|
||||
gpuStats.Reset();
|
||||
|
@ -164,7 +166,7 @@ void __DisplayInit() {
|
|||
CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs), enterVblankEvent, 0);
|
||||
isVblank = 0;
|
||||
vCount = 0;
|
||||
hCountBase = 0.0;
|
||||
hCountBase = 0;
|
||||
curFrameTime = 0.0;
|
||||
nextFrameTime = 0.0;
|
||||
|
||||
|
@ -183,7 +185,7 @@ void __DisplayInit() {
|
|||
}
|
||||
|
||||
void __DisplayDoState(PointerWrap &p) {
|
||||
auto s = p.Section("sceDisplay", 1, 2);
|
||||
auto s = p.Section("sceDisplay", 1, 3);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -192,7 +194,13 @@ void __DisplayDoState(PointerWrap &p) {
|
|||
p.Do(framebufIsLatched);
|
||||
p.Do(frameStartTicks);
|
||||
p.Do(vCount);
|
||||
p.Do(hCountBase);
|
||||
if (s <= 2) {
|
||||
double oldHCountBase;
|
||||
p.Do(oldHCountBase);
|
||||
hCountBase = (int) oldHCountBase;
|
||||
} else {
|
||||
p.Do(hCountBase);
|
||||
}
|
||||
p.Do(isVblank);
|
||||
p.Do(hasSetMode);
|
||||
p.Do(mode);
|
||||
|
@ -290,6 +298,7 @@ void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId) {
|
|||
}
|
||||
|
||||
int vcountUnblock = vblankPausedWaits[pauseKey];
|
||||
vblankPausedWaits.erase(pauseKey);
|
||||
if (vcountUnblock <= vCount) {
|
||||
__KernelResumeThreadFromWait(threadID, 0);
|
||||
return;
|
||||
|
@ -307,6 +316,10 @@ void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps) {
|
|||
*out_actual_fps = actualFps;
|
||||
}
|
||||
|
||||
void __DisplayGetVPS(float *out_vps) {
|
||||
*out_vps = fps;
|
||||
}
|
||||
|
||||
void __DisplayGetAveragedFPS(float *out_vps, float *out_fps) {
|
||||
float avg = 0.0;
|
||||
if (fpsHistoryValid > 0) {
|
||||
|
@ -464,7 +477,7 @@ void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
|
|||
} else {
|
||||
// Wait until we've caught up.
|
||||
while (time_now_d() < nextFrameTime) {
|
||||
Common::SleepCurrentThread(1);
|
||||
sleep_ms(1); // Sleep for 1ms on this thread
|
||||
time_update();
|
||||
}
|
||||
}
|
||||
|
@ -497,9 +510,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
|||
}
|
||||
frameStartTicks = CoreTiming::GetTicks();
|
||||
|
||||
// Fire the vblank listeners before we wake threads.
|
||||
__DisplayFireVblank();
|
||||
|
||||
// Wake up threads waiting for VBlank
|
||||
u32 error;
|
||||
for (size_t i = 0; i < vblankWaitingThreads.size(); i++) {
|
||||
|
@ -550,7 +560,8 @@ void hleEnterVblank(u64 userdata, int cyclesLate) {
|
|||
gpuStats.numFlips++;
|
||||
|
||||
bool throttle, skipFrame;
|
||||
DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.0f / 60.0f));
|
||||
// 1.001f to compensate for the classic 59.94 NTSC framerate that the PSP seems to have.
|
||||
DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * (1.001f / 60.0f));
|
||||
|
||||
// Max 4 skipped frames in a row - 15 fps is really the bare minimum for playability.
|
||||
// We check for 3 here so it's 3 skipped frames, 1 non skipped, 3 skipped, etc.
|
||||
|
@ -584,6 +595,9 @@ void hleLeaveVblank(u64 userdata, int cyclesLate) {
|
|||
isVblank = 0;
|
||||
DEBUG_LOG(SCEDISPLAY,"Leave VBlank %i", (int)userdata - 1);
|
||||
CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs) - cyclesLate, enterVblankEvent, userdata);
|
||||
|
||||
// Fire the vblank listeners after the vblank completes.
|
||||
__DisplayFireVblank();
|
||||
}
|
||||
|
||||
u32 sceDisplayIsVblank() {
|
||||
|
|
|
@ -35,4 +35,7 @@ void __DisplayListenVblank(VblankCallback callback);
|
|||
|
||||
void __DisplayGetDebugStats(char stats[2048]);
|
||||
void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps);
|
||||
void __DisplayGetVPS(float *out_vps);
|
||||
void __DisplayGetAveragedFPS(float *out_vps, float *out_fps);
|
||||
int __DisplayGetVCount();
|
||||
int __DisplayGetFlipCount();
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Core/MemMap.h"
|
||||
#include "Core/Reporting.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "GPU/GPUInterface.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
|
@ -41,6 +42,10 @@ void __DmacDoState(PointerWrap &p) {
|
|||
|
||||
int __DmacMemcpy(u32 dst, u32 src, u32 size) {
|
||||
Memory::Memcpy(dst, Memory::GetPointer(src), size);
|
||||
#ifndef USING_GLES2
|
||||
CBreakPoints::ExecMemCheck(src, false, size, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dst, true, size, currentMIPS->pc);
|
||||
#endif
|
||||
|
||||
src &= ~0x40000000;
|
||||
dst &= ~0x40000000;
|
||||
|
|
|
@ -104,7 +104,6 @@ class LoadedFont;
|
|||
class FontLib;
|
||||
class Font;
|
||||
int GetInternalFontIndex(Font *font);
|
||||
bool packagedFont;
|
||||
|
||||
// These should not need to be state saved.
|
||||
static std::vector<Font *> internalFonts;
|
||||
|
@ -130,30 +129,19 @@ public:
|
|||
}
|
||||
|
||||
Font(const u8 *data, size_t dataSize) {
|
||||
pgf_.ReadPtr(data, dataSize);
|
||||
style_.fontH = (float)pgf_.header.hSize / 64.0f;
|
||||
style_.fontV = (float)pgf_.header.vSize / 64.0f;
|
||||
style_.fontHRes = (float)pgf_.header.hResolution / 64.0f;
|
||||
style_.fontVRes = (float)pgf_.header.vResolution / 64.0f;
|
||||
Init(data, dataSize);
|
||||
}
|
||||
|
||||
Font(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
|
||||
pgf_.ReadPtr(data, dataSize);
|
||||
style_.fontH = entry.hSize / 64.f;
|
||||
style_.fontV = entry.vSize / 64.f;
|
||||
style_.fontHRes = entry.hResolution / 64.f;
|
||||
style_.fontVRes = entry.vResolution / 64.f;
|
||||
style_.fontWeight = (float)entry.weight;
|
||||
style_.fontFamily = (u16)entry.familyCode;
|
||||
style_.fontStyle = (u16)entry.style;
|
||||
style_.fontStyleSub = (u16)entry.styleSub;
|
||||
style_.fontLanguage = (u16)entry.languageCode;
|
||||
style_.fontRegion = (u16)entry.regionCode;
|
||||
style_.fontCountry = (u16)entry.countryCode;
|
||||
strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName));
|
||||
strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName));
|
||||
style_.fontAttributes = entry.extraAttributes;
|
||||
style_.fontExpire = entry.expireDate;
|
||||
Init(data, dataSize, entry);
|
||||
}
|
||||
|
||||
Font (const std::vector<u8> &data) {
|
||||
Init(&data[0], data.size());
|
||||
}
|
||||
|
||||
Font (const std::vector<u8> &data, const FontRegistryEntry &entry) {
|
||||
Init(&data[0], data.size(), entry);
|
||||
}
|
||||
|
||||
const PGFFontStyle &GetFontStyle() const { return style_; }
|
||||
|
@ -210,6 +198,33 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void Init(const u8 *data, size_t dataSize) {
|
||||
pgf_.ReadPtr(data, dataSize);
|
||||
style_.fontH = (float)pgf_.header.hSize / 64.0f;
|
||||
style_.fontV = (float)pgf_.header.vSize / 64.0f;
|
||||
style_.fontHRes = (float)pgf_.header.hResolution / 64.0f;
|
||||
style_.fontVRes = (float)pgf_.header.vResolution / 64.0f;
|
||||
}
|
||||
|
||||
void Init(const u8 *data, size_t dataSize, const FontRegistryEntry &entry) {
|
||||
pgf_.ReadPtr(data, dataSize);
|
||||
style_.fontH = entry.hSize / 64.f;
|
||||
style_.fontV = entry.vSize / 64.f;
|
||||
style_.fontHRes = entry.hResolution / 64.f;
|
||||
style_.fontVRes = entry.vResolution / 64.f;
|
||||
style_.fontWeight = (float)entry.weight;
|
||||
style_.fontFamily = (u16)entry.familyCode;
|
||||
style_.fontStyle = (u16)entry.style;
|
||||
style_.fontStyleSub = (u16)entry.styleSub;
|
||||
style_.fontLanguage = (u16)entry.languageCode;
|
||||
style_.fontRegion = (u16)entry.regionCode;
|
||||
style_.fontCountry = (u16)entry.countryCode;
|
||||
strncpy(style_.fontName, entry.fontName, sizeof(style_.fontName));
|
||||
strncpy(style_.fontFileName, entry.fileName, sizeof(style_.fontFileName));
|
||||
style_.fontAttributes = entry.extraAttributes;
|
||||
style_.fontExpire = entry.expireDate;
|
||||
}
|
||||
|
||||
PGF pgf_;
|
||||
PGFFontStyle style_;
|
||||
DISALLOW_COPY_AND_ASSIGN(Font);
|
||||
|
@ -338,6 +353,7 @@ public:
|
|||
}
|
||||
}
|
||||
u32 args[2] = { params_.userDataAddr, (u32)handle_ };
|
||||
// TODO: The return value of this is leaking.
|
||||
__KernelDirectMipsCall(params_.freeFuncAddr, 0, args, 2, false);
|
||||
handle_ = 0;
|
||||
fonts_.clear();
|
||||
|
@ -498,28 +514,17 @@ void __LoadInternalFonts() {
|
|||
|
||||
if (info.exists) {
|
||||
INFO_LOG(SCEFONT, "Loading font %s (%i bytes)", fontFilename.c_str(), (int)info.size);
|
||||
u8 *buffer = new u8[(size_t)info.size];
|
||||
u32 handle = pspFileSystem.OpenFile(fontFilename, FILEACCESS_READ);
|
||||
if (!handle) {
|
||||
std::vector<u8> buffer;
|
||||
if (pspFileSystem.ReadEntireFile(fontFilename, buffer) < 0) {
|
||||
ERROR_LOG(SCEFONT, "Failed opening font");
|
||||
delete [] buffer;
|
||||
continue;
|
||||
}
|
||||
// Our provided font of jpn0.pgf has size 4367080 bytes
|
||||
// This is an ugly hack to workaround incorrect metrics in it.
|
||||
if (std::string(entry.fileName) == "jpn0.pgf" && (int)info.size == 4367080) {
|
||||
packagedFont = true;
|
||||
}
|
||||
|
||||
pspFileSystem.ReadFile(handle, buffer, info.size);
|
||||
pspFileSystem.CloseFile(handle);
|
||||
|
||||
internalFonts.push_back(new Font(buffer, (size_t)info.size, entry));
|
||||
internalFonts.push_back(new Font(buffer, entry));
|
||||
|
||||
delete [] buffer;
|
||||
INFO_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str());
|
||||
DEBUG_LOG(SCEFONT, "Loaded font %s", fontFilename.c_str());
|
||||
} else {
|
||||
INFO_LOG(SCEFONT, "Font file not found: %s", fontFilename.c_str());
|
||||
WARN_LOG(SCEFONT, "Font file not found: %s", fontFilename.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -706,13 +711,9 @@ u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u32 error
|
|||
return 0;
|
||||
}
|
||||
|
||||
u8 *buffer = new u8[(size_t)info.size];
|
||||
|
||||
u32 fileHandle = pspFileSystem.OpenFile(fileName, FILEACCESS_READ);
|
||||
pspFileSystem.ReadFile(fileHandle, buffer, info.size);
|
||||
pspFileSystem.CloseFile(fileHandle);
|
||||
|
||||
LoadedFont *font = fontLib->OpenFont(new Font(buffer, (size_t)info.size));
|
||||
std::vector<u8> buffer;
|
||||
pspFileSystem.ReadEntireFile(fileName, buffer);
|
||||
LoadedFont *font = fontLib->OpenFont(new Font(buffer));
|
||||
if (font) {
|
||||
fontMap[font->Handle()] = font;
|
||||
Memory::Write_U32(0, errorCodePtr);
|
||||
|
@ -825,8 +826,10 @@ int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr) {
|
|||
}
|
||||
|
||||
DEBUG_LOG(SCEFONT, "sceFontGetCharInfo(%08x, %i, %08x)", fontHandle, charCode, charInfoPtr);
|
||||
auto fontLib = font->GetFontLib();
|
||||
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
|
||||
auto charInfo = Memory::GetStruct<PGFCharInfo>(charInfoPtr);
|
||||
font->GetPGF()->GetCharInfo(charCode, charInfo);
|
||||
font->GetPGF()->GetCharInfo(charCode, charInfo, altCharCode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -842,11 +845,13 @@ int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr) {
|
|||
DEBUG_LOG(SCEFONT, "sceFontGetCharImageRect(%08x, %i, %08x)", fontHandle, charCode, charRectPtr);
|
||||
if (!Memory::IsValidAddress(charRectPtr))
|
||||
return -1;
|
||||
|
||||
|
||||
PGFCharInfo charInfo;
|
||||
LoadedFont *font = GetLoadedFont(fontHandle, false);
|
||||
auto fontLib = font->GetFontLib();
|
||||
int altCharCode = fontLib == NULL ? -1 : fontLib->GetAltCharCode();
|
||||
if (font) {
|
||||
font->GetPGF()->GetCharInfo(charCode, &charInfo);
|
||||
font->GetPGF()->GetCharInfo(charCode, &charInfo, altCharCode);
|
||||
Memory::Write_U16(charInfo.bitmapWidth, charRectPtr); // character bitmap width in pixels
|
||||
Memory::Write_U16(charInfo.bitmapHeight, charRectPtr + 2); // character bitmap height in pixels
|
||||
} else {
|
||||
|
@ -874,7 +879,7 @@ int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr) {
|
|||
DEBUG_LOG(SCEFONT, "sceFontGetCharGlyphImage(%x, %x, %x)", fontHandle, charCode, glyphImagePtr);
|
||||
auto glyph = Memory::GetStruct<const GlyphImage>(glyphImagePtr);
|
||||
int altCharCode = font->GetFontLib()->GetAltCharCode();
|
||||
font->GetPGF()->DrawCharacter(glyph, 0, 0, 8192, 8192, charCode, altCharCode, FONT_PGF_CHARGLYPH, packagedFont);
|
||||
font->GetPGF()->DrawCharacter(glyph, 0, 0, 8192, 8192, charCode, altCharCode, FONT_PGF_CHARGLYPH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -892,7 +897,7 @@ int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePt
|
|||
INFO_LOG(SCEFONT, "sceFontGetCharGlyphImage_Clip(%08x, %i, %08x, %i, %i, %i, %i)", fontHandle, charCode, glyphImagePtr, clipXPos, clipYPos, clipWidth, clipHeight);
|
||||
auto glyph = Memory::GetStruct<const GlyphImage>(glyphImagePtr);
|
||||
int altCharCode = font->GetFontLib()->GetAltCharCode();
|
||||
font->GetPGF()->DrawCharacter(glyph, clipXPos, clipYPos, clipXPos + clipWidth, clipYPos + clipHeight, charCode, altCharCode, FONT_PGF_CHARGLYPH, packagedFont);
|
||||
font->GetPGF()->DrawCharacter(glyph, clipXPos, clipYPos, clipXPos + clipWidth, clipYPos + clipHeight, charCode, altCharCode, FONT_PGF_CHARGLYPH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "sceCtrl.h"
|
||||
|
||||
u32 sceHprmPeekCurrentKey(u32 keyAddress) {
|
||||
INFO_LOG(HLE,"0=sceHprmPeekCurrentKey(ptr)");
|
||||
DEBUG_LOG(HLE,"0=sceHprmPeekCurrentKey(ptr)");
|
||||
Memory::Write_U32(0, keyAddress);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -360,7 +360,7 @@ void __IoSyncNotify(u64 userdata, int cyclesLate) {
|
|||
if (ioManager.WaitResult(f->handle, managerResult)) {
|
||||
result = managerResult;
|
||||
} else {
|
||||
ERROR_LOG(SCEIO, "Unable to complete IO operation.");
|
||||
ERROR_LOG(SCEIO, "Unable to complete IO operation on %s", f->GetName());
|
||||
}
|
||||
|
||||
HLEKernel::ResumeFromWait(threadID, WAITTYPE_IO, fd, result);
|
||||
|
@ -441,8 +441,6 @@ void __IoWakeManager() {
|
|||
}
|
||||
|
||||
void __IoInit() {
|
||||
INFO_LOG(SCEIO, "Starting up I/O...");
|
||||
|
||||
MemoryStick_SetFatState(PSP_FAT_MEMORYSTICK_STATE_ASSIGNED);
|
||||
|
||||
asyncNotifyEvent = CoreTiming::RegisterEvent("IoAsyncNotify", __IoAsyncNotify);
|
||||
|
@ -552,16 +550,22 @@ u32 sceIoUnassign(const char *alias)
|
|||
}
|
||||
|
||||
u32 sceKernelStdin() {
|
||||
// fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497
|
||||
hleEatCycles(1);
|
||||
DEBUG_LOG(SCEIO, "3=sceKernelStdin()");
|
||||
return 3;
|
||||
}
|
||||
|
||||
u32 sceKernelStdout() {
|
||||
// fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497
|
||||
hleEatCycles(1);
|
||||
DEBUG_LOG(SCEIO, "1=sceKernelStdout()");
|
||||
return 1;
|
||||
}
|
||||
|
||||
u32 sceKernelStderr() {
|
||||
// fix Buzz Ultimate Music Quiz Crash Sporadically,issue#4497
|
||||
hleEatCycles(1);
|
||||
DEBUG_LOG(SCEIO, "2=sceKernelStderr()");
|
||||
return 2;
|
||||
}
|
||||
|
@ -1444,7 +1448,6 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
|||
break;
|
||||
case 0x02425823:
|
||||
// Check if FAT enabled
|
||||
hleEatCycles(23500);
|
||||
// If the values added together are >= 0x80000000, or less than outPtr, invalid address.
|
||||
if (((int)outPtr + outLen) < (int)outPtr) {
|
||||
ERROR_LOG(SCEIO, "sceIoDevctl: fatms0: 0x02425823 command, bad address");
|
||||
|
@ -1456,7 +1459,7 @@ u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 outPtr,
|
|||
} else {
|
||||
// Does not care about outLen, even if it's 0.
|
||||
Memory::Write_U32(MemoryStick_FatState(), outPtr);
|
||||
return 0;
|
||||
return hleDelayResult(0, "check fat state", cyclesToUs(23500));
|
||||
}
|
||||
break;
|
||||
case 0x02425824:
|
||||
|
@ -1927,7 +1930,7 @@ int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr, u32 out
|
|||
key_ptr = NULL;
|
||||
}
|
||||
|
||||
INFO_LOG(SCEIO, "Decrypting PGD DRM files");
|
||||
DEBUG_LOG(SCEIO, "Decrypting PGD DRM files");
|
||||
pspFileSystem.SeekFile(f->handle, (s32)f->pgd_offset, FILEMOVE_BEGIN);
|
||||
pspFileSystem.ReadFile(f->handle, pgd_header, 0x90);
|
||||
f->pgdInfo = pgd_open(pgd_header, 2, key_ptr);
|
||||
|
|
|
@ -315,9 +315,9 @@ int sceJpegInitMJpeg()
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sceJpeg_A06A75C4()
|
||||
int sceJpegMJpegCscWithColorOption()
|
||||
{
|
||||
ERROR_LOG_REPORT(ME, "UNIMPL sceJpeg_A06A75C4()");
|
||||
ERROR_LOG_REPORT(ME, "UNIMPL sceJpegMJpegCscWithColorOption()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -337,7 +337,7 @@ const HLEFunction sceJpeg[] =
|
|||
{0x9B36444C, WrapI_V<sceJpeg_9B36444C>, "sceJpeg_9B36444C"},
|
||||
{0x9D47469C, WrapI_II<sceJpegCreateMJpeg>, "sceJpegCreateMJpeg"},
|
||||
{0xAC9E70E6, WrapI_V<sceJpegInitMJpeg>, "sceJpegInitMJpeg"},
|
||||
{0xa06a75c4, WrapI_V<sceJpeg_A06A75C4>, "sceJpeg_A06A75C4"},
|
||||
{0xa06a75c4, WrapI_V<sceJpegMJpegCscWithColorOption>, "sceJpegMJpegCscWithColorOption"},
|
||||
};
|
||||
|
||||
void Register_sceJpeg()
|
||||
|
|
|
@ -287,7 +287,7 @@ void sceKernelExitGameWithStatus()
|
|||
|
||||
u32 sceKernelDevkitVersion()
|
||||
{
|
||||
int firmwareVersion = 150;
|
||||
int firmwareVersion = g_Config.iFirmwareVersion;
|
||||
int major = firmwareVersion / 100;
|
||||
int minor = (firmwareVersion / 10) % 10;
|
||||
int revision = firmwareVersion % 10;
|
||||
|
@ -590,8 +590,8 @@ KernelObject *KernelObjectPool::CreateByIDType(int type)
|
|||
return __KernelThreadObject();
|
||||
case SCE_KERNEL_TMID_VTimer:
|
||||
return __KernelVTimerObject();
|
||||
case SCE_KERNEL_TMID_Tls:
|
||||
return __KernelTlsObject();
|
||||
case SCE_KERNEL_TMID_Tlspl:
|
||||
return __KernelTlsplObject();
|
||||
case PPSSPP_KERNEL_TMID_File:
|
||||
return __KernelFileNodeObject();
|
||||
case PPSSPP_KERNEL_TMID_DirList:
|
||||
|
@ -851,15 +851,14 @@ const HLEFunction ThreadManForUser[] =
|
|||
{0xd8b299ae,WrapU_IUUU<sceKernelSetVTimerHandler>, "sceKernelSetVTimerHandler"},
|
||||
{0x53B00E9A,WrapU_IU64UU<sceKernelSetVTimerHandlerWide>, "sceKernelSetVTimerHandlerWide"},
|
||||
|
||||
// Names are just guesses, not correct.
|
||||
{0x8daff657,WrapI_CUUUUU<sceKernelCreateTls>, "sceKernelCreateTls"},
|
||||
{0x32bf938e,WrapI_I<sceKernelDeleteTls>, "sceKernelDeleteTls"},
|
||||
{0x721067F3,WrapI_IU<sceKernelReferTlsStatus>, "sceKernelReferTlsStatus"},
|
||||
{0x8daff657,WrapI_CUUUUU<sceKernelCreateTlspl>, "sceKernelCreateTlspl"},
|
||||
{0x32bf938e,WrapI_I<sceKernelDeleteTlspl>, "sceKernelDeleteTlspl"},
|
||||
{0x721067F3,WrapI_IU<sceKernelReferTlsplStatus>, "sceKernelReferTlsplStatus"},
|
||||
// Not completely certain about args.
|
||||
{0x4A719FB2,WrapI_I<sceKernelFreeTls>, "sceKernelFreeTls"},
|
||||
// Probably internal, not sure. Takes (uid, &addr) as parameters... probably.
|
||||
//{0x65F54FFB,0, "_sceKernelAllocateTls"},
|
||||
// NOTE: sceKernelAllocateTls is in Kernel_Library, see sceKernelInterrupt.cpp.
|
||||
{0x4A719FB2,WrapI_I<sceKernelFreeTlspl>, "sceKernelFreeTlspl"},
|
||||
// Internal. Takes (uid, &addr) as parameters... probably.
|
||||
//{0x65F54FFB,0, "_sceKernelAllocateTlspl"},
|
||||
// NOTE: sceKernelGetTlsAddr is in Kernel_Library, see sceKernelInterrupt.cpp.
|
||||
|
||||
// Not sure if these should be hooked up. See below.
|
||||
{0x0E927AED, _sceKernelReturnFromTimerHandler, "_sceKernelReturnFromTimerHandler"},
|
||||
|
|
|
@ -328,7 +328,7 @@ enum TMIDPurpose
|
|||
SCE_KERNEL_TMID_SuspendThread = 66,
|
||||
SCE_KERNEL_TMID_DormantThread = 67,
|
||||
// No idea what the correct value is here or how to find out.
|
||||
SCE_KERNEL_TMID_Tls = 0x1001,
|
||||
SCE_KERNEL_TMID_Tlspl = 0x1001,
|
||||
|
||||
// Not official, but need ids for save states.
|
||||
PPSSPP_KERNEL_TMID_Module = 0x100001,
|
||||
|
@ -451,7 +451,8 @@ public:
|
|||
{
|
||||
if (handle < handleOffset || handle >= handleOffset+maxCount || !occupied[handle-handleOffset])
|
||||
{
|
||||
if (handle != 0)
|
||||
// Tekken 6 spams 0x80020001 gets wrong with no ill effects, also on the real PSP
|
||||
if (handle != 0 && handle != 0x80020001)
|
||||
{
|
||||
WARN_LOG(SCEKERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
|
||||
}
|
||||
|
|
|
@ -19,15 +19,16 @@
|
|||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "HLE.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "ChunkFile.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Common/ChunkFile.h"
|
||||
|
||||
#include "sceKernel.h"
|
||||
#include "sceKernelThread.h"
|
||||
#include "sceKernelInterrupt.h"
|
||||
#include "sceKernelMemory.h"
|
||||
#include "sceKernelMutex.h"
|
||||
#include "Core/Debugger/Breakpoints.h"
|
||||
#include "Core/HLE/sceKernel.h"
|
||||
#include "Core/HLE/sceKernelThread.h"
|
||||
#include "Core/HLE/sceKernelInterrupt.h"
|
||||
#include "Core/HLE/sceKernelMemory.h"
|
||||
#include "Core/HLE/sceKernelMutex.h"
|
||||
#include "GPU/GPUCommon.h"
|
||||
|
||||
void __DisableInterrupts();
|
||||
|
@ -580,6 +581,10 @@ u32 sceKernelMemcpy(u32 dst, u32 src, u32 size)
|
|||
*dstp++ = *srcp++;
|
||||
}
|
||||
}
|
||||
#ifndef USING_GLES2
|
||||
CBreakPoints::ExecMemCheck(src, false, size, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(dst, true, size, currentMIPS->pc);
|
||||
#endif
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
@ -600,8 +605,7 @@ const HLEFunction Kernel_Library[] =
|
|||
{0x293b45b8,WrapI_V<sceKernelGetThreadId>, "sceKernelGetThreadId"},
|
||||
{0xD13BDE95,WrapI_V<sceKernelCheckThreadStack>, "sceKernelCheckThreadStack"},
|
||||
{0x1839852A,WrapU_UUU<sceKernelMemcpy>, "sceKernelMemcpy"},
|
||||
// Name is only a guess.
|
||||
{0xfa835cde,WrapI_I<sceKernelAllocateTls>, "sceKernelAllocateTls"},
|
||||
{0xfa835cde,WrapI_I<sceKernelGetTlsAddr>, "sceKernelGetTlsAddr"},
|
||||
};
|
||||
|
||||
void Register_Kernel_Library()
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include "Core/HLE/sceKernelMemory.h"
|
||||
#include "Core/HLE/KernelWaitHelpers.h"
|
||||
|
||||
const int TLS_NUM_INDEXES = 16;
|
||||
const int TLSPL_NUM_INDEXES = 16;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// STATE BEGIN
|
||||
|
@ -41,7 +41,7 @@ BlockAllocator kernelMemory(256);
|
|||
|
||||
static int vplWaitTimer = -1;
|
||||
static int fplWaitTimer = -1;
|
||||
static bool tlsUsedIndexes[TLS_NUM_INDEXES];
|
||||
static bool tlsplUsedIndexes[TLSPL_NUM_INDEXES];
|
||||
// STATE END
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -218,7 +218,7 @@ void __KernelMemoryInit()
|
|||
flags_ = 0;
|
||||
sdkVersion_ = 0;
|
||||
compilerVersion_ = 0;
|
||||
memset(tlsUsedIndexes, 0, sizeof(tlsUsedIndexes));
|
||||
memset(tlsplUsedIndexes, 0, sizeof(tlsplUsedIndexes));
|
||||
|
||||
__KernelRegisterWaitTypeFuncs(WAITTYPE_VPL, __KernelVplBeginCallback, __KernelVplEndCallback);
|
||||
__KernelRegisterWaitTypeFuncs(WAITTYPE_FPL, __KernelFplBeginCallback, __KernelFplEndCallback);
|
||||
|
@ -240,16 +240,20 @@ void __KernelMemoryDoState(PointerWrap &p)
|
|||
p.Do(flags_);
|
||||
p.Do(sdkVersion_);
|
||||
p.Do(compilerVersion_);
|
||||
p.DoArray(tlsUsedIndexes, ARRAY_SIZE(tlsUsedIndexes));
|
||||
p.DoArray(tlsplUsedIndexes, ARRAY_SIZE(tlsplUsedIndexes));
|
||||
}
|
||||
|
||||
void __KernelMemoryShutdown()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
INFO_LOG(SCEKERNEL,"Shutting down user memory pool: ");
|
||||
userMemory.ListBlocks();
|
||||
#endif
|
||||
userMemory.Shutdown();
|
||||
#ifdef _DEBUG
|
||||
INFO_LOG(SCEKERNEL,"Shutting down \"kernel\" memory pool: ");
|
||||
kernelMemory.ListBlocks();
|
||||
#endif
|
||||
kernelMemory.Shutdown();
|
||||
}
|
||||
|
||||
|
@ -704,7 +708,9 @@ public:
|
|||
address = alloc->AllocAligned(size, 0x100, alignment, type == PSP_SMEM_HighAligned, name);
|
||||
else
|
||||
address = alloc->Alloc(size, type == PSP_SMEM_High, name);
|
||||
#ifdef _DEBUG
|
||||
alloc->ListBlocks();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
~PartitionMemoryBlock()
|
||||
|
@ -1577,20 +1583,20 @@ u32 SysMemUserForUser_D8DE5C1E(){
|
|||
|
||||
enum
|
||||
{
|
||||
PSP_ERROR_UNKNOWN_TLS_ID = 0x800201D0,
|
||||
PSP_ERROR_TOO_MANY_TLS = 0x800201D1,
|
||||
PSP_ERROR_UNKNOWN_TLSPL_ID = 0x800201D0,
|
||||
PSP_ERROR_TOO_MANY_TLSPL = 0x800201D1,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// TODO: Complete untested guesses.
|
||||
PSP_TLS_ATTR_FIFO = 0,
|
||||
PSP_TLS_ATTR_PRIORITY = 0x100,
|
||||
PSP_TLS_ATTR_HIGHMEM = 0x4000,
|
||||
PSP_TLS_ATTR_KNOWN = PSP_TLS_ATTR_HIGHMEM | PSP_TLS_ATTR_PRIORITY | PSP_TLS_ATTR_FIFO,
|
||||
PSP_TLSPL_ATTR_FIFO = 0,
|
||||
PSP_TLSPL_ATTR_PRIORITY = 0x100,
|
||||
PSP_TLSPL_ATTR_HIGHMEM = 0x4000,
|
||||
PSP_TLSPL_ATTR_KNOWN = PSP_TLSPL_ATTR_HIGHMEM | PSP_TLSPL_ATTR_PRIORITY | PSP_TLSPL_ATTR_FIFO,
|
||||
};
|
||||
|
||||
struct NativeTls
|
||||
struct NativeTlspl
|
||||
{
|
||||
SceSize_le size;
|
||||
char name[32];
|
||||
|
@ -1602,15 +1608,15 @@ struct NativeTls
|
|||
u32_le numWaitThreads;
|
||||
};
|
||||
|
||||
struct TLS : public KernelObject
|
||||
struct TLSPL : public KernelObject
|
||||
{
|
||||
const char *GetName() {return ntls.name;}
|
||||
const char *GetTypeName() {return "TLS";}
|
||||
static u32 GetMissingErrorCode() { return PSP_ERROR_UNKNOWN_TLS_ID; }
|
||||
static int GetStaticIDType() { return SCE_KERNEL_TMID_Tls; }
|
||||
int GetIDType() const { return SCE_KERNEL_TMID_Tls; }
|
||||
static u32 GetMissingErrorCode() { return PSP_ERROR_UNKNOWN_TLSPL_ID; }
|
||||
static int GetStaticIDType() { return SCE_KERNEL_TMID_Tlspl; }
|
||||
int GetIDType() const { return SCE_KERNEL_TMID_Tlspl; }
|
||||
|
||||
TLS() : next(0) {}
|
||||
TLSPL() : next(0) {}
|
||||
|
||||
virtual void DoState(PointerWrap &p)
|
||||
{
|
||||
|
@ -1625,39 +1631,39 @@ struct TLS : public KernelObject
|
|||
p.Do(usage);
|
||||
}
|
||||
|
||||
NativeTls ntls;
|
||||
NativeTlspl ntls;
|
||||
u32 address;
|
||||
std::vector<SceUID> waitingThreads;
|
||||
int next;
|
||||
std::vector<SceUID> usage;
|
||||
};
|
||||
|
||||
KernelObject *__KernelTlsObject()
|
||||
KernelObject *__KernelTlsplObject()
|
||||
{
|
||||
return new TLS;
|
||||
return new TLSPL;
|
||||
}
|
||||
|
||||
SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSize, u32 count, u32 optionsPtr)
|
||||
SceUID sceKernelCreateTlspl(const char *name, u32 partition, u32 attr, u32 blockSize, u32 count, u32 optionsPtr)
|
||||
{
|
||||
if (!name)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY);
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY);
|
||||
return SCE_KERNEL_ERROR_NO_MEMORY;
|
||||
}
|
||||
if ((attr & ~PSP_TLS_ATTR_KNOWN) >= 0x100)
|
||||
if ((attr & ~PSP_TLSPL_ATTR_KNOWN) >= 0x100)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
|
||||
}
|
||||
if (partition < 1 || partition > 9 || partition == 7)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition);
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, partition);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
// We only support user right now.
|
||||
if (partition != 2 && partition != 6)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition);
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, partition);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_PERM;
|
||||
}
|
||||
|
||||
|
@ -1670,13 +1676,13 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi
|
|||
illegalMemSize = true;
|
||||
if (illegalMemSize)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE);
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE;
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < TLS_NUM_INDEXES; ++i)
|
||||
if (tlsUsedIndexes[i] == false)
|
||||
for (int i = 0; i < TLSPL_NUM_INDEXES; ++i)
|
||||
if (tlsplUsedIndexes[i] == false)
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
|
@ -1684,21 +1690,23 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi
|
|||
|
||||
if (index == -1)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTls(): ran out of indexes for TLS objects", PSP_ERROR_TOO_MANY_TLS);
|
||||
return PSP_ERROR_TOO_MANY_TLS;
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateTlspl(): ran out of indexes for TLS pools", PSP_ERROR_TOO_MANY_TLSPL);
|
||||
return PSP_ERROR_TOO_MANY_TLSPL;
|
||||
}
|
||||
|
||||
u32 totalSize = blockSize * count;
|
||||
u32 blockPtr = userMemory.Alloc(totalSize, (attr & PSP_TLS_ATTR_HIGHMEM) != 0, name);
|
||||
u32 blockPtr = userMemory.Alloc(totalSize, (attr & PSP_TLSPL_ATTR_HIGHMEM) != 0, name);
|
||||
#ifdef _DEBUG
|
||||
userMemory.ListBlocks();
|
||||
#endif
|
||||
|
||||
if (blockPtr == (u32) -1)
|
||||
{
|
||||
ERROR_LOG(SCEKERNEL, "%08x=sceKernelCreateTls(%s, %d, %08x, %d, %d, %08x): failed to allocate memory", SCE_KERNEL_ERROR_NO_MEMORY, name, partition, attr, blockSize, count, optionsPtr);
|
||||
ERROR_LOG(SCEKERNEL, "%08x=sceKernelCreateTlspl(%s, %d, %08x, %d, %d, %08x): failed to allocate memory", SCE_KERNEL_ERROR_NO_MEMORY, name, partition, attr, blockSize, count, optionsPtr);
|
||||
return SCE_KERNEL_ERROR_NO_MEMORY;
|
||||
}
|
||||
|
||||
TLS *tls = new TLS();
|
||||
TLSPL *tls = new TLSPL();
|
||||
SceUID id = kernelObjects.Create(tls);
|
||||
|
||||
tls->ntls.size = sizeof(tls->ntls);
|
||||
|
@ -1706,7 +1714,7 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi
|
|||
tls->ntls.name[KERNELOBJECT_MAX_NAME_LENGTH] = 0;
|
||||
tls->ntls.attr = attr;
|
||||
tls->ntls.index = index;
|
||||
tlsUsedIndexes[index] = true;
|
||||
tlsplUsedIndexes[index] = true;
|
||||
tls->ntls.blockSize = blockSize;
|
||||
tls->ntls.totalBlocks = count;
|
||||
tls->ntls.freeBlocks = count;
|
||||
|
@ -1714,47 +1722,47 @@ SceUID sceKernelCreateTls(const char *name, u32 partition, u32 attr, u32 blockSi
|
|||
tls->address = blockPtr;
|
||||
tls->usage.resize(count, 0);
|
||||
|
||||
WARN_LOG(SCEKERNEL, "%08x=sceKernelCreateTls(%s, %d, %08x, %d, %d, %08x)", id, name, partition, attr, blockSize, count, optionsPtr);
|
||||
WARN_LOG(SCEKERNEL, "%08x=sceKernelCreateTlspl(%s, %d, %08x, %d, %d, %08x)", id, name, partition, attr, blockSize, count, optionsPtr);
|
||||
|
||||
// TODO: just alignment?
|
||||
if (optionsPtr != 0)
|
||||
{
|
||||
u32 size = Memory::Read_U32(optionsPtr);
|
||||
if (size > 4)
|
||||
WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTls(%s) unsupported options parameter, size = %d", name, size);
|
||||
WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTlspl(%s) unsupported options parameter, size = %d", name, size);
|
||||
}
|
||||
if ((attr & PSP_TLS_ATTR_PRIORITY) != 0)
|
||||
WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTls(%s) unsupported attr parameter: %08x", name, attr);
|
||||
if ((attr & PSP_TLSPL_ATTR_PRIORITY) != 0)
|
||||
WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateTlspl(%s) unsupported attr parameter: %08x", name, attr);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// Parameters are an educated guess.
|
||||
int sceKernelDeleteTls(SceUID uid)
|
||||
int sceKernelDeleteTlspl(SceUID uid)
|
||||
{
|
||||
WARN_LOG(SCEKERNEL, "sceKernelDeleteTls(%08x)", uid);
|
||||
WARN_LOG(SCEKERNEL, "sceKernelDeleteTlspl(%08x)", uid);
|
||||
u32 error;
|
||||
TLS *tls = kernelObjects.Get<TLS>(uid, error);
|
||||
TLSPL *tls = kernelObjects.Get<TLSPL>(uid, error);
|
||||
if (tls)
|
||||
{
|
||||
// TODO: Wake waiting threads, probably?
|
||||
userMemory.Free(tls->address);
|
||||
tlsUsedIndexes[tls->ntls.index] = false;
|
||||
kernelObjects.Destroy<TLS>(uid);
|
||||
tlsplUsedIndexes[tls->ntls.index] = false;
|
||||
kernelObjects.Destroy<TLSPL>(uid);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int sceKernelAllocateTls(SceUID uid)
|
||||
int sceKernelGetTlsAddr(SceUID uid)
|
||||
{
|
||||
// TODO: Allocate downward if PSP_TLS_ATTR_HIGHMEM?
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelAllocateTls(%08x)", uid);
|
||||
// TODO: Allocate downward if PSP_TLSPL_ATTR_HIGHMEM?
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelGetTlsAddr(%08x)", uid);
|
||||
|
||||
if (!__KernelIsDispatchEnabled() || __IsInInterrupt())
|
||||
return 0;
|
||||
|
||||
u32 error;
|
||||
TLS *tls = kernelObjects.Get<TLS>(uid, error);
|
||||
TLSPL *tls = kernelObjects.Get<TLSPL>(uid, error);
|
||||
if (tls)
|
||||
{
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
|
@ -1787,7 +1795,7 @@ int sceKernelAllocateTls(SceUID uid)
|
|||
if (allocBlock == -1)
|
||||
{
|
||||
tls->waitingThreads.push_back(threadID);
|
||||
__KernelWaitCurThread(WAITTYPE_TLS, uid, 1, 0, false, "allocate tls");
|
||||
__KernelWaitCurThread(WAITTYPE_TLSPL, uid, 1, 0, false, "allocate tls");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1798,11 +1806,11 @@ int sceKernelAllocateTls(SceUID uid)
|
|||
}
|
||||
|
||||
// Parameters are an educated guess.
|
||||
int sceKernelFreeTls(SceUID uid)
|
||||
int sceKernelFreeTlspl(SceUID uid)
|
||||
{
|
||||
WARN_LOG(SCEKERNEL, "UNIMPL sceKernelFreeTls(%08x)", uid);
|
||||
WARN_LOG(SCEKERNEL, "UNIMPL sceKernelFreeTlspl(%08x)", uid);
|
||||
u32 error;
|
||||
TLS *tls = kernelObjects.Get<TLS>(uid, error);
|
||||
TLSPL *tls = kernelObjects.Get<TLSPL>(uid, error);
|
||||
if (tls)
|
||||
{
|
||||
SceUID threadID = __KernelGetCurThread();
|
||||
|
@ -1827,7 +1835,7 @@ int sceKernelFreeTls(SceUID uid)
|
|||
tls->waitingThreads.erase(tls->waitingThreads.begin());
|
||||
|
||||
// This thread must've been woken up.
|
||||
if (!HLEKernel::VerifyWait(waitingThreadID, WAITTYPE_TLS, uid))
|
||||
if (!HLEKernel::VerifyWait(waitingThreadID, WAITTYPE_TLSPL, uid))
|
||||
continue;
|
||||
|
||||
// Otherwise, if there was a thread waiting, we were full, so this newly freed one is theirs.
|
||||
|
@ -1852,11 +1860,11 @@ int sceKernelFreeTls(SceUID uid)
|
|||
}
|
||||
|
||||
// Parameters are an educated guess.
|
||||
int sceKernelReferTlsStatus(SceUID uid, u32 infoPtr)
|
||||
int sceKernelReferTlsplStatus(SceUID uid, u32 infoPtr)
|
||||
{
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelReferTlsStatus(%08x, %08x)", uid, infoPtr);
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelReferTlsplStatus(%08x, %08x)", uid, infoPtr);
|
||||
u32 error;
|
||||
TLS *tls = kernelObjects.Get<TLS>(uid, error);
|
||||
TLSPL *tls = kernelObjects.Get<TLSPL>(uid, error);
|
||||
if (tls)
|
||||
{
|
||||
// TODO: Check size.
|
||||
|
|
|
@ -35,7 +35,7 @@ void __KernelMemoryShutdown();
|
|||
KernelObject *__KernelMemoryFPLObject();
|
||||
KernelObject *__KernelMemoryVPLObject();
|
||||
KernelObject *__KernelMemoryPMBObject();
|
||||
KernelObject *__KernelTlsObject();
|
||||
KernelObject *__KernelTlsplObject();
|
||||
|
||||
SceUID sceKernelCreateVpl(const char *name, int partition, u32 attr, u32 vplSize, u32 optPtr);
|
||||
int sceKernelDeleteVpl(SceUID uid);
|
||||
|
@ -57,10 +57,10 @@ int sceKernelReferFplStatus(SceUID uid, u32 statusPtr);
|
|||
|
||||
int sceKernelGetCompiledSdkVersion();
|
||||
|
||||
SceUID sceKernelCreateTls(const char *name, u32 partitionid, u32 attr, u32 size, u32 count, u32 optionsPtr);
|
||||
int sceKernelDeleteTls(SceUID uid);
|
||||
int sceKernelAllocateTls(SceUID uid);
|
||||
int sceKernelFreeTls(SceUID uid);
|
||||
int sceKernelReferTlsStatus(SceUID uid, u32 infoPtr);
|
||||
SceUID sceKernelCreateTlspl(const char *name, u32 partitionid, u32 attr, u32 size, u32 count, u32 optionsPtr);
|
||||
int sceKernelDeleteTlspl(SceUID uid);
|
||||
int sceKernelGetTlsAddr(SceUID uid);
|
||||
int sceKernelFreeTlspl(SceUID uid);
|
||||
int sceKernelReferTlsplStatus(SceUID uid, u32 infoPtr);
|
||||
|
||||
void Register_SysMemUserForUser();
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#include "Core/HLE/sceIo.h"
|
||||
#include "Core/HLE/KernelWaitHelpers.h"
|
||||
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
enum {
|
||||
PSP_THREAD_ATTR_USER = 0x80000000
|
||||
};
|
||||
|
@ -175,6 +177,7 @@ struct NativeModule {
|
|||
|
||||
// by QueryModuleInfo
|
||||
struct ModuleInfo {
|
||||
SceSize_le size;
|
||||
u32_le nsegment;
|
||||
u32_le segmentaddr[4];
|
||||
u32_le segmentsize[4];
|
||||
|
@ -257,7 +260,7 @@ public:
|
|||
// Add the symbol to the symbol map for debugging.
|
||||
char temp[256];
|
||||
sprintf(temp,"zz_%s", GetFuncName(func.moduleName, func.nid));
|
||||
symbolMap.AddSymbol(temp, func.stubAddr, 8, ST_FUNCTION);
|
||||
symbolMap.AddFunction(temp,func.stubAddr,8);
|
||||
|
||||
// Keep track and actually hook it up if possible.
|
||||
importedFuncs.push_back(func);
|
||||
|
@ -496,6 +499,7 @@ void WriteVarSymbol(u32 exportAddress, u32 relocAddress, u8 type, bool reverse =
|
|||
// We add 1 in that case so that it ends up the right value.
|
||||
u16 high = (full >> 16) + ((full & 0x8000) ? 1 : 0);
|
||||
Memory::Write_U32((it->data & ~0xFFFF) | high, it->addr);
|
||||
currentMIPS->InvalidateICache(it->addr, 4);
|
||||
}
|
||||
lastHI16Processed = true;
|
||||
}
|
||||
|
@ -692,7 +696,7 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
}
|
||||
*magic = *magicPtr;
|
||||
if (*magic == 0x5053507e) { // "~PSP"
|
||||
INFO_LOG(SCEMODULE, "Decrypting ~PSP file");
|
||||
DEBUG_LOG(SCEMODULE, "Decrypting ~PSP file");
|
||||
PSP_Header *head = (PSP_Header*)ptr;
|
||||
const u8 *in = ptr;
|
||||
u32 size = head->elf_size;
|
||||
|
@ -714,12 +718,13 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
module->nm.entry_addr = -1;
|
||||
module->nm.gp_value = -1;
|
||||
return module;
|
||||
}
|
||||
else if (ret <= 0)
|
||||
{
|
||||
} else if (ret <= 0) {
|
||||
ERROR_LOG(SCEMODULE, "Failed decrypting PRX! That's not normal! ret = %i\n", ret);
|
||||
Reporting::ReportMessage("Failed decrypting the PRX (ret = %i, size = %i, psp_size = %i)!", ret, head->elf_size, head->psp_size);
|
||||
// Fall through to safe exit in the next check.
|
||||
} else {
|
||||
// TODO: Is this right?
|
||||
module->nm.bss_size = head->bss_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -769,6 +774,15 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
else
|
||||
modinfo = (PspModuleInfo *)Memory::GetPointer(reader.GetSegmentVaddr(0) + (reader.GetSegmentPaddr(0) & 0x7FFFFFFF) - reader.GetSegmentOffset(0));
|
||||
|
||||
module->nm.nsegment = reader.GetNumSegments();
|
||||
module->nm.attribute = modinfo->moduleAttrs;
|
||||
module->nm.version[0] = modinfo->moduleVersion & 0xFF;
|
||||
module->nm.version[1] = modinfo->moduleVersion >> 8;
|
||||
module->nm.data_size = 0;
|
||||
// TODO: Is summing them up correct? Must not be since the numbers aren't exactly right.
|
||||
for (int i = 0; i < reader.GetNumSegments(); ++i) {
|
||||
module->nm.data_size += reader.GetSegmentDataSize(i);
|
||||
}
|
||||
module->nm.gp_value = modinfo->gp;
|
||||
strncpy(module->nm.name, modinfo->name, 28);
|
||||
|
||||
|
@ -794,6 +808,12 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
u32 textStart = reader.GetSectionAddr(textSection);
|
||||
u32 textSize = reader.GetSectionSize(textSection);
|
||||
|
||||
module->nm.text_addr = textStart;
|
||||
// TODO: This value appears to be wrong. In one example, the PSP has a value > 0x1000 bigger.
|
||||
module->nm.text_size = textSize;
|
||||
// TODO: It seems like the data size excludes the text size, which kinda makes sense?
|
||||
module->nm.data_size -= textSize;
|
||||
|
||||
#if !defined(USING_GLES2)
|
||||
if (!reader.LoadSymbols())
|
||||
MIPSAnalyst::ScanForFunctions(textStart, textStart+textSize);
|
||||
|
@ -836,6 +856,8 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
u32_le *entryPos = (u32_le *)Memory::GetPointer(modinfo->libstub);
|
||||
u32_le *entryEnd = (u32_le *)Memory::GetPointer(modinfo->libstubend);
|
||||
|
||||
u32_le firstImportStubAddr = 0;
|
||||
|
||||
bool needReport = false;
|
||||
while (entryPos < entryEnd) {
|
||||
PspLibStubEntry *entry = (PspLibStubEntry *)entryPos;
|
||||
|
@ -880,6 +902,9 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
func.stubAddr = entry->firstSymAddr + i * 8;
|
||||
module->ImportFunc(func);
|
||||
}
|
||||
|
||||
if (!firstImportStubAddr || firstImportStubAddr > entry->firstSymAddr)
|
||||
firstImportStubAddr = entry->firstSymAddr;
|
||||
} else if (entry->numFuncs > 0) {
|
||||
WARN_LOG_REPORT(LOADER, "Module entry with %d imports but no valid address", entry->numFuncs);
|
||||
needReport = true;
|
||||
|
@ -943,6 +968,15 @@ Module *__KernelLoadELFFromPtr(const u8 *ptr, u32 loadAddress, std::string *erro
|
|||
Reporting::ReportMessage("Module linking debug info:\n%s", debugInfo.c_str());
|
||||
}
|
||||
|
||||
if (textSection == -1) {
|
||||
u32 textStart = reader.GetVaddr();
|
||||
u32 textEnd = firstImportStubAddr - 4;
|
||||
#if !defined(USING_GLES2)
|
||||
if (!reader.LoadSymbols())
|
||||
MIPSAnalyst::ScanForFunctions(textStart, textEnd);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Look at the exports, too.
|
||||
|
||||
struct PspLibEntEntry
|
||||
|
@ -1139,7 +1173,22 @@ Module *__KernelLoadModule(u8 *fileptr, SceKernelLMOption *options, std::string
|
|||
for (int i = 1; i < numfiles; i++)
|
||||
memcpy(&offsets[i], fileptr + 12 + 4*i, 4);
|
||||
u32 magic = 0;
|
||||
module = __KernelLoadELFFromPtr(fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string, &magic);
|
||||
|
||||
|
||||
u8 *temp = 0;
|
||||
if (offsets[5] & 3) {
|
||||
// Our loader does NOT like to load from an unaligned address on ARM!
|
||||
size_t size = offsets[6] - offsets[5];
|
||||
temp = new u8[size];
|
||||
memcpy(temp, fileptr + offsets[5], size);
|
||||
INFO_LOG(LOADER, "Elf unaligned, aligning!")
|
||||
}
|
||||
|
||||
module = __KernelLoadELFFromPtr(temp ? temp : fileptr + offsets[5], PSP_GetDefaultLoadAddress(), error_string, &magic);
|
||||
|
||||
if (temp) {
|
||||
delete [] temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1208,6 +1257,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
|
|||
//HLE needs to be reset here
|
||||
HLEShutdown();
|
||||
HLEInit();
|
||||
GPU_Reinitialize();
|
||||
}
|
||||
|
||||
__KernelModuleInit();
|
||||
|
@ -1752,21 +1802,53 @@ u32 sceKernelQueryModuleInfo(u32 uid, u32 infoAddr)
|
|||
ERROR_LOG(SCEMODULE, "sceKernelQueryModuleInfo(%i, %08x) - bad infoAddr", uid, infoAddr);
|
||||
return -1;
|
||||
}
|
||||
ModuleInfo info;
|
||||
memcpy(info.segmentaddr, module->nm.segmentaddr, sizeof(info.segmentaddr));
|
||||
memcpy(info.segmentsize, module->nm.segmentsize, sizeof(info.segmentsize));
|
||||
info.nsegment = module->nm.nsegment;
|
||||
info.entry_addr = module->nm.entry_addr;
|
||||
info.gp_value = module->nm.gp_value;
|
||||
info.text_addr = module->nm.text_addr;
|
||||
info.text_size = module->nm.text_size;
|
||||
info.data_size = module->nm.data_size;
|
||||
info.bss_size = module->nm.bss_size;
|
||||
info.attribute = module->nm.attribute;
|
||||
info.version[0] = module->nm.version[0];
|
||||
info.version[1] = module->nm.version[1];
|
||||
memcpy(info.name, module->nm.name, 28);
|
||||
Memory::WriteStruct(infoAddr, &info);
|
||||
|
||||
PSPPointer<ModuleInfo> info;
|
||||
info = infoAddr;
|
||||
|
||||
memcpy(info->segmentaddr, module->nm.segmentaddr, sizeof(info->segmentaddr));
|
||||
memcpy(info->segmentsize, module->nm.segmentsize, sizeof(info->segmentsize));
|
||||
info->nsegment = module->nm.nsegment;
|
||||
info->entry_addr = module->nm.entry_addr;
|
||||
info->gp_value = module->nm.gp_value;
|
||||
info->text_addr = module->nm.text_addr;
|
||||
info->text_size = module->nm.text_size;
|
||||
info->data_size = module->nm.data_size;
|
||||
info->bss_size = module->nm.bss_size;
|
||||
|
||||
// Even if it's bigger, if it's not exactly 96, skip this extra data.
|
||||
// Even if it's 0, the above are all written though.
|
||||
if (info->size == 96) {
|
||||
info->attribute = module->nm.attribute;
|
||||
info->version[0] = module->nm.version[0];
|
||||
info->version[1] = module->nm.version[1];
|
||||
memcpy(info->name, module->nm.name, 28);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceKernelGetModuleIdList(u32 resultBuffer, u32 resultBufferSize, u32 idCountAddr)
|
||||
{
|
||||
ERROR_LOG(SCEMODULE, "UNTESTED sceKernelGetModuleIdList(%08x, %i, %08x)", resultBuffer, resultBufferSize, idCountAddr);
|
||||
|
||||
int idCount = 0;
|
||||
u32 resultBufferOffset = 0;
|
||||
|
||||
u32 error;
|
||||
for (auto mod = loadedModules.begin(), modend = loadedModules.end(); mod != modend; ++mod) {
|
||||
Module *module = kernelObjects.Get<Module>(*mod, error);
|
||||
if (!module->isFake) {
|
||||
if (resultBufferOffset < (int)resultBufferSize) {
|
||||
Memory::Write_U32(module->GetUID(), resultBuffer + resultBufferOffset);
|
||||
resultBufferOffset += 4;
|
||||
}
|
||||
idCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Memory::Write_U32(idCount, idCountAddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1805,7 +1887,7 @@ const HLEFunction ModuleMgrForUser[] =
|
|||
{0xf0a26395,WrapU_V<sceKernelGetModuleId>, "sceKernelGetModuleId"},
|
||||
{0x8f2df740,WrapU_UUUUU<sceKernelStopUnloadSelfModuleWithStatus>,"sceKernelStopUnloadSelfModuleWithStatus"},
|
||||
{0xfef27dc1,&WrapU_CU<sceKernelLoadModuleDNAS> , "sceKernelLoadModuleDNAS"},
|
||||
{0x644395e2,0,"sceKernelGetModuleIdList"},
|
||||
{0x644395e2,WrapU_UUU<sceKernelGetModuleIdList>,"sceKernelGetModuleIdList"},
|
||||
{0xf2d8d1b4,&WrapU_CUU<sceKernelLoadModuleNpDrm>,"sceKernelLoadModuleNpDrm"},
|
||||
{0xe4c4211c,0,"ModuleMgrForUser_E4C4211C"},
|
||||
{0xfbe27467,0,"ModuleMgrForUser_FBE27467"},
|
||||
|
|
|
@ -68,7 +68,7 @@ const WaitTypeNames waitTypeNames[] = {
|
|||
{ WAITTYPE_GELISTSYNC, "GeListSync" },
|
||||
{ WAITTYPE_MODULE, "Module" },
|
||||
{ WAITTYPE_HLEDELAY, "HleDelay" },
|
||||
{ WAITTYPE_TLS, "TLS" },
|
||||
{ WAITTYPE_TLSPL, "TLS" },
|
||||
{ WAITTYPE_VMEM, "Volatile Mem" },
|
||||
{ WAITTYPE_ASYNCIO, "AsyncIO" },
|
||||
};
|
||||
|
@ -520,7 +520,7 @@ public:
|
|||
|
||||
virtual void DoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("Thread", 1, 2);
|
||||
auto s = p.Section("Thread", 1, 4);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -530,8 +530,27 @@ public:
|
|||
p.Do(isProcessingCallbacks);
|
||||
p.Do(currentMipscallId);
|
||||
p.Do(currentCallbackId);
|
||||
|
||||
// TODO: How do I "version" adding a DoState method to ThreadContext?
|
||||
p.Do(context);
|
||||
|
||||
if (s <= 3)
|
||||
{
|
||||
// We must have been loading an old state if we're here.
|
||||
// Reorder VFPU data to new order.
|
||||
float temp[128];
|
||||
memcpy(temp, context.v, 128 * sizeof(float));
|
||||
for (int i = 0; i < 128; i++) {
|
||||
context.v[voffset[i]] = temp[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (s <= 2)
|
||||
{
|
||||
context.other[4] = context.other[5];
|
||||
context.other[3] = context.other[4];
|
||||
}
|
||||
|
||||
p.Do(callbacks);
|
||||
|
||||
p.Do(pendingMipsCalls);
|
||||
|
@ -1928,8 +1947,7 @@ void ThreadContext::reset()
|
|||
vfpuCtrl[VFPU_CTRL_RCX6] = 0x3f800000;
|
||||
vfpuCtrl[VFPU_CTRL_RCX7] = 0x3f800000;
|
||||
fpcond = 0;
|
||||
fcr0 = 0;
|
||||
fcr31 = 0;
|
||||
fcr31 = 0x00000e00;
|
||||
hi = 0xDEADBEEF;
|
||||
lo = 0xDEADBEEF;
|
||||
}
|
||||
|
@ -2328,10 +2346,9 @@ int sceKernelRotateThreadReadyQueue(int priority)
|
|||
// Yield the next thread of this priority to all other threads of same priority.
|
||||
else
|
||||
threadReadyQueue.rotate(priority);
|
||||
|
||||
hleReSchedule("rotatethreadreadyqueue");
|
||||
}
|
||||
|
||||
hleReSchedule("rotatethreadreadyqueue");
|
||||
hleEatCycles(250);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2515,6 +2532,7 @@ int sceKernelChangeThreadPriority(SceUID threadID, int priority)
|
|||
if (thread->isReady())
|
||||
threadReadyQueue.push_back(thread->nt.currentPriority, threadID);
|
||||
|
||||
hleEatCycles(450);
|
||||
hleReSchedule("change thread priority");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ enum WaitType
|
|||
WAITTYPE_GELISTSYNC = 18,
|
||||
WAITTYPE_MODULE = 19,
|
||||
WAITTYPE_HLEDELAY = 20,
|
||||
WAITTYPE_TLS = 21,
|
||||
WAITTYPE_TLSPL = 21,
|
||||
WAITTYPE_VMEM = 22,
|
||||
WAITTYPE_ASYNCIO = 23,
|
||||
|
||||
|
@ -132,7 +132,6 @@ struct ThreadContext
|
|||
u32 hi;
|
||||
u32 lo;
|
||||
|
||||
u32 fcr0;
|
||||
u32 fcr31;
|
||||
u32 fpcond;
|
||||
};
|
||||
|
|
|
@ -71,7 +71,7 @@ u32 sceKernelGetSystemTimeLow()
|
|||
|
||||
u64 sceKernelGetSystemTimeWide()
|
||||
{
|
||||
u64 t = CoreTiming::GetGlobalTimeUs();
|
||||
u64 t = CoreTiming::GetGlobalTimeUsScaled();
|
||||
DEBUG_LOG(SCEKERNEL,"%i=sceKernelGetSystemTimeWide()",(u32)t);
|
||||
hleEatCycles(250);
|
||||
hleReSchedule("system time");
|
||||
|
|
|
@ -612,8 +612,8 @@ u32 sceMp3GetFrameNum(u32 mp3) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceMp3GetVersion(u32 mp3) {
|
||||
DEBUG_LOG(ME, "sceMp3GetVersion(%08x)", mp3);
|
||||
u32 sceMp3GetMPEGVersion(u32 mp3) {
|
||||
DEBUG_LOG(ME, "sceMp3GetMPEGVersion(%08x)", mp3);
|
||||
Mp3Context *ctx = getMp3Ctx(mp3);
|
||||
if (!ctx) {
|
||||
ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3);
|
||||
|
@ -623,8 +623,8 @@ u32 sceMp3GetVersion(u32 mp3) {
|
|||
return ctx->mp3Version;
|
||||
}
|
||||
|
||||
u32 sceMp3ResetPlayPosition2(u32 mp3, int position) {
|
||||
DEBUG_LOG(ME, "sceMp3ResetPlayPosition2(%08x, %i)", mp3, position);
|
||||
u32 sceMp3ResetPlayPositionByFrame(u32 mp3, int position) {
|
||||
DEBUG_LOG(ME, "sceMp3ResetPlayPositionByFrame(%08x, %i)", mp3, position);
|
||||
Mp3Context *ctx = getMp3Ctx(mp3);
|
||||
if (!ctx) {
|
||||
ERROR_LOG(ME, "%s: bad mp3 handle %08x", __FUNCTION__, mp3);
|
||||
|
@ -635,13 +635,13 @@ u32 sceMp3ResetPlayPosition2(u32 mp3, int position) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
u32 sceMp3_1B839B83() {
|
||||
ERROR_LOG_REPORT(ME, "UNIMPL sceMp3_1B839B83(...)");
|
||||
u32 sceMp3LowLevelInit() {
|
||||
ERROR_LOG_REPORT(ME, "UNIMPL sceMp3LowLevelInit(...)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceMp3_E3EE2C81() {
|
||||
ERROR_LOG_REPORT(ME, "UNIMPL sceMp3_E3EE2C81(...)");
|
||||
u32 sceMp3LowLevelDecode() {
|
||||
ERROR_LOG_REPORT(ME, "UNIMPL sceMp3LowLevelDecode(...)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -665,11 +665,11 @@ const HLEFunction sceMp3[] = {
|
|||
{0xD0A56296,WrapI_U<sceMp3CheckStreamDataNeeded>,"sceMp3CheckStreamDataNeeded"},
|
||||
{0xD8F54A51,WrapI_U<sceMp3GetLoopNum>,"sceMp3GetLoopNum"},
|
||||
{0xF5478233,WrapI_U<sceMp3ReleaseMp3Handle>,"sceMp3ReleaseMp3Handle"},
|
||||
{0xAE6D2027,WrapU_U<sceMp3GetVersion>,"sceMp3GetVersion"}, // Incorrect function name
|
||||
{0xAE6D2027,WrapU_U<sceMp3GetMPEGVersion>,"sceMp3GetMPEGVersion"},
|
||||
{0x3548AEC8,WrapU_U<sceMp3GetFrameNum>,"sceMp3GetFrameNum"},
|
||||
{0x0840e808,WrapU_UI<sceMp3ResetPlayPosition2>,"sceMp3ResetPlayPosition2"}, // Incorrect function name
|
||||
{0x1b839b83,WrapU_V<sceMp3_1B839B83>,"sceMp3_1B839B83"},
|
||||
{0xe3ee2c81,WrapU_V<sceMp3_E3EE2C81>,"sceMp3_E3EE2C81"}
|
||||
{0x0840e808,WrapU_UI<sceMp3ResetPlayPositionByFrame>,"sceMp3ResetPlayPositionByFrame"},
|
||||
{0x1b839b83,WrapU_V<sceMp3LowLevelInit>,"sceMp3LowLevelInit"},
|
||||
{0xe3ee2c81,WrapU_V<sceMp3LowLevelDecode>,"sceMp3LowLevelDecode"}
|
||||
};
|
||||
|
||||
void Register_sceMp3() {
|
||||
|
|
|
@ -668,7 +668,7 @@ u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 i
|
|||
DEBUG_LOG(ME, "*buffer = %08x, *init = %08x", buffer, init);
|
||||
|
||||
if (ctx->mediaengine->stepVideo(ctx->videoPixelMode)) {
|
||||
int bufferSize = ctx->mediaengine->writeVideoImage(Memory::GetPointer(buffer), frameWidth, ctx->videoPixelMode);
|
||||
int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode);
|
||||
gpu->InvalidateCache(buffer, bufferSize, GPU_INVALIDATE_SAFE);
|
||||
ctx->avc.avcFrameStatus = 1;
|
||||
ctx->videoFrameCount++;
|
||||
|
@ -915,7 +915,13 @@ int sceMpegRingbufferAvailableSize(u32 ringbufferAddr)
|
|||
}
|
||||
|
||||
hleEatCycles(2020);
|
||||
DEBUG_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr);
|
||||
static int lastFree = 0;
|
||||
if (lastFree != ringbuffer->packetsFree) {
|
||||
DEBUG_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr);
|
||||
lastFree = ringbuffer->packetsFree;
|
||||
} else {
|
||||
VERBOSE_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packetsFree, ringbufferAddr);
|
||||
}
|
||||
return ringbuffer->packetsFree;
|
||||
}
|
||||
|
||||
|
@ -1256,7 +1262,7 @@ u32 sceMpegAtracDecode(u32 mpeg, u32 auAddr, u32 bufferAddr, int init)
|
|||
avcAu.read(auAddr);
|
||||
|
||||
Memory::Memset(bufferAddr, 0, MPEG_ATRAC_ES_OUTPUT_SIZE);
|
||||
ctx->mediaengine->getAudioSamples(Memory::GetPointer(bufferAddr));
|
||||
ctx->mediaengine->getAudioSamples(bufferAddr);
|
||||
avcAu.pts = ctx->mediaengine->getAudioTimeStamp() + ctx->mpegFirstTimestamp;
|
||||
|
||||
avcAu.write(auAddr);
|
||||
|
@ -1280,7 +1286,7 @@ u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth, u32 d
|
|||
int y = Memory::Read_U32(rangeAddr + 4);
|
||||
int width = Memory::Read_U32(rangeAddr + 8);
|
||||
int height = Memory::Read_U32(rangeAddr + 12);
|
||||
int destSize = ctx->mediaengine->writeVideoImageWithRange(Memory::GetPointer(destAddr), frameWidth, ctx->videoPixelMode,
|
||||
int destSize = ctx->mediaengine->writeVideoImageWithRange(destAddr, frameWidth, ctx->videoPixelMode,
|
||||
x, y, width, height);
|
||||
|
||||
gpu->InvalidateCache(destAddr, destSize, GPU_INVALIDATE_SAFE);
|
||||
|
|
|
@ -15,17 +15,19 @@
|
|||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include "net/resolve.h"
|
||||
#include "util/text/parsers.h"
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "HLE.h"
|
||||
#include "../MIPS/MIPS.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/MIPS/MIPS.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
#include "sceKernel.h"
|
||||
#include "sceKernelThread.h"
|
||||
#include "sceKernelMutex.h"
|
||||
#include "sceUtility.h"
|
||||
|
||||
#include "net/resolve.h"
|
||||
|
||||
static bool netInited;
|
||||
static bool netInetInited;
|
||||
static bool netApctlInited;
|
||||
|
@ -130,22 +132,29 @@ u32 sceNetTerm() {
|
|||
}
|
||||
|
||||
u32 sceWlanGetEtherAddr(u32 addrAddr) {
|
||||
static const u8 fakeEtherAddr[6] = { 1, 2, 3, 4, 5, 6 };
|
||||
// Read MAC Address from config
|
||||
uint8_t mac[6] = {0};
|
||||
if (!ParseMacAddress(g_Config.localMacAddress.c_str(), mac)) {
|
||||
ERROR_LOG(SCENET, "Error parsing mac address %s", g_Config.localMacAddress.c_str());
|
||||
}
|
||||
DEBUG_LOG(SCENET, "sceWlanGetEtherAddr(%08x)", addrAddr);
|
||||
for (int i = 0; i < 6; i++)
|
||||
Memory::Write_U8(fakeEtherAddr[i], addrAddr + i);
|
||||
|
||||
Memory::Write_U8(mac[i], addrAddr + i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceNetGetLocalEtherAddr(u32 addrAddr) {
|
||||
return sceWlanGetEtherAddr(addrAddr);
|
||||
}
|
||||
|
||||
u32 sceWlanDevIsPowerOn() {
|
||||
DEBUG_LOG(SCENET, "UNTESTED 0=sceWlanDevIsPowerOn()");
|
||||
return 0;
|
||||
DEBUG_LOG(SCENET, "UNTESTED sceWlanDevIsPowerOn()");
|
||||
return g_Config.bEnableWlan ? 1 : 0;
|
||||
}
|
||||
|
||||
u32 sceWlanGetSwitchState() {
|
||||
DEBUG_LOG(SCENET, "UNTESTED sceWlanGetSwitchState()");
|
||||
return 0;
|
||||
return g_Config.bEnableWlan ? 1 : 0;
|
||||
}
|
||||
|
||||
// Probably a void function, but often returns a useful value.
|
||||
|
@ -348,7 +357,7 @@ const HLEFunction sceNet[] = {
|
|||
{0x281928A9, WrapU_V<sceNetTerm>, "sceNetTerm"},
|
||||
{0x89360950, WrapI_UU<sceNetEtherNtostr>, "sceNetEtherNtostr"},
|
||||
{0xd27961c9, WrapI_UU<sceNetEtherStrton>, "sceNetEtherStrton"},
|
||||
{0x0bf0a3ae, 0, "sceNetGetLocalEtherAddr"},
|
||||
{0x0bf0a3ae, WrapU_U<sceNetGetLocalEtherAddr>, "sceNetGetLocalEtherAddr"},
|
||||
{0x50647530, 0, "sceNetFreeThreadinfo"},
|
||||
{0xcc393e48, WrapI_U<sceNetGetMallocStat>, "sceNetGetMallocStat"},
|
||||
{0xad6844c6, 0, "sceNetThreadAbort"},
|
||||
|
@ -385,7 +394,7 @@ const HLEFunction sceNetInet[] = {
|
|||
{0xcda85c99, WrapI_IUUU<sceNetInetRecv>, "sceNetInetRecv"},
|
||||
{0xc91142e4, 0, "sceNetInetRecvfrom"},
|
||||
{0xeece61d2, 0, "sceNetInetRecvmsg"},
|
||||
{0x7aa671bc, WrapI_IUUU<sceNetInetRecv>, "sceNetInetSend"},
|
||||
{0x7aa671bc, WrapI_IUUU<sceNetInetSend>, "sceNetInetSend"},
|
||||
{0x05038fc7, 0, "sceNetInetSendto"},
|
||||
{0x774e36f4, 0, "sceNetInetSendmsg"},
|
||||
{0xfbabe411, WrapI_V<sceNetInetGetErrno>, "sceNetInetGetErrno"},
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -24,3 +24,6 @@ void Register_sceNetAdhoc();
|
|||
void __NetAdhocInit();
|
||||
void __NetAdhocShutdown();
|
||||
void __NetAdhocDoState(PointerWrap &p);
|
||||
|
||||
// I have to call this from netdialog
|
||||
int sceNetAdhocctlCreate(const char * groupName);
|
||||
|
|
|
@ -46,9 +46,22 @@ void Register_sceNp()
|
|||
RegisterModule("sceNp", ARRAY_SIZE(sceNp), sceNp);
|
||||
}
|
||||
|
||||
int sceNpAuth_4EC1F667()
|
||||
{
|
||||
// No parameters
|
||||
ERROR_LOG(HLE, "UNIMPL sceNpAuth_4EC1F667()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceNpAuth_A1DE86F8(u32 poolSize, u32 stackSize, u32 threadPrio)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL sceNpAuth_A1DE86F8(%08x, %08x, %08x)",poolSize, stackSize, threadPrio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceNpAuth[] = {
|
||||
{0x4EC1F667, 0, "sceNpAuth_4EC1F667"},
|
||||
{0xA1DE86F8, 0, "sceNpAuth_A1DE86F8"},
|
||||
{0x4EC1F667, &WrapI_V<sceNpAuth_4EC1F667>, "sceNpAuth_4EC1F667"},
|
||||
{0xA1DE86F8, &WrapI_UUU<sceNpAuth_A1DE86F8>, "sceNpAuth_A1DE86F8"},
|
||||
};
|
||||
|
||||
void Register_sceNpAuth()
|
||||
|
@ -56,9 +69,22 @@ void Register_sceNpAuth()
|
|||
RegisterModule("sceNpAuth", ARRAY_SIZE(sceNpAuth), sceNpAuth);
|
||||
}
|
||||
|
||||
int sceNpService_00ACFAC3()
|
||||
{
|
||||
// No parameters
|
||||
ERROR_LOG(HLE, "UNIMPL sceNpService_00ACFAC3()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceNpService_0F8F5821(u32 poolSize, u32 stackSize, u32 threadPrio)
|
||||
{
|
||||
ERROR_LOG(HLE, "UNIMPL sceNpService_0F8F5821(%08x, %08x, %08x)",poolSize, stackSize, threadPrio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const HLEFunction sceNpService[] = {
|
||||
{0x00ACFAC3, 0, "sceNpService_00ACFAC3"},
|
||||
{0x0F8F5821, 0, "sceNpService_0F8F5821"},
|
||||
{0x00ACFAC3, &WrapI_V<sceNpService_00ACFAC3>, "sceNpService_00ACFAC3"},
|
||||
{0x0F8F5821, &WrapI_UUU<sceNpService_0F8F5821>, "sceNpService_0F8F5821"},
|
||||
};
|
||||
|
||||
void Register_sceNpService()
|
||||
|
|
|
@ -45,9 +45,6 @@ const int PSP_POWER_CB_BATTERY_FULL = 0x00000064;
|
|||
|
||||
const int POWER_CB_AUTO = -1;
|
||||
|
||||
const int PSP_MODEL_FAT = 0;
|
||||
const int PSP_MODEL_SLIM = 1;
|
||||
|
||||
const int numberOfCBPowerSlots = 16;
|
||||
const int numberOfCBPowerSlotsPrivate = 32;
|
||||
|
||||
|
@ -55,7 +52,7 @@ static bool volatileMemLocked;
|
|||
static int powerCbSlots[numberOfCBPowerSlots];
|
||||
static std::vector<VolatileWaitingThread> volatileWaitingThreads;
|
||||
|
||||
// this should belong here on in CoreTiming?
|
||||
// Should this belong here, or in CoreTiming?
|
||||
static int pllFreq = 222;
|
||||
static int busFreq = 111;
|
||||
|
||||
|
@ -412,7 +409,9 @@ int scePowerTick() {
|
|||
|
||||
|
||||
u32 IsPSPNonFat() {
|
||||
return PSP_MODEL_FAT;
|
||||
DEBUG_LOG(HLE, "%d=scePower_a85880d0_IsPSPNonFat()", g_Config.iPSPModel);
|
||||
|
||||
return g_Config.iPSPModel;
|
||||
}
|
||||
|
||||
static const HLEFunction scePower[] = {
|
||||
|
|
|
@ -1019,7 +1019,7 @@ int scePsmfPlayerGetVideoData(u32 psmfPlayer, u32 videoDataAddr)
|
|||
u32 displaybuf = Memory::Read_U32(videoDataAddr + 4);
|
||||
int displaypts = Memory::Read_U32(videoDataAddr + 8);
|
||||
if (psmfplayer->mediaengine->stepVideo(videoPixelMode)) {
|
||||
int displaybufSize = psmfplayer->mediaengine->writeVideoImage(Memory::GetPointer(displaybuf), frameWidth, videoPixelMode);
|
||||
int displaybufSize = psmfplayer->mediaengine->writeVideoImage(displaybuf, frameWidth, videoPixelMode);
|
||||
gpu->InvalidateCache(displaybuf, displaybufSize, GPU_INVALIDATE_SAFE);
|
||||
}
|
||||
psmfplayer->psmfPlayerAvcAu.pts = psmfplayer->mediaengine->getVideoTimeStamp();
|
||||
|
@ -1050,7 +1050,7 @@ int scePsmfPlayerGetAudioData(u32 psmfPlayer, u32 audioDataAddr)
|
|||
DEBUG_LOG(ME, "scePsmfPlayerGetAudioData(%08x, %08x)", psmfPlayer, audioDataAddr);
|
||||
if (Memory::IsValidAddress(audioDataAddr)) {
|
||||
Memory::Memset(audioDataAddr, 0, audioSamplesBytes);
|
||||
psmfplayer->mediaengine->getAudioSamples(Memory::GetPointer(audioDataAddr));
|
||||
psmfplayer->mediaengine->getAudioSamples(audioDataAddr);
|
||||
}
|
||||
int ret = psmfplayer->mediaengine->IsNoAudioData() ? (int)ERROR_PSMFPLAYER_NO_MORE_DATA : 0;
|
||||
return hleDelayResult(ret, "psmfPlayer audio decode", 3000);
|
||||
|
@ -1288,8 +1288,8 @@ const HLEFunction scePsmf[] = {
|
|||
{0x4E624A34, WrapU_UIU<scePsmfGetEPWithId>, "scePsmfGetEPWithId"},
|
||||
{0x7C0E7AC3, WrapU_UUU<scePsmfGetEPWithTimestamp>, "scePsmfGetEPWithTimestamp"},
|
||||
{0x5F457515, WrapU_UU<scePsmfGetEPidWithTimestamp>, "scePsmfGetEPidWithTimestamp"},
|
||||
{0x43ac7dbb, 0, "scePsmf_43AC7DBB"},
|
||||
{0xde78e9fc, 0, "scePsmf_DE78E9FC"},
|
||||
{0x43ac7dbb, 0, "scePsmfGetPsmfMark"},
|
||||
{0xde78e9fc, 0, "scePsmfGetNumberOfPsmfMarks"},
|
||||
};
|
||||
|
||||
const HLEFunction scePsmfPlayer[] =
|
||||
|
|
|
@ -44,6 +44,10 @@ const u64 rtcMagicOffset = 62135596800000000ULL;
|
|||
// This is the # of microseconds between January 1, 0001 and January 1, 1601 (for Win32 FILETIME.)
|
||||
const u64 rtcFiletimeOffset = 50491123200000000ULL;
|
||||
|
||||
// 400 years is a convenient number, since leap days and everything cycle every 400 years.
|
||||
// 400 years is in other words 20871 full weeks.
|
||||
const u64 rtc400YearTicks = (u64)20871 * 7 * 24 * 3600 * 1000000ULL;
|
||||
|
||||
const int PSP_TIME_INVALID_YEAR = -1;
|
||||
const int PSP_TIME_INVALID_MONTH = -2;
|
||||
const int PSP_TIME_INVALID_DAY = -3;
|
||||
|
@ -153,7 +157,7 @@ void __RtcTmToPspTime(ScePspDateTime &t, tm *val)
|
|||
void __RtcTicksToPspTime(ScePspDateTime &t, u64 ticks)
|
||||
{
|
||||
int numYearAdd = 0;
|
||||
if(ticks < 1000000ULL)
|
||||
if (ticks < 1000000ULL)
|
||||
{
|
||||
t.year = 1;
|
||||
t.month = 1;
|
||||
|
@ -164,16 +168,18 @@ void __RtcTicksToPspTime(ScePspDateTime &t, u64 ticks)
|
|||
t.microsecond = ticks % 1000000ULL;
|
||||
return;
|
||||
}
|
||||
else if(ticks < rtcMagicOffset )
|
||||
else if (ticks < rtcMagicOffset)
|
||||
{
|
||||
// Need to get a year past 1970 for gmtime
|
||||
// Add enough 400 year to pass over 1970.
|
||||
// Each 400 year are equal
|
||||
// 400 year is 20871 weeks
|
||||
u64 ticks400Y = (u64)20871 * 7 * 24 * 3600 * 1000000ULL;
|
||||
numYearAdd = (int) ((rtcMagicOffset - ticks) / ticks400Y + 1);
|
||||
ticks += ticks400Y * numYearAdd;
|
||||
numYearAdd = (int) ((rtcMagicOffset - ticks) / rtc400YearTicks + 1);
|
||||
ticks += rtc400YearTicks * numYearAdd;
|
||||
}
|
||||
|
||||
while (ticks >= rtcMagicOffset + rtc400YearTicks)
|
||||
{
|
||||
ticks -= rtc400YearTicks;
|
||||
--numYearAdd;
|
||||
}
|
||||
|
||||
time_t time = (ticks - rtcMagicOffset) / 1000000ULL;
|
||||
|
@ -207,10 +213,22 @@ u64 __RtcPspTimeToTicks(ScePspDateTime &pt)
|
|||
local.tm_sec = pt.second;
|
||||
local.tm_isdst = 0;
|
||||
|
||||
s64 tickOffset = 0;
|
||||
while (local.tm_year < 70)
|
||||
{
|
||||
tickOffset -= rtc400YearTicks;
|
||||
local.tm_year += 400;
|
||||
}
|
||||
while (local.tm_year >= 470)
|
||||
{
|
||||
tickOffset += rtc400YearTicks;
|
||||
local.tm_year -= 400;
|
||||
}
|
||||
|
||||
time_t seconds = rtc_timegm(&local);
|
||||
u64 result = rtcMagicOffset + (u64) seconds * 1000000ULL;
|
||||
result += pt.microsecond;
|
||||
return result;
|
||||
return result + tickOffset;
|
||||
}
|
||||
|
||||
bool __RtcValidatePspTime(ScePspDateTime &t)
|
||||
|
@ -226,19 +244,21 @@ u32 sceRtcGetTickResolution()
|
|||
|
||||
u32 sceRtcGetCurrentTick(u32 tickPtr)
|
||||
{
|
||||
//Don't spam the log
|
||||
//DEBUG_LOG(SCERTC, "sceRtcGetCurrentTick(%08x)", tickPtr);
|
||||
VERBOSE_LOG(SCERTC, "sceRtcGetCurrentTick(%08x)", tickPtr);
|
||||
|
||||
u64 curTick = __RtcGetCurrentTick();
|
||||
if (Memory::IsValidAddress(tickPtr))
|
||||
Memory::Write_U64(curTick, tickPtr);
|
||||
hleEatCycles(300);
|
||||
hleReSchedule("rtc current tick");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 sceRtcGetAcculumativeTime()
|
||||
u64 sceRtcGetAccumulativeTime()
|
||||
{
|
||||
DEBUG_LOG(SCERTC, "sceRtcGetAcculumativeTime()");
|
||||
DEBUG_LOG(SCERTC, "sceRtcGetAccumulativeTime()");
|
||||
hleEatCycles(300);
|
||||
hleReSchedule("rtc accumulative time");
|
||||
return __RtcGetCurrentTick();
|
||||
}
|
||||
|
||||
|
@ -268,6 +288,7 @@ u32 sceRtcGetCurrentClock(u32 pspTimePtr, int tz)
|
|||
Memory::WriteStruct(pspTimePtr, &ret);
|
||||
|
||||
hleEatCycles(1900);
|
||||
hleReSchedule("rtc current clock");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -293,6 +314,7 @@ u32 sceRtcGetCurrentClockLocalTime(u32 pspTimePtr)
|
|||
Memory::WriteStruct(pspTimePtr, &ret);
|
||||
|
||||
hleEatCycles(2000);
|
||||
hleReSchedule("rtc current clock local");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -365,41 +387,45 @@ u32 sceRtcGetDayOfWeek(u32 year, u32 month, u32 day)
|
|||
return local.tm_wday;
|
||||
}
|
||||
|
||||
u32 sceRtcGetDaysInMonth(u32 year, u32 month)
|
||||
bool __RtcIsLeapYear(u32 year)
|
||||
{
|
||||
DEBUG_LOG(SCERTC, "sceRtcGetDaysInMonth(%d, %d)", year, month);
|
||||
u32 numberOfDays;
|
||||
|
||||
if (year == 0 || month == 0 || month > 12)
|
||||
return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
|
||||
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
|
||||
int __RtcDaysInMonth(u32 year, u32 month)
|
||||
{
|
||||
switch (month)
|
||||
{
|
||||
case 4:
|
||||
case 6:
|
||||
case 9:
|
||||
case 11:
|
||||
numberOfDays = 30;
|
||||
break;
|
||||
return 30;
|
||||
|
||||
case 2:
|
||||
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
|
||||
numberOfDays = 29;
|
||||
else
|
||||
numberOfDays = 28;
|
||||
break;
|
||||
if (__RtcIsLeapYear(year))
|
||||
return 29;
|
||||
return 28;
|
||||
|
||||
default:
|
||||
numberOfDays = 31;
|
||||
break;
|
||||
return 31;
|
||||
}
|
||||
}
|
||||
|
||||
return numberOfDays;
|
||||
u32 sceRtcGetDaysInMonth(u32 year, u32 month)
|
||||
{
|
||||
DEBUG_LOG(SCERTC, "sceRtcGetDaysInMonth(%d, %d)", year, month);
|
||||
|
||||
if (year == 0 || month == 0 || month > 12)
|
||||
return SCE_KERNEL_ERROR_INVALID_ARGUMENT;
|
||||
|
||||
return __RtcDaysInMonth(year, month);
|
||||
}
|
||||
|
||||
u32 sceRtcIsLeapYear(u32 year)
|
||||
{
|
||||
DEBUG_LOG(SCERTC, "sceRtcIsLeapYear(%d)", year);
|
||||
return (year % 4 == 0) && (!(year % 100 == 0) || (year % 400 == 0));
|
||||
return __RtcIsLeapYear(year) ? 1 : 0;
|
||||
}
|
||||
|
||||
int sceRtcConvertLocalTimeToUTC(u32 tickLocalPtr,u32 tickUTCPtr)
|
||||
|
@ -468,19 +494,19 @@ int sceRtcCheckValid(u32 datePtr)
|
|||
{
|
||||
return PSP_TIME_INVALID_DAY;
|
||||
}
|
||||
else if (pt.day > 31) // TODO: Needs to check actual days in month, including leaps
|
||||
else if (pt.day > __RtcDaysInMonth((s16)pt.year, (s16)pt.month))
|
||||
{
|
||||
return PSP_TIME_INVALID_DAY;
|
||||
}
|
||||
else if (pt.hour > 23)
|
||||
else if (pt.hour < 0 || pt.hour > 23)
|
||||
{
|
||||
return PSP_TIME_INVALID_HOUR;
|
||||
}
|
||||
else if (pt.minute > 59)
|
||||
else if (pt.minute < 0 || pt.minute > 59)
|
||||
{
|
||||
return PSP_TIME_INVALID_MINUTES;
|
||||
}
|
||||
else if (pt.second > 59)
|
||||
else if (pt.second < 0 || pt.second > 59)
|
||||
{
|
||||
return PSP_TIME_INVALID_SECONDS;
|
||||
}
|
||||
|
@ -749,7 +775,7 @@ int sceRtcTickAddHours(u32 destTickPtr, u32 srcTickPtr, int numHours)
|
|||
if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr))
|
||||
{
|
||||
s64 srcTick = (s64)Memory::Read_U64(srcTickPtr);
|
||||
srcTick += numHours*3600000000UL;
|
||||
srcTick += numHours * 3600ULL * 1000000ULL;
|
||||
Memory::Write_U64(srcTick, destTickPtr);
|
||||
}
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddMinutes(%d,%d,%d)", destTickPtr, srcTickPtr, numHours);
|
||||
|
@ -762,7 +788,7 @@ int sceRtcTickAddDays(u32 destTickPtr, u32 srcTickPtr, int numDays)
|
|||
{
|
||||
s64 srcTick = (s64)Memory::Read_U64(srcTickPtr);
|
||||
|
||||
srcTick += numDays*86400000000UL;
|
||||
srcTick += numDays * 86400ULL * 1000000ULL;
|
||||
Memory::Write_U64(srcTick, destTickPtr);
|
||||
}
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddDays(%d,%d,%d)", destTickPtr, srcTickPtr, numDays);
|
||||
|
@ -775,7 +801,7 @@ int sceRtcTickAddWeeks(u32 destTickPtr, u32 srcTickPtr, int numWeeks)
|
|||
{
|
||||
s64 srcTick = (s64)Memory::Read_U64(srcTickPtr);
|
||||
|
||||
srcTick += numWeeks*604800000000UL;
|
||||
srcTick += numWeeks * 7ULL * 86400ULL * 1000000ULL;
|
||||
Memory::Write_U64(srcTick, destTickPtr);
|
||||
}
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddWeeks(%d,%d,%d)", destTickPtr, srcTickPtr, numWeeks);
|
||||
|
@ -784,79 +810,69 @@ int sceRtcTickAddWeeks(u32 destTickPtr, u32 srcTickPtr, int numWeeks)
|
|||
|
||||
int sceRtcTickAddMonths(u32 destTickPtr, u32 srcTickPtr, int numMonths)
|
||||
{
|
||||
if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr))
|
||||
if (!Memory::IsValidAddress(destTickPtr) || !Memory::IsValidAddress(srcTickPtr))
|
||||
{
|
||||
u64 srcTick = Memory::Read_U64(srcTickPtr);
|
||||
|
||||
ScePspDateTime pt;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
|
||||
__RtcTicksToPspTime(pt,srcTick);
|
||||
if(((pt.year-1)*12+pt.month) + numMonths < 1 || ((pt.year-1)*12+pt.month) + numMonths > 9999*12)
|
||||
{
|
||||
srcTick = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(numMonths < 0)
|
||||
{
|
||||
pt.year += numMonths/12;
|
||||
int restMonth = pt.month + numMonths%12;
|
||||
if(restMonth < 1)
|
||||
{
|
||||
pt.month = 12+restMonth;
|
||||
pt.year--;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt.month = restMonth;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pt.year += numMonths/12;
|
||||
pt.month += numMonths%12;
|
||||
if(pt.month > 12)
|
||||
{
|
||||
pt.month -= 12;
|
||||
pt.year++;
|
||||
}
|
||||
}
|
||||
u64 yearTicks = __RtcPspTimeToTicks(pt);
|
||||
srcTick =yearTicks;
|
||||
}
|
||||
Memory::Write_U64(srcTick, destTickPtr);
|
||||
WARN_LOG(SCERTC, "sceRtcTickAddMonths(%08x, %08x, %d): invalid address", destTickPtr, srcTickPtr, numMonths);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddMonths(%d,%d,%d)", destTickPtr, srcTickPtr, numMonths);
|
||||
u64 srcTick = Memory::Read_U64(srcTickPtr);
|
||||
|
||||
ScePspDateTime pt;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
|
||||
__RtcTicksToPspTime(pt,srcTick);
|
||||
pt.year += numMonths / 12;
|
||||
pt.month += numMonths % 12;
|
||||
|
||||
if (pt.month < 1)
|
||||
{
|
||||
pt.month += 12;
|
||||
pt.year--;
|
||||
}
|
||||
if (pt.month > 12)
|
||||
{
|
||||
pt.month -= 12;
|
||||
pt.year++;
|
||||
}
|
||||
|
||||
if (__RtcValidatePspTime(pt))
|
||||
{
|
||||
// Did we land on a year that isn't a leap year?
|
||||
if (pt.month == 2 && pt.day == 29 && !__RtcIsLeapYear((s16)pt.year))
|
||||
pt.day = 28;
|
||||
Memory::Write_U64(__RtcPspTimeToTicks(pt), destTickPtr);
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddMonths(%08x, %08x = %lld, %d)", destTickPtr, srcTickPtr, srcTick, numMonths);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sceRtcTickAddYears(u32 destTickPtr, u32 srcTickPtr, int numYears)
|
||||
{
|
||||
if (Memory::IsValidAddress(destTickPtr) && Memory::IsValidAddress(srcTickPtr))
|
||||
if (!Memory::IsValidAddress(destTickPtr) || !Memory::IsValidAddress(srcTickPtr))
|
||||
{
|
||||
u64 srcTick = Memory::Read_U64(srcTickPtr);
|
||||
|
||||
ScePspDateTime pt;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
|
||||
__RtcTicksToPspTime(pt,srcTick);
|
||||
if(pt.year + numYears <= 0 || pt.year + numYears > 9999)
|
||||
{
|
||||
srcTick = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
pt.year += numYears;
|
||||
u64 yearTicks = __RtcPspTimeToTicks(pt);
|
||||
srcTick =yearTicks;
|
||||
}
|
||||
|
||||
Memory::Write_U64(srcTick, destTickPtr);
|
||||
WARN_LOG(SCERTC, "sceRtcTickAddYears(%08x, %08x, %d): invalid address", destTickPtr, srcTickPtr, numYears);
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddYears(%d,%d,%d)", destTickPtr, srcTickPtr, numYears);
|
||||
u64 srcTick = Memory::Read_U64(srcTickPtr);
|
||||
|
||||
ScePspDateTime pt;
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
|
||||
__RtcTicksToPspTime(pt, srcTick);
|
||||
pt.year += numYears;
|
||||
|
||||
if (__RtcValidatePspTime(pt))
|
||||
{
|
||||
// Did we land on a year that isn't a leap year?
|
||||
if (pt.month == 2 && pt.day == 29 && !__RtcIsLeapYear((s16)pt.year))
|
||||
pt.day = 28;
|
||||
Memory::Write_U64(__RtcPspTimeToTicks(pt), destTickPtr);
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCERTC, "sceRtcTickAddYears(%08x, %08x = %lld, %d)", destTickPtr, srcTickPtr, srcTick, numYears);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -886,8 +902,8 @@ const HLEFunction sceRtc[] =
|
|||
{
|
||||
{0xC41C2853, &WrapU_V<sceRtcGetTickResolution>, "sceRtcGetTickResolution"},
|
||||
{0x3f7ad767, &WrapU_U<sceRtcGetCurrentTick>, "sceRtcGetCurrentTick"},
|
||||
{0x011F03C1, &WrapU64_V<sceRtcGetAcculumativeTime>, "sceRtcGetAccumulativeTime"},
|
||||
{0x029CA3B3, &WrapU64_V<sceRtcGetAcculumativeTime>, "sceRtcGetAccumlativeTime"},
|
||||
{0x011F03C1, &WrapU64_V<sceRtcGetAccumulativeTime>, "sceRtcGetAccumulativeTime"},
|
||||
{0x029CA3B3, &WrapU64_V<sceRtcGetAccumulativeTime>, "sceRtcGetAccumlativeTime"},
|
||||
{0x4cfa57b0, &WrapU_UI<sceRtcGetCurrentClock>, "sceRtcGetCurrentClock"},
|
||||
{0xE7C27D1B, &WrapU_U<sceRtcGetCurrentClockLocalTime>, "sceRtcGetCurrentClockLocalTime"},
|
||||
{0x34885E0D, &WrapI_UU<sceRtcConvertUtcToLocalTime>, "sceRtcConvertUtcToLocalTime"},
|
||||
|
@ -925,7 +941,7 @@ const HLEFunction sceRtc[] =
|
|||
{0x62685E98, &WrapI_U<sceRtcGetLastAdjustedTime>, "sceRtcGetLastAdjustedTime"},
|
||||
{0x203ceb0d, 0, "sceRtcGetLastReincarnatedTime"},
|
||||
{0x7d1fbed3, &WrapI_UU<sceRtcSetAlarmTick>, "sceRtcSetAlarmTick"},
|
||||
{0xf5fcc995, 0, "sceRtc_F5FCC995"},
|
||||
{0xf5fcc995, 0, "sceRtcGetCurrentNetworkTick"},
|
||||
{0x81fcda34, 0, "sceRtcIsAlarmed"},
|
||||
{0xfb3b18cd, 0, "sceRtcRegisterCallback"},
|
||||
{0x6a676d2d, 0, "sceRtcUnregisterCallback"},
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
#include "Core/HLE/sceKernelInterrupt.h"
|
||||
#include "Core/HLE/KernelWaitHelpers.h"
|
||||
|
||||
#include "Core/FileSystems/BlockDevices.h"
|
||||
#include "Core/FileSystems/ISOFileSystem.h"
|
||||
#include "Core/FileSystems/VirtualDiscFileSystem.h"
|
||||
|
||||
#include "file/file_util.h"
|
||||
|
||||
const u64 MICRO_DELAY_ACTIVATE = 4000;
|
||||
|
||||
static u8 umdActivated = 1;
|
||||
|
@ -36,6 +42,8 @@ static int umdStatChangeEvent = -1;
|
|||
static std::vector<SceUID> umdWaitingThreads;
|
||||
static std::map<SceUID, u64> umdPausedWaits;
|
||||
|
||||
bool UMDReplacePermit = false;
|
||||
|
||||
struct PspUmdInfo {
|
||||
u32_le size;
|
||||
u32_le type;
|
||||
|
@ -60,7 +68,7 @@ void __UmdInit()
|
|||
|
||||
void __UmdDoState(PointerWrap &p)
|
||||
{
|
||||
auto s = p.Section("sceUmd", 1);
|
||||
auto s = p.Section("sceUmd", 1, 2);
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
|
@ -74,6 +82,9 @@ void __UmdDoState(PointerWrap &p)
|
|||
CoreTiming::RestoreRegisterEvent(umdStatChangeEvent, "UmdChange", __UmdStatChange);
|
||||
p.Do(umdWaitingThreads);
|
||||
p.Do(umdPausedWaits);
|
||||
|
||||
if (s > 1)
|
||||
p.Do(UMDReplacePermit);
|
||||
}
|
||||
|
||||
u8 __KernelUmdGetState()
|
||||
|
@ -266,7 +277,6 @@ u32 sceUmdRegisterUMDCallBack(u32 cbId)
|
|||
// There's only ever one.
|
||||
driveCBId = cbId;
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCEIO, "%d=sceUmdRegisterUMDCallback(id=%08x)", retVal, cbId);
|
||||
return retVal;
|
||||
}
|
||||
|
@ -281,7 +291,6 @@ int sceUmdUnRegisterUMDCallBack(int cbId)
|
|||
retVal = cbId;
|
||||
driveCBId = -1;
|
||||
}
|
||||
|
||||
DEBUG_LOG(SCEIO, "%08x=sceUmdUnRegisterUMDCallBack(id=%08x)", retVal, cbId);
|
||||
return retVal;
|
||||
}
|
||||
|
@ -436,14 +445,48 @@ u32 sceUmdGetErrorStat()
|
|||
return umdErrorStat;
|
||||
}
|
||||
|
||||
void __UmdReplace(std::string filepath) {
|
||||
// Only get system from disc0 seems have been enough.
|
||||
IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:");
|
||||
if (!currentUMD)
|
||||
return;
|
||||
|
||||
IFileSystem* umd2;
|
||||
FileInfo info;
|
||||
if (!getFileInfo(filepath.c_str(), &info)) // This shouldn't happen, but for safety.
|
||||
return;
|
||||
if (info.isDirectory) {
|
||||
umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath);
|
||||
} else {
|
||||
auto bd = constructBlockDevice(filepath.c_str());
|
||||
if (!bd)
|
||||
return;
|
||||
umd2 = new ISOFileSystem(&pspFileSystem, bd);
|
||||
|
||||
pspFileSystem.Remount(currentUMD, umd2);
|
||||
}
|
||||
delete currentUMD;
|
||||
|
||||
// TODO Is this always correct if UMD was not activated?
|
||||
u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED;
|
||||
if (driveCBId != -1)
|
||||
__KernelNotifyCallback(driveCBId, notifyArg);
|
||||
}
|
||||
|
||||
bool getUMDReplacePermit() {
|
||||
return UMDReplacePermit;
|
||||
}
|
||||
|
||||
u32 sceUmdReplaceProhibit()
|
||||
{
|
||||
UMDReplacePermit = false;
|
||||
DEBUG_LOG(SCEIO,"sceUmdReplaceProhibit()");
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 sceUmdReplacePermit()
|
||||
{
|
||||
UMDReplacePermit = true;
|
||||
DEBUG_LOG(SCEIO,"sceUmdReplacePermit()");
|
||||
return 0;
|
||||
}
|
||||
|
@ -464,8 +507,8 @@ const HLEFunction sceUmdUser[] =
|
|||
{0xBD2BDE07,&WrapI_I<sceUmdUnRegisterUMDCallBack>,"sceUmdUnRegisterUMDCallBack"},
|
||||
{0x87533940,WrapU_V<sceUmdReplaceProhibit>,"sceUmdReplaceProhibit"},
|
||||
{0xCBE9F02A,WrapU_V<sceUmdReplacePermit>,"sceUmdReplacePermit"},
|
||||
{0x14c6c45c,0,"sceUmdUser_14C6C45C"},
|
||||
{0xb103fa38,0,"sceUmdUser_B103FA38"},
|
||||
{0x14c6c45c,0,"sceUmdUnuseUMDInMsUsbWlan"},
|
||||
{0xb103fa38,0,"sceUmdUseUMDInMsUsbWlan"},
|
||||
};
|
||||
|
||||
void Register_sceUmdUser()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue