diff --git a/.gitignore b/.gitignore index a221ac1..6449126 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ target/ .vscode/ +*.tlg +*.png +*.tags diff --git a/Cargo.lock b/Cargo.lock index 81a8689..5db015a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,7 +164,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libtlg-rs" -version = "0.2.3" +version = "0.2.4" dependencies = [ "lazy_static", "overf", @@ -253,7 +253,7 @@ dependencies = [ [[package]] name = "tlg" -version = "0.2.3" +version = "0.2.4" dependencies = [ "clap", "libtlg-rs", diff --git a/libtlg-rs/Cargo.toml b/libtlg-rs/Cargo.toml index dc39fc0..f62fc6c 100644 --- a/libtlg-rs/Cargo.toml +++ b/libtlg-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libtlg-rs" -version = "0.2.3" +version = "0.2.4" description = "Rust version of libtlg" edition = "2024" license = "MIT" diff --git a/libtlg-rs/src/lib.rs b/libtlg-rs/src/lib.rs index 0ae48c2..0ea564e 100644 --- a/libtlg-rs/src/lib.rs +++ b/libtlg-rs/src/lib.rs @@ -32,6 +32,9 @@ pub fn is_valid_tlg(data: &[u8]) -> bool { data.starts_with(b"TLG0.0\x00sds\x1a") || data.starts_with(b"TLG5.0\x00raw\x1a") || data.starts_with(b"TLG6.0\x00raw\x1a") + || data.starts_with(b"XXXYYY\x00raw\x1a") + || data.starts_with(b"XXXZZZ\x00raw\x1a") + || data.starts_with(b"JKMXE8\x00raw\x1a") } /// Check if it's a valid TLG. diff --git a/libtlg-rs/src/load_tlg.rs b/libtlg-rs/src/load_tlg.rs index 0b4bf5c..30ebed1 100644 --- a/libtlg-rs/src/load_tlg.rs +++ b/libtlg-rs/src/load_tlg.rs @@ -1,4 +1,4 @@ -use crate::stream::ReadExt; +use crate::stream::*; use crate::tvpgl::*; use crate::*; use overf::wrapping; @@ -328,12 +328,28 @@ fn load_tlg6(src: &mut T) -> Result { } fn internal_load_tlg(src: &mut T) -> Result { + let offset = src.stream_position()?; let mut mark = [0; 11]; src.read_exact(&mut mark)?; if &mark == b"TLG5.0\x00raw\x1a" { load_tlg5(src) } else if &mark == b"TLG6.0\x00raw\x1a" { load_tlg6(src) + } else if &mark == b"XXXYYY\x00raw\x1a" { + let mut stream = XorStream::new(src); + stream.set_key(offset + 0xC, 0xAB); + stream.set_key(offset + 0x10, 0xAC); + load_tlg5(&mut stream) + } else if &mark == b"XXXZZZ\x00raw\x1a" { + let mut stream = XorStream::new(src); + stream.set_key(offset + 0xF, 0xAB); + stream.set_key(offset + 0x13, 0xAC); + load_tlg6(&mut stream) + } else if &mark == b"JKMXE8\x00raw\x1a" { + let mut stream = XorStream::new(src); + stream.set_key(offset + 0xC, 0x1A); + stream.set_key(offset + 0x10, 0x1C); + load_tlg5(&mut stream) } else { Err(TlgError::InvalidFormat) } diff --git a/libtlg-rs/src/stream.rs b/libtlg-rs/src/stream.rs index 0e2ef6b..cb3d374 100644 --- a/libtlg-rs/src/stream.rs +++ b/libtlg-rs/src/stream.rs @@ -1,6 +1,7 @@ -use std::io::Read; +use std::collections::HashMap; #[cfg(feature = "encode")] use std::io::Write; +use std::io::{Read, Seek, SeekFrom}; pub trait ReadExt { fn read_u32(&mut self) -> std::io::Result; @@ -37,3 +38,49 @@ impl WriteExt for W { self.write_all(&[value]) } } + +pub struct XorStream { + inner: R, + keys: HashMap, +} + +impl XorStream { + pub fn new(inner: R) -> Self { + Self { + inner, + keys: HashMap::new(), + } + } + + pub fn set_key(&mut self, offset: u64, key: u8) { + self.keys.insert(offset, key); + } +} + +impl Read for XorStream { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let pos = self.inner.stream_position()?; + let bytes_read = self.inner.read(buf)?; + for i in 0..bytes_read { + if let Some(key) = self.keys.get(&(pos + i as u64)) { + buf[i] ^= *key; + } + } + Ok(bytes_read) + } +} + +impl Seek for XorStream { + fn seek(&mut self, pos: SeekFrom) -> std::io::Result { + self.inner.seek(pos) + } + fn rewind(&mut self) -> std::io::Result<()> { + self.inner.rewind() + } + fn seek_relative(&mut self, offset: i64) -> std::io::Result<()> { + self.inner.seek_relative(offset) + } + fn stream_position(&mut self) -> std::io::Result { + self.inner.stream_position() + } +} diff --git a/tlg/Cargo.toml b/tlg/Cargo.toml index 1aee683..7300572 100644 --- a/tlg/Cargo.toml +++ b/tlg/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tlg" -version = "0.2.3" +version = "0.2.4" description = "Tools to process TLG image file." edition = "2024" license = "MIT"