|
1 | 1 | use clap::Parser;
|
2 | 2 | use fang::{
|
3 |
| - mst::{entry::Entry, Mst, MstVersionKnown}, |
4 |
| - BinReaderExt, BinWriterExt, |
| 3 | + mst::{builder::MstBuilder, entry::Entry, Mst, MstVersionKnown}, |
| 4 | + BinReaderExt, |
5 | 5 | };
|
6 | 6 | use std::{
|
7 |
| - cell::RefCell, |
8 | 7 | fs::File,
|
9 |
| - io::{BufReader, BufWriter, Read, Seek, SeekFrom, Write}, |
| 8 | + io::{BufReader, BufWriter}, |
10 | 9 | path::Path,
|
11 |
| - rc::Rc, |
12 | 10 | };
|
13 | 11 |
|
14 | 12 | #[derive(Parser, Debug)]
|
15 | 13 | pub struct ConvertOpts {
|
16 | 14 | /// Path to MST
|
17 | 15 | #[clap(short = 'i', long)]
|
18 | 16 | input_path: String,
|
19 |
| - /// New major version |
20 |
| - #[clap(long)] |
21 |
| - major: Option<u8>, |
22 | 17 | /// New minor version
|
23 | 18 | #[clap(long)]
|
24 | 19 | minor: Option<u8>,
|
25 | 20 | }
|
26 | 21 |
|
27 | 22 | pub fn convert_mst(opts: ConvertOpts) -> anyhow::Result<()> {
|
| 23 | + // Parse the source Mst from input_path |
28 | 24 | let mut in_file = BufReader::new(File::open(&opts.input_path)?);
|
| 25 | + let mst = in_file.read_le::<Mst>()?; |
29 | 26 |
|
30 |
| - let mut mst = in_file.read_le::<Mst>()?; |
31 |
| - |
32 |
| - let mut content_bufs = Vec::new(); |
33 |
| - for entry in mst.collect_entries() { |
34 |
| - in_file.seek(SeekFrom::Start(entry.offset() as u64))?; |
35 |
| - |
36 |
| - let mut buf = vec![0u8; entry.size()]; |
37 |
| - in_file.read_exact(&mut buf)?; |
38 |
| - content_bufs.push(buf); |
39 |
| - } |
40 |
| - |
41 |
| - let out_path = Path::new(&opts.input_path).with_extension("convert.mst"); |
42 |
| - let mut out_file = BufWriter::new(File::create(&out_path)?); |
| 27 | + // Prepare a new Mst, copying the versions and platform |
| 28 | + let mut mst_builder = MstBuilder::from_mst_empty(&mst)?; |
43 | 29 |
|
| 30 | + // Update the Mst version with given minor version (6, 7, 8) |
44 | 31 | let mut new_mst_version = *mst.body.version();
|
45 |
| - new_mst_version.set_major(opts.major.unwrap_or_else(|| new_mst_version.major())); |
46 | 32 | new_mst_version.set_minor(opts.minor.unwrap_or_else(|| new_mst_version.minor()));
|
47 | 33 | let new_version = MstVersionKnown::try_from(&new_mst_version)?;
|
48 | 34 |
|
49 |
| - mst.body = mst.body.convert(new_version); |
50 |
| - |
51 |
| - let content_offset_offsets = Rc::new(RefCell::new(Vec::new())); |
| 35 | + mst_builder.set_version(&new_version); |
52 | 36 |
|
53 |
| - out_file.write_le_args(&mst, (content_offset_offsets.clone(),))?; |
54 |
| - |
55 |
| - let mut content_offsets = Vec::new(); |
56 |
| - for content_buf in content_bufs { |
57 |
| - let mut pos = out_file.stream_position()?; |
58 |
| - if pos % 2048 > 0 { |
59 |
| - let padding = 2048 - pos % 2048; |
60 |
| - let padding = vec![0u8; padding as usize]; |
61 |
| - out_file.write_all(&padding)?; |
62 |
| - pos = out_file.stream_position()?; |
63 |
| - } |
64 |
| - |
65 |
| - content_offsets.push(pos); |
66 |
| - out_file.write_all(&content_buf)?; |
67 |
| - } |
68 |
| - |
69 |
| - if let Some(min_data_offset) = content_offsets.iter().min() { |
70 |
| - out_file.seek(SeekFrom::Start(28))?; |
71 |
| - |
72 |
| - let offset = *min_data_offset as u32; |
73 |
| - if mst.identifier.is_little() { |
74 |
| - out_file.write_all(&offset.to_le_bytes())?; |
75 |
| - } else { |
76 |
| - out_file.write_all(&offset.to_be_bytes())?; |
77 |
| - } |
| 37 | + // Add all the entries from the source Mst as references |
| 38 | + for entry in mst.collect_entries() { |
| 39 | + mst_builder.add_entry_file( |
| 40 | + entry.filename().to_string(), |
| 41 | + opts.input_path.clone(), |
| 42 | + entry.offset(), |
| 43 | + entry.size(), |
| 44 | + ); |
78 | 45 | }
|
79 | 46 |
|
80 |
| - for (pos, offset) in content_offset_offsets.borrow().iter().zip(content_offsets) { |
81 |
| - out_file.seek(SeekFrom::Start(*pos))?; |
| 47 | + // Finalize and write the Mst with contents to input_path.convert.mst |
| 48 | + let out_path = Path::new(&opts.input_path).with_extension("convert.mst"); |
| 49 | + let mut out_file = BufWriter::new(File::create(&out_path)?); |
82 | 50 |
|
83 |
| - let offset = offset as u32; |
84 |
| - if mst.identifier.is_little() { |
85 |
| - out_file.write_all(&offset.to_le_bytes())?; |
86 |
| - } else { |
87 |
| - out_file.write_all(&offset.to_be_bytes())?; |
88 |
| - } |
89 |
| - } |
| 51 | + mst_builder.write(&mut out_file)?; |
90 | 52 |
|
91 | 53 | Ok(())
|
92 | 54 | }
|
0 commit comments