From 4ae4a9ebd8d1e07d0b67cbd7eb48ab82ed865fe6 Mon Sep 17 00:00:00 2001 From: Pedro de Oliveira Date: Sun, 13 Nov 2022 00:44:15 +0000 Subject: [PATCH] Working --- .gitignore | 5 ++ src/main.rs | 148 +++++++++++++++++++++------------------------------- src/voc.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+), 88 deletions(-) create mode 100644 .gitignore create mode 100644 src/voc.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8019165 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/target +*.VOC +*.voc +*.bak +/voctool.iml diff --git a/src/main.rs b/src/main.rs index ea3ec0c..634c428 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,56 +1,6 @@ -use std::fmt; use std::fs::File; use std::io::{Read, Seek, SeekFrom}; - -#[derive(Debug)] -enum Compression { - Pcm8BitUnsigned, - Adpcm4to8, - Adpcm3to8, - Adpcm2to8, - Pcm16BitSigned, - Alaw1, - Alaw2, - Adpcm4to16 -} - -#[derive(Debug, PartialEq)] -enum BlockType { - Terminator, - SoundData, - SoundContinue, - Silence, - Marker, - ASCII, - Repeat, - EndRepeat -} - -struct DataBlock { - block_type: BlockType, - block_size: i32, - sample_rate: Option, - audio_format: Option, - data: Vec, -} - -impl fmt::Debug for DataBlock { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.block_type == BlockType::SoundData { - f.debug_struct("Voc") - .field("type", &self.block_type) - .field("size", &self.block_size) - .field("sample_rate", &self.sample_rate.unwrap()) - .field("audio_format", &self.audio_format.as_ref().unwrap()) - .finish() - } else { - f.debug_struct("Voc") - .field("type", &self.block_type) - .field("size", &self.block_size) - .finish() - } - } -} +pub mod voc; fn parse_voc(file_name: &str) { println!("Parsing {} ...", file_name); @@ -87,25 +37,28 @@ fn parse_voc(file_name: &str) { panic!("Bad file. Expected {:02X?} got {:02X?}", checksum, checksum_buffer); } + let mut voc = voc::VocFile{ version, blocks: Vec::new() }; + loop { let mut block_type_buffer: [u8; 1] = [0]; std::mem::drop(fp.read(&mut block_type_buffer)); let block_type = match block_type_buffer[0] { - 0 => BlockType::Terminator, - 1 => BlockType::SoundData, - 2 => BlockType::SoundContinue, - 3 => BlockType::Silence, - 4 => BlockType::Marker, - 5 => BlockType::ASCII, - 6 => BlockType::Repeat, - 7 => BlockType::EndRepeat, + 0 => voc::BlockType::Terminator, + 1 => voc::BlockType::SoundData, + 2 => voc::BlockType::SoundContinue, + 3 => voc::BlockType::Silence, + 4 => voc::BlockType::Marker, + 5 => voc::BlockType::ASCII, + 6 => voc::BlockType::Repeat, + 7 => voc::BlockType::EndRepeat, _ => panic!("Bad block type. Got {}", block_type_buffer[0]) }; - if block_type == BlockType::Terminator { - let data_block = DataBlock { block_type, block_size: 0, sample_rate: None, audio_format: None, data: Vec::new() }; - println!("{:?}", data_block); - println!("Found block type 0. Exiting"); + if block_type == voc::BlockType::Terminator { + let block = voc::Block::Terminator( voc::Terminator{ block_type } ); + //println!("{:?}", block); + //println!("Found block type 0. Exiting"); + voc.blocks.push(block); break; } @@ -118,56 +71,75 @@ fn parse_voc(file_name: &str) { let mut address = fp.seek(SeekFrom::Current(0)).unwrap() as i32; let next = address + block_size; - let mut data_block: DataBlock; - match block_type { - BlockType::SoundData => { - let mut sample_rate_buffer: [u8; 1] = [0]; - std::mem::drop(fp.read(&mut sample_rate_buffer)); - let sample_rate: i32 = 1000000i32 / (256i32 - sample_rate_buffer[0] as i32); + voc::BlockType::SoundData => { + let mut frequency_divisor_buffer: [u8; 1] = [0]; + std::mem::drop(fp.read(&mut frequency_divisor_buffer)); + let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32); - let mut audio_format_buffer: [u8; 1] = [0]; - std::mem::drop(fp.read(&mut audio_format_buffer)); - let audio_format = match audio_format_buffer[0] { - 0 => Compression::Pcm8BitUnsigned, - 1 => Compression::Adpcm4to8, - 2 => Compression::Adpcm3to8, - 3 => Compression::Adpcm2to8, - 4 => Compression::Pcm16BitSigned, - 5 => Compression::Alaw1, - 6 => Compression::Alaw2, - 7 => Compression::Adpcm4to16, - _ => panic!("Bad Sound format. Got {}", audio_format_buffer[0]) + let mut codec_buffer: [u8; 1] = [0]; + std::mem::drop(fp.read(&mut codec_buffer)); + let codec = match codec_buffer[0] { + 0 => voc::Codec::Pcm8BitUnsigned, + 1 => voc::Codec::Adpcm4to8, + 2 => voc::Codec::Adpcm3to8, + 3 => voc::Codec::Adpcm2to8, + 4 => voc::Codec::Pcm16BitSigned, + 5 => voc::Codec::Alaw, + 6 => voc::Codec::Ulaw, + 7 => voc::Codec::Adpcm4to16, + _ => panic!("Bad Sound format. Got {}", codec_buffer[0]) }; address = fp.seek(SeekFrom::Current(0)).unwrap() as i32; let mut data: Vec = vec![0; (next - address) as usize]; std::mem::drop(fp.read(&mut data)); - data_block = DataBlock { block_type, block_size, sample_rate: Some(sample_rate), audio_format: Some(audio_format), data }; + let block = voc::Block::SoundData(voc::SoundData { block_type, block_size, sample_rate, codec, data }); + voc.blocks.push(block); }, - BlockType::SoundContinue => { + voc::BlockType::SoundContinue => { let mut data: Vec = vec![0; (next - address) as usize]; std::mem::drop(fp.read(&mut data)); - data_block = DataBlock { block_type, block_size, sample_rate: None, audio_format: None, data }; + let block = voc::Block::SoundDataContinuation(voc::SoundDataContinuation { block_type, block_size, data }); + voc.blocks.push(block); }, - BlockType::ASCII => { + /* + BlockType::Silence => { + let mut length_buffer: [u8; 2] = [0; 2]; + std::mem::drop(fp.read(&mut length_buffer)); + let length = i16::from_le_bytes(length_buffer); + + let mut frequency_divisor_buffer: [u8; 1] = [0]; + std::mem::drop(fp.read(&mut frequency_divisor_buffer)); + let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32); + + data_block = DataBlock { block_type, block_size, sample_rate: Some(sample_rate), codec: None, data: Vec::new()}; + } + */ + voc::BlockType::ASCII => { let mut data: Vec = vec![0; (next - address) as usize]; std::mem::drop(fp.read(&mut data)); - data_block = DataBlock { block_type, block_size, sample_rate: None, audio_format: None, data }; + let block = voc::Block::Text(voc::Text { block_type, block_size, data }); + voc.blocks.push(block); + }, _ => panic!("block Type {:?} not implemented", block_type), } - println!("{:?}", data_block); + } + println!("{:?}", voc); } fn main() { + /* parse_voc("_C24FF78A.voc"); parse_voc("pest.voc"); parse_voc("C24FF78A.voc"); - parse_voc("pest2.voc"); + */ + parse_voc("EDEN.MUS"); + parse_voc("EDEN_.MUS"); } diff --git a/src/voc.rs b/src/voc.rs new file mode 100644 index 0000000..839638f --- /dev/null +++ b/src/voc.rs @@ -0,0 +1,132 @@ + use std::fmt; + + #[derive(Debug)] + pub enum Codec { + Pcm8BitUnsigned, + Adpcm4to8, + Adpcm3to8, + Adpcm2to8, + Pcm16BitSigned, + Alaw, + Ulaw, + Adpcm4to16, + } + + #[derive(Debug, PartialEq)] + pub enum BlockType { + Terminator, + SoundData, + SoundContinue, + Silence, + Marker, + ASCII, + Repeat, + EndRepeat, + } + + #[derive(Debug)] + pub struct VocFile { + pub version: (u8, u8), + pub blocks: Vec + } + + #[derive(Debug)] + pub enum Block { + Terminator(Terminator), + SoundData(SoundData), + SoundDataContinuation(SoundDataContinuation), + Silence(Silence), + Marker(Marker), + Text(Text), + RepeatStart(RepeatStart), + RepeatEnd(RepeatEnd), + } + + pub struct Terminator { + pub block_type: BlockType, + } + + impl fmt::Debug for Terminator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Terminator") + .field("type", &self.block_type) + .finish() + } + } + + pub struct SoundData { + pub block_type: BlockType, + pub block_size: i32, + pub sample_rate: i32, + pub codec: Codec, + pub data: Vec, + } + + impl fmt::Debug for SoundData { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SoundData") + .field("type", &self.block_type) + .field("size", &self.block_size) + .field("sample_rate", &self.sample_rate) + .field("codec", &self.codec) + .finish() + } + } + + pub struct SoundDataContinuation { + pub block_type: BlockType, + pub block_size: i32, + pub data: Vec, + } + + impl fmt::Debug for SoundDataContinuation { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SoundDataContinuation") + .field("type", &self.block_type) + .field("size", &self.block_size) + .finish() + } + } + + #[derive(Debug)] + pub struct Silence { + block_type: BlockType, + block_size: i32, + sample_rate: i32, + length: i16, + } + + #[derive(Debug)] + pub struct Marker { + block_type: BlockType, + block_size: i32, + value: i16, + } + + pub struct Text { + pub block_type: BlockType, + pub block_size: i32, + pub data: Vec, + } + + impl fmt::Debug for Text { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Text") + .field("type", &self.block_type) + .field("size", &self.block_size) + .finish() + } + } + + #[derive(Debug)] + pub struct RepeatStart { + block_type: BlockType, + block_size: i32, + repeat: i16, + } + + #[derive(Debug)] + pub struct RepeatEnd { + block_type: BlockType, + block_size: i32, + }