From 8bed66d4f15620f383352ae4f8a30f4ccc66ef4e Mon Sep 17 00:00:00 2001 From: lifegpc Date: Thu, 12 Jun 2025 17:59:39 +0800 Subject: [PATCH] FIX BSE decode --- Cargo.lock | 72 +++++++++++++++++++++++++++++++++- Cargo.toml | 6 ++- src/scripts/bgi/archive/bse.rs | 64 ++++++++++++------------------ src/types.rs | 12 ++++++ 4 files changed, 114 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ead02d1..031b8a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "anstream" version = "0.6.18" @@ -58,6 +64,12 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.9.1" @@ -116,6 +128,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + [[package]] name = "csv" version = "1.3.1" @@ -146,6 +167,25 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "getrandom" version = "0.3.3" @@ -206,6 +246,16 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "msg_tool" version = "0.1.0" @@ -217,6 +267,7 @@ dependencies = [ "int-enum", "lazy_static", "msg_tool_macro", + "png", "rand", "serde", "serde_json", @@ -238,6 +289,19 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -350,6 +414,12 @@ dependencies = [ "serde", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "strsim" version = "0.11.1" @@ -479,7 +549,7 @@ version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" dependencies = [ - "bitflags", + "bitflags 2.9.1", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 72219e6..410beca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,20 +11,24 @@ encoding_rs = "0.8" int-enum = { version = "1.2", optional = true } lazy_static = "1.5.0" msg_tool_macro = { path = "./msg_tool_macro" } +png = { version = "0.17", optional = true } rand = { version = "0.9", optional = true } serde = { version = "1", features = ["derive"] } serde_json = "1" unicode-segmentation = "1.12" [features] -default = ["bgi", "bgi-arc", "circus", "escude", "escude-arc", "yaneurao", "yaneurao-itufuru"] +default = ["bgi", "bgi-arc", "bgi-img", "circus", "escude", "escude-arc", "yaneurao", "yaneurao-itufuru"] bgi = [] bgi-arc = ["bgi", "utils-bit-stream"] +bgi-img = ["image"] circus = [] escude = ["int-enum"] escude-arc = ["escude", "rand", "utils-bit-stream"] yaneurao = [] yaneurao-itufuru = ["yaneurao"] +# basic feature +image = ["png"] # utils feature utils-bit-stream = [] diff --git a/src/scripts/bgi/archive/bse.rs b/src/scripts/bgi/archive/bse.rs index 11bdd51..88f314d 100644 --- a/src/scripts/bgi/archive/bse.rs +++ b/src/scripts/bgi/archive/bse.rs @@ -5,37 +5,22 @@ use anyhow::Result; use std::io::{Read, Seek}; pub trait BseGenerator { - fn next_key(&mut self) -> u32; -} - -fn rtor(v: u32, count: u8) -> u32 { - let count = count & 0x1F; - return v >> count | v << (32 - count); -} - -fn rot_byte_r(v: u8, count: u8) -> u8 { - let count = count & 0x07; - return v >> count | v << (8 - count); -} - -fn rot_byte_l(v: u8, count: u8) -> u8 { - let count = count & 0x07; - return v << count | v >> (8 - count); + fn next_key(&mut self) -> i32; } pub struct BseGenerator100 { - key: u32, + key: i32, } impl BseGenerator100 { - pub fn new(key: u32) -> Self { + pub fn new(key: i32) -> Self { BseGenerator100 { key } } } impl BseGenerator for BseGenerator100 { - fn next_key(&mut self) -> u32 { - let key = self + fn next_key(&mut self) -> i32 { + let key = (self .key .overflowing_mul(257) .0 @@ -44,26 +29,26 @@ impl BseGenerator for BseGenerator100 { .overflowing_add(self.key.overflowing_mul(97).0) .0 .overflowing_add(23) - .0 + .0) as u32 ^ 0xA6CD9B75; - self.key = rtor(key, 16); + self.key = key.rotate_right(16) as i32; self.key } } pub struct BseGenerator101 { - key: u32, + key: i32, } impl BseGenerator101 { - pub fn new(key: u32) -> Self { + pub fn new(key: i32) -> Self { BseGenerator101 { key } } } impl BseGenerator for BseGenerator101 { - fn next_key(&mut self) -> u32 { - let key = self + fn next_key(&mut self) -> i32 { + let key = (self .key .overflowing_mul(127) .0 @@ -72,9 +57,9 @@ impl BseGenerator for BseGenerator101 { .overflowing_add(self.key.overflowing_mul(83).0) .0 .overflowing_add(53) - .0 + .0) as u32 ^ 0xB97A7E5C; - self.key = rtor(key, 16); + self.key = key.rotate_right(16) as i32; self.key } } @@ -89,14 +74,15 @@ pub struct BseReader Option<&'stati impl Option<&'static ScriptType>> BseReader { pub fn new(mut reader: T, detect: F, filename: &str) -> Result { - let version = reader.peek_u16_at(0x8)?; + reader.seek(std::io::SeekFrom::Start(8))?; + let version = reader.read_u16()?; if version != 0x0100 && version != 0x0101 { return Err(anyhow::anyhow!("Unsupported BSE version: {}", version)); } - let _checksum = reader.peek_u16_at(0xA)?; - let key: u32 = reader.peek_u32_at(0xC)?; + let _checksum = reader.read_u16()?; + let key = reader.read_i32()?; let mut header = [0u8; 0x40]; - reader.peek_extract_at(0x10, &mut header)?; + reader.read_exact(&mut header)?; let generator: Box = if version == 0x0100 { Box::new(BseGenerator100::new(key)) } else { @@ -115,17 +101,19 @@ impl Option<&'static ScriptType>> B fn decode_header(data: &mut [u8; 0x40], mut generator: Box) -> Result<()> { let mut decoded = [false; 0x40]; for _ in 0..0x40 { - let mut dst = generator.next_key() as usize & 0x3F; + let mut dst = (generator.next_key() & 0x3F) as usize; while decoded[dst] { dst = (dst + 1) & 0x3F; } - let shift = (generator.next_key() & 7) as u8; - let right_shift = generator.next_key() & 1 == 0; - let symbol = data[dst].overflowing_sub(generator.next_key() as u8).0; + let shift = generator.next_key() & 7; + let right_shift = (generator.next_key() & 1) == 0; + let key_byte = generator.next_key(); + let symbol = (data[dst] as i32).wrapping_sub(key_byte); + let symbol = symbol as u8; data[dst] = if right_shift { - rot_byte_r(symbol, shift) + symbol.rotate_right(shift as u32) } else { - rot_byte_l(symbol, shift) + symbol.rotate_left(shift as u32) }; decoded[dst] = true; } diff --git a/src/types.rs b/src/types.rs index 8dd9012..99c3efb 100644 --- a/src/types.rs +++ b/src/types.rs @@ -299,3 +299,15 @@ pub struct ReplacementTable { #[serde(flatten)] pub map: HashMap, } + +#[cfg(feature = "image")] +pub enum ImageColorType { + Grayscale, + Rgb24, + Rgba32, +} + +#[cfg(feature = "image")] +pub enum ImageOutputType { + Png, +}