Generate EIF files

master
Ashley N. 2023-08-19 21:36:18 -04:00
parent 029b7d654a
commit e55f9e3fe8
3 changed files with 103 additions and 43 deletions

View File

@ -89,6 +89,13 @@ fn run() -> Result<(), Box<dyn Error>> {
file.write_all( &data )?
}
let eif_files = result.get_eifs()?;
for ( filename, data ) in eif_files {
println!( "Creating EIF instrument file {}", filename );
let mut file = File::create( filename )?;
file.write_all( &data )?
}
// TODO !!
Ok( () )

View File

@ -1,6 +1,6 @@
use std::{error::Error, fs::File, io::Read, convert::TryInto, collections::HashMap, cmp::{min, max}};
use flate2::read::ZlibDecoder;
use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, Ring}, soundtrack::{types::{SampleRate, SampleFormat, PsgEnvelope, Note, Sample, PsgSettings}, engines::echo::EchoFormat}};
use crate::reskit::{utility::{get_string, get_u8, skip, get_u32, get_i8, get_i32, get_u16, get_i16, Ring, print_warning}, soundtrack::{types::{SampleRate, SampleFormat, PsgEnvelope, Note, Sample, PsgSettings}, engines::echo::EchoFormat}};
const DMF_MAGIC_NUMBER: &'static str = ".DelekDefleMask.";
const DMF_SUPPORTED_VERSION: u8 = 27;
@ -377,35 +377,6 @@ impl DmfModule {
}
// Operator 3
{
operators[ 2 ].am = get_u8( bytes.by_ref() )?;
operators[ 2 ].ar = get_u8( bytes.by_ref() )?;
operators[ 2 ].dr = get_u8( bytes.by_ref() )?;
operators[ 2 ].mult = get_u8( bytes.by_ref() )?;
operators[ 2 ].rr = get_u8( bytes.by_ref() )?;
operators[ 2 ].sl = get_u8( bytes.by_ref() )?;
operators[ 2 ].tl = get_u8( bytes.by_ref() )?;
operators[ 2 ].dt2 = get_u8( bytes.by_ref() )?;
operators[ 2 ].rs = get_u8( bytes.by_ref() )?;
operators[ 2 ].dt = get_i8( bytes.by_ref() )? - 3;
operators[ 2 ].d2r = get_u8( bytes.by_ref() )?;
operators[ 2 ].ssg_mode = get_u8( bytes.by_ref() )?;
println!( "Op 3 AM:\t{}", operators[ 2 ].am );
println!( "Op 3 AR:\t{}", operators[ 2 ].ar );
println!( "Op 3 DR:\t{}", operators[ 2 ].dr );
println!( "Op 3 MULT:\t{}", operators[ 2 ].mult );
println!( "Op 3 RR:\t{}", operators[ 2 ].rr );
println!( "Op 3 SL:\t{}", operators[ 2 ].sl );
println!( "Op 3 TL:\t{}", operators[ 2 ].tl );
println!( "Op 3 DT2:\t{}", operators[ 2 ].dt2 );
println!( "Op 3 RS:\t{}", operators[ 2 ].rs );
println!( "Op 3 DT:\t{}", operators[ 2 ].dt );
println!( "Op 3 D2R:\t{}", operators[ 2 ].d2r );
println!( "Op 3 SSG_MODE:\t{}\n", operators[ 2 ].ssg_mode );
}
// Operator 2
{
operators[ 1 ].am = get_u8( bytes.by_ref() )?;
operators[ 1 ].ar = get_u8( bytes.by_ref() )?;
@ -420,18 +391,47 @@ impl DmfModule {
operators[ 1 ].d2r = get_u8( bytes.by_ref() )?;
operators[ 1 ].ssg_mode = get_u8( bytes.by_ref() )?;
println!( "Op 2 AM:\t{}", operators[ 1 ].am );
println!( "Op 2 AR:\t{}", operators[ 1 ].ar );
println!( "Op 2 DR:\t{}", operators[ 1 ].dr );
println!( "Op 2 MULT:\t{}", operators[ 1 ].mult );
println!( "Op 2 RR:\t{}", operators[ 1 ].rr );
println!( "Op 2 SL:\t{}", operators[ 1 ].sl );
println!( "Op 2 TL:\t{}", operators[ 1 ].tl );
println!( "Op 2 DT2:\t{}", operators[ 1 ].dt2 );
println!( "Op 2 RS:\t{}", operators[ 1 ].rs );
println!( "Op 2 DT:\t{}", operators[ 1 ].dt );
println!( "Op 2 D2R:\t{}", operators[ 1 ].d2r );
println!( "Op 2 SSG_MODE:\t{}\n", operators[ 1 ].ssg_mode );
println!( "Op 3 AM:\t{}", operators[ 1 ].am );
println!( "Op 3 AR:\t{}", operators[ 1 ].ar );
println!( "Op 3 DR:\t{}", operators[ 1 ].dr );
println!( "Op 3 MULT:\t{}", operators[ 1 ].mult );
println!( "Op 3 RR:\t{}", operators[ 1 ].rr );
println!( "Op 3 SL:\t{}", operators[ 1 ].sl );
println!( "Op 3 TL:\t{}", operators[ 1 ].tl );
println!( "Op 3 DT2:\t{}", operators[ 1 ].dt2 );
println!( "Op 3 RS:\t{}", operators[ 1 ].rs );
println!( "Op 3 DT:\t{}", operators[ 1 ].dt );
println!( "Op 3 D2R:\t{}", operators[ 1 ].d2r );
println!( "Op 3 SSG_MODE:\t{}\n", operators[ 1 ].ssg_mode );
}
// Operator 2
{
operators[ 2 ].am = get_u8( bytes.by_ref() )?;
operators[ 2 ].ar = get_u8( bytes.by_ref() )?;
operators[ 2 ].dr = get_u8( bytes.by_ref() )?;
operators[ 2 ].mult = get_u8( bytes.by_ref() )?;
operators[ 2 ].rr = get_u8( bytes.by_ref() )?;
operators[ 2 ].sl = get_u8( bytes.by_ref() )?;
operators[ 2 ].tl = get_u8( bytes.by_ref() )?;
operators[ 2 ].dt2 = get_u8( bytes.by_ref() )?;
operators[ 2 ].rs = get_u8( bytes.by_ref() )?;
operators[ 2 ].dt = get_i8( bytes.by_ref() )? - 3;
operators[ 2 ].d2r = get_u8( bytes.by_ref() )?;
operators[ 2 ].ssg_mode = get_u8( bytes.by_ref() )?;
println!( "Op 2 AM:\t{}", operators[ 2 ].am );
println!( "Op 2 AR:\t{}", operators[ 2 ].ar );
println!( "Op 2 DR:\t{}", operators[ 2 ].dr );
println!( "Op 2 MULT:\t{}", operators[ 2 ].mult );
println!( "Op 2 RR:\t{}", operators[ 2 ].rr );
println!( "Op 2 SL:\t{}", operators[ 2 ].sl );
println!( "Op 2 TL:\t{}", operators[ 2 ].tl );
println!( "Op 2 DT2:\t{}", operators[ 2 ].dt2 );
println!( "Op 2 RS:\t{}", operators[ 2 ].rs );
println!( "Op 2 DT:\t{}", operators[ 2 ].dt );
println!( "Op 2 D2R:\t{}", operators[ 2 ].d2r );
println!( "Op 2 SSG_MODE:\t{}\n", operators[ 2 ].ssg_mode );
}
// Operator 4
@ -747,7 +747,56 @@ impl EchoFormat for DmfModule {
// Create feedback + algorithm byte
let alg_fb: u8 = ( settings.fb << 3 ) | settings.alg;
todo!()
// The operators are laid out as FmOperator objects in order 1 -> 3 -> 2 -> 4
// EIF instrument layout below
let mut mult_dt: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
let mut tl: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
let mut ar_rs: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
let mut dr_am: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
let mut sr: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
let mut rr_sl: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
let mut ssg_eg: [u8; 4] = [ 0x00, 0x00, 0x00, 0x00 ];
// Likewise, "operators" is laid out 1 -> 3 -> 2 -> 4
for i in 0..4 {
let dt: u8 = match settings.operators[ i ].dt {
0 => 0b000,
1 => 0b001,
2 => 0b010,
3 => 0b011,
-1 => 0b101,
-2 => 0b110,
-3 => 0b111,
_ => return Err( "invalid file: invalid value given for dt" )?
};
// https://plutiedev.com/ym2612-registers
// https://github.com/sikthehedgehog/Echo/blob/master/doc/eif.txt
mult_dt[ i ] = ( dt << 4 ) | settings.operators[ i ].mult;
tl[ i ] = settings.operators[ i ].tl;
ar_rs[ i ] = ( settings.operators[ i ].rs << 6 ) | settings.operators[ i ].ar;
dr_am[ i ] = ( settings.operators[ i ].am << 7 ) | settings.operators[ i ].dr;
sr[ i ] = settings.operators[ i ].d2r; // "Sometimes also called 'second decay rate' (D2R)."
rr_sl[ i ] = ( settings.operators[ i ].sl << 4 ) | settings.operators[ i ].rr;
if settings.operators[ i ].ssg_mode > 0 {
print_warning( &format!( "SSG-EG mode set on instrument {}, operator {}. this operator may not work on clone hardware or certain emulators", instrument.name, i ) );
}
ssg_eg[ i ] = settings.operators[ i ].ssg_mode;
}
let mut eif: Vec<u8> = Vec::new();
eif.push( alg_fb );
eif.extend( mult_dt );
eif.extend( tl );
eif.extend( ar_rs );
eif.extend( dr_am );
eif.extend( sr );
eif.extend( rr_sl );
eif.extend( ssg_eg );
eifs.insert( format!( "{}.eif", instrument.name), eif );
}
}

View File

@ -45,6 +45,10 @@ pub fn print_good( message: &str ) {
green!( "success: " ); println!( "{}", message );
}
pub fn print_warning( message: &str ) {
yellow!( "warning: " ); println!( "{}", message );
}
pub fn get_string( bytes: &mut Iter<'_, u8>, take: usize ) -> Result<String, Box<dyn Error>> {
let took = bytes.take( take );
let took: Vec<u8> = took.cloned().collect();