1#include <basis/seadRawPrint.h>
2#include <filedevice/seadPath.h>
3#include <heap/seadHeapMgr.h>
4#include <resource/seadResource.h>
5#include <resource/seadResourceMgr.h>
6
7namespace sead
8{
9SEAD_SINGLETON_DISPOSER_IMPL(ResourceMgr)
10
11ResourceMgr::ResourceMgr()
12{
13 if (HeapMgr::sInstancePtr == NULL)
14 {
15 SEAD_ASSERT_MSG(false, "ResourceMgr need HeapMgr");
16 return;
17 }
18
19 mNullResourceFactory =
20 new (HeapMgr::sInstancePtr->findContainHeap(ptr: this)) DirectResourceFactory<DirectResource>();
21 mDefaultResourceFactory = mNullResourceFactory;
22 registerFactory(factory: mNullResourceFactory, name: "");
23}
24
25ResourceMgr::~ResourceMgr()
26{
27 if (mNullResourceFactory == NULL)
28 return;
29
30 delete mNullResourceFactory;
31 mNullResourceFactory = NULL;
32}
33
34// NON_MATCHING: tail call for factory->create
35Resource* ResourceMgr::create(const ResourceMgr::CreateArg& arg)
36{
37 if (!arg.buffer)
38 {
39 SEAD_ASSERT_MSG(false, "buffer null");
40 return nullptr;
41 }
42 if (arg.file_size == 0)
43 {
44 SEAD_ASSERT_MSG(false, "file_size is 0");
45 return nullptr;
46 }
47 if (arg.buffer_size == 0)
48 {
49 SEAD_ASSERT_MSG(false, "buffer_size is 0");
50 return nullptr;
51 }
52
53 if (arg.factory)
54 return arg.factory->create(createArg: arg);
55
56 auto* factory = findFactory(name: arg.ext);
57 if (factory)
58 return factory->create(createArg: arg);
59
60 SEAD_ASSERT_MSG(false, "factory not found: %s", arg.ext.cstr());
61 return nullptr;
62}
63
64void ResourceMgr::registerFactory(ResourceFactory* factory, const SafeString& name)
65{
66 factory->setExt(name);
67
68 mFactoryList.pushBack(item: factory);
69}
70
71ResourceFactory* ResourceMgr::setDefaultFactory(ResourceFactory* factory)
72{
73 ResourceFactory* const previous_default = mDefaultResourceFactory;
74
75 if (!factory)
76 factory = mNullResourceFactory;
77
78 mDefaultResourceFactory = factory;
79 registerFactory(factory, name: "");
80
81 return previous_default;
82}
83
84ResourceFactory* ResourceMgr::findFactory(const SafeString& name)
85{
86 for (auto& factory : mFactoryList)
87 if (factory->getExt() == name)
88 return factory;
89
90 return mDefaultResourceFactory;
91}
92
93void ResourceMgr::registerDecompressor(Decompressor* decompressor, const SafeString& name)
94{
95 if (!name.isEqual(str: SafeString::cEmptyString))
96 decompressor->setName(name);
97
98 mDecompList.pushBack(item: decompressor);
99}
100
101void ResourceMgr::unregisterFactory(ResourceFactory* factory)
102{
103 mFactoryList.erase(item: factory);
104}
105
106void ResourceMgr::unregisterDecompressor(Decompressor* decompressor)
107{
108 mDecompList.erase(item: decompressor);
109}
110
111Decompressor* ResourceMgr::findDecompressor(const SafeString& name)
112{
113 for (auto& decompressor : mDecompList)
114 if (decompressor->getName() == name)
115 return decompressor;
116
117 return nullptr;
118}
119
120Resource* ResourceMgr::tryLoad(const ResourceMgr::LoadArg& arg, const SafeString& factory_name,
121 Decompressor* decompressor)
122{
123 SafeString actual_factory_name;
124 FixedSafeString<32> ext;
125
126 if (!decompressor)
127 {
128 if (!Path::getExt(ext: &ext, path: arg.path))
129 {
130 SEAD_ASSERT_MSG(false, "no file extension");
131 return nullptr;
132 }
133
134 decompressor = findDecompressor(name: ext);
135 }
136
137 if (decompressor)
138 actual_factory_name = factory_name;
139 else
140 actual_factory_name = ext;
141
142 auto* factory = arg.factory;
143 if (!factory)
144 {
145 factory = findFactory(name: actual_factory_name);
146 SEAD_ASSERT(factory);
147 }
148
149 if (arg.has_tried_create_with_decomp)
150 *arg.has_tried_create_with_decomp = decompressor;
151
152 if (decompressor)
153 return factory->tryCreateWithDecomp(loadArg: arg, decompressor);
154 return factory->tryCreate(loadArg: arg);
155}
156
157Resource* ResourceMgr::tryLoadWithoutDecomp(const ResourceMgr::LoadArg& arg)
158{
159 auto* factory = arg.factory;
160 if (!factory)
161 {
162 FixedSafeString<32> ext;
163 if (Path::getExt(ext: &ext, path: arg.path))
164 {
165 factory = findFactory(name: ext);
166 SEAD_ASSERT(factory);
167 }
168 else
169 {
170 factory = mDefaultResourceFactory;
171 }
172 }
173 return factory->tryCreate(loadArg: arg);
174}
175
176void ResourceMgr::unload(Resource* res)
177{
178 if (res)
179 delete res;
180}
181} // namespace sead
182