1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use crate::bres::*;
use crate::sakurai;
use crate::sakurai::ArcSakurai;
use crate::util;
use crate::wii_memory::WiiMemory;
use fancy_slice::FancySlice;
pub(crate) fn arc(data: FancySlice, wii_memory: &WiiMemory, item: bool) -> Arc {
let num_sub_headers = data.u16_be(6);
let name = data.str(0x10).unwrap().to_string();
let mut children = vec![];
let mut header_index = ARC_HEADER_SIZE;
for i in 0..num_sub_headers {
let mut arc_child = arc_child(data.relative_fancy_slice(header_index..));
if arc_child.redirect_index == -1 {
let tag = util::parse_tag(data.relative_slice(header_index + ARC_CHILD_HEADER_SIZE..));
let child_data = data.relative_fancy_slice(header_index + ARC_CHILD_HEADER_SIZE..);
arc_child.data = match tag.as_ref() {
"ARC" => ArcChildData::Arc(arc(child_data, wii_memory, item)),
"EFLS" => ArcChildData::Efls,
"bres" => ArcChildData::Bres(bres(child_data)),
"ATKD" => ArcChildData::Atkd,
"REFF" => ArcChildData::Reff,
"REFT" => ArcChildData::Reft,
"AIPD" => ArcChildData::Aipd,
"W" => ArcChildData::W,
"" if i == 0 => ArcChildData::Sakurai(sakurai::arc_sakurai(
data.relative_fancy_slice(header_index + ARC_CHILD_HEADER_SIZE..),
wii_memory,
item,
)),
_ => ArcChildData::Unknown,
};
header_index += ARC_CHILD_HEADER_SIZE + arc_child.size as usize;
let offset = header_index % ARC_CHILD_HEADER_SIZE;
if offset != 0 {
header_index += ARC_CHILD_HEADER_SIZE - offset;
}
children.push(arc_child);
}
}
Arc { name, children }
}
#[rustfmt::skip]
fn arc_child(data: FancySlice) -> ArcChild {
ArcChild {
ty: data.i16_be(0),
index: data.i16_be(2),
size: data.i32_be(4),
group_index: data.u8(8),
redirect_index: data.i16_be(10),
data: ArcChildData::Unknown,
}
}
impl Arc {
pub fn compile(&self) -> Vec<u8> {
let mut output = Vec::with_capacity(1024 * 1024);
output.extend("ARC".chars().map(|x| x as u8));
output.extend(&[0x00, 0x01, 0x01]);
output.extend(&u16::to_be_bytes(self.children.len() as u16));
output.extend(&[0x00; 8]);
output.extend(self.name.chars().map(|x| x as u8));
while output.len() < ARC_HEADER_SIZE {
output.push(0x00);
}
for child in &self.children {
let start = output.len();
output.extend(&i16::to_be_bytes(child.ty));
output.extend(&i16::to_be_bytes(child.index));
output.extend(&i32::to_be_bytes(child.size));
output.push(child.group_index);
output.push(0x00);
output.extend(&i16::to_be_bytes(child.redirect_index));
while output.len() < start + ARC_CHILD_HEADER_SIZE {
output.push(0x00);
}
match &child.data {
ArcChildData::Arc(arc) => output.extend(arc.compile()),
ArcChildData::Bres(bres) => output.extend(bres.compile()),
_ => {}
}
}
output
}
}
const ARC_HEADER_SIZE: usize = 0x40;
#[derive(Clone, Debug)]
pub struct Arc {
pub name: String,
pub children: Vec<ArcChild>,
}
const ARC_CHILD_HEADER_SIZE: usize = 0x20;
#[derive(Clone, Debug)]
pub struct ArcChild {
ty: i16,
index: i16,
size: i32,
group_index: u8,
redirect_index: i16,
pub data: ArcChildData,
}
#[derive(Clone, Debug)]
pub enum ArcChildData {
Arc(Arc),
Sakurai(ArcSakurai),
Efls,
Bres(Bres),
Atkd,
Reff,
Reft,
Aipd,
W,
Unknown,
}