use crate::cell_note::CellNote;
use crate::import::patternslot::PatternSlot;
use crate::pitch::Pitch;
use bincode::error::DecodeError;
use alloc::vec::Vec;
impl PatternSlot {
pub fn load_xm(src: &[u8]) -> Result<(&[u8], PatternSlot), DecodeError> {
let mut dst: [u8; 5] = [0; 5];
let mut i = 0;
let mut j = 0;
let note = src[i];
i += 1;
if note & 0b1000_0000 != 0 {
dst[j] = if note & 0b0000_0001 != 0 {
i += 1;
src[i - 1]
} else {
0
};
j += 1;
dst[j] = if note & 0b0000_0010 != 0 {
i += 1;
src[i - 1]
} else {
0
};
j += 1;
dst[j] = if note & 0b0000_0100 != 0 {
i += 1;
src[i - 1]
} else {
0
};
j += 1;
dst[j] = if note & 0b0000_1000 != 0 {
i += 1;
src[i - 1]
} else {
0
};
j += 1;
dst[j] = if note & 0b0001_0000 != 0 {
i += 1;
src[i - 1]
} else {
0
};
} else {
dst[j] = note;
j += 1;
dst[j] = src[i];
i += 1;
j += 1;
dst[j] = src[i];
i += 1;
j += 1;
dst[j] = src[i];
i += 1;
j += 1;
dst[j] = src[i];
i += 1;
}
Ok((
&src[i..],
PatternSlot {
note: {
if dst[0] == 97 {
CellNote::KeyOff
} else if dst[0] == 0 {
CellNote::Empty
} else {
match Pitch::try_from(dst[0] - 1) {
Ok(p) => CellNote::Play(p),
Err(_) => CellNote::Empty,
}
}
},
instrument: {
if dst[1] != 0 {
Some(dst[1] as usize - 1)
} else {
None
}
},
volume: dst[2],
effect_type: dst[3],
effect_parameter: dst[4],
},
))
}
pub fn save_xm_unpack(&self) -> Vec<u8> {
let mut bytes: [u8; 5] = [0; 5];
bytes[0] = cell_note_to_xm_byte(&self.note);
bytes[1] = {
if let Some(instr) = self.instrument {
(instr + 1) as u8
} else {
0
}
};
bytes[2] = self.volume;
bytes[3] = self.effect_type;
bytes[4] = self.effect_parameter;
bytes.to_vec()
}
pub fn save_xm(&self) -> Vec<u8> {
let mut bytes: [u8; 5] = [0; 5];
bytes[0] = cell_note_to_xm_byte(&self.note);
bytes[1] = {
if let Some(instr) = self.instrument {
(instr + 1) as u8
} else {
0
}
};
bytes[2] = self.volume;
bytes[3] = self.effect_type;
bytes[4] = self.effect_parameter;
let mut dst: [u8; 5] = [0; 5];
let mut pack_bits = 0;
let mut i = 1;
if bytes[0] > 0 {
pack_bits |= 0b0001;
dst[i] = bytes[0];
i += 1;
} if bytes[1] > 0 {
pack_bits |= 0b0010;
dst[i] = bytes[1];
i += 1;
} if bytes[2] > 0 {
pack_bits |= 0b0100;
dst[i] = bytes[2];
i += 1;
} if bytes[3] > 0 {
pack_bits |= 0b1000;
dst[i] = bytes[3];
i += 1;
}
if pack_bits == 15 {
return bytes.to_vec();
}
if bytes[4] > 0 {
pack_bits |= 16;
dst[i] = bytes[4];
i += 1;
} dst[0] = pack_bits | 0b1000_0000;
dst[0..i].to_vec()
}
}
fn cell_note_to_xm_byte(n: &CellNote) -> u8 {
match n {
CellNote::Empty => 0,
CellNote::Play(p) => p.value() + 1,
CellNote::KeyOff => 97,
CellNote::NoteCut | CellNote::NoteFade => 0,
}
}