From c93c18833c955c79be5e0f7b6d5f9a281d7a0708 Mon Sep 17 00:00:00 2001 From: theubusu <80545678+theubusu@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:05:51 +0100 Subject: [PATCH] add funai_bdp extractor --- README.md | 4 ++ src/formats.rs | 6 +++ src/formats/funai_bdp/include.rs | 17 ++++++++ src/formats/funai_bdp/mod.rs | 63 ++++++++++++++++++++++++++++++ src/formats/funai_upg/funai_des.rs | 2 +- 5 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/formats/funai_bdp/include.rs create mode 100644 src/formats/funai_bdp/mod.rs diff --git a/README.md b/README.md index b151d1d..b040e71 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,10 @@ Options: **Notes:** **Depends on keys** - see keys.rs **Thanks to:** https://github.com/openlgtv/epk2extract +## Funai BDP +**Used in:** Funai & Funai-made Philips Blu-Ray player/HTS (USA market) +**Notes:** N/A + ## Funai UPG **Used in:** Some Funai TVs **Notes:** **Depends on keys** - see keys.rs. diff --git a/src/formats.rs b/src/formats.rs index f1674e2..268653a 100644 --- a/src/formats.rs +++ b/src/formats.rs @@ -21,6 +21,7 @@ pub mod sony_bdp; pub mod rvp; pub mod funai_upg; pub mod funai_upg_phl; +pub mod funai_bdp; pub mod pana_dvd; pub mod android_ota_payload; pub mod bdl; @@ -116,6 +117,11 @@ pub fn get_registry() -> Vec { detector_func: crate::formats::funai_upg_phl::is_funai_upg_phl_file, extractor_func: crate::formats::funai_upg_phl::extract_funai_upg_phl, }, + Format { + name: "funai_bdp", + detector_func: crate::formats::funai_bdp::is_funai_bdp_file, + extractor_func: crate::formats::funai_bdp::extract_funai_bdp, + }, Format { name: "pana_dvd", detector_func: crate::formats::pana_dvd::is_pana_dvd_file, diff --git a/src/formats/funai_bdp/include.rs b/src/formats/funai_bdp/include.rs new file mode 100644 index 0000000..07183ad --- /dev/null +++ b/src/formats/funai_bdp/include.rs @@ -0,0 +1,17 @@ +use binrw::BinRead; +use crate::utils::common; + +pub static DEC_KEY: u32 = 0x13641A98; + +#[derive(BinRead)] +pub struct IndexTableEntry { + name_bytes: [u8; 32], + pub offset: u32, + pub size: u32, + _unk: u32, +} +impl IndexTableEntry { + pub fn name(&self) -> String { + common::string_from_bytes(&self.name_bytes) + } +} \ No newline at end of file diff --git a/src/formats/funai_bdp/mod.rs b/src/formats/funai_bdp/mod.rs new file mode 100644 index 0000000..92b0e8c --- /dev/null +++ b/src/formats/funai_bdp/mod.rs @@ -0,0 +1,63 @@ +mod include; +use std::any::Any; +use crate::AppContext; + +use std::path::Path; +use std::fs::{self, OpenOptions}; +use std::io::{Cursor, Read, Seek, SeekFrom, Write}; +use binrw::BinReaderExt; + +use crate::utils::common; +use crate::formats::funai_upg::funai_des::funai_des_decrypt; +use include::*; + +pub fn is_funai_bdp_file(app_ctx: &AppContext) -> Result>, Box> { + let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)}; + let header = common::read_file(&file, 0, 16)?; + let dec_header = funai_des_decrypt(&header, DEC_KEY); + + if dec_header == b"index_table\x00\x00\x00\x00\x00"{ + Ok(Some(Box::new(()))) + } else { + Ok(None) + } +} + +pub fn extract_funai_bdp(app_ctx: &AppContext, _ctx: Box) -> Result<(), Box> { + let mut file = app_ctx.file().ok_or("Extractor expected file")?; + + let mut data = Vec::new(); //to decrypt entire file + file.read_to_end(&mut data)?; + + println!("Decrypting file..."); + data = funai_des_decrypt(&data, DEC_KEY); + let mut file_reader = Cursor::new(data); + + file_reader.seek(SeekFrom::Start(0x20))?; + + let index_entry_count: u32 = file_reader.read_le()?; + let mut entries: Vec = Vec::new(); + + for _i in 0..index_entry_count { + let entry: IndexTableEntry = file_reader.read_le()?; + entries.push(entry); + } + + for (i, entry) in entries.iter().enumerate() { + println!("\n({}/{}) - {}, Offset: {}, Size: {}", i +1, index_entry_count, entry.name(), entry.offset, entry.size); + + //at start of location there is an additional 0x20 with the entry's name + file_reader.seek(SeekFrom::Start(entry.offset as u64 + 0x20))?; + let data = common::read_exact(&mut file_reader, entry.size as usize - 0x20)?; + + let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", entry.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 diff --git a/src/formats/funai_upg/funai_des.rs b/src/formats/funai_upg/funai_des.rs index d01af96..7abb89b 100644 --- a/src/formats/funai_upg/funai_des.rs +++ b/src/formats/funai_upg/funai_des.rs @@ -34,7 +34,7 @@ fn des_function(mut state: u32, key: u32) -> u32 { } pub fn funai_des_decrypt(input: &[u8], key: u32) -> Vec { - assert!(input.len() % 8 == 0); + //assert!(input.len() % 8 == 0); let mut buf = input.to_vec(); for chunk in buf.chunks_exact_mut(8) {