Skip to content

Commit

Permalink
Merge pull request #3 from ieee802dot11ac/main
Browse files Browse the repository at this point in the history
Initial multitool work
  • Loading branch information
DarkRTA authored Jan 15, 2024
2 parents e5c7c8e + 5dfe7a7 commit c51f5f6
Show file tree
Hide file tree
Showing 9 changed files with 364 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
resolver = "2"

members = [
"crates/dtacheck",
"crates/dtacheck", "crates/milo",
"crates/swap_art_bytes",
]

Expand Down
13 changes: 13 additions & 0 deletions crates/milo/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "milo"
version = "0.1.0"
edition = "2021"
publish = false

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
byteorder = "1.5.0"
clap = { version = "4.4.16", features = ["derive"] }
flate2 = "1.0.28"
tempfile = "3.9.0"
34 changes: 34 additions & 0 deletions crates/milo/src/ark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::error::Error;
use std::fs::File;

use crate::fio::read_u32;
use crate::traits::Load;
pub mod amp;
pub mod freq;

pub enum ArkTypes {
FreqArk(freq::FreqArchive),
AmpArk(amp::AmpArchive),
}

pub fn load_ark_file(f: &mut File) -> Result<ArkTypes, Box<dyn Error>> {
let vercheck = read_u32(f, true)?;
let ark: ArkTypes;
match vercheck {
0x004B5241 => {
let mut freq = freq::FreqArchive::new();
freq.load(f, 0)?;
ark = ArkTypes::FreqArk(freq);
}
0..=2 => {
let mut amp = amp::AmpArchive::new();
amp.load(f, 0)?;
ark = ArkTypes::AmpArk(amp);
}
_ => {
println!("unrecognized ark version. if gh1 or later, use the .hdr and not the .ark");
return Err::<_, Box<dyn Error>>("unkver".into());
}
}
Ok(ark)
}
116 changes: 116 additions & 0 deletions crates/milo/src/ark/amp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use std::fmt::{Formatter, Display};
use std::error::Error;

use crate::traits::Load;
use crate::fio;

#[derive(Clone, Copy)]
struct AmpFileEntry {
offset: u32,
file_name_idx: u32,
folder_name_idx: u32,
size: u32,
inflated_size: u32,
}

impl AmpFileEntry {
pub fn new() -> Self {
Self {
offset: 0,
file_name_idx: 0,
folder_name_idx: 0,
size: 0,
inflated_size: 0,
}
}
}

impl Load for AmpFileEntry {
fn load(&mut self, f: &mut std::fs::File, ver: u32) -> Result<(), Box<dyn std::error::Error>> {
if ver != 1 {self.offset = fio::read_u32(f, true)?;}
self.file_name_idx = fio::read_u32(f, true)?;
self.folder_name_idx = fio::read_u32(f, true)?;
if ver == 1 {self.offset = fio::read_u32(f, true)?;}
self.size = fio::read_u32(f, true)?;
self.inflated_size = fio::read_u32(f, true)?;
Ok(())
}
}

impl Display for AmpFileEntry {
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
fmt.write_fmt(format_args!("Offset: {}", self.offset))?;
fmt.write_fmt(format_args!("File name index: {}", self.file_name_idx))?;
fmt.write_fmt(format_args!("Folder name index: {}", self.folder_name_idx))?;
fmt.write_fmt(format_args!("Size: {}", self.size))?;
fmt.write_fmt(format_args!("Inflated size: {}", self.inflated_size))?;
Ok(())
}
}

pub struct AmpArchive {
version: u32,
entry_ct: u32,
entries: Vec<AmpFileEntry>,
str_table_size: u32,
string_table: Vec<String>,
string_idx_count: u32,
string_idx_entries: Vec<u32>
}

impl AmpArchive {
pub fn new() -> Self {
Self {
version: 0,
entry_ct: 0,
entries: vec![],
str_table_size: 0,
string_table: vec![],
string_idx_count: 0,
string_idx_entries: vec![]
}
}
}

impl Load for AmpArchive {
fn load(&mut self, f: &mut std::fs::File, _: u32) -> Result<(), Box<dyn Error>> {
self.version = fio::read_u32(f, true)?;
self.entry_ct = fio::read_u32(f, true)?;
for _ in 0..self.entry_ct {
let mut ent = AmpFileEntry::new();
ent.load(f, self.version)?;
self.entries.push(ent);
}
self.str_table_size = fio::read_u32(f, true)?;
for _ in 0..self.str_table_size {
let st = fio::readstr(f)?;
self.string_table.push(st);
}
self.string_idx_count = fio::read_u32(f, true)?;
for _ in 0..self.string_idx_count {
let idx = fio::read_u32(f, true)?;
self.string_idx_entries.push(idx);
}
Ok(())
}
}

