Upgrade clap and use format that can be repurposed in toml file

master
Ashley N. 2023-08-30 21:17:10 -04:00
parent ce41fc43a8
commit 421fe3bd14
6 changed files with 146 additions and 126 deletions

View File

@ -9,7 +9,7 @@ edition = "2018"
[dependencies] [dependencies]
image = "^0.23" image = "^0.23"
colour = "^0.5" colour = "^0.5"
clap = "^2.33" clap = { version = "^4.4.1", features = [ "derive" ] }
flate2 = "1.0.26" flate2 = "1.0.26"
samplerate = "0.2.4" samplerate = "0.2.4"
hound = "3.5.0" hound = "3.5.0"

View File

@ -4,134 +4,11 @@ extern crate clap;
extern crate colour; extern crate colour;
mod reskit; mod reskit;
use std::error::Error; use reskit::cli::evaluator::run_command;
use std::fs::File;
use std::io::Write;
use clap::{App, Arg, SubCommand};
use reskit::soundtrack::engines::echo::engine::EchoFormat;
use reskit::soundtrack::formats::dmf::DmfModule;
use reskit::utility; use reskit::utility;
use reskit::tileset;
use crate::reskit::utility::print_good;
fn run() -> Result<(), Box<dyn Error>> {
let matches = App::new( "reskit" )
.version( env!( "CARGO_PKG_VERSION" ) )
.author( "(c) 2021-2023 Ashley N. <ne0ndrag0n@ne0ndrag0n.com>" )
.about( "The Retro Entertainment Software Toolkit - Tools for authoring software for legacy video game systems" )
.subcommand(
SubCommand::with_name( "tileset" )
.about( "Generate a Sega Megadrive VDP tileset + palette from a 15-colour image" )
.arg_from_usage( "-i, --input=<FILE> 'Specify input image'" )
.arg_from_usage( "-o, --output=<FILE> 'Specify output file'")
.arg(
Arg::with_name( "FORMAT" )
.short( "f" )
.long( "format" )
.help( "Specify output format for tileset (valid options: bin, inc)")
.default_value( "bin" )
.takes_value( true )
)
.arg(
Arg::with_name( "TILEORDER" )
.short( "to" )
.long( "tile-order" )
.help( "Specify tile order for tileset (valid options: tile, sprite" )
.default_value( "tile" )
.takes_value( true )
)
)
.subcommand(
SubCommand::with_name( "soundtrack" )
.about( "Generate an on-console soundtrack from a chiptune tracker module" )
.arg_from_usage( "-i, --input=<FILE> 'Specify input module'" )
.arg_from_usage( "-o, --output=<FILE> 'Specify output filename (may output multiple files depending on format)'")
.arg(
Arg::with_name( "ARTIFACT_OUTPUT_DIRECTORY" )
.long( "artifact-output-directory" )
.help( "Specify directory to output secondary artifacts (e.g. instruments)" )
.default_value( "./" )
.takes_value( true )
)
.arg(
Arg::with_name( "SOUNDTRACK_LABEL" )
.long( "soundtrack-label" )
.help( "In sound drivers supporting generated boilerplate, specify label to use for soundtrack" )
.default_value( "MuzPlaceholder1" )
.takes_value( true )
)
.arg(
Arg::with_name( "TRACKER_FORMAT" )
.long( "tracker-format" )
.help( "Specify tracker module format (valid options: dmf (DefleMask Tracker))")
.default_value( "dmf" )
.takes_value( true )
)
.arg(
Arg::with_name( "DRIVER_FORMAT" )
.long( "driver-format" )
.help( "Specify on-console sound driver format (valid options: esf (Echo))")
.default_value( "esf" )
.takes_value( true )
)
.arg(
Arg::with_name( "EXPORT_INSTRUMENT_LIST_LABEL" )
.long( "instrument-list-label" )
.help( "In sound drivers supporting generated boilerplate, specify label to use for instrument list" )
.default_value( "MuzInstrumentList" )
.takes_value( true )
)
.arg(
Arg::with_name( "EXPORT_INSTRUMENT_LIST_FORMAT" )
.long( "instrument-list-format" )
.help( "In sound drivers supporting generated boilerplate, specify output format for instrument list" )
.default_value( "asmx" )
.takes_value( true )
)
)
.get_matches();
if let Some( matches ) = matches.subcommand_matches( "tileset" ) {
let input_filename = matches.value_of( "input" ).ok_or( "expected: input filename (-i,--input)" )?;
let output_filename = matches.value_of( "output" ).ok_or( "expected: output_filename (-o,--output)" )?;
tileset::generate(
input_filename,
output_filename,
matches.value_of( "FORMAT" ).unwrap(),
matches.value_of( "TILEORDER" ).unwrap()
);
Ok( () )
} else if let Some( matches ) = matches.subcommand_matches( "soundtrack" ) {
let input_filename = matches.value_of( "input" ).ok_or( "expected: input filename (-i,--input)" )?;
let output_filename = matches.value_of( "output" ).ok_or( "expected: output_filename (-o,--output)" )?;
let result = DmfModule::from_file( &input_filename )?;
let artifact_path = matches.value_of( "ARTIFACT_OUTPUT_DIRECTORY" ).unwrap_or( "./" );
let soundtrack_label = matches.value_of( "SOUNDTRACK_LABEL" ).unwrap_or( "MuzPlaceholder1" );
for ( filename, data ) in result.get_artifacts( soundtrack_label, output_filename, artifact_path, matches.value_of( "EXPORT_INSTRUMENT_LIST_LABEL" ).ok_or( "internal error" )? )? {
println!( "Creating artifact file {}{}", artifact_path, filename );
let mut file = File::create( format!( "{}{}", artifact_path, filename ) )?;
file.write_all( &data )?
}
println!( "Creating ESF output file {}", output_filename );
let mut file = File::create( output_filename )?;
file.write_all( &result.get_esf()? )?;
print_good( &format!( "successfully compiled soundtrack for {}", output_filename ) );
Ok( () )
} else {
Err( "no tool provided (try --help)" )?
}
}
fn main() { fn main() {
if let Err( error ) = run() { if let Err( error ) = run_command() {
utility::print_error( &format!( "{}", error ) ); utility::print_error( &format!( "{}", error ) );
} }
} }

