mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-01 12:45:56 +00:00
feat(libSceBeisobmf): implement 10 box metadata accessors
This commit is contained in:
1 parent
c14f7543d0
commit
04e35c008b
4 files changed
+248
-60
No files matched your search
@@ -261,6 +261,16 @@ add_custom_target(libs DEPENDS ${PATCHED_OUTPUTS})
|
||||
include(prx/libSceLibreSsl/ProtocolSelection.cmake)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_test_executable(guest_beisobmf_boxes_tests tests/GuestBeisobmfBoxes.cpp)
|
||||
target_include_directories(guest_beisobmf_boxes_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(guest_beisobmf_boxes_tests PRIVATE libSceBeisobmf libc)
|
||||
configure_windows_unwind(guest_beisobmf_boxes_tests)
|
||||
add_test(NAME guest_beisobmf_boxes COMMAND guest_beisobmf_boxes_tests)
|
||||
if(WIN32)
|
||||
set_tests_properties(guest_beisobmf_boxes PROPERTIES ENVIRONMENT_MODIFICATION
|
||||
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceBeisobmf>")
|
||||
endif()
|
||||
|
||||
add_test_executable(guest_posix_scalar_io_tests tests/GuestPosixScalarIo.cpp)
|
||||
target_include_directories(guest_posix_scalar_io_tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(guest_posix_scalar_io_tests PRIVATE libkernel libc)
|
||||
|
||||
@@ -1,100 +1,163 @@
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libSceBeisobmf/include/Api.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "prx/libc/include/GuestArena.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename TValue>
|
||||
TValue ReadField(const void *object, std::size_t offset) {
|
||||
if (!object)
|
||||
throw std::invalid_argument("isobmf box pointer is null");
|
||||
TValue value{};
|
||||
std::memcpy(&value, static_cast<const std::byte *>(object) + offset,
|
||||
sizeof(value));
|
||||
return value;
|
||||
}
|
||||
|
||||
std::uintptr_t ReadPointer(const void *object, std::size_t offset) {
|
||||
return ReadField<std::uintptr_t>(object, offset);
|
||||
}
|
||||
|
||||
void WritePointer(void *object, std::size_t offset, std::uintptr_t value) {
|
||||
std::memcpy(static_cast<std::byte *>(object) + offset, &value, sizeof(value));
|
||||
}
|
||||
|
||||
std::uintptr_t FindMember(void *box, const char *name) {
|
||||
if (!box || !name)
|
||||
throw std::invalid_argument("isobmf member lookup requires a box and name");
|
||||
auto *cursor = static_cast<std::byte *>(box) + 0x50;
|
||||
const GuestArena::HostWrite write(cursor, sizeof(std::uintptr_t));
|
||||
if (!write.Open())
|
||||
throw std::runtime_error(
|
||||
"isobmf member cursor is not writable guest memory");
|
||||
WritePointer(box, 0x50, ReadPointer(box, 0x40));
|
||||
for (auto member = ReadPointer(box, 0x50); member != 0;
|
||||
member = ReadPointer(box, 0x50)) {
|
||||
const auto *memberName = reinterpret_cast<const char *>(member + 0x18);
|
||||
if (std::strncmp(memberName, name, 0x40) == 0)
|
||||
return member;
|
||||
WritePointer(box, 0x50,
|
||||
ReadPointer(reinterpret_cast<const void *>(member), 0x10));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *MemberPointer(std::uintptr_t member) {
|
||||
const auto type =
|
||||
ReadField<std::uint32_t>(reinterpret_cast<const void *>(member), 0x6c);
|
||||
if (type < 20 && ((0x97800u >> (type & 0x1f)) & 1u) != 0)
|
||||
return reinterpret_cast<void *>(
|
||||
ReadPointer(reinterpret_cast<const void *>(member), 0x60));
|
||||
return reinterpret_cast<void *>(member + 0x58);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
APS5_DUMMY_FUN
|
||||
int APS5_VABI isobmf_box_getchildbox_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
void *APS5_VABI isobmf_box_getchildbox_nid_postfix(void *box) {
|
||||
return reinterpret_cast<void *>(ReadPointer(box, 0x10));
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getdiskoffset_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
std::uint64_t APS5_VABI isobmf_box_getdiskoffset_nid_postfix(void *box) {
|
||||
return ReadField<std::uint64_t>(box, 0x80);
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getflags32b_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
std::uint32_t APS5_VABI isobmf_box_getflags32b_nid_postfix(void *box) {
|
||||
if (!box)
|
||||
return 0;
|
||||
const auto member = FindMember(box, "flags");
|
||||
if (!member)
|
||||
return 0;
|
||||
const auto *value = static_cast<const std::uint8_t *>(MemberPointer(member));
|
||||
return static_cast<std::uint32_t>(value[0]) |
|
||||
(static_cast<std::uint32_t>(value[1]) << 8) |
|
||||
(static_cast<std::uint32_t>(value[2]) << 16);
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getmember_length_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
std::uint32_t APS5_VABI
|
||||
isobmf_box_getmember_length_nid_postfix(void *box, const char *name) {
|
||||
const auto member = FindMember(box, name);
|
||||
return member ? ReadField<std::uint32_t>(
|
||||
reinterpret_cast<const void *>(member), 0x68)
|
||||
: 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getmember_ptr_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
void *APS5_VABI isobmf_box_getmember_ptr_nid_postfix(void *box,
|
||||
const char *name) {
|
||||
const auto member = FindMember(box, name);
|
||||
return member ? MemberPointer(member) : nullptr;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getmember_type_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
std::uint32_t APS5_VABI
|
||||
isobmf_box_getmember_type_nid_postfix(void *box, const char *name) {
|
||||
const auto member = FindMember(box, name);
|
||||
return member ? ReadField<std::uint32_t>(
|
||||
reinterpret_cast<const void *>(member), 0x6c)
|
||||
: 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getnextbox_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
void *APS5_VABI isobmf_box_getnextbox_nid_postfix(void *box) {
|
||||
return reinterpret_cast<void *>(ReadPointer(box, 0x20));
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_getstate_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
std::uint32_t APS5_VABI isobmf_box_getstate_nid_postfix(void *box) {
|
||||
return ReadField<std::uint32_t>(box, 0x8c);
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_box_gettype_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
std::uint32_t APS5_VABI isobmf_box_gettype_nid_postfix(void *box) {
|
||||
return ReadField<std::uint32_t>(box, 0x90);
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_clear_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_create_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_decode_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_destroy_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_get_decoder_tree_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_getquerydata_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_next_disk_offset_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
std::uint64_t APS5_VABI
|
||||
isobmf_decoder_next_disk_offset_nid_postfix(void *decoder) {
|
||||
if (!decoder)
|
||||
return 0xffffffff;
|
||||
return ReadField<std::uint64_t>(decoder, 0xc0);
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_decoder_query_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI isobmf_memmanager_set_nid_postfix(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,23 +4,26 @@
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI isobmf_box_getchildbox_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getdiskoffset_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getflags32b_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getmember_length_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getmember_ptr_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getmember_type_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getnextbox_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_getstate_nid_postfix(void);
|
||||
int APS5_VABI isobmf_box_gettype_nid_postfix(void);
|
||||
void *APS5_VABI isobmf_box_getchildbox_nid_postfix(void *box);
|
||||
std::uint64_t APS5_VABI isobmf_box_getdiskoffset_nid_postfix(void *box);
|
||||
std::uint32_t APS5_VABI isobmf_box_getflags32b_nid_postfix(void *box);
|
||||
std::uint32_t APS5_VABI
|
||||
isobmf_box_getmember_length_nid_postfix(void *box, const char *name);
|
||||
void *APS5_VABI isobmf_box_getmember_ptr_nid_postfix(void *box,
|
||||
const char *name);
|
||||
std::uint32_t APS5_VABI isobmf_box_getmember_type_nid_postfix(void *box,
|
||||
const char *name);
|
||||
void *APS5_VABI isobmf_box_getnextbox_nid_postfix(void *box);
|
||||
std::uint32_t APS5_VABI isobmf_box_getstate_nid_postfix(void *box);
|
||||
std::uint32_t APS5_VABI isobmf_box_gettype_nid_postfix(void *box);
|
||||
int APS5_VABI isobmf_decoder_clear_nid_postfix(void);
|
||||
int APS5_VABI isobmf_decoder_create_nid_postfix(void);
|
||||
int APS5_VABI isobmf_decoder_decode_nid_postfix(void);
|
||||
int APS5_VABI isobmf_decoder_destroy_nid_postfix(void);
|
||||
int APS5_VABI isobmf_decoder_get_decoder_tree_nid_postfix(void);
|
||||
int APS5_VABI isobmf_decoder_getquerydata_nid_postfix(void);
|
||||
int APS5_VABI isobmf_decoder_next_disk_offset_nid_postfix(void);
|
||||
std::uint64_t APS5_VABI
|
||||
isobmf_decoder_next_disk_offset_nid_postfix(void *decoder);
|
||||
int APS5_VABI isobmf_decoder_query_nid_postfix(void);
|
||||
int APS5_VABI isobmf_memmanager_set_nid_postfix(void);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#include "prx/libSceBeisobmf/include/Api.hpp"
|
||||
#include "prx/libc/include/GuestArena.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
void Require(bool condition, const char *message) {
|
||||
if (!condition) {
|
||||
std::fprintf(stderr, "BEISOBMF BOXES: %s\n", message);
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
void Write(void *destination, const void *source, std::size_t bytes) {
|
||||
const GuestArena::HostWrite access(destination, bytes);
|
||||
Require(access.Open(), "guest fixture memory was not writable");
|
||||
std::memcpy(destination, source, bytes);
|
||||
}
|
||||
|
||||
template <typename TValue>
|
||||
void WriteField(void *object, std::size_t offset, TValue value) {
|
||||
Write(static_cast<std::byte *>(object) + offset, &value, sizeof(value));
|
||||
}
|
||||
|
||||
void *Allocate(std::size_t bytes) {
|
||||
void *memory = GuestArena::GuestArenaAllocate_nid_postfix(bytes, 16);
|
||||
Require(memory != nullptr, "guest fixture allocation failed");
|
||||
const std::array<std::byte, 0x100> zeros{};
|
||||
auto *destination = static_cast<std::byte *>(memory);
|
||||
for (std::size_t offset = 0; offset < bytes; offset += zeros.size())
|
||||
Write(destination + offset, zeros.data(),
|
||||
(bytes - offset < zeros.size()) ? bytes - offset : zeros.size());
|
||||
return memory;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
auto *box = static_cast<std::byte *>(Allocate(0xa0));
|
||||
auto *inlineMember = static_cast<std::byte *>(Allocate(0x70));
|
||||
auto *pointerMember = static_cast<std::byte *>(Allocate(0x70));
|
||||
auto *payload = static_cast<std::byte *>(Allocate(8));
|
||||
auto *child = Allocate(0x10);
|
||||
auto *next = Allocate(0x10);
|
||||
auto *decoder = static_cast<std::byte *>(Allocate(0xd0));
|
||||
|
||||
WriteField(box, 0x10, child);
|
||||
WriteField(box, 0x20, next);
|
||||
WriteField(box, 0x40, inlineMember);
|
||||
WriteField(box, 0x80, std::uint64_t{0x1122334455667788});
|
||||
WriteField(box, 0x8c, std::uint32_t{7});
|
||||
WriteField(box, 0x90, std::uint32_t{0x1234});
|
||||
WriteField(inlineMember, 0x10, pointerMember);
|
||||
constexpr char flagsName[] = "flags";
|
||||
constexpr char inlineName[] = "inline";
|
||||
constexpr char pointerName[] = "external";
|
||||
Write(inlineMember + 0x18, flagsName, sizeof(flagsName));
|
||||
Write(inlineMember + 0x58, "\x34\x12\x01", 3);
|
||||
WriteField(inlineMember, 0x68, std::uint32_t{3});
|
||||
WriteField(inlineMember, 0x6c, std::uint32_t{0});
|
||||
Write(pointerMember + 0x18, pointerName, sizeof(pointerName));
|
||||
WriteField(pointerMember, 0x68, std::uint32_t{8});
|
||||
WriteField(pointerMember, 0x6c, std::uint32_t{11});
|
||||
WriteField(pointerMember, 0x60, payload);
|
||||
WriteField(decoder, 0xc0, std::uint64_t{0xfedcba9876543210});
|
||||
|
||||
Require(isobmf_box_getchildbox_nid_postfix(box) == child,
|
||||
"child box offset is wrong");
|
||||
Require(isobmf_box_getnextbox_nid_postfix(box) == next,
|
||||
"next box offset is wrong");
|
||||
Require(isobmf_box_getdiskoffset_nid_postfix(box) == 0x1122334455667788,
|
||||
"box disk offset is wrong");
|
||||
Require(isobmf_box_getstate_nid_postfix(box) == 7,
|
||||
"box state offset is wrong");
|
||||
Require(isobmf_box_gettype_nid_postfix(box) == 0x1234,
|
||||
"box type offset is wrong");
|
||||
Require(isobmf_box_getflags32b_nid_postfix(box) == 0x011234,
|
||||
"flags value is wrong");
|
||||
Require(isobmf_box_getmember_length_nid_postfix(box, flagsName) == 3,
|
||||
"inline member length is wrong");
|
||||
Require(isobmf_box_getmember_type_nid_postfix(box, flagsName) == 0,
|
||||
"inline member type is wrong");
|
||||
Require(isobmf_box_getmember_ptr_nid_postfix(box, flagsName) ==
|
||||
inlineMember + 0x58,
|
||||
"inline member pointer is wrong");
|
||||
Require(isobmf_box_getmember_length_nid_postfix(box, pointerName) == 8,
|
||||
"external member length is wrong");
|
||||
Require(isobmf_box_getmember_type_nid_postfix(box, pointerName) == 11,
|
||||
"external member type is wrong");
|
||||
Require(isobmf_box_getmember_ptr_nid_postfix(box, pointerName) == payload,
|
||||
"external member pointer is wrong");
|
||||
Require(isobmf_box_getmember_ptr_nid_postfix(box, "missing") == nullptr,
|
||||
"missing member pointer is not null");
|
||||
Require(isobmf_box_getmember_length_nid_postfix(box, "missing") == 0,
|
||||
"missing member length is not zero");
|
||||
Require(isobmf_box_getmember_type_nid_postfix(box, "missing") == 0,
|
||||
"missing member type is not zero");
|
||||
Require(isobmf_decoder_next_disk_offset_nid_postfix(decoder) ==
|
||||
0xfedcba9876543210,
|
||||
"decoder disk offset is wrong");
|
||||
Require(isobmf_decoder_next_disk_offset_nid_postfix(nullptr) == 0xffffffff,
|
||||
"null decoder sentinel is wrong");
|
||||
|
||||
std::puts("BEISOBMF BOXES tests passed");
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user