use bat_adapters::unity::RawAssetBundle; use bat_adapters::unity::{Unity2021_3Adapter, UnityAdapterRegistry}; fn push_c_string(data: &mut Vec, value: &str) { data.extend_from_slice(value.as_bytes()); data.push(0); } fn push_u16(data: &mut Vec, value: u16) { data.extend_from_slice(&value.to_be_bytes()); } fn push_u32(data: &mut Vec, value: u32) { data.extend_from_slice(&value.to_be_bytes()); } fn push_i32(data: &mut Vec, value: i32) { data.extend_from_slice(&value.to_be_bytes()); } fn push_u64(data: &mut Vec, value: u64) { data.extend_from_slice(&value.to_be_bytes()); } fn align(data: &mut Vec, alignment: usize) { let remainder = data.len() % alignment; if remainder != 0 { data.resize(data.len() + alignment - remainder, 0); } } fn synthetic_minimal_unityfs_bundle() -> Vec { let mut blocks_info = Vec::new(); blocks_info.extend_from_slice(&[0; 16]); push_i32(&mut blocks_info, 1); push_u32(&mut blocks_info, 4); push_u32(&mut blocks_info, 4); push_u16(&mut blocks_info, 0); push_i32(&mut blocks_info, 1); push_u64(&mut blocks_info, 0); push_u64(&mut blocks_info, 4); push_u32(&mut blocks_info, 0); push_c_string(&mut blocks_info, "SYNTHETIC-DEMO-CAB"); let mut data = Vec::new(); push_c_string(&mut data, "UnityFS"); push_u32(&mut data, 8); push_c_string(&mut data, "5.x.x"); push_c_string(&mut data, "2021.3.56f2"); push_u64(&mut data, 0); push_u32(&mut data, blocks_info.len() as u32); push_u32(&mut data, blocks_info.len() as u32); push_u32(&mut data, 0); align(&mut data, 16); data.extend_from_slice(&blocks_info); data.extend_from_slice(b"data"); let total_size = data.len() as u64; let total_size_offset = b"UnityFS\0".len() + 4 + b"5.x.x\0".len() + b"2021.3.56f2\0".len(); data[total_size_offset..total_size_offset + 8].copy_from_slice(&total_size.to_be_bytes()); data } fn main() { println!("๐ŸŽฎ BlueArchiveToolkit - Unity ้€‚้…ๅ™จๆผ”็คบ"); println!("โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"); // ๅˆ›ๅปบ Unity Adapter let adapter = Unity2021_3Adapter::new(); println!("โœ… Unity Adapter: {}", adapter.name()); println!(" ๆ”ฏๆŒ็‰ˆๆœฌ: 2021.3.0 - 2021.3.99"); // ๅˆๆˆๆœ€ๅฐ UnityFS ๆ–‡ไปถ๏ผŒไป…็”จไบŽๆผ”็คบ็‰ˆๆœฌๆฃ€ๆต‹ๅ’Œ้€‚้…ๅ™จ้€‰ๆ‹ฉใ€‚ println!("\n๐Ÿ“ฆ ๆต‹่ฏ• Unity ็‰ˆๆœฌๆฃ€ๆต‹..."); let bundle = RawAssetBundle { data: synthetic_minimal_unityfs_bundle(), path: Some("synthetic-demo.bundle".to_string()), }; if adapter.can_handle(&bundle) { println!(" โœ… ๅฏไปฅๅค„็† Unity 2021.3.56f2"); } else { println!(" โŒ ไธๆ”ฏๆŒๆญค็‰ˆๆœฌ"); } // ๆต‹่ฏ• Registry println!("\n๐Ÿ”„ ๆต‹่ฏ• Adapter Registry..."); let registry = UnityAdapterRegistry::with_defaults(); println!(" ๆณจๅ†Œ็š„้€‚้…ๅ™จๆ•ฐ้‡: {}", registry.count()); match registry.select_adapter(&bundle) { Ok(selected) => { println!(" โœ… ่‡ชๅŠจ้€‰ๆ‹ฉ็š„้€‚้…ๅ™จ: {}", selected.name()); } Err(e) => { println!(" โŒ ้€‰ๆ‹ฉๅคฑ่ดฅ: {}", e); } } println!("\nโœ… ๆผ”็คบๅฎŒๆˆ๏ผ"); println!("โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”"); }