Advertisement
Guest User

Untitled

a guest
Nov 11th, 2018
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 41.82 KB | None | 0 0
  1. use std::env;
  2. use std::fs::File;
  3. use std::io::Read;
  4. use std::io::Seek;
  5.  
  6. extern crate byteorder;
  7. use byteorder::{ReadBytesExt, LittleEndian};
  8.  
  9. fn ftell(file : &mut File) -> u32
  10. {
  11.     file.seek(std::io::SeekFrom::Current(0)).unwrap() as u32
  12. }
  13.  
  14. fn read_u8(file : &mut File) -> u8
  15. {
  16.     file.read_u8().unwrap()
  17. }
  18. fn read_u16(file : &mut File) -> u16
  19. {
  20.     file.read_u16::<LittleEndian>().unwrap()
  21. }
  22. fn read_u32(file : &mut File) -> u32
  23. {
  24.     file.read_u32::<LittleEndian>().unwrap()
  25. }
  26. fn read_u64(file : &mut File) -> u64
  27. {
  28.     file.read_u64::<LittleEndian>().unwrap()
  29. }
  30.  
  31. fn read_i8(file : &mut File) -> i8
  32. {
  33.     file.read_i8().unwrap()
  34. }
  35. fn read_i16(file : &mut File) -> i16
  36. {
  37.     file.read_i16::<LittleEndian>().unwrap()
  38. }
  39. fn read_i32(file : &mut File) -> i32
  40. {
  41.     file.read_i32::<LittleEndian>().unwrap()
  42. }
  43. fn read_i64(file : &mut File) -> i64
  44. {
  45.     file.read_i64::<LittleEndian>().unwrap()
  46. }
  47.  
  48. fn read_f32(file : &mut File) -> f32
  49. {
  50.     file.read_f32::<LittleEndian>().unwrap()
  51. }
  52. fn read_f64(file : &mut File) -> f64
  53. {
  54.     file.read_f64::<LittleEndian>().unwrap()
  55. }
  56.  
  57. fn read_str_prefixed_u32(file : &mut File) -> String
  58. {
  59.     let mut len = read_u32(file);
  60.     read_strn(file, len)
  61. }
  62.  
  63. fn read_strn(file : &mut File, n : u32) -> String
  64. {
  65.     let mut chain = Vec::<char>::new();
  66.     let mut broken = false;
  67.     for _ in 0..n
  68.     {
  69.         let c = read_u8(file) as char;
  70.         broken = broken || c == '\0';
  71.         if !broken
  72.         {
  73.             chain.push(c);
  74.         }
  75.     }
  76.     chain.into_iter().collect()
  77. }
  78.  
  79. fn read_cstr(file : &mut File) -> String
  80. {
  81.     let mut chain = Vec::<char>::new();
  82.     let mut c = read_u8(file) as char;
  83.     while c != '\0'
  84.     {
  85.         chain.push(c);
  86.         c = read_u8(file) as char;
  87.     }
  88.     chain.into_iter().collect()
  89. }
  90.  
  91. fn escape_string(text : &String) -> String
  92. {
  93.     let mut ret = text.clone();
  94.     ret = ret.replace("\\", "\\\\");
  95.     ret = ret.replace("\"", "\\\"");
  96.     ret = ret.replace("\r", "\\r");
  97.     ret = ret.replace("\n", "\\n");
  98.     ret = ret.replace("\t", "\\t");
  99.     ret = ret.replace("\x00", "\\u0000");
  100.     ret = ret.replace("\x01", "\\u0001");
  101.     ret = ret.replace("\x02", "\\u0002");
  102.     ret = ret.replace("\x03", "\\u0003");
  103.     ret = ret.replace("\x04", "\\u0004");
  104.     ret = ret.replace("\x05", "\\u0005");
  105.     ret = ret.replace("\x06", "\\u0006");
  106.     ret = ret.replace("\x07", "\\u0007");
  107.     ret = ret.replace("\x08", "\\u0008");
  108.     ret = ret.replace("\x09", "\\u0009");
  109.     ret = ret.replace("\x0A", "\\u000A");
  110.     ret = ret.replace("\x0B", "\\u000B");
  111.     ret = ret.replace("\x0C", "\\u000C");
  112.     ret = ret.replace("\x0D", "\\u000D");
  113.     ret = ret.replace("\x0E", "\\u000E");
  114.     ret = ret.replace("\x0F", "\\u000F");
  115.     ret = ret.replace("\x10", "\\u0010");
  116.     ret = ret.replace("\x11", "\\u0011");
  117.     ret = ret.replace("\x12", "\\u0012");
  118.     ret = ret.replace("\x13", "\\u0013");
  119.     ret = ret.replace("\x14", "\\u0014");
  120.     ret = ret.replace("\x15", "\\u0015");
  121.     ret = ret.replace("\x16", "\\u0016");
  122.     ret = ret.replace("\x17", "\\u0017");
  123.     ret = ret.replace("\x18", "\\u0018");
  124.     ret = ret.replace("\x19", "\\u0019");
  125.     ret = ret.replace("\x1A", "\\u001A");
  126.     ret = ret.replace("\x1B", "\\u001B");
  127.     ret = ret.replace("\x1C", "\\u001C");
  128.     ret = ret.replace("\x1D", "\\u001D");
  129.     ret = ret.replace("\x1E", "\\u001E");
  130.     ret = ret.replace("\x1F", "\\u001F");
  131.     ret
  132. }
  133.  
  134. #[derive(Clone)]
  135. #[derive(Debug)]
  136. struct SubRecord
  137. {
  138.     name : String,
  139.     data : String,
  140.     special : Option<u32>
  141. }
  142.  
  143. impl SubRecord
  144. {
  145.     fn to_string(&self) -> String
  146.     {
  147.         return self.data.clone();
  148.     }
  149.     fn read(file : &mut File, parent_name : &String, expect : &'static str, startat : u32, stopat : u32) -> SubRecord
  150.    {
  151.        let start = ftell(file);
  152.        
  153.        let mut name : String;
  154.        let mut len : u32;
  155.        
  156.        name = read_strn(file, 4);
  157.        len = read_u32(file);
  158.        
  159.        assert!(expect == "" || name.as_str() == expect, "expected {} got {} at {:08X} in {} {:08X}", expect, name, start, parent_name, startat-16);
  160.        
  161.        let mut data = "".to_string();
  162.        let mut special = None;
  163.        
  164.        match parent_name.as_str()
  165.        {
  166.            "TES3" =>
  167.            {
  168.                match name.as_str()
  169.                {
  170.                    "HEDR" =>
  171.                    {
  172.                        let mut ver : f32;
  173.                        let mut unk : u32;
  174.                        let mut compname : String;
  175.                        let mut description : String;
  176.                        let mut numrecords : u32;
  177.                        
  178.                        ver = read_f32(file);
  179.                        unk = read_u32(file);
  180.                        compname = read_strn(file, 32);
  181.                        description = read_strn(file, 256);
  182.                        numrecords = read_u32(file);
  183.                        
  184.                        data = format!(r#"["{}", {{"version":{},"compname":"{}","description":"{}","numrecords":{}}}]"#, escape_string(&name), ver, escape_string(&compname), escape_string(&description), numrecords);
  185.                        
  186.                        special = Some(numrecords);
  187.                    }
  188.                    "MAST" =>
  189.                    {
  190.                        let text = read_strn(file, len);
  191.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  192.                    }
  193.                    "DATA" =>
  194.                    {
  195.                        let len = read_u64(file);
  196.                        data = format!(r#"["{}", {}]"#, escape_string(&name), len);
  197.                    }
  198.                    unknown =>
  199.                    {
  200.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  201.                    }
  202.                }
  203.            }
  204.            "GMST" =>
  205.            {
  206.                match name.as_str()
  207.                {
  208.                    "NAME" | "STRV" =>
  209.                    {
  210.                        let text = read_strn(file, len);
  211.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  212.                    }
  213.                    "INTV" =>
  214.                    {
  215.                        let val = read_u32(file);
  216.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  217.                    }
  218.                    "FLTV" =>
  219.                    {
  220.                        let val = read_f32(file);
  221.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  222.                    }
  223.                    unknown =>
  224.                    {
  225.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  226.                    }
  227.                }
  228.            }
  229.            "GLOB" =>
  230.            {
  231.                match name.as_str()
  232.                {
  233.                    "NAME" =>
  234.                    {
  235.                        let text = read_strn(file, len);
  236.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  237.                    }
  238.                    "FNAM" =>
  239.                    {
  240.                        assert!(len == 1);
  241.                        let text = read_strn(file, len);
  242.                        assert!(read_strn(file, 4) == "FLTV");
  243.                        assert!(read_u32(file) == 4);
  244.                        
  245.                        data = format!(r#"["{}", "{}", {}]"#, escape_string(&name), escape_string(&text),
  246.                        match text.as_str()
  247.                        {
  248.                            "f" => read_f32(file).to_string(),
  249.                            "l" => (read_f32(file) as i32).to_string(),
  250.                            "s" => (read_f32(file) as i16).to_string(),
  251.                            _ => panic!("FNAM of GLOB must be f, l, or s")
  252.                        });
  253.                    }
  254.                    unknown =>
  255.                    {
  256.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  257.                    }
  258.                }
  259.            }
  260.            "CLAS" =>
  261.            {
  262.                match name.as_str()
  263.                {
  264.                    "NAME" | "FNAM" | "DESC" =>
  265.                    {
  266.                        let text = read_strn(file, len);
  267.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  268.                    }
  269.                    "CLDT" =>
  270.                    {
  271.                        let attribute_1 = read_u32(file);
  272.                        let attribute_2 = read_u32(file);
  273.                        let specialization = read_u32(file);
  274.                        for _ in 0..5
  275.                        {
  276.                            let minor_skill = read_u32(file);
  277.                            let major_skill = read_u32(file);
  278.                        }
  279.                        let isplayable = read_u32(file);
  280.                        let flags = read_u32(file);
  281.                        
  282.                        data = format!(r#"["CLDT (todo)"]"#);
  283.                    }
  284.                    unknown =>
  285.                    {
  286.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  287.                    }
  288.                }
  289.            }
  290.            "FACT" =>
  291.            {
  292.                match name.as_str()
  293.                {
  294.                    "NAME" | "FNAM" | "RNAM" | "ANAM" =>
  295.                    {
  296.                        let text = read_strn(file, len);
  297.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  298.                    }
  299.                    "FADT" =>
  300.                    {
  301.                        let attribute_1 = read_u32(file);
  302.                        let attribute_2 = read_u32(file);
  303.                        for _ in 0..10
  304.                        {
  305.                            let a = read_u32(file);
  306.                            let b = read_u32(file);
  307.                            let c = read_u32(file);
  308.                            let d = read_u32(file);
  309.                            let e = read_u32(file);
  310.                        }
  311.                        for _ in 0..6
  312.                        {
  313.                            let a = read_u32(file);
  314.                        }
  315.                        let unk = read_u32(file);
  316.                        let flags = read_u32(file);
  317.                        
  318.                        data = format!(r#"["FADT (todo)"]"#);
  319.                    }
  320.                    "INTV" =>
  321.                    {
  322.                        let val = read_u32(file);
  323.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  324.                    }
  325.                    unknown =>
  326.                    {
  327.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  328.                    }
  329.                }
  330.            }
  331.            "RACE" =>
  332.            {
  333.                match name.as_str()
  334.                {
  335.                    "NAME" | "FNAM" | "NPCS" | "DESC" =>
  336.                    {
  337.                        let text = read_strn(file, len);
  338.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  339.                    }
  340.                    "RADT" =>
  341.                    {
  342.                        for _ in 0..7
  343.                        {
  344.                            let id = read_u32(file);
  345.                            let bonus = read_u32(file);
  346.                        }
  347.                        for _ in 0..10
  348.                        {
  349.                            let a_tweak = read_u32(file);
  350.                            let b_tweak = read_u32(file);
  351.                        }
  352.                        let flags = read_u32(file);
  353.                        
  354.                        data = format!(r#"["RADT (todo)"]"#);
  355.                    }
  356.                    unknown =>
  357.                    {
  358.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  359.                    }
  360.                }
  361.            }
  362.            "SOUN" =>
  363.            {
  364.                match name.as_str()
  365.                {
  366.                    "NAME" | "FNAM" =>
  367.                    {
  368.                        let text = read_strn(file, len);
  369.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  370.                    }
  371.                    "DATA" =>
  372.                    {
  373.                        data = format!(r#"["{}", {{"volume": {}, "minrange": {}, "maxrange": {}}}]"#, escape_string(&name), read_u8(file), read_u8(file), read_u8(file));
  374.                    }
  375.                    unknown =>
  376.                    {
  377.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  378.                    }
  379.                }
  380.            }
  381.            "SKIL" =>
  382.            {
  383.                match name.as_str()
  384.                {
  385.                    "DESC" =>
  386.                    {
  387.                        let text = read_strn(file, len);
  388.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  389.                    }
  390.                    "SKDT" =>
  391.                    {
  392.                        data = format!(r#"["{}", {{"attribute": {}, "specialization": {}, "usevals": [{}, {}, {}, {}]}}]"#,
  393.                            escape_string(&name), read_u32(file), read_u32(file), read_f32(file), read_f32(file), read_f32(file), read_f32(file));
  394.                    }
  395.                    "INDX" =>
  396.                    {
  397.                        let val = read_u32(file);
  398.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  399.                    }
  400.                    unknown =>
  401.                    {
  402.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  403.                    }
  404.                }
  405.            }
  406.            "MGEF" =>
  407.            {
  408.                match name.as_str()
  409.                {
  410.                    "ITEX" | "PTEX" | "CVFX" | "BVFX" | "HVFX" | "AVFX" | "DESC" | "CSND" | "BSND" | "HSND" | "ASND" =>
  411.                    {
  412.                        let text = read_strn(file, len);
  413.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  414.                    }
  415.                    "MEDT" =>
  416.                    {
  417.                        let school = read_u32(file);
  418.                        let base_cost = read_f32(file);
  419.                        let flags = read_u32(file);
  420.                        let r = read_u32(file);
  421.                        let g = read_u32(file);
  422.                        let b = read_u32(file);
  423.                        let speed = read_f32(file);
  424.                        let size = read_f32(file);
  425.                        let sizecap = read_f32(file);
  426.                        
  427.                        data = format!(r#"["MEDT (todo)"]"#);
  428.                    }
  429.                    "INDX" =>
  430.                    {
  431.                        let val = read_u32(file);
  432.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  433.                    }
  434.                    unknown =>
  435.                    {
  436.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  437.                    }
  438.                }
  439.            }
  440.            "SCPT" =>
  441.            {
  442.                match name.as_str()
  443.                {
  444.                    "SCHD" =>
  445.                    {
  446.                        let script_name = read_strn(file, 32);
  447.                        let num_short = read_u32(file);
  448.                        let num_long = read_u32(file);
  449.                        let num_float = read_u32(file);
  450.                        let script_data_size = read_u32(file);
  451.                        let script_var_size = read_u32(file);
  452.                        data = format!(r#"["{}", "{}", "(redacted)"]"#, escape_string(&name), escape_string(&script_name));
  453.                    }
  454.                    "SCTX" =>
  455.                    {
  456.                        let text = read_strn(file, len);
  457.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  458.                    }
  459.                    ignored =>
  460.                    {
  461.                        while ftell(file) < start+len+8
  462.                        {
  463.                            read_u8(file);
  464.                        }
  465.                        data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  466.                    }
  467.                    unknown =>
  468.                    {
  469.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  470.                    }
  471.                }
  472.            }
  473.            "REGN" =>
  474.            {
  475.                match name.as_str()
  476.                {
  477.                    "NAME" | "FNAM" | "BNAM" =>
  478.                    {
  479.                        let text = read_strn(file, len);
  480.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  481.                    }
  482.                    ignored =>
  483.                    {
  484.                        while ftell(file) < start+len+8
  485.                        {
  486.                            read_u8(file);
  487.                        }
  488.                        data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  489.                    }
  490.                    unknown =>
  491.                    {
  492.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  493.                    }
  494.                }
  495.            }
  496.            "BSGN" =>
  497.            {
  498.                match name.as_str()
  499.                {
  500.                    "NAME" | "FNAM" | "TNAM" | "DESC" | "NPCS" =>
  501.                    {
  502.                        let text = read_strn(file, len);
  503.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  504.                    }
  505.                    unknown =>
  506.                    {
  507.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  508.                    }
  509.                }
  510.            }
  511.            "LTEX" =>
  512.            {
  513.                match name.as_str()
  514.                {
  515.                    "NAME" | "DATA" =>
  516.                    {
  517.                        let text = read_strn(file, len);
  518.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  519.                    }
  520.                    "INTV" =>
  521.                    {
  522.                        let val = read_u32(file);
  523.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  524.                    }
  525.                    unknown =>
  526.                    {
  527.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  528.                    }
  529.                }
  530.            }
  531.            "STAT" =>
  532.            {
  533.                match name.as_str()
  534.                {
  535.                    "NAME" | "MODL" =>
  536.                    {
  537.                        let text = read_strn(file, len);
  538.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  539.                    }
  540.                    unknown =>
  541.                    {
  542.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  543.                    }
  544.                }
  545.            }
  546.            "DOOR" =>
  547.            {
  548.                match name.as_str()
  549.                {
  550.                    "NAME" | "FNAM" | "MODL" | "SCIP" | "SNAM" | "ANAM" | "SCRI" =>
  551.                    {
  552.                        let text = read_strn(file, len);
  553.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  554.                    }
  555.                    unknown =>
  556.                    {
  557.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  558.                    }
  559.                }
  560.            }
  561.            "MISC" =>
  562.            {
  563.                match name.as_str()
  564.                {
  565.                    "NAME" | "MODL" | "FNAM" | "ITEX" | "ENAM" | "SCRI" =>
  566.                    {
  567.                        let text = read_strn(file, len);
  568.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  569.                    }
  570.                    "MCDT" =>
  571.                    {
  572.                        let weight = read_f32(file);
  573.                        let value = read_u32(file);
  574.                        let unk = read_u32(file);
  575.                        data = format!(r#"["{}", "{}", "{}", "{}"]"#, escape_string(&name), weight, value, unk);
  576.                    }
  577.                    unknown =>
  578.                    {
  579.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  580.                    }
  581.                }
  582.            }
  583.            "WEAP" =>
  584.            {
  585.                match name.as_str()
  586.                {
  587.                    "NAME" | "MODL" | "FNAM" | "ITEX" | "ENAM" | "SCRI" =>
  588.                    {
  589.                        let text = read_strn(file, len);
  590.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  591.                    }
  592.                    "WPDT" =>
  593.                    {
  594.                        let weight = read_f32(file);
  595.                        let value = read_u32(file);
  596.                        let kind = read_u16(file);
  597.                        let health = read_u16(file);
  598.                        let speed = read_f32(file);
  599.                        let reach = read_f32(file);
  600.                        let enchant = read_u16(file);
  601.                        let chop_min = read_u8(file);
  602.                        let chop_max = read_u8(file);
  603.                        let slash_min = read_u8(file);
  604.                        let slash_max = read_u8(file);
  605.                        let thrust_min = read_u8(file);
  606.                        let thrust_max = read_u8(file);
  607.                        let flags = read_u32(file);
  608.                        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);
  609.                    }
  610.                    unknown =>
  611.                    {
  612.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  613.                    }
  614.                }
  615.            }
  616.            "CONT" =>
  617.            {
  618.                match name.as_str()
  619.                {
  620.                    "NAME" | "MODL" | "FNAM" | "SCRI" =>
  621.                    {
  622.                        let text = read_strn(file, len);
  623.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  624.                    }
  625.                    "CNDT" =>
  626.                    {
  627.                        let weight = read_f32(file);
  628.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), weight);
  629.                    }
  630.                    "FLAG" =>
  631.                    {
  632.                        let flags = read_u32(file);
  633.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), flags);
  634.                    }
  635.                    "NPCO" =>
  636.                    {
  637.                        let count = read_u32(file);
  638.                        let itemname = read_strn(file, 32);
  639.                        data = format!(r#"["{}", "{}", "{}"]"#, escape_string(&name), count, escape_string(&itemname));
  640.                    }
  641.                    unknown =>
  642.                    {
  643.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  644.                    }
  645.                }
  646.            }
  647.            "SPEL" =>
  648.            {
  649.                match name.as_str()
  650.                {
  651.                    "NAME" | "FNAM" =>
  652.                    {
  653.                        let text = read_strn(file, len);
  654.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  655.                    }
  656.                    "SPDT" =>
  657.                    {
  658.                        let kind = read_u32(file);
  659.                        let count = read_u32(file);
  660.                        let flags = read_u32(file);
  661.                        data = format!(r#"["{}", "{}", "{}", "{}"]"#, escape_string(&name), kind, count, flags);
  662.                    }
  663.                    "ENAM" =>
  664.                    {
  665.                        while ftell(file) < start+len+8
  666.                        {
  667.                            read_u8(file);
  668.                        }
  669.                        data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  670.                    }
  671.                    unknown =>
  672.                    {
  673.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  674.                    }
  675.                }
  676.            }
  677.            "CREA" =>
  678.            {
  679.                match name.as_str()
  680.                {
  681.                    "NAME" | "MODL" | "FNAM" | "SCRI" =>
  682.                    {
  683.                        let text = read_strn(file, len);
  684.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  685.                    }
  686.                    "NPCO" =>
  687.                    {
  688.                        let count = read_u32(file);
  689.                        let itemname = read_strn(file, 32);
  690.                        data = format!(r#"["{}", "{}", "{}"]"#, escape_string(&name), count, escape_string(&itemname));
  691.                    }
  692.                    ignored =>
  693.                    {
  694.                        while ftell(file) < start+len+8
  695.                        {
  696.                            read_u8(file);
  697.                        }
  698.                        data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  699.                    }
  700.                    unknown =>
  701.                    {
  702.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  703.                    }
  704.                }
  705.            }
  706.            "NPC_" =>
  707.            {
  708.                match name.as_str()
  709.                {
  710.                    "NAME" | "FNAM" | "MODL" | "RNAM" | "ANAM" | "BNAM" | "CNAM" | "HNAM" =>
  711.                    {
  712.                        let text = read_strn(file, len);
  713.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  714.                    }
  715.                    "NPCO" =>
  716.                    {
  717.                        let count = read_u32(file);
  718.                        let itemname = read_strn(file, 32);
  719.                        data = format!(r#"["{}", "{}", "{}"]"#, escape_string(&name), count, escape_string(&itemname));
  720.                    }
  721.                    "NPCS" =>
  722.                    {
  723.                        let spellname = read_strn(file, 32);
  724.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&spellname));
  725.                    }
  726.                    ignored =>
  727.                    {
  728.                        while ftell(file) < start+len+8
  729.                        {
  730.                            read_u8(file);
  731.                        }
  732.                        data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  733.                    }
  734.                    unknown =>
  735.                    {
  736.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  737.                    }
  738.                }
  739.            }
  740.            "LEVI" =>
  741.            {
  742.                match name.as_str()
  743.                {
  744.                    "NAME" | "INAM" =>
  745.                    {
  746.                        let text = read_strn(file, len);
  747.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  748.                    }
  749.                    "NNAM" =>
  750.                    {
  751.                        let val = read_u8(file);
  752.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  753.                    }
  754.                    "INDX" | "DATA" =>
  755.                    {
  756.                        let val = read_u32(file);
  757.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  758.                    }
  759.                    "INTV" =>
  760.                    {
  761.                        let val = read_u16(file);
  762.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  763.                    }
  764.                    unknown =>
  765.                    {
  766.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  767.                    }
  768.                }
  769.            }
  770.            "LEVC" =>
  771.            {
  772.                match name.as_str()
  773.                {
  774.                    "NAME" | "CNAM" =>
  775.                    {
  776.                        let text = read_strn(file, len);
  777.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  778.                    }
  779.                    "NNAM" =>
  780.                    {
  781.                        let val = read_u8(file);
  782.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  783.                    }
  784.                    "INDX" | "DATA" =>
  785.                    {
  786.                        let val = read_u32(file);
  787.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  788.                    }
  789.                    "INTV" =>
  790.                    {
  791.                        let val = read_u16(file);
  792.                        data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  793.                    }
  794.                    unknown =>
  795.                    {
  796.                        panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  797.                    }
  798.                }
  799.            }
  800.            "CELL" =>
  801.            {
  802.                match name.as_str()
  803.                {
  804.                    "NAME" | "RGNN" =>
  805.                    {
  806.                        let text = read_strn(file, len);
  807.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  808.                    }
  809.                    "DATA" =>
  810.                    {
  811.                        let flags = read_u32(file);
  812.                        let grid_x = read_u32(file);
  813.                        let grid_y = read_u32(file);
  814.                        data = format!(r#"["{}", {}, {}, {}]"#, escape_string(&name), flags, grid_x, grid_y);
  815.                    }
  816.                    unknown =>
  817.                    {
  818.                        panic!("unknown sub record `{}` in parent record `{}` around `{:08X}`", name, parent_name, ftell(file));
  819.                    }
  820.                }
  821.            }
  822.            "CELL_sub" =>
  823.            {
  824.                match name.as_str()
  825.                {
  826.                    "NAME" | "DNAM" | "KNAM" | "TNAM" | "UNAM" | "ANAM" | "BNAM" | "XSOL" | "CNAM" | "INAM" | "RGNN" =>
  827.                    {
  828.                        let text = read_strn(file, len);
  829.                        data = format!(r#"["{}", "{}"]"#, escape_string(&name), escape_string(&text));
  830.                    }
  831.                    "NAM0" => // should belong to CELL but i don't care
  832.                     {
  833.                         let val = read_u32(file);
  834.                         data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  835.                     }
  836.                     "FRMR" | "DELE" | "FLTV" | "INTV" | "INDX" =>
  837.                     {
  838.                         let val = read_u32(file);
  839.                         data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  840.                     }
  841.                     "XSCL" | "XCHG" =>
  842.                     {
  843.                         let val = read_f32(file);
  844.                         data = format!(r#"["{}", {}]"#, escape_string(&name), val);
  845.                     }
  846.                     "DODT" | "DATA" | "XHLT" =>
  847.                     {
  848.                         let x_pos = read_f32(file);
  849.                         let y_pos = read_f32(file);
  850.                         let z_pos = read_f32(file);
  851.                         let x_rot = read_f32(file);
  852.                         let y_rot = read_f32(file);
  853.                         let z_rot = read_f32(file);
  854.                         data = format!(r#"["{}", {}, {}, {}, {}, {}, {}]"#, escape_string(&name), x_pos, y_pos, z_pos, x_rot, y_rot, z_rot);
  855.                     }
  856.                     ignored =>
  857.                     {
  858.                         while ftell(file) < start+len+8
  859.                         {
  860.                             read_u8(file);
  861.                         }
  862.                         data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  863.                     }
  864.                     unknown =>
  865.                     {
  866.                         panic!("unknown sub record `{}` in parent record `{}` around `{:08X}`", name, parent_name, ftell(file));
  867.                     }
  868.                 }
  869.             }
  870.             ignored =>
  871.             {
  872.                 match name.as_str()
  873.                 {
  874.                     ignored =>
  875.                     {
  876.                         while ftell(file) < start+len+8
  877.                         {
  878.                             read_u8(file);
  879.                         }
  880.                         data = format!(r#"["{} (ignored)"]"#, escape_string(&name));
  881.                     }
  882.                     unknown =>
  883.                     {
  884.                         panic!("unknown sub record `{}` in parent record `{}`", name, parent_name);
  885.                     }
  886.                 }
  887.             }
  888.             unknown =>
  889.             {
  890.                 panic!("unknown parent record `{}`", parent_name);
  891.             }
  892.         }
  893.        
  894.         assert!(ftell(file) <= stopat, "{} {:08X} {:08X} {:08X}", parent_name, startat, stopat, ftell(file));
  895.        
  896.         let ret = SubRecord{name, data, special};
  897.        
  898.         //println!("{:?}", ret);
  899.        
  900.         ret
  901.     }
  902. }
  903.  
  904. #[derive(Clone)]
  905. #[derive(Debug)]
  906. struct Record
  907. {
  908.     name : String,
  909.     len : u32,
  910.     flags : u32,
  911.     sub : Vec<SubRecord>
  912. }
  913. impl Record
  914. {
  915.     fn to_string(&self) -> String
  916.     {
  917.         let mut substrings = Vec::<String>::new();
  918.        
  919.         for sub in &self.sub
  920.         {
  921.             substrings.push(sub.to_string());
  922.         }
  923.        
  924.         return format!("[\"{}\", [\n {}]]", escape_string(&self.name), substrings.join(",\n "));
  925.     }
  926.     fn read(file : &mut File) -> Record
  927.     {
  928.         let mut name : String;
  929.         let mut len : u32;
  930.         let mut unk : u32;
  931.         let mut flags : u32;
  932.        
  933.         name = read_strn(file, 4);
  934.         len = read_u32(file);
  935.         unk = read_u32(file);
  936.         flags = read_u32(file);
  937.        
  938.         let start = ftell(file);
  939.         let end = start + len;
  940.        
  941.         let mut sub = Vec::new();
  942.        
  943.         let mut virt_name = name.clone();
  944.        
  945.         let mut count = 0;
  946.        
  947.         while ftell(file) < end
  948.         {
  949.             sub.push(SubRecord::read(file, &virt_name, "", start, end));
  950.             count += 1;
  951.             if virt_name == "CELL" && count >= 2
  952.             {
  953.                 virt_name = "CELL_sub".to_string();
  954.             }
  955.         }
  956.         /*
  957.         match name.as_str()
  958.         {
  959.             "TES3" =>
  960.             {
  961.                 sub.push(SubRecord::read(file, &name, "HEDR", start, end));
  962.                 while ftell(file) < end
  963.                 {
  964.                     sub.push(SubRecord::read(file, &name, "MAST", start, end));
  965.                     sub.push(SubRecord::read(file, &name, "DATA", start, end));
  966.                 }
  967.             }
  968.             "GMST" =>
  969.             {
  970.                 sub.push(SubRecord::read(file, &name, "NAME", start, end));
  971.                 if ftell(file) < end
  972.                 {
  973.                     sub.push(SubRecord::read(file, &name, "", start, end));
  974.                 }
  975.             }
  976.             "GLOB" =>
  977.             {
  978.                 sub.push(SubRecord::read(file, &name, "NAME", start, end));
  979.                 sub.push(SubRecord::read(file, &name, "FNAM", start, end));
  980.                 //sub.push(SubRecord::read(file, &name, "FLTV", start, end)); // handled virtually by GLOB:FNAM
  981.             }
  982.             "CLAS" =>
  983.             {
  984.                 sub.push(SubRecord::read(file, &name, "NAME", start, end));
  985.                 sub.push(SubRecord::read(file, &name, "FNAM", start, end));
  986.                 sub.push(SubRecord::read(file, &name, "CLDT", start, end));
  987.                 if ftell(file) < end
  988.                 {
  989.                     sub.push(SubRecord::read(file, &name, "DESC", start, end));
  990.                 }
  991.             }
  992.             "FACT" =>
  993.             {
  994.                 sub.push(SubRecord::read(file, &name, "NAME", start, end));
  995.                 sub.push(SubRecord::read(file, &name, "FNAM", start, end));
  996.                 while ftell(file) < end
  997.                 {
  998.                     sub.push(SubRecord::read(file, &name, "", start, end));
  999.                 }
  1000.             }
  1001.             "RACE" =>
  1002.             {
  1003.                 sub.push(SubRecord::read(file, &name, "NAME", start, end));
  1004.                 sub.push(SubRecord::read(file, &name, "FNAM", start, end));
  1005.                 while ftell(file) < end
  1006.                 {
  1007.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1008.                 }
  1009.             }
  1010.             "SOUN" =>
  1011.             {
  1012.                 sub.push(SubRecord::read(file, &name, "NAME", start, end));
  1013.                 sub.push(SubRecord::read(file, &name, "FNAM", start, end));
  1014.                 sub.push(SubRecord::read(file, &name, "DATA", start, end));
  1015.             }
  1016.             "SKIL" =>
  1017.             {
  1018.                 sub.push(SubRecord::read(file, &name, "INDX", start, end));
  1019.                 sub.push(SubRecord::read(file, &name, "SKDT", start, end));
  1020.                 sub.push(SubRecord::read(file, &name, "DESC", start, end));
  1021.             }
  1022.             "MGEF" =>
  1023.             {
  1024.                 sub.push(SubRecord::read(file, &name, "INDX", start, end));
  1025.                 sub.push(SubRecord::read(file, &name, "MEDT", start, end));
  1026.                 while ftell(file) < end
  1027.                 {
  1028.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1029.                 }
  1030.             }
  1031.             "SCPT" =>
  1032.             {
  1033.                 while ftell(file) < end
  1034.                 {
  1035.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1036.                 }
  1037.             }
  1038.             "REGN" =>
  1039.             {
  1040.                 while ftell(file) < end
  1041.                 {
  1042.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1043.                 }
  1044.             }
  1045.             "BSGN" =>
  1046.             {
  1047.                 while ftell(file) < end
  1048.                 {
  1049.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1050.                 }
  1051.             }
  1052.             "LTEX" =>
  1053.             {
  1054.                 while ftell(file) < end
  1055.                 {
  1056.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1057.                 }
  1058.             }
  1059.             "STAT" =>
  1060.             {
  1061.                 while ftell(file) < end
  1062.                 {
  1063.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1064.                 }
  1065.             }
  1066.             "DOOR" =>
  1067.             {
  1068.                 while ftell(file) < end
  1069.                 {
  1070.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1071.                 }
  1072.             }
  1073.             "MISC" =>
  1074.             {
  1075.                 while ftell(file) < end
  1076.                 {
  1077.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1078.                 }
  1079.             }
  1080.             "WEAP" =>
  1081.             {
  1082.                 while ftell(file) < end
  1083.                 {
  1084.                     sub.push(SubRecord::read(file, &name, "", start, end));
  1085.                 }
  1086.             }
  1087.             unknown =>
  1088.             {
  1089.                 panic!("unknown parent record `{}`", unknown);
  1090.             }
  1091.         }
  1092.         */
  1093.        
  1094.         assert!(ftell(file) == end);
  1095.        
  1096.         Record{name, len, flags, sub}
  1097.     }
  1098. }
  1099.  
  1100. fn all_records(file : &mut File) -> Vec<Record>
  1101. {
  1102.     let mut ret = Vec::new();
  1103.    
  1104.     let head_record = Record::read(file);
  1105.    
  1106.     assert!(head_record.name == "TES3");
  1107.    
  1108.     let count = head_record.sub.first().unwrap().special.unwrap();
  1109.    
  1110.     ret.push(head_record);
  1111.     for _ in 0..count
  1112.     {
  1113.         ret.push(Record::read(file));
  1114.     }
  1115.    
  1116.     ret
  1117. }
  1118.  
  1119. //fn stringify_record_list(vec : &Vec<Record>) -> String
  1120. //{
  1121. //    let mut substrings = Vec::<String>::new();
  1122. //    
  1123. //    for sub in &vec
  1124. //    {
  1125. //        substrings.push(sub.to_string());
  1126. //    }
  1127. //    
  1128. //    return format!("[{}]", substrings.join(","));
  1129. //}
  1130.  
  1131. fn main()
  1132. {
  1133.     let args: Vec<String> = env::args().collect();
  1134.     if args.len() != 2
  1135.     {
  1136.         println!("usage:\n./mwdump fname.(esm|esp)");
  1137.     }
  1138.     else
  1139.     {
  1140.         let recs = all_records(&mut File::open(&args[1]).unwrap());
  1141.         println!("[");
  1142.         for i in 0..recs.len()
  1143.         {
  1144.             print!("{}", recs[i].to_string());
  1145.             if i+1 < recs.len()
  1146.             {
  1147.                 println!(",");
  1148.             }
  1149.             else
  1150.             {
  1151.                 println!("");
  1152.             }
  1153.         }
  1154.         println!("]");
  1155.     }
  1156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement