diff --git a/src/main.rs b/src/main.rs index 5c61cb6..a87c3fd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,42 +1,16 @@ use std::env; -use std::str; -use std::fs; -use inflate::inflate_bytes_zlib; +use std::path::Path; pub mod save; +use save::Save; fn main() { let args: Vec<_> = env::args().collect(); let save_path = args.get(1).unwrap(); - let out_path = match args.get(2) { + /*let out_path = match args.get(2) { Some(path) => path, None => "out.bin" - }; + };*/ - let save_buf = fs::read(save_path).unwrap(); - let size = save_buf.len(); - - let mut offset = size; - for i in (0..size - 7).rev() { - let header = match str::from_utf8(&save_buf[i..i+7]) { - Ok(header) => header, - Err(_) => continue - }; - - if header == "" { - offset = i; - break; - } - } - - if offset == size { - panic!("Didn't find any world header"); - } else { - println!("Found offset 0x{:x}", offset); - } - - // offset+0x13 - deflate - match inflate_bytes_zlib(&save_buf[offset+0x13..]) { - Ok(out_buf) => fs::write(out_path, &out_buf).expect("out_buf"), - Err(e) => panic!("{}", e) - }; + let save = Save::load(Path::new(save_path)).expect("load save"); + dbg!(save); } \ No newline at end of file diff --git a/src/save.rs b/src/save.rs index 75fb806..784ede7 100644 --- a/src/save.rs +++ b/src/save.rs @@ -5,29 +5,39 @@ use anyhow::anyhow; use anyhow::Result; use inflate::inflate_bytes_zlib; -struct World { +#[derive(Debug)] +pub struct World { offset: usize, size: usize, data: Vec } impl World { + const DATA_OFFSET: usize = 0x13; + fn decode(raw: &[u8], offset: usize, size: usize) -> Result { - let data = inflate_bytes_zlib(&raw[offset..offset+size]) + let data_offset = offset + World::DATA_OFFSET; + let data = inflate_bytes_zlib(&raw[data_offset..data_offset+size]) .map_err(|e| anyhow!(e))?; Ok(Self { offset, size, data }) } + + pub fn dump(&self, path: &Path) -> Result<()> { + Ok(fs::write(path, &self.data)?) + } } -struct Save { +#[derive(Debug)] +pub struct Save { raw: Vec, worlds: Vec } impl Save { - fn load(path: &Path) -> Result { + pub fn load(path: &Path) -> Result { let raw = fs::read(path)?; + let file_end = raw.len() - 1; let mut offsets: Vec = Vec::new(); for i in 0..raw.len()-7 { let keyword = match str::from_utf8(&raw[i..i+7]) { @@ -40,6 +50,16 @@ impl Save { } } - Ok(Self { raw, worlds: Vec::new() }) + let mut worlds: Vec = Vec::new(); + for i in offsets.chunks(2) { + let offset = i[0]; + let size = i.get(1).unwrap_or(&file_end); + match World::decode(&raw, offset, *size) { + Ok(world) => worlds.push(world), + Err(e) => println!("world 0x{:x} decode error {}", offset, e) + }; + } + + Ok(Self { raw, worlds }) } } \ No newline at end of file