mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-23 17:13:13 -05:00
Add sceSysmoduleUnloadModuleInternalWithArg to match the existing sceSysmoduleLoadModuleInternalWithArg export. Decrement the module load count on valid internal IDs, check module existence in kModuleTable, and set the return pointer when provided. Add unit test coverage in GuestSysmodule for invalid values, unloaded modules, successful argument unload, and unknown IDs. Update technical debt documentation.
385 lines
19 KiB
C++
385 lines
19 KiB
C++
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include "prx/libSceSysmodule/ModuleTable.hpp"
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <initializer_list>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#include <psapi.h>
|
|
#endif
|
|
#ifdef __linux__
|
|
#include <cstdio>
|
|
#include <fstream>
|
|
#include <sys/mman.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
extern "C" {
|
|
int APS5_VABI sceSysmoduleIsLoaded(std::uint16_t id);
|
|
int APS5_VABI sceSysmoduleLoadModule(std::uint16_t id);
|
|
int APS5_VABI sceSysmoduleUnloadModule(std::uint16_t id);
|
|
int APS5_VABI sceSysmoduleLoadModuleInternal(std::uint32_t id);
|
|
int APS5_VABI sceSysmoduleUnloadModuleInternal(std::uint32_t id);
|
|
int APS5_VABI sceSysmoduleIsLoadedInternal(std::uint32_t id);
|
|
int APS5_VABI sceSysmoduleLoadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret);
|
|
int APS5_VABI sceSysmoduleUnloadModuleInternalWithArg(std::uint32_t id, int argc, void* argv, std::uint64_t unk, int* ret);
|
|
int APS5_VABI sceSysmoduleGetModuleInfoForUnwind(std::uint64_t addr, int flags, ModuleInfoForUnwind* info);
|
|
int APS5_VABI sceSysmoduleGetModuleHandleInternal(std::uint32_t id, std::int32_t* handle);
|
|
int APS5_VABI sceKernelDlsym(std::int32_t handle, const char* symbol, void** addr);
|
|
}
|
|
|
|
namespace {
|
|
|
|
void Require(bool value) { if (!value) std::abort(); }
|
|
|
|
template <typename TFunction>
|
|
bool ThrowsRuntimeError(TFunction function) {
|
|
try {
|
|
function();
|
|
} catch (const std::runtime_error&) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
constexpr std::uint16_t kFiberModuleId = 0x0006;
|
|
constexpr std::uint16_t kUltModuleId = 0x0007;
|
|
constexpr int kInvalidValue = static_cast<int>(0x805A1000);
|
|
constexpr int kModuleUnloaded = static_cast<int>(0x805A1001);
|
|
constexpr std::uint32_t kInternalFlag = 0x80000000u;
|
|
constexpr std::uint16_t kAcmModuleId = 0x010b;
|
|
constexpr std::uint16_t kTrophy2ModuleId = 0x0110;
|
|
constexpr std::uint16_t kVoiceChatModuleId = 0x0114;
|
|
constexpr std::uint16_t kPerfModuleId = 0x0005;
|
|
constexpr std::uint16_t kVrSetupDialogModuleId = 0x0130;
|
|
constexpr std::uint16_t kProprietaryVoiceChatHelperModuleId = 0x0132;
|
|
constexpr std::uint16_t kPsmlModuleId = 0x0137;
|
|
constexpr std::uint32_t kAgcDriverModuleId = 0x80000080;
|
|
constexpr std::uint32_t kNgs2InternalModuleId = 0x80000090;
|
|
constexpr std::uint32_t kAgcModuleId = 0x80000094;
|
|
constexpr std::uint32_t kHdrScopesInternalModuleId = 0x800000bd;
|
|
|
|
#ifdef __linux__
|
|
struct Mapping {
|
|
std::uint64_t start = 0;
|
|
std::uint64_t end = 0;
|
|
std::string path;
|
|
};
|
|
|
|
Mapping MapsEntry(std::uint64_t address) {
|
|
std::ifstream maps("/proc/self/maps");
|
|
std::string line;
|
|
while (std::getline(maps, line)) {
|
|
unsigned long long start = 0;
|
|
unsigned long long end = 0;
|
|
char path[4096] = {};
|
|
const int parsed = std::sscanf(line.c_str(), "%llx-%llx %*s %*x %*x:%*x %*u %4095s", &start, &end, path);
|
|
if (parsed >= 2 && address >= start && address < end) return Mapping{start, end, parsed == 3 ? path : ""};
|
|
}
|
|
std::abort();
|
|
}
|
|
|
|
void RequireUnwindMatchesMaps(const void* pointer) {
|
|
const auto address = reinterpret_cast<std::uint64_t>(pointer);
|
|
const auto expected = MapsEntry(address);
|
|
ModuleInfoForUnwind info{};
|
|
Require(sceSysmoduleGetModuleInfoForUnwind(address, 0, &info) == 0);
|
|
Require(info.st_size == sizeof(ModuleInfoForUnwind));
|
|
Require(info.seg0_addr == expected.start && info.seg0_size == expected.end - expected.start);
|
|
Require(std::string(info.name) == expected.path.substr(0, sizeof(info.name) - 1));
|
|
Require(info.eh_frame_hdr_addr == 0 && info.eh_frame_addr == 0 && info.eh_frame_size == 0);
|
|
}
|
|
|
|
void CheckUnwindInfo() {
|
|
RequireUnwindMatchesMaps(reinterpret_cast<const void*>(&RequireUnwindMatchesMaps));
|
|
RequireUnwindMatchesMaps(reinterpret_cast<const void*>(&sceSysmoduleGetModuleInfoForUnwind));
|
|
int local = 0;
|
|
RequireUnwindMatchesMaps(&local);
|
|
const auto page = static_cast<std::size_t>(sysconf(_SC_PAGESIZE));
|
|
void* anonymous = mmap(nullptr, page, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
Require(anonymous != MAP_FAILED);
|
|
RequireUnwindMatchesMaps(anonymous);
|
|
Require(munmap(anonymous, page) == 0);
|
|
void* gap = mmap(nullptr, page, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
|
Require(gap != MAP_FAILED && munmap(gap, page) == 0);
|
|
ModuleInfoForUnwind info{};
|
|
bool threw = false;
|
|
try {
|
|
sceSysmoduleGetModuleInfoForUnwind(reinterpret_cast<std::uint64_t>(gap), 0, &info);
|
|
} catch (const std::runtime_error&) {
|
|
threw = true;
|
|
}
|
|
Require(threw);
|
|
}
|
|
#endif
|
|
|
|
std::uint16_t UnknownModuleId() {
|
|
for (std::uint32_t id = 0xffff; id != 0; --id) {
|
|
if (kModuleTable.find(id) == kModuleTable.end()) return static_cast<std::uint16_t>(id);
|
|
}
|
|
std::abort();
|
|
}
|
|
|
|
void CheckUnknownIds() {
|
|
const std::uint16_t id = UnknownModuleId();
|
|
const std::uint32_t internalId = id | kInternalFlag;
|
|
Require(kModuleTable.find(internalId) == kModuleTable.end());
|
|
Require(sceSysmoduleIsLoaded(id) == 0);
|
|
Require(sceSysmoduleLoadModule(id) == 0);
|
|
Require(sceSysmoduleIsLoaded(id) == 0);
|
|
Require(sceSysmoduleUnloadModule(id) == 0);
|
|
Require(sceSysmoduleUnloadModule(id) == 0);
|
|
Require(sceSysmoduleIsLoaded(id) == 0);
|
|
Require(ThrowsRuntimeError([internalId] { sceSysmoduleLoadModuleInternal(internalId); }));
|
|
Require(ThrowsRuntimeError([internalId] { sceSysmoduleUnloadModuleInternal(internalId); }));
|
|
int result = 0x5a5a5a5a;
|
|
Require(ThrowsRuntimeError([internalId, &result] { sceSysmoduleLoadModuleInternalWithArg(internalId, 0, nullptr, 0, &result); }));
|
|
Require(result == 0x5a5a5a5a);
|
|
int unloadResult = 0x5a5a5a5a;
|
|
Require(ThrowsRuntimeError([internalId, &unloadResult] { sceSysmoduleUnloadModuleInternalWithArg(internalId, 0, nullptr, 0, &unloadResult); }));
|
|
Require(unloadResult == 0x5a5a5a5a);
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
void RequireUnwindMatchesRegion(const void* pointer) {
|
|
const auto address = reinterpret_cast<std::uint64_t>(pointer);
|
|
MEMORY_BASIC_INFORMATION expected{};
|
|
Require(VirtualQuery(pointer, &expected, sizeof(expected)) != 0);
|
|
char mapped[4096] = {};
|
|
const DWORD length = GetMappedFileNameA(GetCurrentProcess(), expected.BaseAddress, mapped, sizeof(mapped) - 1);
|
|
mapped[length] = '\0';
|
|
for (int repeat = 0; repeat < 3; ++repeat) {
|
|
ModuleInfoForUnwind info{};
|
|
Require(sceSysmoduleGetModuleInfoForUnwind(address, 0, &info) == 0);
|
|
Require(info.st_size == sizeof(ModuleInfoForUnwind));
|
|
Require(info.seg0_addr == reinterpret_cast<std::uint64_t>(expected.BaseAddress) && info.seg0_size == expected.RegionSize);
|
|
Require(std::strncmp(info.name, mapped, sizeof(info.name) - 1) == 0);
|
|
Require(info.eh_frame_hdr_addr == 0 && info.eh_frame_addr == 0 && info.eh_frame_size == 0);
|
|
}
|
|
}
|
|
|
|
void CheckUnwindInfo() {
|
|
RequireUnwindMatchesRegion(reinterpret_cast<const void*>(&RequireUnwindMatchesRegion));
|
|
RequireUnwindMatchesRegion(reinterpret_cast<const void*>(&sceSysmoduleGetModuleInfoForUnwind));
|
|
RequireUnwindMatchesRegion(reinterpret_cast<const void*>(&GetModuleHandleW));
|
|
const auto* host = reinterpret_cast<const char*>(&GetModuleHandleW);
|
|
MEMORY_BASIC_INFORMATION hostRegion{};
|
|
Require(VirtualQuery(host, &hostRegion, sizeof(hostRegion)) != 0);
|
|
for (const std::size_t step : {std::size_t{0x1000}, std::size_t{0x3000}, std::size_t{0x10000}}) {
|
|
if (hostRegion.RegionSize > step) RequireUnwindMatchesRegion(host + step);
|
|
}
|
|
RequireUnwindMatchesRegion(host + 0x2000);
|
|
RequireUnwindMatchesRegion(host);
|
|
const auto* anchor = reinterpret_cast<const char*>(&RtlPcToFileHeader);
|
|
MEMORY_BASIC_INFORMATION anchorRegion{};
|
|
Require(VirtualQuery(anchor, &anchorRegion, sizeof(anchorRegion)) != 0);
|
|
if (anchorRegion.RegionSize > 0x4000) {
|
|
RequireUnwindMatchesRegion(anchor + 0x3000);
|
|
RequireUnwindMatchesRegion(anchor);
|
|
RequireUnwindMatchesRegion(anchor + 0x1000);
|
|
RequireUnwindMatchesRegion(anchor + 0x2000);
|
|
}
|
|
static int data = 1;
|
|
static const char text[] = "unwind region";
|
|
RequireUnwindMatchesRegion(&data);
|
|
RequireUnwindMatchesRegion(text);
|
|
RequireUnwindMatchesRegion(reinterpret_cast<const void*>(&RequireUnwindMatchesRegion));
|
|
int local = 0;
|
|
RequireUnwindMatchesRegion(&local);
|
|
SYSTEM_INFO system{};
|
|
GetSystemInfo(&system);
|
|
const std::size_t page = system.dwPageSize;
|
|
auto* memory = static_cast<char*>(VirtualAlloc(nullptr, 3 * page, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE));
|
|
Require(memory != nullptr);
|
|
RequireUnwindMatchesRegion(memory);
|
|
DWORD previous = 0;
|
|
Require(VirtualProtect(memory + 2 * page, page, PAGE_READONLY, &previous) != 0);
|
|
RequireUnwindMatchesRegion(memory);
|
|
RequireUnwindMatchesRegion(memory + 2 * page);
|
|
Require(VirtualFree(memory, 0, MEM_RELEASE) != 0);
|
|
RequireUnwindMatchesRegion(memory);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
int main() {
|
|
CheckUnknownIds();
|
|
Require(sceSysmoduleIsLoaded(0) == kInvalidValue);
|
|
Require(sceSysmoduleLoadModule(0) == kInvalidValue);
|
|
Require(sceSysmoduleUnloadModule(0) == kInvalidValue);
|
|
for (std::uint32_t id : {0u, kInternalFlag}) {
|
|
Require(sceSysmoduleIsLoadedInternal(id) == kInvalidValue);
|
|
Require(sceSysmoduleLoadModuleInternal(id) == kInvalidValue);
|
|
Require(sceSysmoduleUnloadModuleInternal(id) == kInvalidValue);
|
|
int result = 0x5a5a5a5a;
|
|
Require(sceSysmoduleLoadModuleInternalWithArg(id, 0, nullptr, 0, &result) == kInvalidValue);
|
|
Require(result == 0x5a5a5a5a);
|
|
}
|
|
|
|
Require(ThrowsRuntimeError([] { sceSysmoduleIsLoadedInternal(0x00ffffffu); }));
|
|
Require(sceSysmoduleIsLoadedInternal(kFiberModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleIsLoaded(kFiberModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModuleInternal(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleIsLoadedInternal(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleLoadModuleInternal(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kFiberModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModuleInternal(kFiberModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kUltModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kUltModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kUltModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kUltModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kUltModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kUltModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kAcmModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kAcmModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kAcmModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kAcmModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kAcmModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kAcmModuleId) == kModuleUnloaded);
|
|
|
|
constexpr std::uint16_t kShareModuleId = 0x010f;
|
|
Require(sceSysmoduleIsLoaded(kShareModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kShareModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kShareModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kShareModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kShareModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kTrophy2ModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModuleInternal(kTrophy2ModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kTrophy2ModuleId) == 0);
|
|
Require(sceSysmoduleLoadModuleInternal(kTrophy2ModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kTrophy2ModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kTrophy2ModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kTrophy2ModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kTrophy2ModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModuleInternal(kTrophy2ModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kVoiceChatModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kVoiceChatModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kVoiceChatModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kVoiceChatModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kVoiceChatModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kVoiceChatModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kPsmlModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kPsmlModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kPsmlModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kPsmlModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kPsmlModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kPsmlModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kProprietaryVoiceChatHelperModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kProprietaryVoiceChatHelperModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kProprietaryVoiceChatHelperModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kProprietaryVoiceChatHelperModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kProprietaryVoiceChatHelperModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kProprietaryVoiceChatHelperModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kPerfModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kPerfModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kPerfModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kPerfModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kPerfModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kPerfModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoaded(kVrSetupDialogModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModule(kVrSetupDialogModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kVrSetupDialogModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kVrSetupDialogModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModule(kVrSetupDialogModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kVrSetupDialogModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcDriverModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModuleInternal(kAgcDriverModuleId) == 0);
|
|
Require(sceSysmoduleLoadModuleInternal(kAgcDriverModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcDriverModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcDriverModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcDriverModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleUnloadModuleInternal(kNgs2InternalModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModuleInternal(kNgs2InternalModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kNgs2InternalModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kNgs2InternalModuleId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleUnloadModuleInternal(kHdrScopesInternalModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModuleInternal(kHdrScopesInternalModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kHdrScopesInternalModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kHdrScopesInternalModuleId) == kModuleUnloaded);
|
|
|
|
int unloadArgResult = -1;
|
|
Require(sceSysmoduleUnloadModuleInternalWithArg(0, 0, nullptr, 0, &unloadArgResult) == kInvalidValue);
|
|
Require(unloadArgResult == -1);
|
|
Require(sceSysmoduleUnloadModuleInternalWithArg(kAgcInternalId, 0, nullptr, 0, &unloadArgResult) == kModuleUnloaded);
|
|
Require(unloadArgResult == -1);
|
|
int loadArgResult = -1;
|
|
Require(sceSysmoduleLoadModuleInternalWithArg(kAgcInternalId, 0, nullptr, 0, &loadArgResult) == 0);
|
|
Require(loadArgResult == 0);
|
|
Require(sceSysmoduleIsLoadedInternal(kAgcInternalId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternalWithArg(kAgcInternalId, 0, nullptr, 0, &unloadArgResult) == 0);
|
|
Require(unloadArgResult == 0);
|
|
Require(sceSysmoduleIsLoadedInternal(kAgcInternalId) == kModuleUnloaded);
|
|
|
|
Require(sceSysmoduleIsLoadedInternal(kAgcModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModuleInternal(kAgcModuleId) == 0);
|
|
Require(sceSysmoduleIsLoadedInternal(kAgcModuleId) == 0);
|
|
Require(sceSysmoduleLoadModuleInternal(kAgcModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcModuleId) == 0);
|
|
Require(sceSysmoduleIsLoadedInternal(kAgcModuleId) == 0);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcModuleId) == 0);
|
|
Require(sceSysmoduleIsLoadedInternal(kAgcModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleUnloadModuleInternal(kAgcModuleId) == kModuleUnloaded);
|
|
#if defined(__linux__) || defined(_WIN32)
|
|
CheckUnwindInfo();
|
|
#endif
|
|
|
|
std::int32_t handle = -1;
|
|
Require(sceSysmoduleGetModuleHandleInternal(kFiberModuleId, &handle) == kModuleUnloaded);
|
|
Require(handle == -1);
|
|
Require(ThrowsRuntimeError([] { sceSysmoduleGetModuleHandleInternal(0, nullptr); }));
|
|
Require(ThrowsRuntimeError([&] { sceSysmoduleGetModuleHandleInternal(0, &handle); }));
|
|
Require(ThrowsRuntimeError([] { sceSysmoduleGetModuleHandleInternal(kFiberModuleId, nullptr); }));
|
|
Require(ThrowsRuntimeError([&] { sceSysmoduleGetModuleHandleInternal(0x00ffffffu, &handle); }));
|
|
|
|
Require(sceSysmoduleLoadModule(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleGetModuleHandleInternal(kFiberModuleId, &handle) == 0);
|
|
Require(handle >= 0);
|
|
std::int32_t again = -1;
|
|
Require(sceSysmoduleGetModuleHandleInternal(kFiberModuleId, &again) == 0);
|
|
Require(again == handle);
|
|
void* symbol = nullptr;
|
|
Require(sceKernelDlsym(handle, "sceFiberOptParamInitialize", &symbol) == 0);
|
|
Require(symbol != nullptr);
|
|
Require(sceSysmoduleUnloadModule(kFiberModuleId) == 0);
|
|
Require(sceSysmoduleGetModuleHandleInternal(kFiberModuleId, &handle) == kModuleUnloaded);
|
|
|
|
constexpr std::uint16_t kAudioPropagationModuleId = 0x0120;
|
|
std::int32_t audioPropagationHandle = -1;
|
|
Require(sceSysmoduleGetModuleHandleInternal(kAudioPropagationModuleId, &audioPropagationHandle) == kModuleUnloaded);
|
|
Require(audioPropagationHandle == -1);
|
|
|
|
Require(sceSysmoduleIsLoaded(kAudioPropagationModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleLoadModule(kAudioPropagationModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kAudioPropagationModuleId) == 0);
|
|
Require(sceSysmoduleGetModuleHandleInternal(kAudioPropagationModuleId, &audioPropagationHandle) == 0);
|
|
Require(audioPropagationHandle >= 0);
|
|
void* audioPropagationSymbol = nullptr;
|
|
Require(sceKernelDlsym(audioPropagationHandle, "sceAudioPropagationSystemCreate", &audioPropagationSymbol) == 0);
|
|
Require(audioPropagationSymbol != nullptr);
|
|
|
|
Require(sceSysmoduleUnloadModule(kAudioPropagationModuleId) == 0);
|
|
Require(sceSysmoduleIsLoaded(kAudioPropagationModuleId) == kModuleUnloaded);
|
|
Require(sceSysmoduleGetModuleHandleInternal(kAudioPropagationModuleId, &audioPropagationHandle) == kModuleUnloaded);
|
|
}
|