diff --git a/README.md b/README.md index 1a397cc..8bb321d 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,10 @@ Options: **Used in:** Funai & Funai-made Philips TVs (USA market) **Notes:** **Depends on keys** - see keys.rs (most common keys should be included). +## GX DVB +**Used in:** Cheap NationalChip GX-based DVB tuners +**Notes:** None, all files should be supported + ## INVINCIBLE_IMAGE **Used in:** LG Broadcom-based Blu-Ray players **Notes:** Only version 3 is supported (2011+) diff --git a/src/formats.rs b/src/formats.rs index 047d930..f833c4a 100644 --- a/src/formats.rs +++ b/src/formats.rs @@ -29,6 +29,7 @@ pub mod amlogic; pub mod sdboot; pub mod sdimage; pub mod cd5; +pub mod gx_dvb; pub mod pup; @@ -220,6 +221,11 @@ pub fn get_registry() -> Vec { detector_func: crate::formats::cd5::is_cd5_file, extractor_func: crate::formats::cd5::extract_cd5, }, + Format { + name: "gx_dvb", + detector_func: crate::formats::gx_dvb::is_gx_dvb_file, + extractor_func: crate::formats::gx_dvb::extract_gx_dvb, + }, ] } \ No newline at end of file diff --git a/src/formats/gx_dvb/include.rs b/src/formats/gx_dvb/include.rs new file mode 100644 index 0000000..9293d11 --- /dev/null +++ b/src/formats/gx_dvb/include.rs @@ -0,0 +1,25 @@ +use crate::utils::common; +use binrw::BinRead; + +pub static TABLE_OFFSET: u64 = 0x20000; + +#[derive(BinRead)] +pub struct PartTable { + _magic_bytes: [u8;4], + pub part_count: u8, + #[br(count=part_count)] pub part_entries: Vec, +} + +#[derive(BinRead)] +pub struct PartEntry { + name_bytes: [u8; 8], + pub total_size: u32, + pub used_size: u32, + pub start: u32, //offset + _flags: u32, +} +impl PartEntry { + pub fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} \ No newline at end of file diff --git a/src/formats/gx_dvb/mod.rs b/src/formats/gx_dvb/mod.rs new file mode 100644 index 0000000..ed9e974 --- /dev/null +++ b/src/formats/gx_dvb/mod.rs @@ -0,0 +1,46 @@ +mod include; +use std::any::Any; +use std::fs::{self, OpenOptions}; +use std::io::{Seek, SeekFrom, Write}; +use std::path::Path; +use crate::AppContext; + +use crate::utils::common; +use binrw::BinReaderExt; +use include::*; + +pub fn is_gx_dvb_file(app_ctx: &AppContext) -> Result>, Box> { + let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)}; + + let table_magic = common::read_file(&file, TABLE_OFFSET, 4)?; + if table_magic == b"\xAA\xBC\xDE\xFA" { + Ok(Some(Box::new(()))) + } else { + Ok(None) + } +} + +pub fn extract_gx_dvb(app_ctx: &AppContext, _ctx: Box) -> Result<(), Box> { + let mut file = app_ctx.file().ok_or("Extractor expected file")?; + + file.seek(SeekFrom::Start(TABLE_OFFSET))?; + let table: PartTable = file.read_be()?; + + println!("Part count: {}", table.part_count); + + for (i, part) in table.part_entries.iter().enumerate() { + println!("\n({}/{}) - {}, Offset: {}, Total size: {}, Used size: {}", + i+1, table.part_count, part.name(), part.start, part.total_size, part.used_size); + + let data = common::read_file(&file, part.start as u64, part.total_size as usize)?; + + let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", part.name())); + fs::create_dir_all(&app_ctx.output_dir)?; + let mut out_file = OpenOptions::new().write(true).create(true).open(output_path)?; + out_file.write_all(&data)?; + + println!("- Saved file!"); + } + + Ok(()) +} \ No newline at end of file