Working
This commit is contained in:
parent
9eab9dd9a3
commit
d55935c54b
147
src/main.rs
147
src/main.rs
|
@ -1,145 +1,5 @@
|
||||||
use std::fs::File;
|
|
||||||
use std::io::{Read, Seek, SeekFrom};
|
|
||||||
|
|
||||||
pub mod voc;
|
pub mod voc;
|
||||||
|
|
||||||
fn parse_voc(file_name: &str) {
|
|
||||||
println!("Parsing {} ...", file_name);
|
|
||||||
let mut fp = File::open(file_name).unwrap();
|
|
||||||
|
|
||||||
// Signature - Creative Voice File
|
|
||||||
let mut signature1_buffer: [u8; 19] = [0; 19];
|
|
||||||
drop(fp.read(&mut signature1_buffer));
|
|
||||||
let signature1_expected = "Creative Voice File";
|
|
||||||
let signature1 = std::str::from_utf8(&signature1_buffer).unwrap();
|
|
||||||
if signature1 != signature1_expected {
|
|
||||||
panic!("Bad file. Expected \"{}\" got \"{}\"", signature1_expected, signature1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signature - 1A 1A 00
|
|
||||||
let mut signature2_buffer: [u8; 3] = [0; 3];
|
|
||||||
drop(fp.read(&mut signature2_buffer));
|
|
||||||
let signature2_expected: [u8; 3] = [0x1A, 0x1A, 0x0];
|
|
||||||
if signature2_buffer != signature2_expected {
|
|
||||||
panic!("Bad file. Expected {:02X?} got {:02X?}", signature2_expected, signature2_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Version
|
|
||||||
let mut version_buffer: [u8; 2] = [0; 2];
|
|
||||||
drop(fp.read(&mut version_buffer));
|
|
||||||
let version_int = i16::from_le_bytes(version_buffer);
|
|
||||||
let version = (version_buffer[1], version_buffer[0]);
|
|
||||||
|
|
||||||
// Version checksum
|
|
||||||
let mut checksum_buffer: [u8; 2] = [0; 2];
|
|
||||||
drop(fp.read(&mut checksum_buffer));
|
|
||||||
let checksum = (!version_int + 0x1234).to_le_bytes();
|
|
||||||
if checksum_buffer != checksum {
|
|
||||||
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];
|
|
||||||
drop(fp.read(&mut block_type_buffer));
|
|
||||||
let block_type = match block_type_buffer[0] {
|
|
||||||
0 => voc::BlockType::Terminator,
|
|
||||||
1 => voc::BlockType::SoundData,
|
|
||||||
2 => voc::BlockType::SoundDataContinuation,
|
|
||||||
3 => voc::BlockType::Silence,
|
|
||||||
4 => voc::BlockType::Marker,
|
|
||||||
5 => voc::BlockType::Text,
|
|
||||||
6 => voc::BlockType::Repeat,
|
|
||||||
7 => voc::BlockType::EndRepeat,
|
|
||||||
_ => panic!("Bad block type. Got {}", block_type_buffer[0])
|
|
||||||
};
|
|
||||||
|
|
||||||
if block_type == voc::BlockType::Terminator {
|
|
||||||
let block = voc::Terminator::new();
|
|
||||||
voc.blocks.push(Box::new(block));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut block_size_buffer: [u8; 3] = [0; 3];
|
|
||||||
drop(fp.read(&mut block_size_buffer));
|
|
||||||
let block_size = i32::from_le_bytes(
|
|
||||||
[block_size_buffer[0], block_size_buffer[1], block_size_buffer[2], 0]
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
|
|
||||||
let next = address + block_size;
|
|
||||||
|
|
||||||
match block_type {
|
|
||||||
voc::BlockType::SoundData => {
|
|
||||||
let mut frequency_divisor_buffer: [u8; 1] = [0];
|
|
||||||
drop(fp.read(&mut frequency_divisor_buffer));
|
|
||||||
println!("Byte: {}", frequency_divisor_buffer[0]);
|
|
||||||
let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
|
|
||||||
println!("sample_rate: {}", sample_rate);
|
|
||||||
|
|
||||||
let mut codec_buffer: [u8; 1] = [0];
|
|
||||||
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<u8> = vec![0; (next - address) as usize];
|
|
||||||
drop(fp.read(&mut data));
|
|
||||||
|
|
||||||
let block = voc::SoundData::new(block_size, sample_rate, codec, data);
|
|
||||||
voc.blocks.push(Box::new(block));
|
|
||||||
},
|
|
||||||
voc::BlockType::SoundDataContinuation => {
|
|
||||||
let mut data: Vec<u8> = vec![0; (next - address) as usize];
|
|
||||||
drop(fp.read(&mut data));
|
|
||||||
|
|
||||||
let block = voc::SoundDataContinuation::new(block_size, data);
|
|
||||||
voc.blocks.push(Box::new(block));
|
|
||||||
},
|
|
||||||
|
|
||||||
voc::BlockType::Silence => {
|
|
||||||
let mut length_buffer: [u8; 2] = [0; 2];
|
|
||||||
drop(fp.read(&mut length_buffer));
|
|
||||||
let length = i16::from_le_bytes(length_buffer);
|
|
||||||
|
|
||||||
let mut frequency_divisor_buffer: [u8; 1] = [0];
|
|
||||||
drop(fp.read(&mut frequency_divisor_buffer));
|
|
||||||
let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
|
|
||||||
|
|
||||||
let block = voc::Silence { block_type, size: block_size, sample_rate, length};
|
|
||||||
voc.blocks.push(Box::new(block));
|
|
||||||
}
|
|
||||||
|
|
||||||
voc::BlockType::Text => {
|
|
||||||
let mut data: Vec<u8> = vec![0; (next - address) as usize];
|
|
||||||
drop(fp.read(&mut data));
|
|
||||||
|
|
||||||
let block = voc::Text { block_type, size: block_size, data };
|
|
||||||
voc.blocks.push(Box::new(block));
|
|
||||||
|
|
||||||
},
|
|
||||||
_ => panic!("block Type {:?} not implemented", block_type),
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("{:?}", voc);
|
|
||||||
for b in voc.blocks {
|
|
||||||
println!("{:02X?}", b.to_bytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
/*
|
/*
|
||||||
parse_voc("_C24FF78A.voc");
|
parse_voc("_C24FF78A.voc");
|
||||||
|
@ -147,7 +7,12 @@ fn main() {
|
||||||
parse_voc("C24FF78A.voc");
|
parse_voc("C24FF78A.voc");
|
||||||
parse_voc("pest2.voc");
|
parse_voc("pest2.voc");
|
||||||
*/
|
*/
|
||||||
parse_voc("pest2.voc");
|
|
||||||
//parse_voc("EDEN.MUS");
|
//parse_voc("EDEN.MUS");
|
||||||
//parse_voc("EDEN_.MUS");
|
//parse_voc("EDEN_.MUS");
|
||||||
|
|
||||||
|
let voc = voc::VocFile::from_file("pest2.voc");
|
||||||
|
println!("{:?}", voc);
|
||||||
|
for b in voc.blocks {
|
||||||
|
println!("{:02X?}", b.to_bytes());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
136
src/voc.rs
136
src/voc.rs
|
@ -1,4 +1,6 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Seek, SeekFrom};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum Codec {
|
pub enum Codec {
|
||||||
|
@ -12,7 +14,7 @@
|
||||||
Adpcm4to16,
|
Adpcm4to16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum BlockType {
|
pub enum BlockType {
|
||||||
Terminator,
|
Terminator,
|
||||||
SoundData,
|
SoundData,
|
||||||
|
@ -30,6 +32,138 @@
|
||||||
pub blocks: Vec<BlockT>
|
pub blocks: Vec<BlockT>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl VocFile {
|
||||||
|
pub(crate) fn from_file(file_name: &str) -> Self {
|
||||||
|
println!("Parsing {} ...", file_name);
|
||||||
|
let mut fp = File::open(file_name).unwrap();
|
||||||
|
|
||||||
|
// Signature - Creative Voice File
|
||||||
|
let mut signature1_buffer: [u8; 19] = [0; 19];
|
||||||
|
drop(fp.read(&mut signature1_buffer));
|
||||||
|
let signature1_expected = "Creative Voice File";
|
||||||
|
let signature1 = std::str::from_utf8(&signature1_buffer).unwrap();
|
||||||
|
if signature1 != signature1_expected {
|
||||||
|
panic!("Bad file. Expected \"{}\" got \"{}\"", signature1_expected, signature1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signature - 1A 1A 00
|
||||||
|
let mut signature2_buffer: [u8; 3] = [0; 3];
|
||||||
|
drop(fp.read(&mut signature2_buffer));
|
||||||
|
let signature2_expected: [u8; 3] = [0x1A, 0x1A, 0x0];
|
||||||
|
if signature2_buffer != signature2_expected {
|
||||||
|
panic!("Bad file. Expected {:02X?} got {:02X?}", signature2_expected, signature2_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version
|
||||||
|
let mut version_buffer: [u8; 2] = [0; 2];
|
||||||
|
drop(fp.read(&mut version_buffer));
|
||||||
|
let version_int = i16::from_le_bytes(version_buffer);
|
||||||
|
let version = (version_buffer[1], version_buffer[0]);
|
||||||
|
|
||||||
|
// Version checksum
|
||||||
|
let mut checksum_buffer: [u8; 2] = [0; 2];
|
||||||
|
drop(fp.read(&mut checksum_buffer));
|
||||||
|
let checksum = (!version_int + 0x1234).to_le_bytes();
|
||||||
|
if checksum_buffer != checksum {
|
||||||
|
panic!("Bad file. Expected {:02X?} got {:02X?}", checksum, checksum_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut voc = VocFile{ version, blocks: Vec::new() };
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut block_type_buffer: [u8; 1] = [0];
|
||||||
|
drop(fp.read(&mut block_type_buffer));
|
||||||
|
let block_type = match block_type_buffer[0] {
|
||||||
|
0 => BlockType::Terminator,
|
||||||
|
1 => BlockType::SoundData,
|
||||||
|
2 => BlockType::SoundDataContinuation,
|
||||||
|
3 => BlockType::Silence,
|
||||||
|
4 => BlockType::Marker,
|
||||||
|
5 => BlockType::Text,
|
||||||
|
6 => BlockType::Repeat,
|
||||||
|
7 => BlockType::EndRepeat,
|
||||||
|
_ => panic!("Bad block type. Got {}", block_type_buffer[0])
|
||||||
|
};
|
||||||
|
|
||||||
|
if block_type == BlockType::Terminator {
|
||||||
|
let block = Terminator::new();
|
||||||
|
voc.blocks.push(Box::new(block));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut block_size_buffer: [u8; 3] = [0; 3];
|
||||||
|
drop(fp.read(&mut block_size_buffer));
|
||||||
|
let block_size = i32::from_le_bytes(
|
||||||
|
[block_size_buffer[0], block_size_buffer[1], block_size_buffer[2], 0]
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
|
||||||
|
let next = address + block_size;
|
||||||
|
|
||||||
|
match block_type {
|
||||||
|
BlockType::SoundData => {
|
||||||
|
let mut frequency_divisor_buffer: [u8; 1] = [0];
|
||||||
|
drop(fp.read(&mut frequency_divisor_buffer));
|
||||||
|
println!("Byte: {}", frequency_divisor_buffer[0]);
|
||||||
|
let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
|
||||||
|
println!("sample_rate: {}", sample_rate);
|
||||||
|
|
||||||
|
let mut codec_buffer: [u8; 1] = [0];
|
||||||
|
drop(fp.read(&mut codec_buffer));
|
||||||
|
let codec = match codec_buffer[0] {
|
||||||
|
0 => Codec::Pcm8BitUnsigned,
|
||||||
|
1 => Codec::Adpcm4to8,
|
||||||
|
2 => Codec::Adpcm3to8,
|
||||||
|
3 => Codec::Adpcm2to8,
|
||||||
|
4 => Codec::Pcm16BitSigned,
|
||||||
|
5 => Codec::Alaw,
|
||||||
|
6 => Codec::Ulaw,
|
||||||
|
7 => Codec::Adpcm4to16,
|
||||||
|
_ => panic!("Bad Sound format. Got {}", codec_buffer[0])
|
||||||
|
};
|
||||||
|
|
||||||
|
address = fp.seek(SeekFrom::Current(0)).unwrap() as i32;
|
||||||
|
let mut data: Vec<u8> = vec![0; (next - address) as usize];
|
||||||
|
drop(fp.read(&mut data));
|
||||||
|
|
||||||
|
let block = SoundData::new(block_size, sample_rate, codec, data);
|
||||||
|
voc.blocks.push(Box::new(block));
|
||||||
|
},
|
||||||
|
BlockType::SoundDataContinuation => {
|
||||||
|
let mut data: Vec<u8> = vec![0; (next - address) as usize];
|
||||||
|
drop(fp.read(&mut data));
|
||||||
|
|
||||||
|
let block = SoundDataContinuation::new(block_size, data);
|
||||||
|
voc.blocks.push(Box::new(block));
|
||||||
|
},
|
||||||
|
BlockType::Silence => {
|
||||||
|
let mut length_buffer: [u8; 2] = [0; 2];
|
||||||
|
drop(fp.read(&mut length_buffer));
|
||||||
|
let length = i16::from_le_bytes(length_buffer);
|
||||||
|
|
||||||
|
let mut frequency_divisor_buffer: [u8; 1] = [0];
|
||||||
|
drop(fp.read(&mut frequency_divisor_buffer));
|
||||||
|
let sample_rate: i32 = 1000000i32 / (256i32 - frequency_divisor_buffer[0] as i32);
|
||||||
|
|
||||||
|
let block = Silence { block_type, size: block_size, sample_rate, length};
|
||||||
|
voc.blocks.push(Box::new(block));
|
||||||
|
}
|
||||||
|
BlockType::Text => {
|
||||||
|
let mut data: Vec<u8> = vec![0; (next - address) as usize];
|
||||||
|
drop(fp.read(&mut data));
|
||||||
|
|
||||||
|
let block = Text { block_type, size: block_size, data };
|
||||||
|
voc.blocks.push(Box::new(block));
|
||||||
|
|
||||||
|
},
|
||||||
|
_ => panic!("block Type {:?} not implemented", block_type),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
voc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Block: std::fmt::Debug {
|
pub trait Block: std::fmt::Debug {
|
||||||
fn to_bytes(&self) -> Vec<u8>;
|
fn to_bytes(&self) -> Vec<u8>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue