comparison src/th06/ecl.rs @ 714:fcc8f736c746

ecl: Simplify parsing.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Mon, 23 Sep 2019 00:06:02 +0200
parents 81232dac8136
children 5016c09e5d7c
comparison
equal deleted inserted replaced
713:258f4aebf3fc 714:fcc8f736c746
2 2
3 use nom::{ 3 use nom::{
4 IResult, 4 IResult,
5 number::complete::{le_u8, le_u16, le_u32, le_i16, le_i32, le_f32}, 5 number::complete::{le_u8, le_u16, le_u32, le_i16, le_i32, le_f32},
6 sequence::tuple, 6 sequence::tuple,
7 multi::many_m_n, 7 multi::{count, many0},
8 error::ErrorKind,
9 Err,
8 }; 10 };
9 use encoding_rs::SHIFT_JIS; 11 use encoding_rs::SHIFT_JIS;
10 use bitflags::bitflags; 12 use bitflags::bitflags;
11 13
12 bitflags! { 14 bitflags! {
144 } 146 }
145 }; 147 };
146 } 148 }
147 149
148 /// Parse a SHIFT_JIS byte string of length 34 into a String. 150 /// Parse a SHIFT_JIS byte string of length 34 into a String.
151 #[allow(non_snake_case)]
149 pub fn le_String(i: &[u8]) -> IResult<&[u8], String> { 152 pub fn le_String(i: &[u8]) -> IResult<&[u8], String> {
150 assert_eq!(i.len(), 34);
151 let data = i.splitn(2, |c| *c == b'\0').nth(0).unwrap(); 153 let data = i.splitn(2, |c| *c == b'\0').nth(0).unwrap();
152 let (string, encoding, replaced) = SHIFT_JIS.decode(data); 154 let (string, _encoding, _replaced) = SHIFT_JIS.decode(data);
153 Ok((&i[34..], string.into_owned())) 155 Ok((&i[34..], string.into_owned()))
154 } 156 }
155 157
156 macro_rules! declare_sub_instructions { 158 macro_rules! declare_sub_instructions {
157 ($($opcode:tt => fn $name:ident($($arg:ident: $arg_type:ident),*)),*,) => { 159 ($($opcode:tt => fn $name:ident($($arg:ident: $arg_type:ident),*)),*,) => {
299 113 => fn SetLowLifeTrigger(trigger: i32), 301 113 => fn SetLowLifeTrigger(trigger: i32),
300 114 => fn SetLowLifeCallback(sub: i32), 302 114 => fn SetLowLifeCallback(sub: i32),
301 115 => fn SetTimeout(timeout: i32), 303 115 => fn SetTimeout(timeout: i32),
302 116 => fn SetTimeoutCallback(sub: i32), 304 116 => fn SetTimeoutCallback(sub: i32),
303 117 => fn SetTouchable(touchable: i32), 305 117 => fn SetTouchable(touchable: i32),
304 118 => fn DropParticles(anim: i32, number: u32, r: u8, g: u8, b: u8, UNUSED: u8), 306 118 => fn DropParticles(anim: i32, number: u32, r: u8, g: u8, b: u8, a: u8),
305 119 => fn DropBonus(number: i32), 307 119 => fn DropBonus(number: i32),
306 120 => fn SetAutomaticOrientation(automatic: i32), 308 120 => fn SetAutomaticOrientation(automatic: i32),
307 121 => fn CallSpecialFunction(function: i32, argument: i32), 309 121 => fn CallSpecialFunction(function: i32, argument: i32),
308 // TODO: Found in stage 3 then 5 onward. 310 122 => fn SetSpecialFunctionCallback(function: i32),
309 122 => fn UNK_ins122(TODO: i32),
310 123 => fn SkipFrames(frames: i32), 311 123 => fn SkipFrames(frames: i32),
311 124 => fn DropSpecificBonus(type_: i32), 312 124 => fn DropSpecificBonus(type_: i32),
312 // TODO: Found in stage 3. 313 // TODO: Found in stage 3.
313 125 => fn UNK_ins125(), 314 125 => fn UNK_ins125(),
314 126 => fn SetRemainingLives(lives: i32), 315 126 => fn SetRemainingLives(lives: i32),
324 // TODO: Found in stage 4. 325 // TODO: Found in stage 4.
325 134 => fn UNK_ins134(), 326 134 => fn UNK_ins134(),
326 135 => fn EnableSpellcardBonus(UNKNOW: i32), 327 135 => fn EnableSpellcardBonus(UNKNOW: i32),
327 } 328 }
328 329
330 fn parse_sub_instruction(input: &[u8]) -> IResult<&[u8], CallSub> {
331 let i = &input[..];
332 let (i, (time, opcode)) = tuple((le_i32, le_u16))(i)?;
333 if time == -1 || opcode == 0xffff {
334 return Err(Err::Error((i, ErrorKind::Eof)));
335 }
336
337 let (i, (size, rank_mask, param_mask)) = tuple((le_u16, le_u16, le_u16))(i)?;
338 let rank_mask = Rank::from_bits(rank_mask).unwrap();
339 let (i, instr) = parse_sub_instruction_args(i, opcode)?;
340 assert_eq!(input.len() - i.len(), size as usize);
341 let call = CallSub { time, rank_mask, param_mask, instr };
342 Ok((i, call))
343 }
344
345 fn parse_sub(i: &[u8]) -> IResult<&[u8], Sub> {
346 let (i, instructions) = many0(parse_sub_instruction)(i)?;
347 let sub = Sub { instructions };
348 Ok((i, sub))
349 }
350
351 fn parse_main_instruction(input: &[u8]) -> IResult<&[u8], CallMain> {
352 let i = &input[..];
353 let (i, (time, sub)) = tuple((le_u16, le_u16))(i)?;
354 if time == 0xffff && sub == 4 {
355 return Err(Err::Error((i, ErrorKind::Eof)));
356 }
357
358 let (i, (opcode, size)) = tuple((le_u16, le_u16))(i)?;
359 let size = size as usize;
360 let (i, instr) = parse_main_instruction_args(i, opcode)?;
361 assert_eq!(input.len() - i.len(), size as usize);
362 let call = CallMain { time, sub, instr };
363 Ok((i, call))
364 }
365
366 fn parse_main(i: &[u8]) -> IResult<&[u8], Main> {
367 let (i, instructions) = many0(parse_main_instruction)(i)?;
368 let main = Main { instructions };
369 Ok((i, main))
370 }
371
329 fn parse_ecl(input: &[u8]) -> IResult<&[u8], Ecl> { 372 fn parse_ecl(input: &[u8]) -> IResult<&[u8], Ecl> {
330 let i = input; 373 let i = input;
331 374
332 let (i, sub_count) = le_u16(i)?; 375 let (i, (sub_count, main_count)) = tuple((le_u16, le_u16))(i)?;
333 let sub_count = sub_count as usize; 376 let sub_count = sub_count as usize;
334 let (i, main_count) = le_u16(i)?; 377
335 assert_eq!(main_count, 0); 378 if main_count != 0 {
336 379 // TODO: use a better error.
337 let (i, main_offsets) = many_m_n(3, 3, le_u32)(i)?; 380 return Err(Err::Error((i, ErrorKind::Eof)));
338 let (_, sub_offsets) = many_m_n(sub_count, sub_count, le_u32)(i)?; 381 }
382
383 let (_, (main_offsets, sub_offsets)) = tuple((
384 count(le_u32, 3),
385 count(le_u32, sub_count),
386 ))(i)?;
339 387
340 // Read all subs. 388 // Read all subs.
341 let mut subs = Vec::new(); 389 let mut subs = Vec::new();
342 for offset in sub_offsets.into_iter().map(|offset| offset as usize) { 390 for offset in sub_offsets.into_iter().map(|offset| offset as usize) {
343 let mut i = &input[offset..]; 391 let (_, sub) = parse_sub(&input[offset..])?;
344 let mut instructions = Vec::new(); 392 subs.push(sub);
345 loop {
346 let (i2, (time, opcode)) = tuple((le_i32, le_u16))(i)?;
347 if time == -1 || opcode == 0xffff {
348 break;
349 }
350
351 let (i2, (size, rank_mask, param_mask)) = tuple((le_u16, le_u16, le_u16))(i2)?;
352 let size = size as usize;
353 let rank_mask = Rank::from_bits(rank_mask).unwrap();
354 // FIXME: this - 12 can trigger a panic, fuzz it!
355 let data = &i2[..size - 12];
356 let (data, instr) = parse_sub_instruction_args(data, opcode)?;
357 assert_eq!(data.len(), 0);
358 instructions.push(CallSub { time, rank_mask, param_mask, instr });
359 i = &i[size..];
360 }
361 subs.push(Sub { instructions });
362 } 393 }
363 394
364 // Read all mains (always a single one atm). 395 // Read all mains (always a single one atm).
365 let mut mains = Vec::new(); 396 let mut mains = Vec::new();
366 for offset in main_offsets.into_iter().map(|offset| offset as usize) { 397 for offset in main_offsets.into_iter().map(|offset| offset as usize) {
367 if offset == 0 { 398 if offset == 0 {
368 break; 399 break;
369 } 400 }
370 401 let (_, main) = parse_main(&input[offset..])?;
371 let mut i = &input[offset..]; 402 mains.push(main);
372 let mut instructions = Vec::new();
373 loop {
374 let (i2, (time, sub)) = tuple((le_u16, le_u16))(i)?;
375 if time == 0xffff && sub == 4 {
376 break;
377 }
378
379 let (i2, (opcode, size)) = tuple((le_u16, le_u16))(i2)?;
380 let size = size as usize;
381 // FIXME: this - 8 can trigger a panic, fuzz it!
382 let data = &i2[..size - 8];
383 let (data, instr) = parse_main_instruction_args(data, opcode)?;
384 assert_eq!(data.len(), 0);
385 instructions.push(CallMain { time, sub, instr });
386 i = &i[size..];
387 }
388 mains.push(Main { instructions });
389 } 403 }
390 404
391 let ecl = Ecl { 405 let ecl = Ecl {
392 subs, 406 subs,
393 mains, 407 mains,