* VocFile
- Dont panic on invalid version checksum - Add new field to store checksum status * BlockInfo - New struct - Contains start and end address of the block in the file - Contains a get_size() function * Block Trait - Add a get_info() function that returns a BlockInfo * Main - Prettify the *info* command. - Now shows the file version, checksum, and info about all the blocks.
This commit is contained in:
parent
1dd3997587
commit
59cbcff192
47
src/main.rs
47
src/main.rs
|
@ -7,25 +7,54 @@ fn main() {
|
||||||
.subcommand_value_name("COMMAND")
|
.subcommand_value_name("COMMAND")
|
||||||
.subcommand_help_heading("COMMAND")
|
.subcommand_help_heading("COMMAND")
|
||||||
.subcommand(clap::Command::new("info")
|
.subcommand(clap::Command::new("info")
|
||||||
.about("Show information about the <file>")
|
.about("Show information about the <file>")
|
||||||
.arg(
|
.arg(
|
||||||
clap::arg!(<file>)
|
clap::arg!(<file>)
|
||||||
.value_parser(clap::value_parser!(String))
|
.value_parser(clap::value_parser!(String))
|
||||||
.required(true)
|
.required(true)
|
||||||
.help("Filename"),
|
.help("Filename"),
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
.subcommand(clap::Command::new("extract")
|
||||||
|
.about("Extract all the blocks from the <file>")
|
||||||
|
.arg(
|
||||||
|
clap::arg!(<file>)
|
||||||
|
.value_parser(clap::value_parser!(String))
|
||||||
|
.required(true)
|
||||||
|
.help("Filename"),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
let matches = cmd.get_matches();
|
let matches = cmd.get_matches();
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("info", arguments)) => {
|
Some(("info", arguments)) => {
|
||||||
|
let filename = arguments.get_one::<String>("file").unwrap();
|
||||||
|
let voc = voc::VocFile::from_file(filename);
|
||||||
|
println!("Version {}.{} - Checksum: {}",
|
||||||
|
voc.version.0,
|
||||||
|
voc.version.1,
|
||||||
|
if voc.checksum { "Valid!" } else { "Invalid!" }
|
||||||
|
);
|
||||||
|
for (n, block) in voc.blocks.into_iter().enumerate() {
|
||||||
|
if let Some(block_info) = block.get_info() {
|
||||||
|
println!("Block #{} - Start Address: {:02X?} - End Address: {:02X?} - Size {}",
|
||||||
|
n,
|
||||||
|
block_info.start_address,
|
||||||
|
block_info.end_address,
|
||||||
|
block_info.get_size()
|
||||||
|
);
|
||||||
|
println!("{:?}", block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(("extract", _arguments)) => {
|
||||||
|
/*
|
||||||
let filename = arguments.get_one::<String>("file").unwrap();
|
let filename = arguments.get_one::<String>("file").unwrap();
|
||||||
let voc = voc::VocFile::from_file(filename);
|
let voc = voc::VocFile::from_file(filename);
|
||||||
println!("{:?}", voc);
|
println!("{:?}", voc);
|
||||||
voc.to_file("lulz.voc");
|
voc.to_file("lulz.voc");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
_ => unreachable!("parser should ensure only valid subcommand names are used"),
|
_ => unreachable!("parser should ensure only valid subcommand names are used"),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
184
src/voc.rs
184
src/voc.rs
|
@ -31,6 +31,7 @@ pub enum BlockType {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct VocFile {
|
pub struct VocFile {
|
||||||
pub version: (u8, u8),
|
pub version: (u8, u8),
|
||||||
|
pub checksum: bool,
|
||||||
pub blocks: Vec<BlockT>,
|
pub blocks: Vec<BlockT>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,13 +66,13 @@ impl VocFile {
|
||||||
let mut checksum_buffer: [u8; 2] = [0; 2];
|
let mut checksum_buffer: [u8; 2] = [0; 2];
|
||||||
drop(fp.read(&mut checksum_buffer));
|
drop(fp.read(&mut checksum_buffer));
|
||||||
let checksum = (!version_int + 0x1234).to_le_bytes();
|
let checksum = (!version_int + 0x1234).to_le_bytes();
|
||||||
if checksum_buffer != checksum {
|
let checksum_result = checksum_buffer == checksum;
|
||||||
panic!("Bad file. Expected {:02X?} got {:02X?}", checksum, checksum_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut voc = VocFile { version, blocks: Vec::new() };
|
let mut voc = VocFile { version, checksum: checksum_result, blocks: Vec::new() };
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
let block_start_address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
||||||
|
|
||||||
// Block Type
|
// Block Type
|
||||||
let mut block_type_buffer: [u8; 1] = [0];
|
let mut block_type_buffer: [u8; 1] = [0];
|
||||||
drop(fp.read(&mut block_type_buffer));
|
drop(fp.read(&mut block_type_buffer));
|
||||||
|
@ -98,41 +99,41 @@ impl VocFile {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
let current_address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
||||||
let end_address = address + block_size;
|
let block_end_address = current_address + block_size;
|
||||||
|
|
||||||
match block_type {
|
match block_type {
|
||||||
BlockType::Terminator => {
|
BlockType::Terminator => {
|
||||||
let block = Terminator::from_stream(&mut fp, end_address);
|
let block = Terminator::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BlockType::SoundData => {
|
BlockType::SoundData => {
|
||||||
let block = SoundData::from_stream(&mut fp, end_address);
|
let block = SoundData::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
BlockType::SoundDataContinuation => {
|
BlockType::SoundDataContinuation => {
|
||||||
let block = SoundDataContinuation::from_stream(&mut fp, end_address);
|
let block = SoundDataContinuation::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
BlockType::Silence => {
|
BlockType::Silence => {
|
||||||
let block = Silence::from_stream(&mut fp, end_address);
|
let block = Silence::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
BlockType::Marker => {
|
BlockType::Marker => {
|
||||||
let block = Marker::from_stream(&mut fp, end_address);
|
let block = Marker::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
BlockType::Text => {
|
BlockType::Text => {
|
||||||
let block = Text::from_stream(&mut fp, end_address);
|
let block = Text::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
BlockType::RepeatStart => {
|
BlockType::RepeatStart => {
|
||||||
let block = RepeatStart::from_stream(&mut fp, end_address);
|
let block = RepeatStart::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
BlockType::RepeatEnd => {
|
BlockType::RepeatEnd => {
|
||||||
let block = RepeatEnd::from_stream(&mut fp, end_address);
|
let block = RepeatEnd::from_stream(&mut fp, block_start_address, block_end_address);
|
||||||
voc.blocks.push(Box::new(block));
|
voc.blocks.push(Box::new(block));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,28 +178,41 @@ type BlockT = Box<dyn Block>;
|
||||||
|
|
||||||
pub trait Block: fmt::Debug {
|
pub trait Block: fmt::Debug {
|
||||||
fn to_bytes(&self) -> Vec<u8>;
|
fn to_bytes(&self) -> Vec<u8>;
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BlockInfo {
|
||||||
|
pub start_address: u32,
|
||||||
|
pub end_address: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockInfo {
|
||||||
|
pub fn get_size(&self) -> u32 {
|
||||||
|
self.end_address - self.start_address
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terminator
|
// Terminator
|
||||||
|
|
||||||
pub struct Terminator {
|
pub struct Terminator {
|
||||||
|
info: Option<BlockInfo>,
|
||||||
block_type: BlockType,
|
block_type: BlockType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Terminator {
|
impl Terminator {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self { Self { info: None, block_type: BlockType::Terminator } }
|
||||||
Self { block_type: BlockType::Terminator }
|
pub fn from_stream(_fp: &mut File, start_address: u32, end_address: u32) -> Self
|
||||||
}
|
{
|
||||||
|
Self {
|
||||||
pub fn from_stream(_fp: &mut File, _end_address: u32) -> Self {
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
Self::new()
|
block_type: BlockType::Terminator,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Block for Terminator {
|
impl Block for Terminator {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> { vec![self.block_type as u8] }
|
||||||
vec![self.block_type as u8]
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Terminator {
|
impl fmt::Debug for Terminator {
|
||||||
|
@ -211,15 +225,17 @@ impl fmt::Debug for Terminator {
|
||||||
// SoundData
|
// SoundData
|
||||||
|
|
||||||
pub struct SoundData {
|
pub struct SoundData {
|
||||||
|
info: Option<BlockInfo>,
|
||||||
block_type: BlockType,
|
block_type: BlockType,
|
||||||
pub sample_rate: u32,
|
sample_rate: u32,
|
||||||
pub codec: Codec,
|
codec: Codec,
|
||||||
pub data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SoundData {
|
impl SoundData {
|
||||||
pub fn new(sample_rate: u32, codec: Codec, data: Vec<u8>) -> Self {
|
pub fn new(sample_rate: u32, codec: Codec, data: Vec<u8>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
info: None,
|
||||||
block_type: BlockType::SoundData,
|
block_type: BlockType::SoundData,
|
||||||
sample_rate,
|
sample_rate,
|
||||||
codec,
|
codec,
|
||||||
|
@ -227,7 +243,7 @@ impl SoundData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_stream(fp: &mut File, end_address: u32) -> Self {
|
pub fn from_stream(fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
let mut frequency_divisor_buffer: [u8; 1] = [0];
|
let mut frequency_divisor_buffer: [u8; 1] = [0];
|
||||||
drop(fp.read(&mut frequency_divisor_buffer));
|
drop(fp.read(&mut frequency_divisor_buffer));
|
||||||
let sample_rate: u32 = 1000000u32 / (256u32 - frequency_divisor_buffer[0] as u32);
|
let sample_rate: u32 = 1000000u32 / (256u32 - frequency_divisor_buffer[0] as u32);
|
||||||
|
@ -250,7 +266,13 @@ impl SoundData {
|
||||||
let mut data: Vec<u8> = vec![0; (end_address - address) as usize];
|
let mut data: Vec<u8> = vec![0; (end_address - address) as usize];
|
||||||
drop(fp.read(&mut data));
|
drop(fp.read(&mut data));
|
||||||
|
|
||||||
Self::new(sample_rate, codec, data)
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
|
block_type: BlockType::SoundData,
|
||||||
|
sample_rate,
|
||||||
|
codec,
|
||||||
|
data,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +294,7 @@ impl Block for SoundData {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SoundData {
|
impl fmt::Debug for SoundData {
|
||||||
|
@ -287,24 +310,29 @@ impl fmt::Debug for SoundData {
|
||||||
// SoundDataContinuation
|
// SoundDataContinuation
|
||||||
|
|
||||||
pub struct SoundDataContinuation {
|
pub struct SoundDataContinuation {
|
||||||
pub block_type: BlockType,
|
info: Option<BlockInfo>,
|
||||||
pub data: Vec<u8>,
|
block_type: BlockType,
|
||||||
|
data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SoundDataContinuation {
|
impl SoundDataContinuation {
|
||||||
pub fn new(data: Vec<u8>) -> Self {
|
pub fn new(data: Vec<u8>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
info: None,
|
||||||
block_type: BlockType::SoundDataContinuation,
|
block_type: BlockType::SoundDataContinuation,
|
||||||
data,
|
data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn from_stream(fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
pub fn from_stream(fp: &mut File, end_address: u32) -> Self {
|
|
||||||
let address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
let address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
||||||
let mut data: Vec<u8> = vec![0; (end_address - address) as usize];
|
let mut data: Vec<u8> = vec![0; (end_address - address) as usize];
|
||||||
drop(fp.read(&mut data));
|
drop(fp.read(&mut data));
|
||||||
|
|
||||||
Self::new(data)
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
|
block_type: BlockType::SoundDataContinuation,
|
||||||
|
data,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,12 +343,13 @@ impl Block for SoundDataContinuation {
|
||||||
self.block_type as u8,
|
self.block_type as u8,
|
||||||
size_bytes[0],
|
size_bytes[0],
|
||||||
size_bytes[1],
|
size_bytes[1],
|
||||||
size_bytes[2]
|
size_bytes[2],
|
||||||
];
|
];
|
||||||
|
|
||||||
result.extend_from_slice(&self.data);
|
result.extend_from_slice(&self.data);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for SoundDataContinuation {
|
impl fmt::Debug for SoundDataContinuation {
|
||||||
|
@ -334,21 +363,22 @@ impl fmt::Debug for SoundDataContinuation {
|
||||||
// Silence
|
// Silence
|
||||||
|
|
||||||
pub struct Silence {
|
pub struct Silence {
|
||||||
pub block_type: BlockType,
|
info: Option<BlockInfo>,
|
||||||
pub length: u16,
|
block_type: BlockType,
|
||||||
pub sample_rate: u32,
|
length: u16,
|
||||||
|
sample_rate: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Silence {
|
impl Silence {
|
||||||
pub fn new(length: u16, sample_rate: u32) -> Self {
|
pub fn new(length: u16, sample_rate: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
info: None,
|
||||||
block_type: BlockType::Silence,
|
block_type: BlockType::Silence,
|
||||||
length,
|
length,
|
||||||
sample_rate
|
sample_rate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn from_stream(fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
pub fn from_stream(fp: &mut File, _end_address: u32) -> Self {
|
|
||||||
let mut length_buffer: [u8; 2] = [0; 2];
|
let mut length_buffer: [u8; 2] = [0; 2];
|
||||||
drop(fp.read(&mut length_buffer));
|
drop(fp.read(&mut length_buffer));
|
||||||
let length = u16::from_le_bytes(length_buffer) + 1;
|
let length = u16::from_le_bytes(length_buffer) + 1;
|
||||||
|
@ -357,7 +387,12 @@ impl Silence {
|
||||||
drop(fp.read(&mut frequency_divisor_buffer));
|
drop(fp.read(&mut frequency_divisor_buffer));
|
||||||
let sample_rate: u32 = 1000000u32 / (256u32 - frequency_divisor_buffer[0] as u32);
|
let sample_rate: u32 = 1000000u32 / (256u32 - frequency_divisor_buffer[0] as u32);
|
||||||
|
|
||||||
Self::new(length, sample_rate)
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
|
block_type: BlockType::Silence,
|
||||||
|
length,
|
||||||
|
sample_rate,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,6 +414,7 @@ impl Block for Silence {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Silence {
|
impl fmt::Debug for Silence {
|
||||||
|
@ -393,6 +429,7 @@ impl fmt::Debug for Silence {
|
||||||
// Marker
|
// Marker
|
||||||
|
|
||||||
pub struct Marker {
|
pub struct Marker {
|
||||||
|
info: Option<BlockInfo>,
|
||||||
block_type: BlockType,
|
block_type: BlockType,
|
||||||
value: u16,
|
value: u16,
|
||||||
}
|
}
|
||||||
|
@ -400,17 +437,21 @@ pub struct Marker {
|
||||||
impl Marker {
|
impl Marker {
|
||||||
pub fn new(value: u16) -> Self {
|
pub fn new(value: u16) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
info: None,
|
||||||
block_type: BlockType::Marker,
|
block_type: BlockType::Marker,
|
||||||
value
|
value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn from_stream(fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
pub fn from_stream(fp: &mut File, _end_address: u32) -> Self {
|
|
||||||
let mut value_buffer: [u8; 2] = [0; 2];
|
let mut value_buffer: [u8; 2] = [0; 2];
|
||||||
drop(fp.read(&mut value_buffer));
|
drop(fp.read(&mut value_buffer));
|
||||||
let value = u16::from_le_bytes(value_buffer);
|
let value = u16::from_le_bytes(value_buffer);
|
||||||
|
|
||||||
Self::new(value)
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
|
block_type: BlockType::Marker,
|
||||||
|
value,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,6 +471,7 @@ impl Block for Marker {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Marker {
|
impl fmt::Debug for Marker {
|
||||||
|
@ -443,24 +485,23 @@ impl fmt::Debug for Marker {
|
||||||
// Text
|
// Text
|
||||||
|
|
||||||
pub struct Text {
|
pub struct Text {
|
||||||
block_type: BlockType,
|
pub info: Option<BlockInfo>,
|
||||||
|
pub block_type: BlockType,
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Text {
|
impl Text {
|
||||||
pub fn new(data: Vec<u8>) -> Self {
|
pub fn new(data: Vec<u8>) -> Self { Self { info: None, block_type: BlockType::Text, data } }
|
||||||
Self {
|
pub fn from_stream(fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
block_type: BlockType::Text,
|
|
||||||
data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_stream(fp: &mut File, end_address: u32) -> Self {
|
|
||||||
let address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
let address = fp.seek(SeekFrom::Current(0)).unwrap() as u32;
|
||||||
let mut data: Vec<u8> = vec![0; (end_address - address) as usize];
|
let mut data: Vec<u8> = vec![0; (end_address - address) as usize];
|
||||||
drop(fp.read(&mut data));
|
drop(fp.read(&mut data));
|
||||||
|
|
||||||
Self::new(data)
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
|
block_type: BlockType::Text,
|
||||||
|
data,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,6 +520,7 @@ impl Block for Text {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Text {
|
impl fmt::Debug for Text {
|
||||||
|
@ -492,24 +534,29 @@ impl fmt::Debug for Text {
|
||||||
// RepeatStart
|
// RepeatStart
|
||||||
|
|
||||||
pub struct RepeatStart {
|
pub struct RepeatStart {
|
||||||
|
info: Option<BlockInfo>,
|
||||||
block_type: BlockType,
|
block_type: BlockType,
|
||||||
pub count: u16
|
count: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RepeatStart {
|
impl RepeatStart {
|
||||||
pub fn new(count: u16) -> Self {
|
pub fn new(count: u16) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
info: None,
|
||||||
block_type: BlockType::RepeatStart,
|
block_type: BlockType::RepeatStart,
|
||||||
count
|
count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn from_stream(fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
pub fn from_stream(fp: &mut File, _end_address: u32) -> Self {
|
|
||||||
let mut count_buffer: [u8; 2] = [0; 2];
|
let mut count_buffer: [u8; 2] = [0; 2];
|
||||||
drop(fp.read(&mut count_buffer));
|
drop(fp.read(&mut count_buffer));
|
||||||
let count = u16::from_le_bytes(count_buffer) + 1;
|
let count = u16::from_le_bytes(count_buffer) + 1;
|
||||||
|
|
||||||
Self::new(count)
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
|
block_type: BlockType::RepeatStart,
|
||||||
|
count,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,6 +576,7 @@ impl Block for RepeatStart {
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for RepeatStart {
|
impl fmt::Debug for RepeatStart {
|
||||||
|
@ -542,16 +590,17 @@ impl fmt::Debug for RepeatStart {
|
||||||
// RepeatEnd
|
// RepeatEnd
|
||||||
|
|
||||||
pub struct RepeatEnd {
|
pub struct RepeatEnd {
|
||||||
block_type: BlockType
|
info: Option<BlockInfo>,
|
||||||
|
block_type: BlockType,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RepeatEnd {
|
impl RepeatEnd {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self { Self { info: None, block_type: BlockType::RepeatEnd } }
|
||||||
Self { block_type: BlockType::RepeatEnd }
|
pub fn from_stream(_fp: &mut File, start_address: u32, end_address: u32) -> Self {
|
||||||
}
|
Self {
|
||||||
|
info: Some(BlockInfo { start_address, end_address }),
|
||||||
pub fn from_stream(_fp: &mut File, _end_address: u32) -> Self {
|
block_type: BlockType::RepeatEnd,
|
||||||
Self::new()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,6 +608,7 @@ impl Block for RepeatEnd {
|
||||||
fn to_bytes(&self) -> Vec<u8> {
|
fn to_bytes(&self) -> Vec<u8> {
|
||||||
vec![self.block_type as u8]
|
vec![self.block_type as u8]
|
||||||
}
|
}
|
||||||
|
fn get_info(&self) -> &Option<BlockInfo> { &self.info }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for RepeatEnd {
|
impl fmt::Debug for RepeatEnd {
|
||||||
|
|
Loading…
Reference in New Issue