View File

@ -0,0 +1,41 @@
use std::{error::Error, fs::File, io::Write};
use clap::Parser;
use crate::reskit::{tileset, soundtrack::{formats::dmf::DmfModule, engines::echo::engine::EchoFormat}, utility::print_good};
use super::settings::{Args, Tools, TileOutputFormat, TileOrder};
pub fn run_command() -> Result<(), Box<dyn Error>> {
let cli = Args::parse();
match cli.tool {
Tools::Tileset { input_file, output_file, format, tile_order } =>
tileset::generate(
&input_file,
&output_file,
match format {
TileOutputFormat::Bin => "bin",
TileOutputFormat::Inc => "inc"
},
match tile_order {
TileOrder::Tile => "tile",
TileOrder::Sprite => "sprite"
}
),
Tools::Soundtrack { input_file, output_file, input_format: _, output_format: _, source_file_format: _, artifact_output_directory, soundtrack_label, instrument_list_label } => {
let result = DmfModule::from_file( &input_file )?;
for ( filename, data ) in result.get_artifacts( &soundtrack_label, &output_file, &artifact_output_directory, &instrument_list_label )? {
println!( "Creating artifact file {}{}", artifact_output_directory, filename );
let mut file = File::create( format!( "{}{}", artifact_output_directory, filename ) )?;
file.write_all( &data )?
}
println!( "Creating ESF output file {}", output_file );
let mut file = File::create( &output_file )?;
file.write_all( &result.get_esf()? )?;
print_good( &format!( "successfully compiled soundtrack for {}", output_file ) );
}
};
Ok( () )
}

2
src/reskit/cli/mod.rs Normal file
View File

@ -0,0 +1,2 @@
pub mod evaluator;
pub mod settings;

View File

@ -0,0 +1,99 @@
use clap::{Parser, Subcommand, ValueEnum};
#[derive(Parser)]
#[command(name = "reskit")]
#[command(version = env!("CARGO_PKG_VERSION"))]
#[command(long_about = "reskit\nThe Retro Entertainment Software Toolkit - Utilities for authoring software for legacy video game systems\n(c) 2023 Ashley N. (ne0ndrag0n)")]
pub struct Args {
#[command(subcommand)]
pub tool: Tools
}
#[derive(Clone, ValueEnum)]
pub enum TileOrder {
Tile,
Sprite
}
#[derive(Clone, ValueEnum)]
pub enum TileOutputFormat {
Bin,
Inc
}
#[derive(Clone, ValueEnum)]
pub enum SequenceFormat {
Dmf
}
#[derive(Clone, ValueEnum)]
pub enum DriverFormat {
Esf
}
#[derive(Clone, ValueEnum)]
pub enum ArtifactListFormat {
Asmx
}
#[derive(Subcommand)]
pub enum Tools {
#[command(name = "tileset")]
#[command(about = "Generate a set of tiles from an input image. Supports Sega Mega Drive VDP output format.")]
Tileset {
/// Input filename
#[arg(short, long)]
input_file: String,
/// Output filename
#[arg(short, long)]
output_file: String,
/// Output format
#[arg(short, long, value_enum, default_value_t=TileOutputFormat::Bin)]
format: TileOutputFormat,
/// Tile order
#[arg(short, long, value_enum, default_value_t=TileOrder::Tile)]
tile_order: TileOrder
},
#[command(name = "soundtrack")]
#[command(about = "Generate a console-compatible soundtrack from a sequence file.")]
Soundtrack {
/// Input filename
#[arg(short, long)]
input_file: String,
/// Output filename
#[arg(short, long)]
output_file: String,
/// Input sequence file format (the kind of tracker used to compose the track)
#[arg(long, value_enum, default_value_t=SequenceFormat::Dmf)]
input_format: SequenceFormat,
/// Output console file format (the sound driver your console uses)
#[arg(long, value_enum, default_value_t=DriverFormat::Esf)]
output_format: DriverFormat,
/// Output format for the generated source file linking soundtracks and instruments
#[arg(long, value_enum, default_value_t=ArtifactListFormat::Asmx)]
source_file_format: ArtifactListFormat,
/// Directory to output artifacts (instruments and samples)
#[arg(long, default_value_t=String::from( "./" ))]
artifact_output_directory: String,
/// Identifier used for the soundtrack in the generated source file
#[arg(long, default_value_t=String::from( "MuzPlaceholder1" ))]
soundtrack_label: String,
/// Identifier used for the soundtrack's artifacts in the generated source file
#[arg(long, default_value_t=String::from( "MuzInstrumentList" ))]
instrument_list_label: String
}
}

View File

@ -1,3 +1,4 @@
pub mod cli;
pub mod soundtrack; pub mod soundtrack;
pub mod tileset; pub mod tileset;
pub mod utility; pub mod utility;