From 72d100323ca3c03d3dc71d0446de947e6280ebfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Thu, 24 Sep 2020 21:05:33 +0200 Subject: [PATCH] ksys/res: Implement OffsetReadFileDevice --- data/uking_functions.csv | 18 ++-- src/KingSystem/Resource/CMakeLists.txt | 2 + .../Resource/resOffsetReadFileDevice.cpp | 94 +++++++++++++++++++ .../Resource/resOffsetReadFileDevice.h | 41 ++++++++ 4 files changed, 146 insertions(+), 9 deletions(-) create mode 100644 src/KingSystem/Resource/resOffsetReadFileDevice.cpp create mode 100644 src/KingSystem/Resource/resOffsetReadFileDevice.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index e7d5705b..84f10258 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -94588,15 +94588,15 @@ 0x0000007101307abc,sub_7101307ABC,24, 0x0000007101307ad4,sub_7101307AD4,48, 0x0000007101307b04,sub_7101307B04,92, -0x0000007101307b60,MainFileDevice::ctor,64, -0x0000007101307ba0,j__ZN4sead14MainFileDeviceD2Ev,4, -0x0000007101307ba4,sub_7101307BA4,8, -0x0000007101307bac,_ZN4sead14MainFileDeviceD0Ev_0,36, -0x0000007101307bd0,sub_7101307BD0,40, -0x0000007101307bf8,sub_7101307BF8,8, -0x0000007101307c00,sub_7101307C00,476, -0x0000007101307ddc,_ZNK4sead14MainFileDevice27checkDerivedRuntimeTypeInfoEPKNS_15RuntimeTypeInfo9InterfaceE,288, -0x0000007101307efc,_ZNK4sead14MainFileDevice18getRuntimeTypeInfoEv_0,92, +0x0000007101307b60,MainFileDevice::ctor,64,_ZN4ksys3res20OffsetReadFileDeviceC1EPN4sead4HeapE +0x0000007101307ba0,j__ZN4sead14MainFileDeviceD2Ev,4,_ZN4ksys3res20OffsetReadFileDeviceD2Ev +0x0000007101307ba4,sub_7101307BA4,8,_ZThn136_N4ksys3res20OffsetReadFileDeviceD1Ev +0x0000007101307bac,_ZN4sead14MainFileDeviceD0Ev_0,36,_ZN4ksys3res20OffsetReadFileDeviceD0Ev +0x0000007101307bd0,sub_7101307BD0,40,_ZThn136_N4ksys3res20OffsetReadFileDeviceD0Ev +0x0000007101307bf8,sub_7101307BF8,8,_ZN4ksys3res20OffsetReadFileDevice13setFileDeviceEPN4sead10FileDeviceE +0x0000007101307c00,sub_7101307C00,476,_ZN4ksys3res20OffsetReadFileDevice7doLoad_ERN4sead10FileDevice7LoadArgE +0x0000007101307ddc,_ZNK4sead14MainFileDevice27checkDerivedRuntimeTypeInfoEPKNS_15RuntimeTypeInfo9InterfaceE,288,_ZNK4ksys3res20OffsetReadFileDevice27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007101307efc,_ZNK4sead14MainFileDevice18getRuntimeTypeInfoEv_0,92,_ZNK4ksys3res20OffsetReadFileDevice18getRuntimeTypeInfoEv 0x0000007101307f58,sub_7101307F58,140, 0x0000007101307fe4,sub_7101307FE4,32, 0x0000007101308004,sub_7101308004,192, diff --git a/src/KingSystem/Resource/CMakeLists.txt b/src/KingSystem/Resource/CMakeLists.txt index 0098d6c6..75aaab56 100644 --- a/src/KingSystem/Resource/CMakeLists.txt +++ b/src/KingSystem/Resource/CMakeLists.txt @@ -90,6 +90,8 @@ target_sources(uking PRIVATE resHandle.h resLoadRequest.cpp resLoadRequest.h + resOffsetReadFileDevice.cpp + resOffsetReadFileDevice.h resResource.cpp resResource.h diff --git a/src/KingSystem/Resource/resOffsetReadFileDevice.cpp b/src/KingSystem/Resource/resOffsetReadFileDevice.cpp new file mode 100644 index 00000000..5bc3f9ac --- /dev/null +++ b/src/KingSystem/Resource/resOffsetReadFileDevice.cpp @@ -0,0 +1,94 @@ +#include "KingSystem/Resource/resOffsetReadFileDevice.h" +#include +#include +#include "KingSystem/Resource/resSystem.h" + +namespace ksys::res { + +OffsetReadFileDevice::OffsetReadFileDevice(sead::Heap* heap) : sead::MainFileDevice(heap) { + resetOffsetRead(); +} + +void OffsetReadFileDevice::setFileDevice(sead::FileDevice* device) { + OffsetRead::setFileDevice(device); +} + +/// This is a modified version of `sead::FileDevice::doLoad_`. +u8* OffsetReadFileDevice::doLoad_(sead::FileDevice::LoadArg& arg) { + if (arg.buffer && arg.buffer_size == 0) { + stubbedLogFunction(); + return nullptr; + } + + sead::FileDevice* device = mOffsetReadFileDevice; + if (!device) + device = this; + + sead::FileHandle handle; + if (!device->tryOpen(&handle, arg.path, FileDevice::cFileOpenFlag_ReadOnly, arg.div_size)) + return nullptr; + + u32 bytesToRead = arg.buffer_size; + if (!arg.buffer || arg.check_read_entire_file) { + u32 fileSize = 0; + if (!device->tryGetFileSize(&fileSize, &handle)) + return nullptr; + + if (fileSize == 0) { + stubbedLogFunction(); + return nullptr; + } + + if (bytesToRead != 0) { + if (bytesToRead < fileSize) { + stubbedLogFunction(); + return nullptr; + } + } else { + bytesToRead = mOffsetReadOffset + sead::Mathi::roundUpPow2Positive( + fileSize, FileDevice::cBufferMinAlignment); + } + } + + u8* buf = arg.buffer; + bool allocated = false; + + if (buf == nullptr) { + const s32 sign = (arg.alignment < 0) ? -1 : 1; + s32 alignment = sead::abs(arg.alignment); + alignment = sign * ((alignment < cBufferMinAlignment) ? cBufferMinAlignment : alignment); + + sead::Heap* heap = arg.heap; + if (!heap) + heap = sead::HeapMgr::instance()->getCurrentHeap(); + + void* raw_buf = heap->tryAlloc(bytesToRead, alignment); + if (!raw_buf) + return nullptr; + + buf = new (raw_buf) u8[bytesToRead]; + allocated = true; + } + + u32 bytesRead = 0; + if (!device->tryRead(&bytesRead, &handle, buf + mOffsetReadOffset, + bytesToRead - mOffsetReadOffset)) { + if (allocated) + delete[] buf; + return nullptr; + } + + if (!device->tryClose(&handle)) { + if (allocated) + delete[] buf; + return nullptr; + } + + arg.read_size = bytesRead; + arg.roundup_size = bytesToRead; + arg.need_unload = allocated; + + return buf; +} + +} // namespace ksys::res diff --git a/src/KingSystem/Resource/resOffsetReadFileDevice.h b/src/KingSystem/Resource/resOffsetReadFileDevice.h new file mode 100644 index 00000000..93c4800f --- /dev/null +++ b/src/KingSystem/Resource/resOffsetReadFileDevice.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include "KingSystem/Utils/Types.h" + +namespace ksys::res { + +class OffsetRead { +public: + OffsetRead() { resetOffsetRead(); } + virtual ~OffsetRead() = default; + + void setReadOffset(u32 offset) { mOffsetReadOffset = offset; } + void setFileDevice(sead::FileDevice* device) { mOffsetReadFileDevice = device; } + + void resetOffsetRead() { + mOffsetReadOffset = 0; + mOffsetReadFileDevice = nullptr; + } + +protected: + u32 mOffsetReadOffset; + sead::FileDevice* mOffsetReadFileDevice; +}; +KSYS_CHECK_SIZE_NX150(OffsetRead, 0x18); + +class OffsetReadFileDevice : public sead::MainFileDevice, public OffsetRead { + SEAD_RTTI_OVERRIDE(OffsetReadFileDevice, sead::MainFileDevice) +public: + explicit OffsetReadFileDevice(sead::Heap* heap); + ~OffsetReadFileDevice() override = default; + + void setReadOffset(u32 offset) { OffsetRead::setReadOffset(offset); } + void setFileDevice(sead::FileDevice* device); + +protected: + u8* doLoad_(LoadArg& arg) override; +}; +KSYS_CHECK_SIZE_NX150(OffsetReadFileDevice, 0xa0); + +} // namespace ksys::res