Kinoko
A reimplementation of Mario Kart Wii's physics engine in C++
Toggle main menu visibility
Loading...
Searching...
No Matches
Archive.cc
1
#include "Archive.hh"
2
3
#include <cstring>
4
5
namespace
Kinoko::Abstract
{
6
8
ArchiveHandle::ArchiveHandle(
void
*archiveStart) : m_startAddress(archiveStart) {
9
RawArchive *rawArchive =
reinterpret_cast<
RawArchive *
>
(archiveStart);
10
ASSERT(rawArchive->isValidSignature());
11
12
m_nodes =
reinterpret_cast<
Node *
>
(
13
static_cast<
u8 *
>
(archiveStart) + parse<u32>(rawArchive->nodesOffset));
14
15
// "The right bound of the root node is the number of nodes"
16
m_count = parse<u32>(node(0)->directory.next);
17
// Strings exist directly after the last node
18
m_strings =
reinterpret_cast<
const
char
*
>
(&m_nodes[m_count]);
19
m_currentNode = 0;
20
}
21
23
s32 ArchiveHandle::convertPathToEntryId(
const
char
*path)
const
{
24
u32 entryId = m_currentNode;
25
26
while
(
true
) {
27
// End search
28
if
(path[0] ==
'\0'
) {
29
return
entryId;
30
}
31
32
// Send initial slash to root directory
33
if
(path[0] ==
'/'
) {
34
entryId = 0;
35
path++;
36
continue
;
37
}
38
39
// Handle special cases
40
if
(path[0] ==
'.'
) {
41
if
(path[1] ==
'.'
) {
42
if
(path[2] ==
'/'
) {
43
entryId = node(entryId)->directory.parent;
44
path += 3;
45
continue
;
46
}
else
if
(path[2] ==
'\0'
) {
47
return
node(entryId)->directory.parent;
48
}
else
{
49
// Malformed "..*" case
50
return
-1;
51
}
52
}
else
if
(path[1] ==
'/'
) {
53
path += 2;
54
continue
;
55
}
else
if
(path[1] ==
'\0'
) {
56
return
entryId;
57
}
58
}
59
60
// Main search
61
const
char
*nameEnd = path;
62
for
(; nameEnd[0] !=
'\0'
&& nameEnd[0] !=
'/'
; nameEnd++) {}
63
64
bool
endOfPath = nameEnd[0] ==
'\0'
;
65
s32 nameLength = nameEnd - path;
66
67
bool
found =
false
;
68
const
u32 anchor = entryId++;
69
while
(entryId < parse<u32>(node(anchor)->directory.next)) {
70
if
(!node(anchor)->isDirectory() && endOfPath) {
71
entryId++;
72
continue
;
73
}
74
75
const
char
*entryName = m_strings + node(entryId)->stringOffset();
76
77
if
(entryName[0] ==
'.'
&& entryName[1] ==
'\0'
) {
78
entryId++;
79
continue
;
80
}
81
82
if
(strncmp(path, entryName, nameLength) == 0) {
83
found =
true
;
84
break
;
85
}
86
87
entryId++;
88
}
89
90
if
(!found) {
91
return
-1;
92
}
93
94
if
(endOfPath) {
95
return
entryId;
96
}
97
98
path += nameLength + 1;
99
}
100
}
101
103
bool
ArchiveHandle::open(s32 entryId, FileInfo &info)
const
{
104
if
(entryId < 0 ||
static_cast<
u32
>
(entryId) >= m_count) {
105
return
false
;
106
}
107
108
auto
*node_ = node(entryId);
109
if
(node_->isDirectory()) {
110
return
false
;
111
}
112
113
info.startOffset = parse<u32>(node_->file.startAddress);
114
info.length = parse<u32>(node_->file.length);
115
return
true
;
116
}
117
118
}
// namespace Kinoko::Abstract
Kinoko::Abstract
An abstraction of components from the nw4r and RVL libraries.
Definition
Archive.cc:5
abstract
Archive.cc
Made by
Malleo
. Logo by
vabold
. Website generated by
Doxygen
1.17.0