NSMBW-Decomp
A decompilation of New Super Mario Bros. Wii
Loading...
Searching...
No Matches
d_res_info.cpp
1#include <dol/bases/d_res.hpp>
2#include <dol/mLib/m_heap.hpp>
3#include <lib/rvl/vi/VI.h>
4#include <lib/rvl/os/OSCache.h>
5#include <lib/MSL_C/string.h>
6
8 mRefCount(0),
9 mpDvdCmd(nullptr),
10 mpArchive(nullptr),
11 mpMountHeap(nullptr),
12 mpArcBinary(nullptr),
13 mDataHeap(nullptr),
14 mpFiles(nullptr) {
15}
16
18 if (!mpDvdCmd->mDone) {
19 // Wait until the command is done
20 do {
21 VIWaitForRetrace();
22 } while (!mpDvdCmd->mDone);
23 }
24 cleanup();
25}
26
28 // Clean up the DVD command
29 if (mpDvdCmd != nullptr) {
30 if (!mpDvdCmd->mDone) {
31 return false;
32 }
33 mpArchive = mpDvdCmd->mpArchive;
34 mpArcBinary = mpDvdCmd->getArcBinary();
35 mpMountHeap = mpDvdCmd->mpHeap;
36 mUnk = mpDvdCmd->mUnk;
37 mpDvdCmd->destroy();
38
39 mpDvdCmd = nullptr;
40 }
41
42 // Clean up the archive and its associated heap
43 if (mpArchive != nullptr) {
44 if (mDataHeap != nullptr) {
45 mHeap::destroyFrmHeap(mDataHeap);
46 mDataHeap = nullptr;
47 }
48 mpArchive->unmount();
49
50 mpArchive = nullptr;
51 mpFiles = nullptr;
52 }
53
54 // Free the archive binary
55 if (mpArcBinary != nullptr) {
56 EGG::Heap::free(mpArcBinary, nullptr);
57
58 mpArcBinary = nullptr;
59 }
60 return true;
61}
62
63bool dRes_c::info_c::set(const char *arcName, const char *containingFolder, u8 allocDir, EGG::Heap *heap) {
64 char pathBuf[80];
65 snprintf(pathBuf, sizeof(pathBuf), "/%s/%s.arc", containingFolder, arcName);
66 mpDvdCmd = mDvd_mountMemArchive_c::create(pathBuf, allocDir, heap);
67
68 if (mpDvdCmd == nullptr) {
69 return false;
70 }
71
72 strncpy(mName, arcName, sizeof(mName));
73 if (mSetCallback != nullptr) {
74 mSetCallback(pathBuf, heap);
75 }
76 return true;
77}
78
80 if (mpArchive == nullptr) {
81 if (mpDvdCmd == nullptr) {
82 return -1;
83 }
84 if (!mpDvdCmd->mDone) {
85 return 1;
86 }
87
88 // Copy over the properties from the DVD command, then destroy it
89 mpArchive = mpDvdCmd->mpArchive;
90 mpArcBinary = mpDvdCmd->getArcBinary();
91 mpMountHeap = mpDvdCmd->mpHeap;
92 mUnk = mpDvdCmd->mUnk;
93 mpDvdCmd->destroy();
94 mpDvdCmd = nullptr;
95
96 if (mpArchive == nullptr) {
97 return -1;
98 }
99
100 // Prepare the heap for the archive data
101 EGG::Heap *heap = (mpMountHeap != nullptr) ? mpMountHeap : mHeap::g_gameHeaps[0];
102 mDataHeap = mHeap::makeFrmHeapAndUpdate(-1, heap, "dRes_c::info_c::mDataHeap", 0x20, 0);
103 if (mDataHeap == nullptr) {
104 return -1;
105 }
106
107 int resStatus = loadRes(callback);
108
109 // Restore the previous heap
110 mHeap::restoreCurrentHeap();
111 mHeap::adjustFrmHeap(mDataHeap);
112 if (resStatus == -1) {
113 return resStatus;
114 }
115
116 // Ensure data is written to main memory
117 DCStoreRangeNoSync(mDataHeap, (size_t) mDataHeap->mpHeapHead->mpHeapEnd - (size_t) mDataHeap);
118 }
119
120 return 0;
121}
122
123void dRes_c::searchCallback_c::callback(void *file, const ARCDirEntry *dirEntry, const char *path) {
124 if (dirEntry->mIsDirectory) {
125 // Copy the first 4 characters of the folder name and pad with spaces
126 const char *name = dirEntry->mpName;
127 mFolderSig = ' ';
128 int nameLen = strlen(name);
129 memcpy(&mFolderSig, name, (nameLen <= 4) ? nameLen : 4);
130 } else {
131 // Callback only called for files
132 u8 *cbRes = (u8 *) mpCallback->execute(file, mFolderSig);
133 if (mFileIdx < mNumFiles) {
134 mpFiles[mFileIdx++] = cbRes;
135 }
136 }
137}
138
139void dRes_c::searchCallback_c::callback(void *cbInfo, void *file, const ARCDirEntry *dirEntry, const char *path) {
140 ((searchCallback_c *) cbInfo)->callback(file, dirEntry, path);
141}
142
144 int numFiles = mpArchive->countFile();
145 mpFiles = new u8 *[numFiles];
146 if (mpFiles == nullptr) {
147 return -1;
148 }
149
150 // Prepare the file array
151 for (unsigned int i = 0; i < numFiles; i++) {
152 mpFiles[i] = nullptr;
153 }
154
155 if (callback != nullptr) {
156 // Use the callback to populate ::mpFiles
157 callback->init(mName);
158 searchCallback_c searchCallback(callback, mpFiles, numFiles, 0, ' ');
159 mpArchive->searchInside(&dRes_c::searchCallback_c::callback, &searchCallback);
160 } else {
161 // Simply populate ::mpFiles with the files
162 mpArchive->getFileArray(mpFiles, numFiles);
163 }
164 return 0;
165}
A callback class for processing resources.
Definition d_res.hpp:17
virtual void init(const char *name)=0
Initializes the callback with the resource name.
virtual void * execute(void *data, u32 folderSig)=0
Executes the callback.
bool set(const char *arcName, const char *containingFolder, u8 allocDirection, EGG::Heap *heap)
Sets information about the archive to be loaded.
~info_c()
Destroys this info_c.
info_c()
Constructs a new info_c.
Definition d_res_info.cpp:7
int setRes(callback_c *callback)
Attempts to load the archive into memory and load the resources with a callback.
int loadRes(callback_c *callback)
Executes a callback on each file and folder of the archive.
bool cleanup()
Unmounts the archive and frees the holder for use.
A callback class for EGG::Archive::searchInside.
Definition d_res.hpp:33
static void callback(void *cbInfo, void *file, const ARCDirEntry *dirEntry, const char *path)
The callback function.
static void(* mSetCallback)(const char *arcName, EGG::Heap *heap)
[Unused]. The callback for when dRes_c::info_c::set is called.
Definition d_res.hpp:224
callback_c * mpCallback
The callback for when a resource is loaded.
Definition d_res.hpp:221