mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-08 13:50:20 +00:00
AnyPS5's app info record always reports category 0xffffffff, so the initialization check, the 0x20F00 exemption and the Initialize throw were never reached. SetCamera2AppCategoryForTest_nid_no_patch overrides the category the Camera2 calls read, and the test runs categories 0, 0x20F00 and 0x1000000.
117 lines
6.0 KiB
C++
117 lines
6.0 KiB
C++
#include "prx/libSceCamera/libSceCamera.hpp"
|
|
#include "prx/libSceCamera/include/Camera.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
|
|
#include <chrono>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
namespace {
|
|
|
|
constexpr int ErrorParam = static_cast<int>(0x8A760000);
|
|
constexpr int ErrorNotInit = static_cast<int>(0x8A760002);
|
|
constexpr int ErrorCameraOpen = static_cast<int>(0x8A760015);
|
|
|
|
using NoArgumentFn = int (APS5_VABI*)();
|
|
using HandleFn = int (APS5_VABI*)(std::int32_t);
|
|
using OpenFn = int (APS5_VABI*)(std::int32_t, std::int32_t, std::int32_t, void*);
|
|
|
|
void Require(bool condition, const char* message) {
|
|
if (condition) return;
|
|
std::fprintf(stderr, "Camera2: %s\n", message);
|
|
std::abort();
|
|
}
|
|
|
|
template <typename Function, typename Export>
|
|
Function As(Export function) {
|
|
return reinterpret_cast<Function>(function);
|
|
}
|
|
|
|
bool InitializeThrows(NoArgumentFn initialize) {
|
|
try {
|
|
initialize();
|
|
} catch (const std::runtime_error&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
int main() {
|
|
const auto original = std::filesystem::current_path();
|
|
const auto directory = original / ("camera2-test-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count()));
|
|
Require(std::filesystem::create_directory(directory), "the test directory could not be created");
|
|
std::filesystem::current_path(directory);
|
|
std::filesystem::create_directories("app0/sce_sys");
|
|
{
|
|
std::ofstream param("app0/sce_sys/param.json", std::ios::binary);
|
|
param << R"({"titleId":"PPSA00000","localizedParameters":{"en-US":{"titleName":"Example"}}})";
|
|
Require(static_cast<bool>(param), "param.json could not be written");
|
|
}
|
|
|
|
const auto initialize = As<NoArgumentFn>(&sceCamera2Initialize);
|
|
const auto finalize = As<NoArgumentFn>(&sceCamera2Finalize);
|
|
const auto open = As<OpenFn>(&sceCamera2Open);
|
|
const auto isAttached = As<HandleFn>(&sceCamera2IsAttached);
|
|
const HandleFn handleCalls[] = {
|
|
As<HandleFn>(&sceCamera2Close), As<HandleFn>(&sceCamera2GetAttribute), As<HandleFn>(&sceCamera2SetAttribute),
|
|
As<HandleFn>(&sceCamera2GetAutoExposureGain), As<HandleFn>(&sceCamera2SetAutoExposureGain), As<HandleFn>(&sceCamera2GetAutoWhiteBalance),
|
|
As<HandleFn>(&sceCamera2SetAutoWhiteBalance), As<HandleFn>(&sceCamera2GetConfig), As<HandleFn>(&sceCamera2SetConfig),
|
|
As<HandleFn>(&sceCamera2GetContrast), As<HandleFn>(&sceCamera2SetContrast), As<HandleFn>(&sceCamera2GetExposureGain),
|
|
As<HandleFn>(&sceCamera2SetExposureGain), As<HandleFn>(&sceCamera2GetGamma), As<HandleFn>(&sceCamera2SetGamma),
|
|
As<HandleFn>(&sceCamera2GetHue), As<HandleFn>(&sceCamera2SetHue), As<HandleFn>(&sceCamera2GetSaturation),
|
|
As<HandleFn>(&sceCamera2SetSaturation), As<HandleFn>(&sceCamera2GetSharpness), As<HandleFn>(&sceCamera2SetSharpness),
|
|
As<HandleFn>(&sceCamera2GetWhiteBalance), As<HandleFn>(&sceCamera2SetWhiteBalance), As<HandleFn>(&sceCamera2GetFieldOfView),
|
|
As<HandleFn>(&sceCamera2GetFrameData), As<HandleFn>(&sceCamera2IsValidFrameData), As<HandleFn>(&sceCamera2SetVideoSync),
|
|
As<HandleFn>(&sceCamera2Start), As<HandleFn>(&sceCamera2Stop),
|
|
};
|
|
|
|
for (const std::int32_t handle : {0, 1, 2, -1}) {
|
|
for (const auto call : handleCalls) Require(call(handle) == ErrorParam, "a handle that sceCamera2Open never returned was accepted");
|
|
}
|
|
Require(open(0xFE, 0, 0, nullptr) == ErrorParam, "sceCamera2Open took a user other than the system user");
|
|
Require(open(0xFF, 1, 0, nullptr) == ErrorParam && open(0xFF, 0, 1, nullptr) == ErrorParam, "sceCamera2Open took a nonzero type or index");
|
|
Require(isAttached(0) == ErrorParam && isAttached(2) == ErrorParam, "sceCamera2IsAttached took a device other than 1");
|
|
|
|
Require(initialize() == 0 && initialize() == 0, "sceCamera2Initialize failed");
|
|
for (const auto call : handleCalls) Require(call(1) == ErrorParam, "an initialized Camera2 accepted a handle it never opened");
|
|
Require(finalize() == 0, "sceCamera2Finalize failed with no camera open");
|
|
|
|
const int camera = sceCameraOpen(0xFF, 0, 0, nullptr);
|
|
Require(camera > 0, "sceCameraOpen failed");
|
|
Require(finalize() == ErrorCameraOpen, "sceCamera2Finalize ran while a camera was open");
|
|
Require(sceCameraClose(camera) == 0, "sceCameraClose failed");
|
|
Require(finalize() == 0, "sceCamera2Finalize failed after the camera closed");
|
|
|
|
const std::uint32_t checked = 0;
|
|
SetCamera2AppCategoryForTest_nid_no_patch(&checked);
|
|
for (const auto call : handleCalls) Require(call(1) == ErrorNotInit, "a category below 0x1000000 skipped the initialization check");
|
|
Require(finalize() == ErrorNotInit && open(0xFF, 0, 0, nullptr) == ErrorNotInit, "a checked category finalized or opened before sceCamera2Initialize");
|
|
Require(InitializeThrows(initialize), "sceCamera2Initialize answered for a checked category it doesn't model");
|
|
|
|
const std::uint32_t exempt = 0x20F00;
|
|
SetCamera2AppCategoryForTest_nid_no_patch(&exempt);
|
|
for (const auto call : handleCalls) Require(call(1) == ErrorParam, "category 0x20F00 was checked for initialization");
|
|
Require(initialize() == 0, "sceCamera2Initialize failed for category 0x20F00");
|
|
SetCamera2AppCategoryForTest_nid_no_patch(&checked);
|
|
for (const auto call : handleCalls) Require(call(1) == ErrorParam, "a checked category stayed uninitialized after sceCamera2Initialize");
|
|
Require(finalize() == 0, "sceCamera2Finalize failed for an initialized checked category");
|
|
|
|
const std::uint32_t unchecked = 0x1000000;
|
|
SetCamera2AppCategoryForTest_nid_no_patch(&unchecked);
|
|
for (const auto call : handleCalls) Require(call(1) == ErrorParam, "category 0x1000000 was checked for initialization");
|
|
Require(initialize() == 0 && finalize() == 0, "sceCamera2Initialize or Finalize failed for category 0x1000000");
|
|
SetCamera2AppCategoryForTest_nid_no_patch(nullptr);
|
|
|
|
std::filesystem::current_path(original);
|
|
std::filesystem::remove_all(directory);
|
|
std::puts("Camera2 tests passed");
|
|
return 0;
|
|
}
|