impl Display for AmpArchive {
fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result {
fmt.write_fmt(format_args!("Version: {}", self.version))?;
fmt.write_str("BEGIN ENTRIES")?;
for ent in self.entries.clone() {
ent.fmt(fmt)?;
}
fmt.write_str("END ENTRIES")?;
fmt.write_fmt(format_args!("String table size: {}", self.str_table_size))?;
for i in 0..self.str_table_size {
fmt.write_fmt(format_args!("Entry {i}: {}", self.string_table[i as usize]))?;
}
fmt.write_fmt(format_args!("String index count: {}", self.string_idx_count))?;
for i in 0..self.string_idx_entries.len() {
fmt.write_fmt(format_args!("Index {i}: {}", self.string_idx_entries[i]))?;
}
Ok(())
}
}
109 changes: 109 additions & 0 deletions crates/milo/src/ark/freq.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
use crate::traits::Load;
use crate::fio;
use std::fmt::Display;
use std::fs::File;
use std::error::Error;

#[derive(Clone, Copy)]
struct FreqFileEntry { // 24 bytes
unknown: u32, // Path name hash?
file_name_offset: u32,
folder_name_index: u16,
block_offset: u16,
block: u32, // Use block * block_size + block_offset to get file position
file_size: u32,
inflated_size: u32, // Same as file size if not compressed
fake_file_offset: u32 // = (block * 2048) + block_offset;
}

impl Load for FreqFileEntry {
fn load(&mut self, f: &mut File, _: u32) -> Result<(), Box<dyn Error>> {
self.unknown = fio::read_u32(f, true)?;
self.file_name_offset = fio::read_u32(f, true)?;
self.folder_name_index = fio::read_u16(f, true)?;
self.block_offset = fio::read_u16(f, true)?;
self.block = fio::read_u32(f, true)?;
self.file_size = fio::read_u32(f, true)?;
self.inflated_size = fio::read_u32(f, true)?;
self.fake_file_offset = (self.block * 2048) + self.block_offset as u32;
Ok(())
}
}

impl Display for FreqFileEntry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("Unknown value (possibly a pathname hash?): {}", self.unknown))?;
f.write_fmt(format_args!("File name offset: {}", self.file_name_offset))?;
f.write_fmt(format_args!("Folder name index: {}", self.folder_name_index))?;
f.write_fmt(format_args!("Block offset: {}", self.block_offset))?;
f.write_fmt(format_args!("Block #: {}", self.block))?;
f.write_fmt(format_args!("File offset (calculated): {}", self.fake_file_offset))?;
f.write_fmt(format_args!("File size: {}", self.file_size))?;
f.write_fmt(format_args!("Inflated filesize: {}", self.inflated_size))?;
Ok(())
}
}

#[derive(Clone, Copy)]
pub struct FreqArchive {
magic: u32, // technically a char[4] but 0x204B5241 is easier to check
version: u32,
file_entry_offset: u32, // Always 256
file_entry_count: u32,
folder_entry_offset: u32,
folder_entry_count: u32,
string_table_offset: u32,
string_count: u32,
total_hdr_size: u32, // Size of header + string offsets + string table
block_size: u32, // Used for padding, always 2048?
}

impl FreqArchive {
pub fn new() -> Self {
Self {
magic: 0x204B5241,
version: 0,
file_entry_offset: 256,
file_entry_count: 0,
folder_entry_offset: 0,
folder_entry_count: 0,
string_table_offset: 0,
string_count: 0,
total_hdr_size: 40,
block_size: 2048
}
}
}

impl Load for FreqArchive {
fn load(&mut self, f: &mut File, _: u32) -> Result<(), Box<dyn Error>> {
self.magic = fio::read_u32(f, true)?;
self.version = fio::read_u32(f, true)?;
self.file_entry_offset = fio::read_u32(f, true)?;
self.file_entry_count = fio::read_u32(f, true)?;
self.folder_entry_offset = fio::read_u32(f, true)?;
self.folder_entry_count = fio::read_u32(f, true)?;
self.string_table_offset = fio::read_u32(f, true)?;
self.string_count = fio::read_u32(f, true)?;
self.total_hdr_size = fio::read_u32(f, true)?;
self.block_size = fio::read_u32(f, true)?;
Ok(())
}
}

