diff options
| author | Léo Lam <leo@leolam.fr> | 2020-09-24 21:05:33 +0200 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2020-09-24 21:30:18 +0200 |
| commit | 72d100323ca3c03d3dc71d0446de947e6280ebfc (patch) | |
| tree | 1afa5fc88c4e95f7fa4b245ccbd3e0fcfb4effd0 /src | |
| parent | 7d51cbac51e2b70aff47268131c6fdfad13bfc57 (diff) | |
ksys/res: Implement OffsetReadFileDevice
Diffstat (limited to 'src')
| -rw-r--r-- | src/KingSystem/Resource/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resOffsetReadFileDevice.cpp | 94 | ||||
| -rw-r--r-- | src/KingSystem/Resource/resOffsetReadFileDevice.h | 41 |
3 files changed, 137 insertions, 0 deletions
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 <heap/seadHeapMgr.h> +#include <math/seadMathCalcCommon.h> +#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 <filedevice/seadMainFileDevice.h> +#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 |
