Mercurial > touhou
comparison formats/src/th06/std.rs @ 774:d08eb4c9fce3
formats: Upgrade nom to version 8
| author | Link Mauve <linkmauve@linkmauve.fr> |
|---|---|
| date | Mon, 29 Sep 2025 11:10:15 +0000 |
| parents | 21b186be2590 |
| children | 94033091458b |
comparison
equal
deleted
inserted
replaced
| 773:317e93b7d586 | 774:d08eb4c9fce3 |
|---|---|
| 1 //! STD background format support. | 1 //! STD background format support. |
| 2 | 2 |
| 3 use nom::{ | 3 use nom::{ |
| 4 IResult, | 4 IResult, |
| 5 Parser, | |
| 5 bytes::complete::tag, | 6 bytes::complete::tag, |
| 6 number::complete::{le_u8, le_u16, le_u32, le_i32, le_f32}, | 7 number::complete::{le_u8, le_u16, le_u32, le_i32, le_f32}, |
| 7 sequence::tuple, | |
| 8 combinator::map, | 8 combinator::map, |
| 9 multi::{many0, count}, | 9 multi::{many0, count}, |
| 10 error::ErrorKind, | 10 error::ErrorKind, |
| 11 Err, | 11 Err, |
| 12 }; | 12 }; |
| 162 4 => fn StartInterpolatingFog(frame: u32, _unused: i32, _unused: i32), | 162 4 => fn StartInterpolatingFog(frame: u32, _unused: i32, _unused: i32), |
| 163 5 => fn Unknown(_unused: i32, _unused: i32, _unused: i32), | 163 5 => fn Unknown(_unused: i32, _unused: i32, _unused: i32), |
| 164 } | 164 } |
| 165 | 165 |
| 166 fn parse_quad(i: &[u8]) -> IResult<&[u8], Quad> { | 166 fn parse_quad(i: &[u8]) -> IResult<&[u8], Quad> { |
| 167 let (i, (unk1, size)) = tuple((le_u16, le_u16))(i)?; | 167 let (i, (unk1, size)) = (le_u16, le_u16).parse(i)?; |
| 168 if unk1 == 0xffff { | 168 if unk1 == 0xffff { |
| 169 return Err(Err::Error(nom::error::Error::new(i, ErrorKind::Eof))); | 169 return Err(Err::Error(nom::error::Error::new(i, ErrorKind::Eof))); |
| 170 } | 170 } |
| 171 // TODO: replace this assert with a custom error. | 171 // TODO: replace this assert with a custom error. |
| 172 assert_eq!(size, 0x1c); | 172 assert_eq!(size, 0x1c); |
| 173 let (i, (anm_script, _, x, y, z, width, height)) = tuple((le_u16, tag(b"\0\0"), le_f32, le_f32, le_f32, le_f32, le_f32))(i)?; | 173 let (i, (anm_script, _, x, y, z, width, height)) = (le_u16, tag(&b"\0\0"[..]), le_f32, le_f32, le_f32, le_f32, le_f32).parse(i)?; |
| 174 let quad = Quad { | 174 let quad = Quad { |
| 175 anm_script, | 175 anm_script, |
| 176 pos: Position { x, y, z }, | 176 pos: Position { x, y, z }, |
| 177 size_override: Box2D { width, height }, | 177 size_override: Box2D { width, height }, |
| 178 }; | 178 }; |
| 179 Ok((i, quad)) | 179 Ok((i, quad)) |
| 180 } | 180 } |
| 181 | 181 |
| 182 fn parse_model(i: &[u8]) -> IResult<&[u8], Model> { | 182 fn parse_model(i: &[u8]) -> IResult<&[u8], Model> { |
| 183 let (i, (_id, unknown, x, y, z, width, height, depth, quads)) = tuple((le_u16, le_u16, le_f32, le_f32, le_f32, le_f32, le_f32, le_f32, many0(parse_quad)))(i)?; | 183 let (i, (_id, unknown, x, y, z, width, height, depth, quads)) = (le_u16, le_u16, le_f32, le_f32, le_f32, le_f32, le_f32, le_f32, many0(parse_quad)).parse(i)?; |
| 184 let bounding_box = [x, y, z, width, height, depth]; | 184 let bounding_box = [x, y, z, width, height, depth]; |
| 185 let model = Model { | 185 let model = Model { |
| 186 unknown, | 186 unknown, |
| 187 bounding_box, | 187 bounding_box, |
| 188 quads, | 188 quads, |
| 189 }; | 189 }; |
| 190 Ok((i, model)) | 190 Ok((i, model)) |
| 191 } | 191 } |
| 192 | 192 |
| 193 fn parse_instance(i: &[u8]) -> IResult<&[u8], Instance> { | 193 fn parse_instance(i: &[u8]) -> IResult<&[u8], Instance> { |
| 194 let (i, (id, unknown, x, y, z)) = tuple((le_u16, le_u16, le_f32, le_f32, le_f32))(i)?; | 194 let (i, (id, unknown, x, y, z)) = (le_u16, le_u16, le_f32, le_f32, le_f32).parse(i)?; |
| 195 if id == 0xffff && unknown == 0xffff { | 195 if id == 0xffff && unknown == 0xffff { |
| 196 return Err(Err::Error(nom::error::Error::new(i, ErrorKind::Eof))); | 196 return Err(Err::Error(nom::error::Error::new(i, ErrorKind::Eof))); |
| 197 } | 197 } |
| 198 // TODO: replace this assert with a custom error. | 198 // TODO: replace this assert with a custom error. |
| 199 assert_eq!(unknown, 0x100); | 199 assert_eq!(unknown, 0x100); |
| 203 }; | 203 }; |
| 204 Ok((i, instance)) | 204 Ok((i, instance)) |
| 205 } | 205 } |
| 206 | 206 |
| 207 fn parse_instruction(i: &[u8]) -> IResult<&[u8], Call> { | 207 fn parse_instruction(i: &[u8]) -> IResult<&[u8], Call> { |
| 208 let (i, (time, opcode, size)) = tuple((le_u32, le_u16, le_u16))(i)?; | 208 let (i, (time, opcode, size)) = (le_u32, le_u16, le_u16).parse(i)?; |
| 209 if time == 0xffffffff && opcode == 0xffff && size == 0xffff { | 209 if time == 0xffffffff && opcode == 0xffff && size == 0xffff { |
| 210 return Err(Err::Error(nom::error::Error::new(i, ErrorKind::Eof))); | 210 return Err(Err::Error(nom::error::Error::new(i, ErrorKind::Eof))); |
| 211 } | 211 } |
| 212 // TODO: replace this assert with a custom error. | 212 // TODO: replace this assert with a custom error. |
| 213 assert_eq!(size, 12); | 213 assert_eq!(size, 12); |
| 218 } | 218 } |
| 219 | 219 |
| 220 fn parse_stage(input: &[u8]) -> IResult<&[u8], Stage> { | 220 fn parse_stage(input: &[u8]) -> IResult<&[u8], Stage> { |
| 221 let i = &input[..]; | 221 let i = &input[..]; |
| 222 | 222 |
| 223 let (i, (num_models, _num_faces, object_instances_offset, script_offset, _, name, music_names, music_paths)) = tuple(( | 223 let (i, (num_models, _num_faces, object_instances_offset, script_offset, _, name, music_names, music_paths)) = ( |
| 224 le_u16, le_u16, le_u32, le_u32, tag(b"\0\0\0\0"), | 224 le_u16, le_u16, le_u32, le_u32, tag(&b"\0\0\0\0"[..]), |
| 225 le_String, | 225 le_String, |
| 226 map(tuple((le_String, le_String, le_String, le_String)), |(a, b, c, d)| [a, b, c, d]), | 226 map((le_String, le_String, le_String, le_String), |(a, b, c, d)| [a, b, c, d]), |
| 227 map(tuple((le_String, le_String, le_String, le_String)), |(a, b, c, d)| [a, b, c, d]) | 227 map((le_String, le_String, le_String, le_String), |(a, b, c, d)| [a, b, c, d]) |
| 228 ))(i)?; | 228 ).parse(i)?; |
| 229 let musics = music_names.iter().zip(&music_paths).map(|(name, path)| if name == " " { None } else { Some((name.clone(), path.clone())) }).collect(); | 229 let musics = music_names.iter().zip(&music_paths).map(|(name, path)| if name == " " { None } else { Some((name.clone(), path.clone())) }).collect(); |
| 230 | 230 |
| 231 let (_, offsets) = count(le_u32, num_models as usize)(i)?; | 231 let (_, offsets) = count(le_u32, num_models as usize).parse(i)?; |
| 232 | 232 |
| 233 let mut models = vec![]; | 233 let mut models = vec![]; |
| 234 for offset in offsets { | 234 for offset in offsets { |
| 235 let (_, model) = parse_model(&input[offset as usize..])?; | 235 let (_, model) = parse_model(&input[offset as usize..])?; |
| 236 models.push(model); | 236 models.push(model); |
| 237 } | 237 } |
| 238 | 238 |
| 239 let (_, instances) = many0(parse_instance)(&input[object_instances_offset as usize..])?; | 239 let (_, instances) = many0(parse_instance).parse(&input[object_instances_offset as usize..])?; |
| 240 let (_, script) = many0(parse_instruction)(&input[script_offset as usize..])?; | 240 let (_, script) = many0(parse_instruction).parse(&input[script_offset as usize..])?; |
| 241 | 241 |
| 242 let stage = Stage { | 242 let stage = Stage { |
| 243 name, | 243 name, |
| 244 musics, | 244 musics, |
| 245 models, | 245 models, |
