This commit is contained in:
Pedro de Oliveira 2022-11-08 02:52:33 +00:00
parent 785eb00f46
commit 7c2f95ff78
3 changed files with 262 additions and 32 deletions

146
Cargo.lock generated
View File

@ -3,14 +3,152 @@
version = 3
[[package]]
name = "byteorder"
version = "1.4.3"
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "clap"
version = "4.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91b9970d7505127a162fdaa9b96428d28a479ba78c9ec7550a63a5d9863db682"
dependencies = [
"atty",
"bitflags",
"clap_lex",
"once_cell",
"strsim",
"termcolor",
]
[[package]]
name = "clap_lex"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "itoa"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "libc"
version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
[[package]]
name = "losteden"
version = "0.1.0"
dependencies = [
"byteorder",
"clap",
"serde",
"serde_json",
]
[[package]]
name = "once_cell"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "os_str_bytes"
version = "6.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.147"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
[[package]]
name = "serde_json"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -6,4 +6,6 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
byteorder = "1.4.3"
clap = { version = "4.0.22", features = ["cargo"] }
serde = "1.0.147"
serde_json = "1.0.87"

View File

@ -1,9 +1,6 @@
use std::fs::File;
use std::io::{Read, Seek, Write};
// https://gist.github.com/falsovsky/da9a2de2c9a65282527fbd462bd92914
// https://github.com/scummvm/scummvm/blob/90f2ff2532ca71033b4393b9ce604c9b0e6cafa0/engines/cryo/defs.h#L761
// https://github.com/scummvm/scummvm/blob/master/engines/cryo/resource.cpp#L73
use std::fs;
use std::io::{BufWriter, Read, Seek, SeekFrom, Write};
#[derive(Debug)]
struct DatHeader {
@ -12,8 +9,22 @@ struct DatHeader {
}
impl DatHeader {
fn new(total: u16) -> Self {
Self { total, files: Vec::new() }
fn new(filename: &str) -> Self {
let mut f = File::open(filename).unwrap();
// Read Total Files
let mut file_dat: [u8; 2] = [0; 2];
let _ = f.read(&mut file_dat);
let mut result = DatHeader::from_bytes(file_dat);
for _ in 0..result.total {
let mut file_dat: [u8; 25] = [0; 25];
let _ = f.read(&mut file_dat);
if file_dat[0] == 0 {
continue
}
let my_file = DatFile::from_bytes(file_dat);
result.files.push(my_file);
}
result
}
fn from_bytes(buffer: [u8; 2]) -> Self {
@ -69,33 +80,112 @@ impl DatFile {
}
}
fn main() -> std::io::Result<()> {
let mut f = File::open("EDEN.DAT")?;
// Read Total Files
let mut file_dat: [u8; 2] = [0; 2];
let _ = f.read(&mut file_dat);
let mut dat = DatHeader::from_bytes(file_dat);
println!("Valor: {:?} - Hex: {:02X?}", dat.total, dat.to_bytes());
for _ in 0..dat.total {
let mut file_dat: [u8; 25] = [0; 25];
let _ = f.read(&mut file_dat);
if file_dat[0] == 0 {
continue
}
let my_file = DatFile::from_bytes(file_dat);
println!("{:?} - {:02X?}", my_file, my_file.to_bytes());
dat.files.push(my_file);
}
let mut f = File::create("NOVO.DAT")?;
let _ = f.write(&dat.to_bytes());
for file in dat.files {
let _ = f.write(&file.to_bytes());
}
Ok(())
#[derive(Debug)]
struct JsonFile {
name: String,
padding: u32,
}
fn extract_file(rec: &DatFile) {
let mut source = File::open("EDEN.DAT").unwrap();
let _ = source.seek(SeekFrom::Start(rec.offset as u64)).unwrap();
let filename = format!("extract/{}", rec.name);
let mut destination = File::create(filename).unwrap();
let mut contents: Vec<u8> = Vec::new();
let _ = source.take(rec.size as u64).read_to_end(&mut contents);
let _ = destination.write(&*contents);
}
fn create_json(dat: &DatHeader) {
let mut file_list: Vec<String> = Vec::new();
for f in &dat.files {
file_list.push(format!("extract/{}", f.name.clone()));
}
let mut w = BufWriter::new(File::create("list.json").unwrap());
serde_json::to_writer_pretty(&mut w, &file_list).unwrap();
w.flush().unwrap();
}
fn read_json() -> Vec<String> {
let data = fs::read_to_string("list.json").expect("Unable to read file");
serde_json::from_str(&data).expect("Unable to parse")
}
fn create_dat(files: Vec<String>) {
let mut f = File::create("NOVO.DAT").unwrap();
let dat: DatHeader = DatHeader { total: 2621, files: Vec::new() };
let _ = f.write(&dat.to_bytes());
let mut jsonfiles : Vec<JsonFile> = Vec::new();
let mut address: i32 = 65536;
for file in files {
// Obter tamanho do ficheiro
let file_size: i32 = fs::metadata(&file).unwrap().len() as i32;
// Separar o Nome da Path
let split: Vec<_> = file.split('/').collect();
let file_name = split[1].clone();
// Gravar info da Header
let datfile = DatFile::new(file_name.to_string(), file_size as u32, address as u32, 0);
let _ = f.write(&datfile.to_bytes());
// Ver se o final do ficheiro está alinhado a 16
address += file_size;
address += (-address).checked_rem_euclid(16).unwrap();
jsonfiles.push(JsonFile { name: file.to_string(), padding: address as u32 });
}
// Preencher ate 65535 com 0
let new_position = f.seek(SeekFrom::Current(0)).unwrap();
if new_position < 65536 {
for _ in new_position..65536 {
let _ = f.write(&[0]);
}
}
// Gravar conteudo dos ficheiros no DAT
for file in jsonfiles {
let mut source = File::open(file.name).unwrap();
let mut contents: Vec<u8> = Vec::new();
let _ = source.read_to_end(&mut contents);
let _ = f.write(&*contents);
let current_position= f.seek(SeekFrom::Current(0)).unwrap() as u32;
if current_position < file.padding {
for _ in current_position..file.padding {
let _ = f.write(&[0]);
}
}
}
}
fn main() {
let cmd = clap::Command::new(env!("CARGO_CRATE_NAME"))
.multicall(false)
.arg_required_else_help(true)
.subcommand_value_name("COMMAND")
.subcommand_help_heading("COMMAND")
.subcommand(clap::Command::new("extract").about("Extracts all files from EDEN.DAT"))
.subcommand(
clap::Command::new("json").about("Creates a JSON with the list of files inside EDEN.DAT")
)
.subcommand(clap::Command::new("generate").about("Creates a new EDEN.DAT based on list.json"));
match cmd.get_matches().subcommand_name() {
Some("extract") => {
let dat = DatHeader::new("EDEN.DAT");
for f in dat.files {
extract_file(&f);
println!("Extracting {} - Size: {}, Offset: {}", &f.name, &f.size, &f.offset)
}
}
Some("json") => {
let dat = DatHeader::new("EDEN.DAT");
create_json(&dat);
println!("Created {}", "list.json");
}
Some("generate") => {
let files = read_json();
create_dat(files);
}
_ => unreachable!("parser should ensure only valid subcommand names are used"),
}
}