Merge branch 'android' into android-2

This commit is contained in:
SSimco
2023-12-23 18:00:09 +02:00
300 changed files with 16097 additions and 1732 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
[submodule "dependencies/ZArchive"]
path = dependencies/ZArchive
url = https://github.com/Exzap/ZArchive
url = https://github.com/SSimco/ZArchive
shallow = true
[submodule "dependencies/cubeb"]
path = dependencies/cubeb
+23 -8
View File
@@ -17,13 +17,20 @@ if (EXPERIMENTAL_VERSION)
endif()
if (ENABLE_VCPKG)
if(UNIX AND NOT APPLE)
if(UNIX AND NOT APPLE AND NOT VCPKG_TARGET_ANDROID)
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports_linux")
else()
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/dependencies/vcpkg_overlay_ports")
endif()
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
if(VCPKG_TARGET_ANDROID)
set(ENV{ANDROID_NDK_HOME} ${ANDROID_NDK})
set(ENV{VCPKG_ROOT} "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg")
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/vcpkg_android.cmake")
else()
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/vcpkg/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "Vcpkg toolchain file")
endif()
# Set this so that all the various find_package() calls don't need an explicit
# CONFIG option
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
@@ -50,8 +57,10 @@ endif()
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# enable link time optimization for release builds
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
if(NOT ANDROID)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON)
endif()
if (MSVC)
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT CemuBin)
@@ -122,11 +131,17 @@ option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON)
set(THREADS_PREFER_PTHREAD_FLAG true)
find_package(Threads REQUIRED)
find_package(SDL2 REQUIRED)
if(ENABLE_SDL)
find_package(SDL2 REQUIRED)
add_compile_definitions("HAS_SDL=1")
endif()
find_package(CURL REQUIRED)
find_package(pugixml REQUIRED)
find_package(RapidJSON REQUIRED)
find_package(Boost COMPONENTS program_options filesystem nowide REQUIRED)
if(ANDROID)
find_package(Boost COMPONENTS context iostreams REQUIRED)
endif()
find_package(libzip REQUIRED)
find_package(glslang REQUIRED)
find_package(ZLIB REQUIRED)
@@ -141,7 +156,7 @@ if (NOT TARGET glslang::SPIRV AND TARGET SPIRV)
add_library(glslang::SPIRV ALIAS SPIRV)
endif()
if (UNIX AND NOT APPLE)
if (UNIX AND NOT APPLE AND NOT ANDROID)
find_package(X11 REQUIRED)
if (ENABLE_WAYLAND)
find_package(Wayland REQUIRED Client)
@@ -180,7 +195,7 @@ if (ENABLE_HIDAPI)
add_compile_definitions(HAS_HIDAPI)
endif ()
if(UNIX AND NOT APPLE)
if(UNIX AND NOT APPLE AND NOT ANDROID)
if(ENABLE_FERAL_GAMEMODE)
add_compile_definitions(ENABLE_FERAL_GAMEMODE)
add_subdirectory(dependencies/gamemode EXCLUDE_FROM_ALL)
+99
View File
@@ -0,0 +1,99 @@
#
# vcpkg_android.cmake
#
# Helper script when using vcpkg with cmake. It should be triggered via the variable VCPKG_TARGET_ANDROID
#
# For example:
# if (VCPKG_TARGET_ANDROID)
# include("cmake/vcpkg_android.cmake")
# endif()
#
# This script will:
# 1 & 2. check the presence of needed env variables: ANDROID_NDK_HOME and VCPKG_ROOT
# 3. set VCPKG_TARGET_TRIPLET according to ANDROID_ABI
# 4. Combine vcpkg and Android toolchains by setting CMAKE_TOOLCHAIN_FILE
# and VCPKG_CHAINLOAD_TOOLCHAIN_FILE
# Note: VCPKG_TARGET_ANDROID is not an official Vcpkg variable.
# it is introduced for the need of this script
if (VCPKG_TARGET_ANDROID)
#
# 1. Check the presence of environment variable ANDROID_NDK_HOME
#
if (NOT DEFINED ENV{ANDROID_NDK_HOME})
message(FATAL_ERROR "
Please set an environment variable ANDROID_NDK_HOME
For example:
export ANDROID_NDK_HOME=/home/your-account/Android/Sdk/ndk-bundle
Or:
export ANDROID_NDK_HOME=/home/your-account/Android/android-ndk-r21b
")
endif()
#
# 2. Check the presence of environment variable VCPKG_ROOT
#
if (NOT DEFINED ENV{VCPKG_ROOT})
message(FATAL_ERROR "
Please set an environment variable VCPKG_ROOT
For example:
export VCPKG_ROOT=/path/to/vcpkg
")
endif()
#
# 3. Set VCPKG_TARGET_TRIPLET according to ANDROID_ABI
#
# There are four different Android ABI, each of which maps to
# a vcpkg triplet. The following table outlines the mapping from vcpkg architectures to android architectures
#
# |VCPKG_TARGET_TRIPLET | ANDROID_ABI |
# |---------------------------|----------------------|
# |arm64-android | arm64-v8a |
# |arm-android | armeabi-v7a |
# |x64-android | x86_64 |
# |x86-android | x86 |
#
# The variable must be stored in the cache in order to successfully the two toolchains.
#
if (ANDROID_ABI MATCHES "arm64-v8a")
set(VCPKG_TARGET_TRIPLET "arm64-android" CACHE STRING "" FORCE)
elseif(ANDROID_ABI MATCHES "armeabi-v7a")
set(VCPKG_TARGET_TRIPLET "arm-android" CACHE STRING "" FORCE)
elseif(ANDROID_ABI MATCHES "x86_64")
set(VCPKG_TARGET_TRIPLET "x64-android" CACHE STRING "" FORCE)
elseif(ANDROID_ABI MATCHES "x86")
set(VCPKG_TARGET_TRIPLET "x86-android" CACHE STRING "" FORCE)
else()
message(FATAL_ERROR "
Please specify ANDROID_ABI
For example
cmake ... -DANDROID_ABI=armeabi-v7a
Possible ABIs are: arm64-v8a, armeabi-v7a, x64-android, x86-android
")
endif()
message("vcpkg_android.cmake: VCPKG_TARGET_TRIPLET was set to ${VCPKG_TARGET_TRIPLET}")
#
# 4. Combine vcpkg and Android toolchains
#
# vcpkg and android both provide dedicated toolchains:
#
# vcpkg_toolchain_file=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
# android_toolchain_file=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake
#
# When using vcpkg, the vcpkg toolchain shall be specified first.
# However, vcpkg provides a way to preload and additional toolchain,
# with the VCPKG_CHAINLOAD_TOOLCHAIN_FILE option.
set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE $ENV{ANDROID_NDK_HOME}/build/cmake/android.toolchain.cmake)
set(CMAKE_TOOLCHAIN_FILE $ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
message("vcpkg_android.cmake: CMAKE_TOOLCHAIN_FILE was set to ${CMAKE_TOOLCHAIN_FILE}")
message("vcpkg_android.cmake: VCPKG_CHAINLOAD_TOOLCHAIN_FILE was set to ${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
endif(VCPKG_TARGET_ANDROID)
-7
View File
@@ -17,9 +17,6 @@
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
#ifdef __ANDROID__
#include <log/log.h>
#endif
#include "ih264_typedefs.h"
#include "ih264_macros.h"
#include "ih264_platform_macros.h"
@@ -902,10 +899,6 @@ WORD32 ih264d_read_mmco_commands(struct _DecStruct * ps_dec)
{
if (j >= MAX_REF_BUFS)
{
#ifdef __ANDROID__
ALOGE("b/25818142");
android_errorWriteLog(0x534e4554, "25818142");
#endif
ps_dpb_cmds->u1_num_of_commands = 0;
return -1;
}
+36 -15
View File
@@ -18,6 +18,8 @@ elseif(UNIX)
VK_USE_PLATFORM_MACOS_MVK
VK_USE_PLATFORM_METAL_EXT
)
elseif(ANDROID)
add_compile_definitions(VK_USE_PLATFORM_ANDROID_KHR)
else()
add_compile_definitions(
VK_USE_PLATFORM_XLIB_KHR # legacy. Do we need to support XLIB surfaces?
@@ -40,7 +42,11 @@ add_compile_definitions(VK_NO_PROTOTYPES)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_subdirectory(Common)
add_subdirectory(gui)
if(ANDROID)
add_subdirectory(android/app/src/main/cpp)
else()
add_subdirectory(gui)
endif()
add_subdirectory(Cafe)
add_subdirectory(Cemu)
add_subdirectory(config)
@@ -51,22 +57,28 @@ add_subdirectory(imgui)
add_subdirectory(resource)
add_subdirectory(asm)
add_executable(CemuBin
main.cpp
mainLLE.cpp
)
if(ANDROID)
add_library(CemuBin STATIC
main.cpp
mainLLE.cpp
)
else()
add_executable(CemuBin
main.cpp
mainLLE.cpp
)
if(WIN32)
target_sources(CemuBin PRIVATE
resource/cemu.rc
if(WIN32)
target_sources(CemuBin PRIVATE
resource/cemu.rc
../dist/windows/cemu.manifest
)
endif()
set_property(TARGET CemuBin PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set_property(TARGET CemuBin PROPERTY WIN32_EXECUTABLE $<NOT:$<CONFIG:Debug>>)
set(OUTPUT_NAME "Cemu_$<LOWER_CASE:$<CONFIG>>")
endif()
set_property(TARGET CemuBin PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set_property(TARGET CemuBin PROPERTY WIN32_EXECUTABLE $<NOT:$<CONFIG:Debug>>)
set(OUTPUT_NAME "Cemu_$<LOWER_CASE:$<CONFIG>>")
if (MACOS_BUNDLE)
set_property(TARGET CemuBin PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resource/MacOSXBundleInfo.plist.in")
@@ -115,13 +127,22 @@ target_link_libraries(CemuBin PRIVATE
CemuCommon
CemuComponents
CemuConfig
CemuGui
CemuInput
CemuUtil
OpenGL::GL
SDL2::SDL2
)
if(NOT ANDROID)
target_link_libraries(CemuBin PRIVATE CemuGui)
endif()
if(ENABLE_OPENGL)
target_link_libraries(CemuBin PRIVATE OpenGL::GL)
endif()
if(ENABLE_SDL)
target_link_libraries(CemuBin PRIVATE SDL2::SDL2)
endif()
if(UNIX AND NOT APPLE)
# due to nasm output some linkers will make stack executable
# cemu does not require this so we explicity disable it
+7 -5
View File
@@ -497,6 +497,13 @@ if(APPLE)
target_sources(CemuCafe PRIVATE "HW/Latte/Renderer/Vulkan/CocoaSurface.mm")
endif()
if(ANDROID)
target_sources(CemuCafe PRIVATE
Filesystem/fscDeviceAndroidSAF.cpp
Filesystem/fscDeviceAndroidSAF.h
)
endif()
set_property(TARGET CemuCafe PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
target_include_directories(CemuCafe PUBLIC "../")
@@ -507,7 +514,6 @@ target_link_libraries(CemuCafe PRIVATE
CemuCommon
CemuComponents
CemuConfig
CemuGui
CemuInput
CemuResource
CemuUtil
@@ -543,10 +549,6 @@ if (ENABLE_NSYSHID_LIBUSB)
endif ()
endif ()
if (ENABLE_WXWIDGETS)
target_link_libraries(CemuCafe PRIVATE wx::base wx::core)
endif()
if(WIN32)
target_link_libraries(CemuCafe PRIVATE iphlpapi)
endif()
+24 -10
View File
@@ -1,5 +1,4 @@
#include "Cafe/OS/common/OSCommon.h"
#include "gui/wxgui.h"
#include "Cafe/OS/libs/gx2/GX2.h"
#include "Cafe/GameProfile/GameProfile.h"
#include "Cafe/HW/Espresso/Interpreter/PPCInterpreterInternal.h"
@@ -61,9 +60,6 @@
// HW interfaces
#include "Cafe/HW/SI/si.h"
// dependency to be removed
#include "gui/guiWrapper.h"
#include <time.h>
#if BOOST_OS_LINUX
@@ -168,7 +164,7 @@ void LoadMainExecutable()
applicationRPX = RPLLoader_LoadFromMemory(rpxData, rpxSize, (char*)_pathToExecutable.c_str());
if (!applicationRPX)
{
wxMessageBox(_("Failed to run this title because the executable is damaged"));
cemuLog_log(LogType::Force, "Failed to run this title because the executable is damaged");
cemuLog_createLogFile(false);
cemuLog_waitForFlush();
exit(0);
@@ -353,7 +349,9 @@ uint32 LoadSharedData()
void cemu_initForGame()
{
gui_updateWindowTitles(false, true, 0.0);
auto cafeSystemCallbacks = CafeSystem::getCafeSystemCallbacks();
if (cafeSystemCallbacks)
cafeSystemCallbacks->updateWindowTitles(false, true, 0.0);
// input manager apply game profile
InputManager::instance().apply_game_profile();
// log info for launched title
@@ -423,6 +421,20 @@ void cemu_initForGame()
namespace CafeSystem
{
CafeSystemCallbacks* sCafeSystemCallbacks = nullptr;
void registerCafeSystemCallbacks(CafeSystemCallbacks* cafeSystemCallbacks)
{
sCafeSystemCallbacks = cafeSystemCallbacks;
}
void unregisterCafeSystemCallbacks()
{
sCafeSystemCallbacks = nullptr;
}
CafeSystemCallbacks* getCafeSystemCallbacks()
{
return sCafeSystemCallbacks;
}
void InitVirtualMlcStorage();
void MlcStorageMountTitle(TitleInfo& titleInfo);
void MlcStorageUnmountAllTitles();
@@ -798,10 +810,10 @@ namespace CafeSystem
// check for content folder
fs::path contentPath = executablePath.parent_path().parent_path().append("content");
std::error_code ec;
if (fs::is_directory(contentPath, ec))
if (cemu::fs::is_directory(contentPath, ec))
{
// mounting content folder
bool r = FSCDeviceHostFS_Mount(std::string("/vol/content").c_str(), _pathToUtf8(contentPath), FSC_PRIORITY_BASE);
bool r = FSCDeviceHost_Mount(std::string("/vol/content").c_str(), _pathToUtf8(contentPath), FSC_PRIORITY_BASE);
if (!r)
{
cemuLog_log(LogType::Force, "Failed to mount {}", _pathToUtf8(contentPath));
@@ -810,7 +822,7 @@ namespace CafeSystem
}
}
// mount code folder to a virtual temporary path
FSCDeviceHostFS_Mount(std::string("/internal/code/").c_str(), _pathToUtf8(executablePath.parent_path()), FSC_PRIORITY_BASE);
FSCDeviceHost_Mount(std::string("/internal/code/").c_str(), _pathToUtf8(executablePath.parent_path()), FSC_PRIORITY_BASE);
std::string internalExecutablePath = "/internal/code/";
internalExecutablePath.append(_pathToUtf8(executablePath.filename()));
_pathToExecutable = internalExecutablePath;
@@ -847,7 +859,9 @@ namespace CafeSystem
PPCTimer_waitForInit();
// start system
sSystemRunning = true;
gui_notifyGameLoaded();
auto cafeSystemCallbacks = CafeSystem::getCafeSystemCallbacks();
if (cafeSystemCallbacks)
cafeSystemCallbacks->notifyGameLoaded();
std::thread t(_LaunchTitleThread);
t.detach();
}
+11
View File
@@ -20,6 +20,17 @@ namespace CafeSystem
//BAD_META_DATA, - the title list only stores titles with valid meta, so this error code is impossible
};
class CafeSystemCallbacks
{
public:
virtual void updateWindowTitles(bool isIdle, bool isLoading, double fps) = 0;
virtual void notifyGameLoaded() = 0;
};
void registerCafeSystemCallbacks(CafeSystemCallbacks* cafeSystemCallbacks);
void unregisterCafeSystemCallbacks();
CafeSystemCallbacks* getCafeSystemCallbacks();
void Initialize();
void SetImplementation(SystemImplementation* impl);
void Shutdown();
+2 -4
View File
@@ -1,4 +1,3 @@
#include <wx/msgdlg.h>
#include <mutex>
#include <gui/helpers/wxHelpers.h>
@@ -75,7 +74,7 @@ void KeyCache_Prepare()
}
else
{
wxMessageBox(_("Unable to create file keys.txt\nThis can happen if Cemu does not have write permission to its own directory, the disk is full or if anti-virus software is blocking Cemu."), _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
cemuLog_log(LogType::Force, "Unable to create file keys.txt\nThis can happen if Cemu does not have write permission to it's own directory, the disk is full or if anti-virus software is blocking Cemu.");
}
mtxKeyCache.unlock();
return;
@@ -108,8 +107,7 @@ void KeyCache_Prepare()
continue;
if( strishex(line) == false )
{
auto errorMsg = formatWxString(_("Error in keys.txt at line {}"), lineNumber);
wxMessageBox(errorMsg, _("Error"), wxOK | wxCENTRE | wxICON_ERROR);
cemuLog_log(LogType::Force, "rror in keys.txt in line {}", lineNumber);
continue;
}
if(line.size() == 32 )
+15
View File
@@ -210,3 +210,18 @@ bool FSCDeviceHostFS_Mount(std::string_view mountPath, std::string_view hostTarg
// redirect device
void fscDeviceRedirect_map();
void fscDeviceRedirect_add(std::string_view virtualSourcePath, const fs::path& targetFilePath, sint32 priority);
#if __ANDROID__
#include "Common/unix/FilesystemAndroid.h"
bool FSCDeviceAndroidSAF_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority);
#endif // __ANDROID__
inline bool FSCDeviceHost_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority)
{
#if __ANDROID__
if (FilesystemAndroid::isContentUri(std::string(hostTargetPath)))
return FSCDeviceAndroidSAF_Mount(mountPath, hostTargetPath, priority);
else
#endif // __ANDROID__
return FSCDeviceHostFS_Mount(mountPath, hostTargetPath, priority);
}
+235
View File
@@ -0,0 +1,235 @@
#include "Cafe/Filesystem/fscDeviceAndroidSAF.h"
#include <memory>
#include <stdexcept>
#include "Cafe/Filesystem/fsc.h"
#include "Common/FileStream.h"
#include "Common/unix/FilesystemAndroid.h"
FSCVirtualFile_AndroidSAF::~FSCVirtualFile_AndroidSAF()
{
if (m_type == FSC_TYPE_FILE)
delete m_fs;
}
sint32 FSCVirtualFile_AndroidSAF::fscGetType()
{
return m_type;
}
uint32 FSCVirtualFile_AndroidSAF::fscDeviceAndroidSAFFSFile_getFileSize()
{
if (m_type == FSC_TYPE_FILE)
{
if (m_fileSize > 0xFFFFFFFFULL)
cemu_assert_suspicious(); // files larger than 4GB are not supported by Wii U filesystem
return (uint32)m_fileSize;
}
return 0;
}
uint64 FSCVirtualFile_AndroidSAF::fscQueryValueU64(uint32 id)
{
if (m_type == FSC_TYPE_FILE)
{
if (id == FSC_QUERY_SIZE)
return fscDeviceAndroidSAFFSFile_getFileSize();
else if (id == FSC_QUERY_WRITEABLE)
return m_isWritable;
else
cemu_assert_unimplemented();
}
else if (m_type == FSC_TYPE_DIRECTORY)
{
if (id == FSC_QUERY_SIZE)
return fscDeviceAndroidSAFFSFile_getFileSize();
else
cemu_assert_unimplemented();
}
cemu_assert_unimplemented();
return 0;
}
uint32 FSCVirtualFile_AndroidSAF::fscWriteData(void* buffer, uint32 size)
{
throw std::logic_error("write not supported with SAF");
return 0;
}
uint32 FSCVirtualFile_AndroidSAF::fscReadData(void* buffer, uint32 size)
{
if (m_type != FSC_TYPE_FILE)
return 0;
if (size >= (2UL * 1024UL * 1024UL * 1024UL))
{
cemu_assert_suspicious();
return 0;
}
uint32 bytesLeft = (uint32)(m_fileSize - m_seek);
bytesLeft = std::min(bytesLeft, 0x7FFFFFFFu);
sint32 bytesToRead = std::min(bytesLeft, size);
uint32 bytesRead = m_fs->readData(buffer, bytesToRead);
m_seek += bytesRead;
return bytesRead;
}
void FSCVirtualFile_AndroidSAF::fscSetSeek(uint64 seek)
{
if (m_type != FSC_TYPE_FILE)
return;
this->m_seek = seek;
cemu_assert_debug(seek <= m_fileSize);
m_fs->SetPosition(seek);
}
uint64 FSCVirtualFile_AndroidSAF::fscGetSeek()
{
if (m_type != FSC_TYPE_FILE)
return 0;
return m_seek;
}
void FSCVirtualFile_AndroidSAF::fscSetFileLength(uint64 endOffset)
{
if (m_type != FSC_TYPE_FILE)
return;
m_fs->SetPosition(endOffset);
bool r = m_fs->SetEndOfFile();
m_seek = std::min(m_seek, endOffset);
m_fileSize = m_seek;
m_fs->SetPosition(m_seek);
if (!r)
cemuLog_log(LogType::Force, "fscSetFileLength: Failed to set size to 0x{:x}", endOffset);
}
bool FSCVirtualFile_AndroidSAF::fscDirNext(FSCDirEntry* dirEntry)
{
if (m_type != FSC_TYPE_DIRECTORY)
return false;
if (!m_files)
{
// init iterator on first iteration attempt
m_files = std::make_unique<std::vector<fs::path>>(FilesystemAndroid::listFiles(*m_path));
m_filesIterator = m_files->begin();
if (!m_files)
{
cemuLog_log(LogType::Force, "Failed to iterate directory: {}", _pathToUtf8(*m_path));
return false;
}
}
if (m_filesIterator == m_files->end())
return false;
const fs::path& file = *m_filesIterator;
std::string fileName = file.filename().generic_string();
if (fileName.size() >= sizeof(dirEntry->path) - 1)
fileName.resize(sizeof(dirEntry->path) - 1);
strncpy(dirEntry->path, fileName.data(), sizeof(dirEntry->path));
if (FilesystemAndroid::isDirectory(file))
{
dirEntry->isDirectory = true;
dirEntry->isFile = false;
dirEntry->fileSize = 0;
}
else
{
dirEntry->isDirectory = false;
dirEntry->isFile = true;
dirEntry->fileSize = 0;
auto fs = FileStream::openFile2(file);
if (fs)
{
dirEntry->fileSize = fs->GetSize();
delete fs;
}
}
m_filesIterator++;
return true;
}
FSCVirtualFile* FSCVirtualFile_AndroidSAF::OpenFile(const fs::path& path, FSC_ACCESS_FLAG accessFlags, sint32& fscStatus)
{
if (!HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE) && !HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
cemu_assert_debug(false); // not allowed. At least one of both flags must be set
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::WRITE_PERMISSION) ||
HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::FILE_ALLOW_CREATE) ||
HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::FILE_ALWAYS_CREATE))
throw std::logic_error("writing and creating a file is not supported with SAF");
// attempt to open as file
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_FILE))
{
FileStream* fs = FileStream::openFile2(path);
if (fs)
{
FSCVirtualFile_AndroidSAF* vf = new FSCVirtualFile_AndroidSAF(FSC_TYPE_FILE);
vf->m_fs = fs;
vf->m_isWritable = false;
vf->m_fileSize = fs->GetSize();
fscStatus = FSC_STATUS_OK;
return vf;
}
}
// attempt to open as directory
if (HAS_FLAG(accessFlags, FSC_ACCESS_FLAG::OPEN_DIR))
{
bool isExistingDir = FilesystemAndroid::exists(path);
if (isExistingDir)
{
FSCVirtualFile_AndroidSAF* vf = new FSCVirtualFile_AndroidSAF(FSC_TYPE_DIRECTORY);
vf->m_path.reset(new std::filesystem::path(path));
fscStatus = FSC_STATUS_OK;
return vf;
}
}
fscStatus = FSC_STATUS_FILE_NOT_FOUND;
return nullptr;
}
/* Device implementation */
class fscDeviceAndroidSAFFSC : public fscDeviceC
{
public:
FSCVirtualFile* fscDeviceOpenByPath(std::string_view path, FSC_ACCESS_FLAG accessFlags, void* ctx, sint32* fscStatus) override
{
*fscStatus = FSC_STATUS_OK;
FSCVirtualFile* vf = FSCVirtualFile_AndroidSAF::OpenFile(_utf8ToPath(path), accessFlags, *fscStatus);
cemu_assert_debug((bool)vf == (*fscStatus == FSC_STATUS_OK));
return vf;
}
bool fscDeviceCreateDir(std::string_view path, void* ctx, sint32* fscStatus) override
{
throw std::logic_error("creating a directory is not supported with SAF");
return false;
}
bool fscDeviceRemoveFileOrDir(std::string_view path, void* ctx, sint32* fscStatus) override
{
throw std::logic_error("removing a file or dir is not supported with SAF");
return false;
}
bool fscDeviceRename(std::string_view srcPath, std::string_view dstPath, void* ctx, sint32* fscStatus) override
{
throw std::logic_error("renaming not supported with SAF");
return false;
}
// singleton
public:
static fscDeviceAndroidSAFFSC& instance()
{
static fscDeviceAndroidSAFFSC _instance;
return _instance;
}
};
bool FSCDeviceAndroidSAF_Mount(std::string_view mountPath, std::string_view hostTargetPath, sint32 priority)
{
return fsc_mount(mountPath, hostTargetPath, &fscDeviceAndroidSAFFSC::instance(), nullptr, priority) == FSC_STATUS_OK;
}
+36
View File
@@ -0,0 +1,36 @@
#pragma once
#include "Cafe/Filesystem/fsc.h"
class FSCVirtualFile_AndroidSAF : public FSCVirtualFile
{
public:
static FSCVirtualFile* OpenFile(const fs::path& path, FSC_ACCESS_FLAG accessFlags, sint32& fscStatus);
~FSCVirtualFile_AndroidSAF() override;
sint32 fscGetType() override;
uint32 fscDeviceAndroidSAFFSFile_getFileSize();
uint64 fscQueryValueU64(uint32 id) override;
uint32 fscWriteData(void* buffer, uint32 size) override;
uint32 fscReadData(void* buffer, uint32 size) override;
void fscSetSeek(uint64 seek) override;
uint64 fscGetSeek() override;
void fscSetFileLength(uint64 endOffset) override;
bool fscDirNext(FSCDirEntry* dirEntry) override;
private:
FSCVirtualFile_AndroidSAF(uint32 type) : m_type(type){};
uint32 m_type; // FSC_TYPE_*
class FileStream* m_fs{};
// file
uint64 m_seek{0};
uint64 m_fileSize{0};
bool m_isWritable{false};
// directory
std::unique_ptr<fs::path> m_path{};
std::unique_ptr<std::vector<fs::path>> m_files{};
std::vector<fs::path>::iterator m_filesIterator;
};
+1 -4
View File
@@ -5,9 +5,7 @@
#include "Cafe/OS/RPL/rpl_structs.h"
#include "boost/algorithm/string.hpp"
#include "gui/wxgui.h" // for wxMessageBox
#include "gui/helpers/wxHelpers.h"
// error handler
void PatchErrorHandler::printError(class PatchGroup* patchGroup, sint32 lineNumber, std::string_view errorMsg)
{
@@ -63,8 +61,7 @@ void PatchErrorHandler::showStageErrorMessageBox()
errorMsg.append("\n");
}
}
wxMessageBox(errorMsg, _("Graphic pack error"));
cemuLog_log(LogType::Force, "Graphic pack error: {}", errorMsg);
}
// loads Cemu-style patches (patch_<anything>.asm)
+39 -15
View File
@@ -1,12 +1,9 @@
#include "gui/guiWrapper.h"
#include "Debugger.h"
#include "Cafe/OS/RPL/rpl_structs.h"
#include "Cemu/PPCAssembler/ppcAssembler.h"
#include "Cafe/HW/Espresso/Recompiler/PPCRecompiler.h"
#include "Cemu/ExpressionParser/ExpressionParser.h"
#include "gui/debugger/DebuggerWindow2.h"
#include "Cafe/OS/libs/coreinit/coreinit.h"
#if BOOST_OS_WINDOWS
@@ -15,6 +12,21 @@
debuggerState_t debuggerState{ };
DebuggerCallbacks* sDebuggerCallbacks = nullptr;
void debugger_registerDebuggerCallbacks(DebuggerCallbacks* debuggerCallbacks)
{
sDebuggerCallbacks = debuggerCallbacks;
}
void debugger_unregisterDebuggerCallbacks()
{
sDebuggerCallbacks = nullptr;
}
DebuggerCallbacks* debugger_getDebuggerCallbacks()
{
return sDebuggerCallbacks;
}
DebuggerBreakpoint* debugger_getFirstBP(uint32 address)
{
for (auto& it : debuggerState.breakpoints)
@@ -326,7 +338,8 @@ void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* b
{
bp->enabled = state;
debugger_updateExecutionBreakpoint(address);
debuggerWindow_updateViewThreadsafe2();
if (sDebuggerCallbacks)
sDebuggerCallbacks->updateViewThreadsafe();
}
else if (bpItr->isMemBP())
{
@@ -348,7 +361,8 @@ void debugger_toggleBreakpoint(uint32 address, bool state, DebuggerBreakpoint* b
debugger_updateMemoryBreakpoint(bpItr);
else
debugger_updateMemoryBreakpoint(nullptr);
debuggerWindow_updateViewThreadsafe2();
if (sDebuggerCallbacks)
sDebuggerCallbacks->updateViewThreadsafe();
}
return;
}
@@ -456,8 +470,8 @@ void debugger_stepInto(PPCInterpreter_t* hCPU, bool updateDebuggerWindow = true)
PPCInterpreterSlim_executeInstruction(hCPU);
debugger_updateExecutionBreakpoint(initialIP);
debuggerState.debugSession.instructionPointer = hCPU->instructionPointer;
if(updateDebuggerWindow)
debuggerWindow_moveIP();
if(updateDebuggerWindow && sDebuggerCallbacks)
sDebuggerCallbacks->moveIP();
ppcRecompilerEnabled = isRecEnabled;
}
@@ -476,7 +490,8 @@ bool debugger_stepOver(PPCInterpreter_t* hCPU)
// nothing to skip, use step-into
debugger_stepInto(hCPU);
debugger_updateExecutionBreakpoint(initialIP);
debuggerWindow_moveIP();
if (sDebuggerCallbacks)
sDebuggerCallbacks->moveIP();
ppcRecompilerEnabled = isRecEnabled;
return false;
}
@@ -484,7 +499,8 @@ bool debugger_stepOver(PPCInterpreter_t* hCPU)
debugger_createCodeBreakpoint(initialIP + 4, DEBUGGER_BP_T_ONE_SHOT);
// step over current instruction (to avoid breakpoint)
debugger_stepInto(hCPU);
debuggerWindow_moveIP();
if (sDebuggerCallbacks)
sDebuggerCallbacks->moveIP();
// restore breakpoints
debugger_updateExecutionBreakpoint(initialIP);
// run
@@ -543,8 +559,11 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
DebuggerBreakpoint* singleshotBP = debugger_getFirstBP(debuggerState.debugSession.instructionPointer, DEBUGGER_BP_T_ONE_SHOT);
if (singleshotBP)
debugger_deleteBreakpoint(singleshotBP);
debuggerWindow_notifyDebugBreakpointHit2();
debuggerWindow_updateViewThreadsafe2();
if (sDebuggerCallbacks)
{
sDebuggerCallbacks->notifyDebugBreakpointHit();
sDebuggerCallbacks->updateViewThreadsafe();
}
// reset step control
debuggerState.debugSession.stepInto = false;
debuggerState.debugSession.stepOver = false;
@@ -561,14 +580,16 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
break; // if true is returned, continue with execution
}
debugger_createPPCStateSnapshot(hCPU);
debuggerWindow_updateViewThreadsafe2();
if (sDebuggerCallbacks)
sDebuggerCallbacks->updateViewThreadsafe();
debuggerState.debugSession.stepOver = false;
}
if (debuggerState.debugSession.stepInto)
{
debugger_stepInto(hCPU);
debugger_createPPCStateSnapshot(hCPU);
debuggerWindow_updateViewThreadsafe2();
if (sDebuggerCallbacks)
sDebuggerCallbacks->updateViewThreadsafe();
debuggerState.debugSession.stepInto = false;
continue;
}
@@ -585,8 +606,11 @@ void debugger_enterTW(PPCInterpreter_t* hCPU)
debuggerState.debugSession.isTrapped = false;
debuggerState.debugSession.hCPU = nullptr;
debuggerWindow_updateViewThreadsafe2();
debuggerWindow_notifyRun();
if (sDebuggerCallbacks)
{
sDebuggerCallbacks->updateViewThreadsafe();
sDebuggerCallbacks->notifyRun();
}
}
void debugger_shouldBreak(PPCInterpreter_t* hCPU)
+15
View File
@@ -98,6 +98,21 @@ typedef struct
extern debuggerState_t debuggerState;
// new API
class DebuggerCallbacks
{
public:
virtual void updateViewThreadsafe() = 0;
virtual void notifyDebugBreakpointHit() = 0;
virtual void notifyRun() = 0;
virtual void moveIP() = 0;
virtual void notifyModuleLoaded(void* module) = 0;
virtual void notifyModuleUnloaded(void* module) = 0;
};
void debugger_registerDebuggerCallbacks(DebuggerCallbacks* debuggerCallbacks);
void debugger_unregisterDebuggerCallbacks();
DebuggerCallbacks* debugger_getDebuggerCallbacks();
DebuggerBreakpoint* debugger_getFirstBP(uint32 address);
void debugger_createCodeBreakpoint(uint32 address, uint8 bpType);
void debugger_createExecuteBreakpoint(uint32 address);
+6 -5
View File
@@ -1,6 +1,5 @@
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "gui/guiWrapper.h"
#include "config/CemuConfig.h"
@@ -14,6 +13,8 @@
#include "input/InputManager.h"
#include "util/SystemInfo/SystemInfo.h"
#include "Cemu/GuiSystem/GuiSystem.h"
#include <cinttypes>
struct OverlayStats
@@ -513,17 +514,17 @@ void LatteOverlay_render(bool pad_view)
return;
sint32 w = 0, h = 0;
if (pad_view && gui_isPadWindowOpen())
gui_getPadWindowPhysSize(w, h);
if (pad_view && GuiSystem::isPadWindowOpen())
GuiSystem::getPadWindowPhysSize(w, h);
else
gui_getWindowPhysSize(w, h);
GuiSystem::getWindowPhysSize(w, h);
if (w == 0 || h == 0)
return;
const Vector2f window_size{ (float)w,(float)h };
float fontDPIScale = !pad_view ? gui_getWindowDPIScale() : gui_getPadDPIScale();
float fontDPIScale = !pad_view ? GuiSystem::getWindowDPIScale() : GuiSystem::getPadDPIScale();
float overlayFontSize = 14.0f * (float)config.overlay.text_scale / 100.0f * fontDPIScale;
@@ -1,6 +1,6 @@
#include "Cafe/HW/Latte/Core/LattePerformanceMonitor.h"
#include "Cafe/HW/Latte/Core/LatteOverlay.h"
#include "gui/guiWrapper.h"
#include "Cafe/CafeSystem.h"
performanceMonitor_t performanceMonitor{};
@@ -104,15 +104,18 @@ void LattePerformanceMonitor_frameEnd()
// next update in 1 second
performanceMonitor.cycle[performanceMonitor.cycleIndex].lastUpdate = GetTickCount();
auto cafeSystemCallbacks = CafeSystem::getCafeSystemCallbacks();
if (isFirstUpdate)
{
LatteOverlay_updateStats(0.0, 0, 0);
gui_updateWindowTitles(false, false, 0.0);
if (cafeSystemCallbacks)
cafeSystemCallbacks->updateWindowTitles(false, false, 0.0);
}
else
{
LatteOverlay_updateStats(fps, drawCallCounter / elapsedFrames, fastDrawCallCounter / elapsedFrames);
gui_updateWindowTitles(false, false, fps);
if (cafeSystemCallbacks)
cafeSystemCallbacks->updateWindowTitles(false, false, fps);
}
}
}
+6 -6
View File
@@ -12,7 +12,7 @@
#include "Cafe/GraphicPack/GraphicPack2.h"
#include "config/ActiveSettings.h"
#include "Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.h"
#include "gui/guiWrapper.h"
#include "Cemu/GuiSystem/GuiSystem.h"
#include "Cafe/OS/libs/erreula/erreula.h"
#include "input/InputManager.h"
#include "Cafe/OS/libs/swkbd/swkbd.h"
@@ -871,10 +871,10 @@ sint32 _currentOutputImageHeight = 0;
void LatteRenderTarget_getScreenImageArea(sint32* x, sint32* y, sint32* width, sint32* height, sint32* fullWidth, sint32* fullHeight, bool padView)
{
int w, h;
if(padView && gui_isPadWindowOpen())
gui_getPadWindowPhysSize(w, h);
if(padView && GuiSystem::isPadWindowOpen())
GuiSystem::getPadWindowPhysSize(w, h);
else
gui_getWindowPhysSize(w, h);
GuiSystem::getWindowPhysSize(w, h);
sint32 scaledOutputX;
sint32 scaledOutputY;
@@ -1039,8 +1039,8 @@ void LatteRenderTarget_itHLECopyColorBufferToScanBuffer(MPTR colorBufferPtr, uin
return;
}
const bool tabPressed = gui_isKeyDown(PlatformKeyCodes::TAB);
const bool ctrlPressed = gui_isKeyDown(PlatformKeyCodes::LCONTROL);
const bool tabPressed = GuiSystem::isKeyDown(GuiSystem::PlatformKeyCodes::TAB);
const bool ctrlPressed = GuiSystem::isKeyDown(GuiSystem::PlatformKeyCodes::LCONTROL);
bool showDRC = swkbd_hasKeyboardInputHook() == false && tabPressed;
bool& alwaysDisplayDRC = LatteGPUState.alwaysDisplayDRC;
+5 -39
View File
@@ -4,9 +4,9 @@
#include "Cafe/HW/Latte/Core/LatteShader.h"
#include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h"
#include "Cafe/HW/Latte/Core/FetchShader.h"
#include "Cemu/FileCache/FileCache.h"
#include "Cafe/GameProfile/GameProfile.h"
#include "gui/guiWrapper.h"
#include "Cemu/FileCache/FileCache.h"
#include "Cemu/GuiSystem/GuiSystem.h"
#include "Cafe/HW/Latte/Renderer/Renderer.h"
#include "Cafe/HW/Latte/Renderer/OpenGL/RendererShaderGL.h"
@@ -24,8 +24,6 @@
#include "Cafe/HW/Latte/Common/ShaderSerializer.h"
#include "util/helpers/Serializer.h"
#include <wx/msgdlg.h>
#if BOOST_OS_WINDOWS
#include <psapi.h>
#endif
@@ -66,8 +64,6 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId);
bool LatteShaderCache_updatePipelineLoadingProgress();
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines);
void LatteShaderCache_handleDeprecatedCacheFiles(fs::path pathGeneric, fs::path pathGenericPre1_25_0, fs::path pathGenericPre1_16_0);
struct
{
struct
@@ -245,10 +241,7 @@ void LatteShaderCache_Load()
RendererShaderGL::ShaderCacheLoading_begin(cacheTitleId);
// get cache file name
const auto pathGeneric = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}_shaders.bin", cacheTitleId);
const auto pathGenericPre1_25_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:016x}.bin", cacheTitleId); // before 1.25.0
const auto pathGenericPre1_16_0 = ActiveSettings::GetCachePath("shaderCache/transferable/{:08x}.bin", CafeSystem::GetRPXHashBase()); // before 1.16.0
LatteShaderCache_handleDeprecatedCacheFiles(pathGeneric, pathGenericPre1_25_0, pathGenericPre1_16_0);
// calculate extraVersion for transferable and precompiled shader cache
uint32 transferableExtraVersion = SHADER_CACHE_GENERIC_EXTRA_VERSION;
s_shaderCacheGeneric = FileCache::Open(pathGeneric, false, transferableExtraVersion); // legacy extra version (1.25.0 - 1.25.1b)
@@ -345,7 +338,7 @@ void LatteShaderCache_Load()
if (g_renderer->GetType() == RendererAPI::Vulkan)
LatteShaderCache_LoadVulkanPipelineCache(cacheTitleId);
#if !__ANDROID__
g_renderer->BeginFrame(true);
if (g_renderer->ImguiBegin(true))
{
@@ -358,7 +351,7 @@ void LatteShaderCache_Load()
LatteShaderCache_drawBackgroundImage(g_shaderCacheLoaderState.textureDRCId, 854, 480);
g_renderer->ImguiEnd();
}
#endif // __ANDROID__
g_renderer->SwapBuffers(true, true);
if (g_shaderCacheLoaderState.textureTVId)
@@ -388,7 +381,7 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
continue;
int w, h;
gui_getWindowPhysSize(w, h);
GuiSystem::getWindowPhysSize(w, h);
const Vector2f window_size{ (float)w,(float)h };
ImGui_GetFont(window_size.y / 32.0f); // = 24 by default
@@ -779,30 +772,3 @@ void LatteShaderCache_Close()
if (g_renderer->GetType() == RendererAPI::Vulkan)
VulkanPipelineStableCache::GetInstance().Close();
}
#include <wx/msgdlg.h>
void LatteShaderCache_handleDeprecatedCacheFiles(fs::path pathGeneric, fs::path pathGenericPre1_25_0, fs::path pathGenericPre1_16_0)
{
std::error_code ec;
bool hasOldCacheFiles = fs::exists(pathGenericPre1_25_0, ec) || fs::exists(pathGenericPre1_16_0, ec);
bool hasNewCacheFiles = fs::exists(pathGeneric, ec);
if (hasOldCacheFiles && !hasNewCacheFiles)
{
// ask user if they want to delete or keep the old cache file
auto infoMsg = _("Cemu detected that the shader cache for this game is outdated.\nOnly shader caches generated with Cemu 1.25.0 or above are supported.\n\nWe recommend deleting the outdated cache file as it will no longer be used by Cemu.");
wxMessageDialog dialog(nullptr, infoMsg, _("Outdated shader cache"),
wxYES_NO | wxCENTRE | wxICON_EXCLAMATION);
dialog.SetYesNoLabels(_("Delete outdated cache file [recommended]"), _("Keep outdated cache file"));
const auto result = dialog.ShowModal();
if (result == wxID_YES)
{
fs::remove(pathGenericPre1_16_0, ec);
fs::remove(pathGenericPre1_25_0, ec);
}
}
}

Some files were not shown because too many files have changed in this diff Show More