24
24
use crate :: Result ;
25
25
use color_eyre:: eyre:: eyre;
26
26
use nom:: { number:: Endianness , IResult } ;
27
- use std:: ffi:: CString ;
27
+ use std:: {
28
+ ffi:: CString ,
29
+ fmt:: { self , Debug , Display , Formatter } ,
30
+ } ;
28
31
29
32
const RCX_TAG : & str = "RCXI" ;
30
- const MAX_CHUNKS : usize = 10 ;
33
+ const MAX_SECTIONS : usize = 10 ;
34
+ const INDENT : & str = " " ;
31
35
32
36
#[ derive( Clone , Debug , PartialEq , Eq ) ]
33
37
pub struct RcxBin {
34
38
pub signature : [ u8 ; 4 ] ,
35
39
pub version : u16 ,
36
- pub chunk_count : u16 ,
40
+ pub section_count : u16 ,
37
41
pub symbol_count : u16 ,
38
42
pub target_type : u8 ,
39
43
pub reserved : u8 ,
40
- pub chunks : Vec < Chunk > ,
44
+ pub sections : Vec < Section > ,
41
45
pub symbols : Vec < Symbol > ,
42
46
}
43
47
@@ -49,46 +53,71 @@ impl RcxBin {
49
53
}
50
54
51
55
pub fn verify ( & self ) -> Result < ( ) > {
52
- fn repeated_idx ( chunks : & [ Chunk ] ) -> bool {
53
- let mut c = chunks . iter ( ) . map ( |c| c. number ) . collect :: < Vec < _ > > ( ) ;
56
+ fn repeated_idx ( sections : & [ Section ] ) -> bool {
57
+ let mut c = sections . iter ( ) . map ( |c| c. number ) . collect :: < Vec < _ > > ( ) ;
54
58
c. sort_unstable ( ) ;
55
59
c. dedup ( ) ;
56
- c. len ( ) != chunks . len ( )
60
+ c. len ( ) != sections . len ( )
57
61
}
58
62
59
63
// check chunk count
60
- if self . chunk_count as usize != self . chunks . len ( )
61
- || self . chunks . len ( ) > MAX_CHUNKS
64
+ if self . section_count as usize != self . sections . len ( )
65
+ || self . sections . len ( ) > MAX_SECTIONS
62
66
{
63
67
Err ( eyre ! ( "Invalid number of chunks" ) )
64
- } else if repeated_idx ( & self . chunks ) {
68
+ } else if repeated_idx ( & self . sections ) {
65
69
Err ( eyre ! ( "Nonunique chunk numbers" ) )
66
70
} else {
67
71
Ok ( ( ) )
68
72
}
69
73
}
70
74
}
71
75
76
+ impl Display for RcxBin {
77
+ fn fmt ( & self , fmt : & mut Formatter < ' _ > ) -> fmt:: Result {
78
+ writeln ! (
79
+ fmt,
80
+ "Signature: {}" ,
81
+ String :: from_utf8_lossy( & self . signature) ,
82
+ ) ?;
83
+ writeln ! ( fmt, "Version: {:x}" , self . version) ?;
84
+ writeln ! (
85
+ fmt,
86
+ "{} sections, {} symbols" ,
87
+ self . section_count, self . symbol_count,
88
+ ) ?;
89
+ writeln ! ( fmt, "Target: {}" , self . target_type) ?;
90
+ writeln ! ( fmt, "Sections:" ) ?;
91
+ for section in & self . sections {
92
+ writeln ! ( fmt, "{section}" ) ?;
93
+ }
94
+ writeln ! ( fmt, "Symbols:" ) ?;
95
+ for symbol in & self . symbols {
96
+ writeln ! ( fmt, "{symbol}" ) ?;
97
+ }
98
+ Ok ( ( ) )
99
+ }
100
+ }
72
101
#[ derive( Clone , Debug , PartialEq , Eq ) ]
73
- pub struct Chunk {
74
- pub ty : ChunkType ,
102
+ pub struct Section {
103
+ pub ty : SectionType ,
75
104
pub number : u8 ,
76
105
pub length : u16 ,
77
106
pub data : Vec < u8 > ,
78
107
}
79
108
80
- fn parse_chunk ( i : & [ u8 ] ) -> IResult < & [ u8 ] , Chunk > {
109
+ fn parse_chunk ( i : & [ u8 ] ) -> IResult < & [ u8 ] , Section > {
81
110
let read_u16 = nom:: number:: complete:: u16 ( Endianness :: Little ) ;
82
111
let read_u8 = nom:: number:: complete:: u8;
83
112
84
- let ( i, ty) = ChunkType :: parse ( i) ?;
113
+ let ( i, ty) = SectionType :: parse ( i) ?;
85
114
let ( i, number) = read_u8 ( i) ?;
86
115
let ( i, length) = read_u16 ( i) ?;
87
116
let ( i, data) = nom:: bytes:: complete:: take ( length) ( i) ?;
88
117
89
118
Ok ( (
90
119
i,
91
- Chunk {
120
+ Section {
92
121
ty,
93
122
number,
94
123
length,
@@ -97,17 +126,25 @@ fn parse_chunk(i: &[u8]) -> IResult<&[u8], Chunk> {
97
126
) )
98
127
}
99
128
100
- #[ derive( Clone , Debug , PartialEq , Eq ) ]
129
+ impl Display for Section {
130
+ fn fmt ( & self , fmt : & mut Formatter ) -> fmt:: Result {
131
+ writeln ! ( fmt, "{INDENT}{} - {} bytes" , self . ty, self . length) ?;
132
+ writeln ! ( fmt, "{INDENT}{INDENT}{}" , hex:: encode( & self . data) ) ?;
133
+ Ok ( ( ) )
134
+ }
135
+ }
136
+
137
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
101
138
#[ repr( u8 ) ]
102
- pub enum ChunkType {
139
+ pub enum SectionType {
103
140
Task = 0 ,
104
141
SubChunk ,
105
142
Sound ,
106
143
Animation ,
107
144
Count ,
108
145
}
109
146
110
- impl ChunkType {
147
+ impl SectionType {
111
148
pub fn parse ( i : & [ u8 ] ) -> IResult < & [ u8 ] , Self > {
112
149
let ( i, ty) = nom:: number:: complete:: u8 ( i) ?;
113
150
let ty = match ty {
@@ -127,6 +164,12 @@ impl ChunkType {
127
164
}
128
165
}
129
166
167
+ impl Display for SectionType {
168
+ fn fmt ( & self , fmt : & mut Formatter < ' _ > ) -> fmt:: Result {
169
+ Debug :: fmt ( self , fmt)
170
+ }
171
+ }
172
+
130
173
#[ derive( Clone , Debug , PartialEq , Eq ) ]
131
174
pub struct Symbol {
132
175
pub ty : u8 ,
@@ -160,6 +203,18 @@ fn parse_symbol(i: &[u8]) -> IResult<&[u8], Symbol> {
160
203
) )
161
204
}
162
205
206
+ impl Display for Symbol {
207
+ fn fmt ( & self , fmt : & mut Formatter ) -> fmt:: Result {
208
+ writeln ! (
209
+ fmt,
210
+ "{INDENT}{} at {} - {} bytes" ,
211
+ self . ty, self . index, self . length
212
+ ) ?;
213
+ writeln ! ( fmt, "{INDENT}{INDENT}{:?}" , self . name) ?;
214
+ Ok ( ( ) )
215
+ }
216
+ }
217
+
163
218
fn parse ( bin : & [ u8 ] ) -> IResult < & [ u8 ] , RcxBin > {
164
219
let read_u16 = nom:: number:: complete:: u16 ( Endianness :: Little ) ;
165
220
let read_u8 = nom:: number:: complete:: u8;
@@ -179,11 +234,11 @@ fn parse(bin: &[u8]) -> IResult<&[u8], RcxBin> {
179
234
RcxBin {
180
235
signature : signature. try_into ( ) . unwrap_or ( [ 0 ; 4 ] ) ,
181
236
version,
182
- chunk_count,
237
+ section_count : chunk_count,
183
238
symbol_count,
184
239
target_type,
185
240
reserved,
186
- chunks,
241
+ sections : chunks,
187
242
symbols,
188
243
} ,
189
244
) )
@@ -208,12 +263,12 @@ mod test {
208
263
RcxBin {
209
264
signature: * b"RCXI" ,
210
265
version: 0x0102 ,
211
- chunk_count : 1 ,
266
+ section_count : 1 ,
212
267
symbol_count: 1 ,
213
268
target_type: 0 ,
214
269
reserved: 0 ,
215
- chunks : vec![ Chunk {
216
- ty: ChunkType :: Task ,
270
+ sections : vec![ Section {
271
+ ty: SectionType :: Task ,
217
272
number: 0 ,
218
273
length: 20 ,
219
274
data: vec![
0 commit comments