1#include <filedevice/seadFileDeviceMgr.h>
2#include <math/seadMathCalcCommon.h>
3#include <prim/seadPtrUtil.h>
4#include <resource/seadResource.h>
5
6namespace sead
7{
8Resource::Resource() = default;
9
10Resource::~Resource() = default;
11
12DirectResource::DirectResource() = default;
13
14DirectResource::~DirectResource()
15{
16 if (mSettingFlag.isOnBit(bit: 0))
17 delete[] mRawData;
18}
19
20s32 DirectResource::getLoadDataAlignment() const
21{
22 return 4;
23}
24
25void DirectResource::doCreate_(u8*, u32, Heap*) {}
26
27void DirectResource::create(u8* buffer, u32 bufferSize, u32 allocSize, bool allocated, Heap* heap)
28{
29 if (mRawData)
30 {
31 SEAD_ASSERT_MSG(false, "read twice");
32 return;
33 }
34
35 mRawData = buffer;
36 mRawSize = bufferSize;
37 mBufferSize = allocSize;
38
39 mSettingFlag.changeBit(bit: 0, on: allocated);
40
41 doCreate_(buffer, bufferSize, heap);
42}
43
44ResourceFactory::~ResourceFactory()
45{
46 auto* mgr = ResourceMgr::instance();
47 if (mgr == nullptr)
48 return;
49
50 mgr->unregisterFactory(factory: this);
51 if (mgr->getDefaultFactory() == this)
52 mgr->setDefaultFactory(nullptr);
53}
54
55Resource* DirectResourceFactoryBase::create(const ResourceMgr::CreateArg& createArg)
56{
57 DirectResource* resource = newResource_(heap: createArg.heap, alignment: createArg.alignment);
58 if (resource == nullptr)
59 {
60 SEAD_ASSERT_MSG(false, "resource new failed.");
61 return nullptr;
62 }
63
64 if (!PtrUtil::isAligned(ptr: createArg.buffer, alignment: resource->getLoadDataAlignment()))
65 {
66 SEAD_ASSERT_MSG(false, "buffer alignment invalid: %p, %d", createArg.buffer,
67 resource->getLoadDataAlignment());
68 delete resource;
69 return nullptr;
70 }
71
72 resource->create(buffer: createArg.buffer, bufferSize: createArg.file_size, allocSize: createArg.buffer_size,
73 allocated: createArg.need_unload, heap: createArg.heap);
74 return resource;
75}
76
77Resource* DirectResourceFactoryBase::tryCreate(const ResourceMgr::LoadArg& loadArg)
78{
79 DirectResource* resource = newResource_(heap: loadArg.instance_heap, alignment: loadArg.instance_alignment);
80 if (resource == nullptr)
81 return nullptr;
82
83 FileDevice::LoadArg fileLoadArg;
84 u8* data;
85
86 fileLoadArg.path = loadArg.path;
87 fileLoadArg.buffer = loadArg.load_data_buffer;
88 fileLoadArg.buffer_size = loadArg.load_data_buffer_size;
89 fileLoadArg.buffer_size_alignment = loadArg.load_data_buffer_alignment;
90 fileLoadArg.heap = loadArg.load_data_heap;
91 fileLoadArg.div_size = loadArg.div_size;
92 fileLoadArg.assert_on_alloc_fail = loadArg.assert_on_alloc_fail;
93
94 if (loadArg.load_data_alignment != 0)
95 fileLoadArg.alignment = loadArg.load_data_alignment;
96 else
97 fileLoadArg.alignment =
98 Mathi::sign(value: loadArg.instance_alignment) * resource->getLoadDataAlignment();
99
100 if (loadArg.device != NULL)
101 data = loadArg.device->tryLoad(arg&: fileLoadArg);
102 else
103 data = FileDeviceMgr::instance()->tryLoad(arg&: fileLoadArg);
104
105 if (data == NULL)
106 {
107 delete resource;
108 return NULL;
109 }
110
111 resource->create(buffer: data, bufferSize: fileLoadArg.read_size, allocSize: fileLoadArg.roundup_size, allocated: fileLoadArg.need_unload,
112 heap: loadArg.instance_heap);
113 return resource;
114}
115
116Resource* DirectResourceFactoryBase::tryCreateWithDecomp(const ResourceMgr::LoadArg& loadArg,
117 Decompressor* decompressor)
118{
119 DirectResource* resource = newResource_(heap: loadArg.instance_heap, alignment: loadArg.instance_alignment);
120 if (resource == NULL)
121 return NULL;
122
123 u32 outSize = 0;
124 u32 outAllocSize = 0;
125 bool outAllocated = false;
126
127 u8* data = decompressor->tryDecompFromDevice(loadArg, resource, outSize: &outSize, outAllocSize: &outAllocSize,
128 outAllocated: &outAllocated);
129
130 if (!data)
131 {
132 delete resource;
133 return nullptr;
134 }
135
136 resource->create(buffer: data, bufferSize: outSize, allocSize: outAllocSize, allocated: outAllocated, heap: loadArg.instance_heap);
137 return resource;
138}
139
140} // namespace sead
141