1#include "Library/Resource/Resource.h"
2
3#include <filedevice/seadArchiveFileDevice.h>
4#include <g3d/aglNW4FToNN.h>
5#include <heap/seadHeapMgr.h>
6#include <nn/g3d/ResFile.h>
7#include <resource/seadArchiveRes.h>
8
9#include "Library/Base/HashCodeUtil.h"
10#include "Library/Base/StringUtil.h"
11#include "Library/File/FileUtil.h"
12
13// NON_MATCHING __cxx_global_array_dtor and _GLOBAL__sub_I_Resource.cpp are misplaced.
14static sead::DirectoryEntry sEntries[0x1000];
15
16namespace al {
17Resource::Resource(const sead::SafeString& path)
18 : mName(path), mHeap(sead::HeapMgr::instance()->getCurrentHeap()) {
19 mArchive = loadArchive(fileName: path);
20 mDevice = new sead::ArchiveFileDevice(mArchive);
21}
22
23Resource::Resource(const sead::SafeString& path, sead::ArchiveRes* archive)
24 : mName(path), mHeap(sead::HeapMgr::instance()->getCurrentHeap()) {
25 mArchive = archive;
26 mDevice = new sead::ArchiveFileDevice(mArchive);
27}
28
29bool Resource::isExistFile(const sead::SafeString& filePath) const {
30 bool exists = false;
31 mDevice->tryIsExistFile(exists: &exists, path: filePath);
32
33 return exists;
34}
35
36bool Resource::isExistByml(const char* filePath) const {
37 StringTmp<0x80> filePathExt;
38 filePathExt.copy(src: filePath);
39 filePathExt.append(str: ".byml");
40
41 return isExistFile(filePath: filePathExt.cstr());
42}
43
44u32 Resource::getSize() const {
45 return mArchive->getRawSize();
46}
47
48u32 Resource::getEntryNum(const sead::SafeString& directoryPath) const {
49 sead::DirectoryHandle handle;
50
51 if (!mDevice->tryOpenDirectory(handle: &handle, path: directoryPath))
52 return 0;
53
54 u32 entriesRead = mDevice->readDirectory(handle: &handle, entries: sEntries, num_entries: 0x1000);
55 mDevice->tryCloseDirectory(handle: &handle);
56
57 return entriesRead;
58}
59
60void Resource::getEntryName(sead::BufferedSafeString* outName,
61 const sead::SafeString& directoryPath, u32 entryNum) const {
62 sead::DirectoryHandle handle;
63
64 mDevice->tryOpenDirectory(handle: &handle, path: directoryPath);
65 mDevice->readDirectory(handle: &handle, entries: sEntries, num_entries: 0x1000);
66 mDevice->tryCloseDirectory(handle: &handle);
67
68 outName->format(formatStr: "%s", sEntries[entryNum].name.cstr());
69}
70
71u32 Resource::getFileSize(const sead::SafeString& filePath) const {
72 return mDevice->getFileSize(path: filePath);
73}
74
75const u8* Resource::getByml(const sead::SafeString& filePath) const {
76 StringTmp<0x80> filePathExt;
77 filePathExt.copy(src: filePath);
78 filePathExt.append(str: ".byml");
79
80 return (const u8*)getFile(filePath: filePathExt);
81}
82
83const void* Resource::getFile(const sead::SafeString& filePath) const {
84 return mArchive->getFile(file_path: filePath);
85}
86
87const u8* Resource::tryGetByml(const sead::SafeString& filePath) const {
88 StringTmp<0x80> filePathExt;
89 filePathExt.copy(src: filePath);
90 filePathExt.append(str: ".byml");
91
92 if (!isExistFile(filePath: filePathExt.cstr()))
93 return nullptr;
94
95 return (const u8*)getFile(filePath: filePathExt);
96}
97
98const void* Resource::getKcl(const sead::SafeString& filePath) const {
99 StringTmp<0x80> filePathExt;
100 filePathExt.copy(src: filePath);
101 filePathExt.append(str: ".kcl");
102
103 return getFile(filePath: filePathExt);
104}
105
106const void* Resource::tryGetKcl(const sead::SafeString& filePath) const {
107 StringTmp<0x80> filePathExt;
108 filePathExt.copy(src: filePath);
109 filePathExt.append(str: ".kcl");
110
111 if (!isExistFile(filePath: filePathExt.cstr()))
112 return nullptr;
113
114 return getFile(filePath: filePathExt);
115}
116
117const void* Resource::getPa(const sead::SafeString& filePath) const {
118 StringTmp<0x80> filePathExt = {"%s.pa", filePath.cstr()};
119
120 return getFile(filePath: filePathExt);
121}
122
123const void* Resource::tryGetPa(const sead::SafeString& filePath) const {
124 StringTmp<0x80> filePathExt;
125 filePathExt.copy(src: filePath);
126 filePathExt.append(str: ".pa");
127
128 if (!isExistFile(filePath: filePathExt.cstr()))
129 return nullptr;
130
131 return getFile(filePath: filePathExt);
132}
133
134const void* Resource::getOtherFile(const sead::SafeString& filePath) const {
135 return getFile(filePath);
136}
137
138const char* Resource::getArchiveName() const {
139 return getBaseName(name: mName.cstr());
140}
141
142bool Resource::tryCreateResGraphicsFile(const sead::SafeString& filePath,
143 nn::g3d::ResFile* resFile) {
144 if (mResFile)
145 return false;
146
147 mResFile = nn::g3d::ResFile::ResCast((void*)getFile(filePath));
148 if (resFile)
149 agl::g3d::ResFile::BindTexture(mResFile, resFile);
150 agl::g3d::ResFile::Setup(mResFile);
151 agl::g3d::ResFile::BindTexture(mResFile, mResFile);
152
153 return true;
154}
155
156void Resource::cleanupResGraphicsFile() {
157 if (!mResFile)
158 return;
159
160 mResFile->ReleaseTexture();
161 mResFile->Reset();
162 agl::g3d::ResFile::Cleanup(mResFile);
163
164 mResFile = nullptr;
165}
166} // namespace al
167