summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2020-09-24 21:05:33 +0200
committerLéo Lam <leo@leolam.fr>2020-09-24 21:30:18 +0200
commit72d100323ca3c03d3dc71d0446de947e6280ebfc (patch)
tree1afa5fc88c4e95f7fa4b245ccbd3e0fcfb4effd0 /src
parent7d51cbac51e2b70aff47268131c6fdfad13bfc57 (diff)
ksys/res: Implement OffsetReadFileDevice
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/Resource/CMakeLists.txt2
-rw-r--r--src/KingSystem/Resource/resOffsetReadFileDevice.cpp94
-rw-r--r--src/KingSystem/Resource/resOffsetReadFileDevice.h41
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