improvements to slp

This commit is contained in:
theubusu
2026-04-09 22:23:55 +02:00
parent 8ac15ae011
commit 5cc00a773d
2 changed files with 109 additions and 58 deletions
+37 -25
View File
@@ -1,43 +1,55 @@
use crate::utils::common;
use binrw::BinRead;
#[derive(PartialEq, Eq, Debug)]
pub enum SlpVariant {
Old,
Old2,
New,
}
#[derive(BinRead)]
pub struct Header {
pub struct CommonMetaHeader {
_magic_bytes: [u8; 4],
version_bytes: [u8; 8],
model_bytes: [u8; 16],
firmware_bytes: [u8; 16],
_unk: u32,
check: [u8; 8],
_unk2: [u8; 8],
user_version_bytes: [u8; 8],
project_name_bytes: [u8; 16],
firmware_version_bytes: [u8; 16],
}
impl Header {
pub fn version(&self) -> String {
common::string_from_bytes(&self.version_bytes)
impl CommonMetaHeader {
pub fn user_version(&self) -> String {
common::string_from_bytes(&self.user_version_bytes)
}
pub fn model(&self) -> String {
common::string_from_bytes(&self.model_bytes)
pub fn project_name(&self) -> String {
common::string_from_bytes(&self.project_name_bytes)
}
pub fn firmware(&self) -> String {
common::string_from_bytes(&self.firmware_bytes)
}
pub fn is_new_type(&self) -> bool {
&self.check == b"\x01VER_PR1"
pub fn firmware_version(&self) -> String {
common::string_from_bytes(&self.firmware_version_bytes)
}
}
#[derive(BinRead)]
pub struct EntryOld {
pub size: u32,
pub _unk: u32,
pub offset: u32,
pub _unk2: u32,
pub struct MetaHeaderExtOld {
pub snapshot_included: u8,
pub snapshot_entry_offset: u32,
_unuse: [u8; 15]
}
#[derive(BinRead)]
pub struct EntryNew {
pub struct MetaHeaderExtNew {
pub num_image: u32,
pub snapshot_included: u8,
snapshot_board_version_bytes: [u8; 15]
}
impl MetaHeaderExtNew {
pub fn snapshot_board_version(&self) -> String {
common::string_from_bytes(&self.snapshot_board_version_bytes)
}
}
#[derive(BinRead)]
pub struct EntryCommon {
pub size: u32,
_unk: u32,
_crc32: u32,
pub offset: u32,
_unk2: [u8; 12],
pub magic: u32,
}
+72 -33
View File
@@ -10,64 +10,103 @@ use binrw::BinReaderExt;
use crate::utils::common;
use include::*;
pub struct SlpContext {
variant: SlpVariant,
}
pub fn is_slp_file(app_ctx: &AppContext) -> Result<Option<Box<dyn Any>>, Box<dyn std::error::Error>> {
let file = match app_ctx.file() {Some(f) => f, None => return Ok(None)};
let header = common::read_file(&file, 0, 4)?;
if header == b"SLP\x00" {
Ok(Some(Box::new(())))
let check = common::read_file(&file, 44, 1)?[0];
let variant: SlpVariant;
if check == 0 || check == 1 {
variant = SlpVariant::Old
}
else if check == 5 || check == 6 { //?
variant = SlpVariant::Old2
}
else {
variant = SlpVariant::New
}
Ok(Some(Box::new(SlpContext {variant})))
} else {
Ok(None)
}
}
pub fn extract_slp(app_ctx: &AppContext, _ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
pub fn extract_slp(app_ctx: &AppContext, ctx: Box<dyn Any>) -> Result<(), Box<dyn std::error::Error>> {
let mut file = app_ctx.file().ok_or("Extractor expected file")?;
let ctx = ctx.downcast::<SlpContext>().expect("Missing context");
let header: Header = file.read_le()?;
println!("File info:\nModel: {}\nVersion: {}\nFirmware: {}\nNew type: {}\n",
header.model(), header.version(), header.firmware(), header.is_new_type());
let meta_header: CommonMetaHeader = file.read_le()?;
println!("File info:\nType: {:?}\nProject name: {}\nFirmware Version: {}\nFirmware Version(USER): {}",
ctx.variant, meta_header.project_name(), meta_header.firmware_version(), meta_header.user_version());
let mut first_entry_offset = 0;
let mut entries: Vec<EntryOld> = Vec::new();
for i in 0..100 {
if (i != 0) && (file.stream_position()? >= first_entry_offset) {
break
}
let offset;
let size;
if header.is_new_type() {
let entry: EntryNew = file.read_le()?;
offset = entry.offset;
size = entry.size;
let num_image;
let mut snapshot_entry_offset: Option<u32> = None;
if ctx.variant == SlpVariant::New {
let meta_header_ext: MetaHeaderExtNew = file.read_le()?;
if meta_header_ext.snapshot_included == 0x01 {
println!("Snapshot Image: Included");
println!("S/S Img. Board Version: {}", meta_header_ext.snapshot_board_version())
} else {
let entry: EntryOld = file.read_le()?;
offset = entry.offset;
size = entry.size;
println!("Snapshot Image: Excluded");
}
if i == 0 {
first_entry_offset = offset as u64;
num_image = meta_header_ext.num_image;
}
else if ctx.variant == SlpVariant::Old {
let meta_header_ext: MetaHeaderExtOld = file.read_le()?;
if meta_header_ext.snapshot_included == 0x01 {
println!("Snapshot Image: Included");
println!("Snapshot Image offset: {}", meta_header_ext.snapshot_entry_offset);
snapshot_entry_offset = Some(meta_header_ext.snapshot_entry_offset);
} else {
println!("Snapshot Image: Excluded");
}
println!("{}. Offset: {}, Size: {}", i + 1, offset, size);
entries.push(EntryOld {size: size, _unk: 0, offset: offset, _unk2: 0});
num_image = 5; //hardcoded for old variant
}
else if ctx.variant == SlpVariant::Old2 {
let meta_header_ext: MetaHeaderExtNew = file.read_le()?;
//snapshot fields of new meta_header_ext are not used in this case
num_image = meta_header_ext.num_image;
}
else {
return Err("invalid slp variant".into());
}
let mut i = 1;
for entry in &entries {
println!("\n({}/{}) - Offset: {}, Size: {}", i, &entries.len(), entry.offset, entry.size);
let mut entries: Vec<EntryCommon> = Vec::new();
for _i in 0..num_image {
let entry: EntryCommon = file.read_le()?;
if ctx.variant == SlpVariant::New {
let _version_bytes = common::read_exact(&mut file, 8)?;
}
entries.push(entry);
}
//push additional snapshot entry
if let Some(offset) = snapshot_entry_offset {
file.seek(SeekFrom::Start(offset as u64))?;
let entry: EntryCommon = file.read_le()?;
entries.push(entry);
}
for (i, entry) in entries.iter().enumerate() {
println!("\n({}/{}) - Offset: {}, Size: {}, Magic: 0x{:02X}", i+1, &entries.len(), entry.offset, entry.size, entry.magic);
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", i+1));
file.seek(SeekFrom::Start(entry.offset.into()))?;
let data = common::read_exact(&mut file, entry.size as usize)?;
let output_path = Path::new(&app_ctx.output_dir).join(format!("{}.bin", i));
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!");
i += 1;
}
Ok(())