diff --git a/Cargo.lock b/Cargo.lock index 0ca5b6d..bc58c83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "aho-corasick" @@ -47,9 +47,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" [[package]] name = "env_logger" @@ -93,9 +93,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "indexmap" -version = "2.7.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", @@ -118,9 +118,9 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" @@ -235,9 +235,9 @@ dependencies = [ [[package]] name = "rkyv" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b11a153aec4a6ab60795f8ebe2923c597b16b05bb1504377451e705ef1a45323" +checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" dependencies = [ "bytecheck", "bytes", @@ -254,9 +254,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb382a4d9f53bd5c0be86b10d8179c3f8a14c30bf774ff77096ed6581e35981" +checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" dependencies = [ "proc-macro2", "quote", @@ -271,9 +271,9 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "syn" -version = "2.0.96" +version = "2.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" dependencies = [ "proc-macro2", "quote", @@ -306,15 +306,15 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" [[package]] name = "uuid" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744018581f9a3454a9e15beb8a33b017183f1e7c0cd170232a2d1453b23a51c4" +checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" [[package]] name = "winapi" diff --git a/Cargo.toml b/Cargo.toml index 72c2075..c7a5140 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,4 +6,4 @@ edition = "2021" [dependencies] env_logger = "0.9" log = "0.4.20" -rkyv = { version = "0.8.9", features = ["unaligned", "little_endian"] } +rkyv = { version = "0.8.10", features = ["unaligned", "big_endian"]} diff --git a/src/main.rs b/src/main.rs index 502794c..77bb0e7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,13 +19,13 @@ enum ChunkType { impl From<[u8; 4]> for ChunkType { fn from(value: [u8; 4]) -> Self { match value { - [109, 104, 98, 100] => ChunkType::Database, - [109, 104, 115, 100] => ChunkType::DataSet, - [109, 104, 105, 97] => ChunkType::AlbumList, - [109, 104, 108, 97] => ChunkType::AlbumItem, - [109, 104, 108, 116] => ChunkType::TrackList, - [109, 104, 105, 116] => ChunkType::TrackItem, - [109, 104, 111, 100] => ChunkType::StringTypes, + [0x6D, 0x68, 0x62, 0x64] => ChunkType::Database, + [0x6D, 0x68, 0x73, 0x64] => ChunkType::DataSet, + [0x6D, 0x68, 0x69, 0x61] => ChunkType::AlbumList, + [0x6D, 0x68, 0x6C, 0x61] => ChunkType::AlbumItem, + [0x6D, 0x68, 0x6C, 0x74] => ChunkType::TrackList, + [0x6D, 0x68, 0x69, 0x74] => ChunkType::TrackItem, + [0x6D, 0x68, 0x6F, 0x64] => ChunkType::StringTypes, [0x6D, 0x68, 0x6C, 0x70] => ChunkType::PlaylistList, [0x6D, 0x68, 0x79, 0x70] => ChunkType::Playlist, _ => ChunkType::Unknown @@ -33,17 +33,11 @@ impl From<[u8; 4]> for ChunkType { } } -#[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] -#[rkyv(compare(PartialEq), derive(Debug))] -struct ChunkHeader { - chunk_type: [u8; 4], - end_of_chunk: u32, - children_count: u32 -} - #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] #[rkyv(compare(PartialEq), derive(Debug))] struct Database { + header_length: u32, + total_length: u32, unknown: u32, version: u32, children_count: u32, @@ -57,12 +51,16 @@ struct Database { #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] #[rkyv(compare(PartialEq), derive(Debug))] struct DataSet { + header_length: u32, + total_length: u32, data_type: u32 } #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] #[rkyv(compare(PartialEq), derive(Debug))] struct AlbumItem { + header_length: u32, + total_length: u32, // length of header + all child records number_of_strings: u32, unknown: u16, album_id_for_track: u16, @@ -73,6 +71,8 @@ struct AlbumItem { #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] #[rkyv(compare(PartialEq), derive(Debug))] struct TrackItem { + header_length: u32, + total_length: u32, // length of header + all child records number_of_strings: u32, // number of mhod's count unique_id: u32, visible: u32, @@ -148,6 +148,8 @@ struct TrackItem { #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] #[rkyv(compare(PartialEq), derive(Debug))] struct Entry { // mhod + header_length: u32, + total_length: u32, entry_type: u32, unk1: u32, unk2: u32, @@ -160,6 +162,8 @@ struct Entry { // mhod #[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] #[rkyv(compare(PartialEq), derive(Debug))] struct Playlist { + header_length: u32, + total_length: u32, // length of header + all child records data_object_child_count: u32, playlist_item_count: u32, is_master_playlist_flag: u8, @@ -172,6 +176,13 @@ struct Playlist { list_sort_order: u32 } +#[derive(Archive, Deserialize, Serialize, Debug, PartialEq)] +#[rkyv(compare(PartialEq), derive(Debug))] +struct Header { + header_length: u32, + total_length: u32 +} + enum ChunkState { Header, Data @@ -179,50 +190,55 @@ enum ChunkState { fn db(data: &[u8]) { let mut state = ChunkState::Header; - let mut chunk_header = None; + let mut chunk_type = None; let mut i = 0; while i < data.len() { state = match state { ChunkState::Header => { - chunk_header = Some(rkyv::access::(&data[i..i+12]).unwrap()); - //info!("header: {:?}", chunk_header); - i += 12; + let a: [u8; 4] = data[i..i+4].try_into().unwrap(); + chunk_type = Some(ChunkType::from(a)); + i += 4; ChunkState::Data }, ChunkState::Data => { - let header = chunk_header.unwrap(); let mut u = 0; - // usize::try_from(header.end_of_chunk).unwrap() - 12 - match header.chunk_type { - [109, 104, 98, 100] => { //mhbd - u = usize::try_from(header.end_of_chunk).unwrap() - 12; - info!("val: {:?}", rkyv::access::(&data[i..i+u]).unwrap()); + match chunk_type.unwrap() { + ChunkType::Database => { + let db = rkyv::access::(&data[i..i+std::mem::size_of::()]).unwrap(); + info!("val: {:?}", db); + info!("i: {}", data[i]); + u = usize::try_from(db.header_length).unwrap() - 4; }, - [109, 104, 115, 100] => { //mhsd - u = usize::try_from(header.end_of_chunk).unwrap() - 12; - info!("val: {:?}", rkyv::access::(&data[i..i+u]).unwrap()); + ChunkType::DataSet => { + let ds = rkyv::access::(&data[i..i+std::mem::size_of::()]).unwrap(); + info!("val: {:?}", ds); + u = usize::try_from(ds.total_length).unwrap() - 4; }, - [109, 104, 105, 97] => { // mhla + ChunkType::AlbumList => { info!("AlbumList"); - u = usize::try_from(header.end_of_chunk).unwrap() - 12; + let header = rkyv::access::(&data[i..i+std::mem::size_of::
()]).unwrap(); + u = usize::try_from(header.total_length).unwrap() - 4; }, - [109, 104, 108, 97] => { // mhia - u = usize::try_from(header.end_of_chunk).unwrap() - 12; - info!("val: {:?}", rkyv::access::(&data[i..i+u]).unwrap()); + ChunkType::AlbumItem => { + let ai = rkyv::access::(&data[i..i+std::mem::size_of::()]).unwrap(); + info!("val: {:?}", ai); + u = usize::try_from(ai.total_length).unwrap() - 4; }, - [109, 104, 108, 116] => { // mhlt + ChunkType::TrackList => { info!("TrackList"); - u = usize::try_from(header.end_of_chunk).unwrap() - 12; + let header = rkyv::access::(&data[i..i+std::mem::size_of::
()]).unwrap(); + u = usize::try_from(header.total_length).unwrap() - 4; }, - [109, 104, 105, 116] => { // mhit - //info!("head: {}, {}", header.end_of_chunk, header.children_count); - u = usize::try_from(header.end_of_chunk).unwrap() - 12; - info!("val: {:?}", rkyv::access::(&data[i..i+u]).unwrap()); + ChunkType::TrackItem => { + let ti = rkyv::access::(&data[i..i+std::mem::size_of::()]).unwrap(); + info!("val: {:?}", ti); + u = usize::try_from(ti.total_length).unwrap() - 4; }, - [109, 104, 111, 100] => { // mhod - u = usize::try_from(header.children_count).unwrap() - 12; - let header_offset: usize = (header.end_of_chunk + 4) as usize; - let str_end: usize = (header.children_count - 12) as usize; + ChunkType::StringTypes => { + let header = rkyv::access::(&data[i..i+std::mem::size_of::
()]).unwrap(); + u = usize::try_from(header.header_length).unwrap() - 4; + let header_offset: usize = (header.total_length + 4) as usize; + let str_end: usize = (header.header_length - 4) as usize; let entry = rkyv::access::(&data[i..i+28]).unwrap(); info!("val: {:?}", &entry); let mut bytes = Vec::new(); @@ -237,20 +253,20 @@ fn db(data: &[u8]) { let g = String::from_utf8(bytes).unwrap(); info!("str: {}", g); }, - [0x6D, 0x68, 0x6C, 0x70] => { // mhlp - //info!("head: {}, {}", header.end_of_chunk, header.children_count); - info!("Playlists count: {}", header.children_count); - u = usize::try_from(header.end_of_chunk).unwrap() - 12; + ChunkType::PlaylistList => { + let header = rkyv::access::(&data[i..i+std::mem::size_of::
()]).unwrap(); + info!("Playlists count: {}", header.header_length); + u = usize::try_from(header.total_length).unwrap() - 4; }, - [0x6D, 0x68, 0x79, 0x70] => { // mhyp - u = usize::try_from(header.end_of_chunk).unwrap() - 12; - let playlist = rkyv::access::(&data[i..i+u]).unwrap(); + ChunkType::Playlist => { + let playlist = rkyv::access::(&data[i..i+std::mem::size_of::()]).unwrap(); info!("playlist: {:?}", playlist); + u = usize::try_from(playlist.total_length).unwrap() - 4; }, _ => return } i += u; - chunk_header = None; + chunk_type = None; ChunkState::Header } }