Merge branch 'master' of https://github.com/hrydgard/ppsspp into improvedTilControls

This commit is contained in:
bollu 2013-12-14 16:45:29 +05:30
commit b0c7e824be
401 changed files with 28256 additions and 19843 deletions

View file

@ -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

View file

@ -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>

View 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)

View file

@ -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

View file

@ -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()

View file

@ -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

View file

@ -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;
}
};

View file

@ -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

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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" />

View file

@ -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" />

View file

@ -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)
{}

View file

@ -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

View file

@ -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) {

View file

@ -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);

View file

@ -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

View file

@ -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;
}

View file

@ -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_

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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; }

View file

@ -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

View file

@ -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

View file

@ -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_

View file

@ -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;
}
};

View file

@ -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)

View file

@ -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;
}
};

View file

@ -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", &currentDirectory, "");
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;
}

View file

@ -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;

View file

@ -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();
}

View file

@ -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" />

View file

@ -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>

View file

@ -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;
};

View file

@ -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)

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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; };

File diff suppressed because it is too large Load diff

View 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

View file

@ -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;

View file

@ -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");

View file

@ -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_);

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -46,4 +46,4 @@ public:
private:
SceUtilityNetconfParam request;
};
};

View file

@ -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;
}

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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 = &sections[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;
//...
}

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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_;
};

View file

@ -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> &paramsfo) {
return ReadSFO(&paramsfo[0], paramsfo.size());
}
int GetDataOffset(const u8 *paramsfo, std::string dataName);
private:

View file

@ -382,11 +382,15 @@ u32 ISOFileSystem::OpenFile(std::string filename, FileAccess access, const char
{
u32 sectorStart = 0xFFFFFFFF, readSize = 0xFFFFFFFF;
parseLBN(filename, &sectorStart, &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();

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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
View 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(&parameter,0,sizeof(parameter));
strcpy((char *)&parameter.nickname.data, g_Config.sNickName.c_str());
parameter.channel = 1; // Fake Channel 1
// Prepare Login Packet
getLocalMac(&parameter.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
View 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);

View file

@ -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);

View file

@ -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"},

View file

@ -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);

View file

@ -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() {

View file

@ -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();

View file

@ -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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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()

View file

@ -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"},

View file

@ -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);
}

View file

@ -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()

View file

@ -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.

View file

@ -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();

View file

@ -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"},

View file

@ -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;
}

View file

@ -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;
};

View file

@ -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");

View file

@ -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() {

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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()

View file

@ -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[] = {

View file

@ -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[] =

View file

@ -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"},

View file

@ -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