diff --git a/core/libs/prx/libkernel/AppMetadata/src/AppMetadata.cpp b/core/libs/prx/libkernel/AppMetadata/src/AppMetadata.cpp index bc423779a..79df79827 100644 --- a/core/libs/prx/libkernel/AppMetadata/src/AppMetadata.cpp +++ b/core/libs/prx/libkernel/AppMetadata/src/AppMetadata.cpp @@ -42,6 +42,18 @@ void ensureTitleLoaded() { g_titleLoaded = true; } +const bool g_downloadDataMounted = [] { + try { + const auto run = std::filesystem::current_path(); + const auto paramJson = run / "app0" / "sce_sys" / "param.json"; + if (!std::filesystem::exists(paramJson) || parseParamJson(paramJson).downloadDataSizeMiB == 0) return false; + std::filesystem::create_directories(run / "download0"); + return true; + } catch (const std::exception&) { + return false; + } +}(); + void ensureIconLoaded() { if (g_iconAttempted) return; g_iconAttempted = true; diff --git a/core/libs/prx/libkernel/CMakeLists.txt b/core/libs/prx/libkernel/CMakeLists.txt index b53d8a265..2ceb0cfa1 100644 --- a/core/libs/prx/libkernel/CMakeLists.txt +++ b/core/libs/prx/libkernel/CMakeLists.txt @@ -69,6 +69,29 @@ endif() configure_windows_unwind(libkernel) if(BUILD_TESTING) + add_test_executable(download_data_mount_tests ${LIBS_INCLUDE_DIR}/tests/GuestDownloadDataMount.cpp) + target_include_directories(download_data_mount_tests PRIVATE ${LIBS_INCLUDE_DIR}) + target_link_libraries(download_data_mount_tests PRIVATE libkernel libc) + configure_windows_unwind(download_data_mount_tests) + foreach(downloadDataCase IN ITEMS declared:256 none:0 invalid:256) + string(REPLACE ":" ";" downloadDataCase ${downloadDataCase}) + list(GET downloadDataCase 0 downloadDataName) + list(GET downloadDataCase 1 downloadDataSize) + set(downloadDataRun ${CMAKE_CURRENT_BINARY_DIR}/download_data_mount_${downloadDataName}) + if(downloadDataName STREQUAL "invalid") + file(WRITE ${downloadDataRun}/app0/sce_sys/param.json "{\"downloadDataSize\":${downloadDataSize}}") + else() + file(WRITE ${downloadDataRun}/app0/sce_sys/param.json + "{\"titleId\":\"PPSA00000\",\"localizedParameters\":{\"en-US\":{\"titleName\":\"Example\"}},\"downloadDataSize\":${downloadDataSize}," + "\"userDefinedParam1\":0,\"userDefinedParam2\":0,\"userDefinedParam3\":0,\"userDefinedParam4\":0}") + endif() + add_test(NAME download_data_mount_${downloadDataName} COMMAND download_data_mount_tests ${downloadDataName} + WORKING_DIRECTORY ${downloadDataRun}) + if(WIN32) + set_tests_properties(download_data_mount_${downloadDataName} PROPERTIES ENVIRONMENT_MODIFICATION + "PATH=path_list_prepend:$") + endif() + endforeach() add_test_executable(param_json_parser_tests ${LIBS_INCLUDE_DIR}/tests/ParamJsonParser.cpp) target_include_directories(param_json_parser_tests PRIVATE ${LIBS_INCLUDE_DIR}) target_link_libraries(param_json_parser_tests PRIVATE libkernel libc) diff --git a/core/libs/tests/GuestDownloadDataMount.cpp b/core/libs/tests/GuestDownloadDataMount.cpp new file mode 100644 index 000000000..e588f786d --- /dev/null +++ b/core/libs/tests/GuestDownloadDataMount.cpp @@ -0,0 +1,26 @@ +#include "prx/libkernel/AppMetadata/include/AppMetadata.hpp" +#include +#include +#include +#include +#include + +static void Require(bool value) { if (!value) std::abort(); } + +int main(int argc, char** argv) { + Require(argc == 2); + const std::string_view mode = argv[1]; + Require(std::filesystem::is_directory("download0") == (mode == "declared")); + if (mode == "invalid") { + bool rejected = false; + try { + GetAppTitleId_nid_postfix(); + } catch (const std::runtime_error&) { + rejected = true; + } + Require(rejected); + return 0; + } + Require(std::strcmp(GetAppTitleId_nid_postfix().value, "PPSA00000") == 0); + std::filesystem::remove_all("download0"); +}