-
Notifications
You must be signed in to change notification settings - Fork 6
/
rmd.rs
173 lines (151 loc) · 5.52 KB
/
rmd.rs
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//! RMD files are sort of data pointers for the Objects and
//! Tiles and include things like which file they are in and
//! if they are a part of an animation or so.
//!
//! [HEADER]
//! String
//! 12 empty bytes
//! String
//! int animation parts (this is for object animations)
//! int animation rows
//! String
//! int rmd rows
//!
//! [RMD RowEntry]
//! int ImageCount (How many images this row/entry contains,
//! like an image from sadad for example can
//! contain: Body, color hair, color body, weapon)
//!
//! [RMD RowEntry - Images]
//! int SourceX // upper-left x coordinate
//! int SourceY // upper-right x coordinate
//! int SourceWidth // lower-left y coordinate
//! int SourceHeight // lower-right y coordinate
//! int empty
//! int renderz
//! int DestX
//! int DestY
//! int Draw Type (Shadow, skill, normal)
//! int ImageIDCount
//!
//! [RMD Row - Images - Image ID]
//! int ImageID (Lst row pointer,
//! this is a array so different weapons can be used)
//!
//! int AnimationsCount
//!
//! [RMD Animation]
//! int AnimationFrames
//!
//! [RMD Animation - Frame]
//! int RMDRowPointer (points to a row of the RMD)
use std::str::from_utf8;
use std::io::Cursor;
use std::io::Seek;
use std::io::SeekFrom;
use byteorder::ReadBytesExt;
use byteorder::LittleEndian as LE;
use crate::entity::rmd::Rmd;
use crate::entity::rmd_animation::RmdAnimation;
use crate::entity::rmd_entry::RmdEntry;
use crate::entity::rmd_type::RmdType;
use crate::entity::rmd_image::RmdImage;
use crate::error::Error;
use crate::utility::parsing::{parse_string, parse_cp949, parse_u8_vec};
pub fn parse_rmd(kind: RmdType, data: &[u8]) -> Result<Rmd, Error> {
let mut cursor = Cursor::new(data);
let mut rmd = Rmd::new(kind);
// filetype string: Equal to ""
let string_1 = parse_string(&mut cursor)?;
// println!("{:?}", string_1);
let file_number = cursor.read_u32::<LE>()?; // 4
// println!("file_number: {}", file_number);
// 8 empty bytes
let padding = cursor.read_u32::<LE>()?; // 8
if padding != 0 { println!("p2: {}", padding); }
let padding = cursor.read_u32::<LE>()?; // 12
if padding != 0 { println!("p3: {}", padding); }
// let string = parse_string(&mut cursor)?;
// let string = parse_u8_vec(&mut cursor)?;
let string = parse_cp949(&mut cursor)?;
// println!("str 1: `{:?}`", string);
rmd.animation_parts = cursor.read_i32::<LE>()?;
rmd.animation_entry_count = cursor.read_i32::<LE>()?;
// let string = parse_u8_vec(&mut cursor)?;
let string = parse_cp949(&mut cursor)?;
// println!("str 2: `{:?}`", string);
rmd.entry_count = cursor.read_i32::<LE>()?;
// println!("end header offset: `{}`", cursor.position());
// read the Rmd rows
for _ in 0..rmd.entry_count {
let mut entry = RmdEntry::new();
entry.set_image_count(cursor.read_i32::<LE>()?);
for _ in 0..entry.image_count() {
let mut img = RmdImage::new();
img.source_x1 = cursor.read_i32::<LE>()?;
img.source_y1 = cursor.read_i32::<LE>()?;
img.source_x2 = cursor.read_i32::<LE>()?;
img.source_y2 = cursor.read_i32::<LE>()?;
img.empty_1 = cursor.read_i32::<LE>()?;
img.empty_2 = cursor.read_i32::<LE>()?;
img.dest_x = cursor.read_i32::<LE>()?;
img.dest_y = cursor.read_i32::<LE>()?;
img.render_z = cursor.read_i32::<LE>()?;
img.draw_type = cursor.read_i32::<LE>()?;
img.image_id_count = cursor.read_i32::<LE>()?;
for _ in 0..img.image_id_count {
img.image_id.push(cursor.read_i32::<LE>()?);
}
entry.add_image(img);
}
rmd.add_entry(entry);
}
rmd.animation_count = cursor.read_i32::<LE>()?;
for _ in 0..rmd.animation_count {
let mut ani = RmdAnimation::new(cursor.read_i32::<LE>()?);
for _ in 0..ani.frame_count() {
ani.add_frame(cursor.read_i16::<LE>()?);
}
rmd.add_animation(ani);
}
// println!("{:?}", rmd);
Ok(rmd)
}
#[cfg(test)]
mod tests {
use super::*;
fn print_ani_info(rmd: &Rmd) {
println!();
println!("rmd.animation_count: {:?}", &rmd.animation_count);
println!("rmd.image_count: {:?}", &rmd.entry_count);
assert!(false);
}
#[test]
fn test_tle_00001() {
let data = include_bytes!("../../../data/DATAs/Tle/tle00001.rmd");
let rmd = parse_rmd(RmdType::Tile, data).unwrap();
assert_eq!(rmd.animation_count as usize, rmd.animations.len());
}
#[test]
fn test_obj_00001() {
let data = include_bytes!("../../../data/DATAs/Obj/obj00001.rmd");
let rmd = parse_rmd(RmdType::Object, data).unwrap();
// assert!(rmd.row_count as usize == rmd.rows.len());
// assert!(rmd.animation_count as usize == rmd.animations.len());
}
#[test]
fn test_chr_00001() {
let data = include_bytes!("../../../data/DATAs/Chr/chr00001.rmd");
let rmd = parse_rmd(RmdType::Character, data).unwrap();
// print_ani_info(&rmd);
// assert!(rmd.row_count as usize == rmd.rows.len());
// assert!(rmd.animation_count as usize == rmd.animations.len());
}
#[test]
fn test_chr_00042() {
let data = include_bytes!("../../../data/DATAs/Chr/chr00042.rmd");
let rmd = parse_rmd(RmdType::Character, data).unwrap();
// assert!(rmd.row_count as usize == rmd.rows.len());
// assert!(rmd.animation_count as usize == rmd.animations.len());
}
}