impl Display for FreqArchive {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("Magic value: {:#010X} \n", self.magic))?;
f.write_fmt(format_args!("Should be 0x004B5241.\n"))?;
f.write_fmt(format_args!("Version: {}\n", self.version))?;
f.write_fmt(format_args!("File entry offset: {}\n", self.file_entry_offset))?;
f.write_fmt(format_args!("File entry count: {}\n", self.file_entry_count))?;
f.write_fmt(format_args!("Folder entry offset: {}\n", self.folder_entry_offset))?;
f.write_fmt(format_args!("Folder entry count: {}\n", self.folder_entry_count))?;
f.write_fmt(format_args!("String table offset: {}\n", self.string_table_offset))?;
f.write_fmt(format_args!("String count: {}\n", self.string_count))?;
f.write_fmt(format_args!("Total header size (includes string table): {}\n", self.total_hdr_size))?;
f.write_fmt(format_args!("Block size: {}\n", self.block_size))?;
Ok(())
}
}
52 changes: 52 additions & 0 deletions crates/milo/src/fio.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use std::fs::File;
use std::error::Error;
use std::io::Read;
use byteorder::{LittleEndian, BigEndian, ReadBytesExt};

fn readlen(f: &mut File, len: usize) -> Result<Vec<u8>, Box<dyn Error>> {
let mut buf = vec![0u8; len];
f.read_exact(&mut buf)?;
Ok(buf)
}

pub fn readstr(src: &mut File) -> Result<String, Box<dyn Error>> {
let mut ret: String = String::with_capacity(256);
for _ in 0..256 { // 256 is a good length limit, right
let asciidiot = readlen(src, 1)?[0];
if asciidiot == 0 {
ret.shrink_to_fit();
break
}
let test = char::from_u32(asciidiot as u32);
ret.push(test.expect("found eof"));
}
Ok(ret)
}

pub fn read_u32(f: &mut File, little_endian: bool) -> Result<u32, Box<dyn Error>> {
if little_endian { Ok(f.read_u32::<LittleEndian>()?) }
else { Ok(f.read_u32::<BigEndian>()?) }
}

pub fn read_i32(f: &mut File, little_endian: bool) -> Result<i32, Box<dyn Error>> {
if little_endian { Ok(f.read_i32::<LittleEndian>()?) }
else { Ok(f.read_i32::<BigEndian>()?) }
}

pub fn read_u16(f: &mut File, little_endian: bool) -> Result<u16, Box<dyn Error>> {
if little_endian { Ok(f.read_u16::<LittleEndian>()?) }
else { Ok(f.read_u16::<BigEndian>()?) }
}

pub fn read_i16(f: &mut File, little_endian: bool) -> Result<i16, Box<dyn Error>> {
if little_endian { Ok(f.read_i16::<LittleEndian>()?) }
else { Ok(f.read_i16::<BigEndian>()?) }
}

pub fn read_u8(f: &mut File) -> Result<u8, Box<dyn Error>> { Ok(f.read_u8()?) }
pub fn read_i8(f: &mut File) -> Result<i8, Box<dyn Error>> { Ok(f.read_i8()?) }

pub fn read_f32(f: &mut File, little_endian: bool) -> Result<f32, Box<dyn Error>> {
if little_endian { Ok(f.read_f32::<LittleEndian>()?) }
else { Ok(f.read_f32::<BigEndian>()?) }
}
3 changes: 3 additions & 0 deletions crates/milo/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod ark;
pub mod traits;
mod fio;
21 changes: 21 additions & 0 deletions crates/milo/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use std::fs::File;
use std::error::Error;
use std::path::PathBuf;
use clap::Parser;
use milo::ark;
use milo::traits::Load;

#[derive(clap::Parser)]
struct Args {
input: PathBuf,
}

fn main() -> Result<(), Box<dyn Error>> {
println!("Hello, world!");
let args = Args::parse();
let mut infile = File::open(args.input)?;
let mut freqindasheets = ark::freq::FreqArchive::new();
freqindasheets.load(&mut infile, 0)?;
println!("{}", freqindasheets);
Ok(())
}
15 changes: 15 additions & 0 deletions crates/milo/src/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use std::error::Error;
use std::fs::File;

pub trait Load {
fn load(&mut self, f: &mut File, ver: u32) -> Result<(), Box<dyn Error>>;
}

pub trait Save {
fn save(&mut self, f: &mut File) -> Result<(), Box<dyn Error>>;
}

pub trait Port {
fn import(&mut self, f: &mut File) -> Result<(), Box<dyn Error>>;
fn export(&mut self, f: &mut File) -> Result<(), Box<dyn Error>>;
}

0 comments on commit c51f5f6

Please sign in to comment.