Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::env;
- use std::fs::File;
- use std::io::Read;
- use std::io::Seek;
- extern crate byteorder;
- use byteorder::{ReadBytesExt, LittleEndian};
- fn ftell(file : &mut File) -> u32
- {
- file.seek(std::io::SeekFrom::Current(0)).unwrap() as u32
- }
- fn read_u8(file : &mut File) -> u8
- {
- file.read_u8().unwrap()
- }
- fn read_u16(file : &mut File) -> u16
- {
- file.read_u16::<LittleEndian>().unwrap()
- }
- fn read_u32(file : &mut File) -> u32
- {
- file.read_u32::<LittleEndian>().unwrap()
- }
- fn read_u64(file : &mut File) -> u64
- {
- file.read_u64::<LittleEndian>().unwrap()
- }
- fn read_i8(file : &mut File) -> i8
- {
- file.read_i8().unwrap()
- }
- fn read_i16(file : &mut File) -> i16
- {
- file.read_i16::<LittleEndian>().unwrap()
- }
- fn read_i32(file : &mut File) -> i32
- {
- file.read_i32::<LittleEndian>().unwrap()
- }
- fn read_i64(file : &mut File) -> i64
- {
- file.read_i64::<LittleEndian>().unwrap()
- }
- fn read_f32(file : &mut File) -> f32
- {
- file.read_f32::<LittleEndian>().unwrap()
- }
- fn read_f64(file : &mut File) -> f64
- {
- file.read_f64::<LittleEndian>().unwrap()
- }
- fn read_str_prefixed_u32(file : &mut File) -> String
- {
- let mut len = read_u32(file);
- read_strn(file, len)
- }
- fn read_strn(file : &mut File, n : u32) -> String
- {
- let mut chain = Vec::<char>::new();
- let mut broken = false;
- for _ in 0..n
- {
- let c = read_u8(file) as char;
- broken = broken || c == '\0';
- if !broken
- {
- chain.push(c);
- }
- }
- chain.into_iter().collect()
- }
- fn read_cstr(file : &mut File) -> String
- {
- let mut chain = Vec::<char>::new();
- let mut c = read_u8(file) as char;
- while c != '\0'
- {
- chain.push(c);
- c = read_u8(file) as char;
- }
- chain.into_iter().collect()
- }
- fn escape_string(text : &String) -> String
- {
- let mut ret = text.clone();
- ret = ret.replace("\\", "\\\\");
- ret = ret.replace("\"", "\\\"");
- ret = ret.replace("\r", "\\r");
- ret = ret.replace("\n", "\\n");
- ret = ret.replace("\t", "\\t");
- ret = ret.replace("\x00", "\\u0000");
- ret = ret.replace("\x01", "\\u0001");
- ret = ret.replace("\x02", "\\u0002");
- ret = ret.replace("\x03", "\\u0003");
- ret = ret.replace("\x04", "\\u0004");
- ret = ret.replace("\x05", "\\u0005");
- ret = ret.replace("\x06", "\\u0006");
- ret = ret.replace("\x07", "\\u0007");
- ret = ret.replace("\x08", "\\u0008");
- ret = ret.replace("\x09", "\\u0009");
- ret = ret.replace("\x0A", "\\u000A");
- ret = ret.replace("\x0B", "\\u000B");
- ret = ret.replace("\x0C", "\\u000C");
- ret = ret.replace("\x0D", "\\u000D");
- ret = ret.replace("\x0E", "\\u000E");
- ret = ret.replace("\x0F", "\\u000F");
- ret = ret.replace("\x10", "\\u0010");
- ret = ret.replace("\x11", "\\u0011");
- ret = ret.replace("\x12", "\\u0012");
- ret = ret.replace("\x13", "\\u0013");
- ret = ret.replace("\x14", "\\u0014");
- ret = ret.replace("\x15", "\\u0015");
- ret = ret.replace("\x16", "\\u0016");
- ret = ret.replace("\x17", "\\u0017");
- ret = ret.replace("\x18", "\\u0018");
- ret = ret.replace("\x19", "\\u0019");
- ret = ret.replace("\x1A", "\\u001A");
- ret = ret.replace("\x1B", "\\u001B");
- ret = ret.replace("\x1C", "\\u001C");
- ret = ret.replace("\x1D", "\\u001D");
- ret = ret.replace("\x1E", "\\u001E");
- ret = ret.replace("\x1F", "\\u001F");
- ret
- }
- #[derive(Clone)]
- #[derive(Debug)]
- struct SubRecord
- {
- name : String,
- data : String,
- special : Option<u32>
- }
- impl SubRecord
- {
- fn to_string(&self) -> String
- {
- return self.data.clone();
- }
- fn read(file : &mut File, parent_name : &String, expect : &'static str, startat : u32, stopat : u32) -> SubRecord
- {
- let start = ftell(file);
- let mut name : String;
- let mut len : u32;
- name = read_strn(file, 4);
- len = read_u32(file);
- assert!(expect == "" || name.as_str() == expect, "expected {} got {} at {:08X} in {} {:08X}", expect, name, start, parent_name, startat-16);
- let mut data = "".to_string();
- let mut special = None;
- match parent_name.as_str()
- {
- "TES3" =>
- {
- match name.as_str()
- {
- "HEDR" =>
- {
- let mut ver : f32;
- let mut unk : u32;
- let mut compname : String;
- let mut description : String;
- let mut numrecords : u32;
- ver = read_f32(file);
- unk = read_u32(file);
- compname = read_strn(file, 32);
- description = read_strn(file, 256);
- numrecords = read_u32(file);
- data = format!(r#"["{}", {{"version":{},"compname":"{}","description":"{}","numrecords":{}}}]"#, escape_string(&name), ver, escape_string(&compname), escape_string(&description), numrecords);
- special = Some(numrecords);
- }
- "MAST" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "DATA" =>
- {
- let len = read_u64(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), len);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "GMST" =>
- {
- match name.as_str()
- {
- "NAME" | "STRV" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "INTV" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "FLTV" =>
- {
- let val = read_f32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "GLOB" =>
- {
- match name.as_str()
- {
- "NAME" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "FNAM" =>
- {
- assert!(len == 1);
- let text = read_strn(file, len);
- assert!(read_strn(file, 4) == "FLTV");
- assert!(read_u32(file) == 4);
- data = format!(r#"["{}", "{}", {}]"#, escape_string(&name), escape_string(&text),
- match text.as_str()
- {
- "f" => read_f32(file).to_string(),
- "l" => (read_f32(file) as i32).to_string(),
- "s" => (read_f32(file) as i16).to_string(),
- _ => panic!("FNAM of GLOB must be f, l, or s")
- });
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "CLAS" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "DESC" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "CLDT" =>
- {
- let attribute_1 = read_u32(file);
- let attribute_2 = read_u32(file);
- let specialization = read_u32(file);
- for _ in 0..5
- {
- let minor_skill = read_u32(file);
- let major_skill = read_u32(file);
- }
- let isplayable = read_u32(file);
- let flags = read_u32(file);
- data = format!(r#"["CLDT (todo)"]"#);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "FACT" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "RNAM" | "ANAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "FADT" =>
- {
- let attribute_1 = read_u32(file);
- let attribute_2 = read_u32(file);
- for _ in 0..10
- {
- let a = read_u32(file);
- let b = read_u32(file);
- let c = read_u32(file);
- let d = read_u32(file);
- let e = read_u32(file);
- }
- for _ in 0..6
- {
- let a = read_u32(file);
- }
- let unk = read_u32(file);
- let flags = read_u32(file);
- data = format!(r#"["FADT (todo)"]"#);
- }
- "INTV" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "RACE" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "NPCS" | "DESC" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "RADT" =>
- {
- for _ in 0..7
- {
- let id = read_u32(file);
- let bonus = read_u32(file);
- }
- for _ in 0..10
- {
- let a_tweak = read_u32(file);
- let b_tweak = read_u32(file);
- }
- let flags = read_u32(file);
- data = format!(r#"["RADT (todo)"]"#);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "SOUN" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "DATA" =>
- {
- data = format!(r#"["{}", {{"volume": {}, "minrange": {}, "maxrange": {}}}]"#, escape_string(&name), read_u8(file), read_u8(file), read_u8(file));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "SKIL" =>
- {
- match name.as_str()
- {
- "DESC" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "SKDT" =>
- {
- data = format!(r#"["{}", {{"attribute": {}, "specialization": {}, "usevals": [{}, {}, {}, {}]}}]"#,
- escape_string(&name), read_u32(file), read_u32(file), read_f32(file), read_f32(file), read_f32(file), read_f32(file));
- }
- "INDX" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "MGEF" =>
- {
- match name.as_str()
- {
- "ITEX" | "PTEX" | "CVFX" | "BVFX" | "HVFX" | "AVFX" | "DESC" | "CSND" | "BSND" | "HSND" | "ASND" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "MEDT" =>
- {
- let school = read_u32(file);
- let base_cost = read_f32(file);
- let flags = read_u32(file);
- let r = read_u32(file);
- let g = read_u32(file);
- let b = read_u32(file);
- let speed = read_f32(file);
- let size = read_f32(file);
- let sizecap = read_f32(file);
- data = format!(r#"["MEDT (todo)"]"#);
- }
- "INDX" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "SCPT" =>
- {
- match name.as_str()
- {
- "SCHD" =>
- {
- let script_name = read_strn(file, 32);
- let num_short = read_u32(file);
- let num_long = read_u32(file);
- let num_float = read_u32(file);
- let script_data_size = read_u32(file);
- let script_var_size = read_u32(file);
- data = format!(r#"["{}", "{}", "(redacted)"]"#, escape_string(&name), escape_string(&script_name));
- }
- "SCTX" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- ignored =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "REGN" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "BNAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- ignored =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "BSGN" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "TNAM" | "DESC" | "NPCS" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "LTEX" =>
- {
- match name.as_str()
- {
- "NAME" | "DATA" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "INTV" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "STAT" =>
- {
- match name.as_str()
- {
- "NAME" | "MODL" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "DOOR" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "MODL" | "SCIP" | "SNAM" | "ANAM" | "SCRI" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "MISC" =>
- {
- match name.as_str()
- {
- "NAME" | "MODL" | "FNAM" | "ITEX" | "ENAM" | "SCRI" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "MCDT" =>
- {
- let weight = read_f32(file);
- let value = read_u32(file);
- let unk = read_u32(file);
- data = format!(r#"["{}", "{}", "{}", "{}"]"#, escape_string(&name), weight, value, unk);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "WEAP" =>
- {
- match name.as_str()
- {
- "NAME" | "MODL" | "FNAM" | "ITEX" | "ENAM" | "SCRI" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "WPDT" =>
- {
- let weight = read_f32(file);
- let value = read_u32(file);
- let kind = read_u16(file);
- let health = read_u16(file);
- let speed = read_f32(file);
- let reach = read_f32(file);
- let enchant = read_u16(file);
- let chop_min = read_u8(file);
- let chop_max = read_u8(file);
- let slash_min = read_u8(file);
- let slash_max = read_u8(file);
- let thrust_min = read_u8(file);
- let thrust_max = read_u8(file);
- let flags = read_u32(file);
- data = format!(r#"["{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}", "{}"]"#, escape_string(&name), weight, value, kind, health, speed, reach, enchant, chop_min, chop_max, slash_min, slash_max, thrust_min, thrust_max, flags);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "CONT" =>
- {
- match name.as_str()
- {
- "NAME" | "MODL" | "FNAM" | "SCRI" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "CNDT" =>
- {
- let weight = read_f32(file);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), weight);
- }
- "FLAG" =>
- {
- let flags = read_u32(file);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), flags);
- }
- "NPCO" =>
- {
- let count = read_u32(file);
- let itemname = read_strn(file, 32);
- data = format!(r#"["{}", "{}", "{}"]"#, escape_string(&name), count, escape_string(&itemname));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "SPEL" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "SPDT" =>
- {
- let kind = read_u32(file);
- let count = read_u32(file);
- let flags = read_u32(file);
- data = format!(r#"["{}", "{}", "{}", "{}"]"#, escape_string(&name), kind, count, flags);
- }
- "ENAM" =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "CREA" =>
- {
- match name.as_str()
- {
- "NAME" | "MODL" | "FNAM" | "SCRI" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "NPCO" =>
- {
- let count = read_u32(file);
- let itemname = read_strn(file, 32);
- data = format!(r#"["{}", "{}", "{}"]"#, escape_string(&name), count, escape_string(&itemname));
- }
- ignored =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "NPC_" =>
- {
- match name.as_str()
- {
- "NAME" | "FNAM" | "MODL" | "RNAM" | "ANAM" | "BNAM" | "CNAM" | "HNAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "NPCO" =>
- {
- let count = read_u32(file);
- let itemname = read_strn(file, 32);
- data = format!(r#"["{}", "{}", "{}"]"#, escape_string(&name), count, escape_string(&itemname));
- }
- "NPCS" =>
- {
- let spellname = read_strn(file, 32);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&spellname));
- }
- ignored =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "LEVI" =>
- {
- match name.as_str()
- {
- "NAME" | "INAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "NNAM" =>
- {
- let val = read_u8(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "INDX" | "DATA" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "INTV" =>
- {
- let val = read_u16(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "LEVC" =>
- {
- match name.as_str()
- {
- "NAME" | "CNAM" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "NNAM" =>
- {
- let val = read_u8(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "INDX" | "DATA" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "INTV" =>
- {
- let val = read_u16(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- "CELL" =>
- {
- match name.as_str()
- {
- "NAME" | "RGNN" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "DATA" =>
- {
- let flags = read_u32(file);
- let grid_x = read_u32(file);
- let grid_y = read_u32(file);
- data = format!(r#"["{}", {}, {}, {}]"#, escape_string(&name), flags, grid_x, grid_y);
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}` around `{:08X}`", name, parent_name, ftell(file));
- }
- }
- }
- "CELL_sub" =>
- {
- match name.as_str()
- {
- "NAME" | "DNAM" | "KNAM" | "TNAM" | "UNAM" | "ANAM" | "BNAM" | "XSOL" | "CNAM" | "INAM" | "RGNN" =>
- {
- let text = read_strn(file, len);
- data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
- }
- "NAM0" => // should belong to CELL but i don't care
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "FRMR" | "DELE" | "FLTV" | "INTV" | "INDX" =>
- {
- let val = read_u32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "XSCL" | "XCHG" =>
- {
- let val = read_f32(file);
- data = format!(r#"["{}", {}]"#, escape_string(&name), val);
- }
- "DODT" | "DATA" | "XHLT" =>
- {
- let x_pos = read_f32(file);
- let y_pos = read_f32(file);
- let z_pos = read_f32(file);
- let x_rot = read_f32(file);
- let y_rot = read_f32(file);
- let z_rot = read_f32(file);
- data = format!(r#"["{}", {}, {}, {}, {}, {}, {}]"#, escape_string(&name), x_pos, y_pos, z_pos, x_rot, y_rot, z_rot);
- }
- ignored =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}` around `{:08X}`", name, parent_name, ftell(file));
- }
- }
- }
- ignored =>
- {
- match name.as_str()
- {
- ignored =>
- {
- while ftell(file) < start+len+8
- {
- read_u8(file);
- }
- data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
- }
- unknown =>
- {
- panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
- }
- }
- }
- unknown =>
- {
- panic!("unknown parent record `{}`", parent_name);
- }
- }
- assert!(ftell(file) <= stopat, "{} {:08X} {:08X} {:08X}", parent_name, startat, stopat, ftell(file));
- let ret = SubRecord{name, data, special};
- //println!("{:?}", ret);
- ret
- }
- }
- #[derive(Clone)]
- #[derive(Debug)]
- struct Record
- {
- name : String,
- len : u32,
- flags : u32,
- sub : Vec<SubRecord>
- }
- impl Record
- {
- fn to_string(&self) -> String
- {
- let mut substrings = Vec::<String>::new();
- for sub in &self.sub
- {
- substrings.push(sub.to_string());
- }
- return format!("[\"{}\", [\n {}]]", escape_string(&self.name), substrings.join(",\n "));
- }
- fn read(file : &mut File) -> Record
- {
- let mut name : String;
- let mut len : u32;
- let mut unk : u32;
- let mut flags : u32;
- name = read_strn(file, 4);
- len = read_u32(file);
- unk = read_u32(file);
- flags = read_u32(file);
- let start = ftell(file);
- let end = start + len;
- let mut sub = Vec::new();
- let mut virt_name = name.clone();
- let mut count = 0;
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &virt_name, "", start, end));
- count += 1;
- if virt_name == "CELL" && count >= 2
- {
- virt_name = "CELL_sub".to_string();
- }
- }
- /*
- match name.as_str()
- {
- "TES3" =>
- {
- sub.push(SubRecord::read(file, &name, "HEDR", start, end));
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "MAST", start, end));
- sub.push(SubRecord::read(file, &name, "DATA", start, end));
- }
- }
- "GMST" =>
- {
- sub.push(SubRecord::read(file, &name, "NAME", start, end));
- if ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "GLOB" =>
- {
- sub.push(SubRecord::read(file, &name, "NAME", start, end));
- sub.push(SubRecord::read(file, &name, "FNAM", start, end));
- //sub.push(SubRecord::read(file, &name, "FLTV", start, end)); // handled virtually by GLOB:FNAM
- }
- "CLAS" =>
- {
- sub.push(SubRecord::read(file, &name, "NAME", start, end));
- sub.push(SubRecord::read(file, &name, "FNAM", start, end));
- sub.push(SubRecord::read(file, &name, "CLDT", start, end));
- if ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "DESC", start, end));
- }
- }
- "FACT" =>
- {
- sub.push(SubRecord::read(file, &name, "NAME", start, end));
- sub.push(SubRecord::read(file, &name, "FNAM", start, end));
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "RACE" =>
- {
- sub.push(SubRecord::read(file, &name, "NAME", start, end));
- sub.push(SubRecord::read(file, &name, "FNAM", start, end));
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "SOUN" =>
- {
- sub.push(SubRecord::read(file, &name, "NAME", start, end));
- sub.push(SubRecord::read(file, &name, "FNAM", start, end));
- sub.push(SubRecord::read(file, &name, "DATA", start, end));
- }
- "SKIL" =>
- {
- sub.push(SubRecord::read(file, &name, "INDX", start, end));
- sub.push(SubRecord::read(file, &name, "SKDT", start, end));
- sub.push(SubRecord::read(file, &name, "DESC", start, end));
- }
- "MGEF" =>
- {
- sub.push(SubRecord::read(file, &name, "INDX", start, end));
- sub.push(SubRecord::read(file, &name, "MEDT", start, end));
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "SCPT" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "REGN" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "BSGN" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "LTEX" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "STAT" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "DOOR" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "MISC" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- "WEAP" =>
- {
- while ftell(file) < end
- {
- sub.push(SubRecord::read(file, &name, "", start, end));
- }
- }
- unknown =>
- {
- panic!("unknown parent record `{}`", unknown);
- }
- }
- */
- assert!(ftell(file) == end);
- Record{name, len, flags, sub}
- }
- }
- fn all_records(file : &mut File) -> Vec<Record>
- {
- let mut ret = Vec::new();
- let head_record = Record::read(file);
- assert!(head_record.name == "TES3");
- let count = head_record.sub.first().unwrap().special.unwrap();
- ret.push(head_record);
- for _ in 0..count
- {
- ret.push(Record::read(file));
- }
- ret
- }
- //fn stringify_record_list(vec : &Vec<Record>) -> String
- //{
- // let mut substrings = Vec::<String>::new();
- //
- // for sub in &vec
- // {
- // substrings.push(sub.to_string());
- // }
- //
- // return format!("[{}]", substrings.join(","));
- //}
- fn main()
- {
- let args: Vec<String> = env::args().collect();
- if args.len() != 2
- {
- println!("usage:\n./mwdump fname.(esm|esp)");
- }
- else
- {
- let recs = all_records(&mut File::open(&args[1]).unwrap());
- println!("[");
- for i in 0..recs.len()
- {
- print!("{}", recs[i].to_string());
- if i+1 < recs.len()
- {
- println!(",");
- }
- else
- {
- println!("");
- }
- }
- println!("]");
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement