Basic project suport
This commit is contained in:
parent
e3ed4a3b43
commit
4ea7575057
File diff suppressed because it is too large
Load Diff
|
@ -34,5 +34,8 @@ hound = "3.5.1"
|
||||||
paste = "1.0.15"
|
paste = "1.0.15"
|
||||||
png = "0.17.16"
|
png = "0.17.16"
|
||||||
rubato = "0.16.1"
|
rubato = "0.16.1"
|
||||||
|
serde = {version = "1.0.219", features = ["derive"]}
|
||||||
|
serde_json = "1.0"
|
||||||
symphonia = {version = "0.5.4", optional = true, default-features = false}
|
symphonia = {version = "0.5.4", optional = true, default-features = false}
|
||||||
|
tim_tool = {path = "../tim_tool"}
|
||||||
tool_helper = {path = "../tool_helper"}
|
tool_helper = {path = "../tool_helper"}
|
||||||
|
|
|
@ -23,7 +23,7 @@ pub struct Point {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Point {
|
impl Point {
|
||||||
pub const POINT_VALUE_NAME:&'static str = "{x,y}";
|
pub const POINT_VALUE_NAME:&'static str = "{x,y}";
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for Point {
|
impl std::default::Default for Point {
|
||||||
|
|
|
@ -9,13 +9,13 @@ use tool_helper::{Error, Input};
|
||||||
#[derive(Args)]
|
#[derive(Args)]
|
||||||
pub struct Arguments {
|
pub struct Arguments {
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
global: super::args::Arguments,
|
pub(crate) global: super::args::Arguments,
|
||||||
|
|
||||||
#[clap(long, value_parser, default_value_t, value_name = Point::POINT_VALUE_NAME)]
|
#[clap(long, value_parser, default_value_t, value_name = Point::POINT_VALUE_NAME)]
|
||||||
clut_pos: Point,
|
pub(crate) clut_pos: Point,
|
||||||
|
|
||||||
#[clap(long, value_parser, default_value_t, value_name = Point::POINT_VALUE_NAME)]
|
#[clap(long, value_parser, default_value_t, value_name = Point::POINT_VALUE_NAME)]
|
||||||
tex_pos: Point,
|
pub(crate) tex_pos: Point,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert(args: Arguments, input: Input, output: &mut dyn Write) -> Result<(), Error> {
|
pub fn convert(args: Arguments, input: Input, output: &mut dyn Write) -> Result<(), Error> {
|
||||||
|
|
|
@ -1,3 +1,67 @@
|
||||||
pub mod audio;
|
pub mod audio;
|
||||||
pub mod images;
|
pub mod images;
|
||||||
pub mod nothing;
|
pub mod nothing;
|
||||||
|
pub mod project;
|
||||||
|
|
||||||
|
use crate::audio::*;
|
||||||
|
use crate::images::*;
|
||||||
|
|
||||||
|
use clap::Subcommand;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tool_helper::Error;
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
pub enum SubCommands {
|
||||||
|
Nothing,
|
||||||
|
SimpleTIM(reduced_tim::Arguments),
|
||||||
|
TIM(tim::Arguments),
|
||||||
|
VAG(vag::Arguments),
|
||||||
|
XA(xa::Arguments),
|
||||||
|
Project,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_subcommand(compress_lz4: bool, input_path: Option<PathBuf>, output_path: Option<PathBuf>, sub_command: SubCommands) -> Result<(), Error> {
|
||||||
|
let mut input = tool_helper::open_input(&input_path)?;
|
||||||
|
let mut buffer = Vec::<u8>::new();
|
||||||
|
let mut output_file = tool_helper::open_output(&output_path)?;
|
||||||
|
let dst_buffer = {
|
||||||
|
if compress_lz4 {
|
||||||
|
&mut buffer as &mut dyn std::io::Write
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
&mut output_file as &mut dyn std::io::Write
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let cmd_result: Result<(), Error> = {
|
||||||
|
match sub_command {
|
||||||
|
SubCommands::Nothing => nothing::copy(&mut input, dst_buffer),
|
||||||
|
SubCommands::SimpleTIM(args) => reduced_tim::convert(args, input, dst_buffer),
|
||||||
|
SubCommands::TIM(args) => tim::convert(args, input, dst_buffer),
|
||||||
|
SubCommands::VAG(args) => audio::vag::convert(args, &output_path, input, dst_buffer),
|
||||||
|
SubCommands::XA(args) => audio::xa::convert(args, input, dst_buffer),
|
||||||
|
SubCommands::Project => project::run_project(input, input_path, &output_path),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(cmd_error) = cmd_result {
|
||||||
|
if let Some(file_path) = output_path {
|
||||||
|
let _result = std::fs::remove_file(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
tool_helper::print_warning("Open stream detected! Incomplete file can not be deleted".to_owned());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(cmd_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We encoded the file to a temporary buffer and now need to write it
|
||||||
|
if compress_lz4 {
|
||||||
|
let buffer = tool_helper::compress::psx_default::lz4(&buffer)?;
|
||||||
|
output_file.write(&buffer)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
use clap::{Parser, Subcommand};
|
use clap::Parser;
|
||||||
use psxfileconv::{audio::{self, *}, images::*, nothing};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tool_helper::{exit_with_error, Error};
|
use psxfileconv::{SubCommands, run_subcommand};
|
||||||
|
use tool_helper::exit_with_error;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(about = "Converts files to various JabyEngine related file formats", long_about = None)]
|
#[clap(about = "Converts files to various JabyEngine related file formats", long_about = None)]
|
||||||
struct CommandLine {
|
pub struct CommandLine {
|
||||||
#[clap(long="lz4", default_value_t=false)]
|
#[clap(long="lz4", default_value_t=false)]
|
||||||
compress_lz4: bool,
|
compress_lz4: bool,
|
||||||
|
|
||||||
|
@ -19,64 +19,10 @@ struct CommandLine {
|
||||||
sub_command: SubCommands,
|
sub_command: SubCommands,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
|
||||||
enum SubCommands {
|
|
||||||
Nothing,
|
|
||||||
SimpleTIM(reduced_tim::Arguments),
|
|
||||||
TIM(tim::Arguments),
|
|
||||||
VAG(vag::Arguments),
|
|
||||||
XA(xa::Arguments),
|
|
||||||
}
|
|
||||||
|
|
||||||
fn run_main(cmd: CommandLine) -> Result<(), Error> {
|
|
||||||
let mut input = tool_helper::open_input(&cmd.input_file)?;
|
|
||||||
let mut buffer = Vec::<u8>::new();
|
|
||||||
let mut output_file = tool_helper::open_output(&cmd.output_file)?;
|
|
||||||
let dst_buffer = {
|
|
||||||
if cmd.compress_lz4 {
|
|
||||||
&mut buffer as &mut dyn std::io::Write
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
&mut output_file as &mut dyn std::io::Write
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let cmd_result: Result<(), Error> = {
|
|
||||||
match cmd.sub_command {
|
|
||||||
SubCommands::Nothing => nothing::copy(&mut input, dst_buffer),
|
|
||||||
SubCommands::SimpleTIM(args) => reduced_tim::convert(args, input, dst_buffer),
|
|
||||||
SubCommands::TIM(args) => tim::convert(args, input, dst_buffer),
|
|
||||||
SubCommands::VAG(args) => audio::vag::convert(args, &cmd.output_file, input, dst_buffer),
|
|
||||||
SubCommands::XA(args) => audio::xa::convert(args, input, dst_buffer),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(cmd_error) = cmd_result {
|
|
||||||
if let Some(file_path) = cmd.output_file {
|
|
||||||
let _result = std::fs::remove_file(file_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
tool_helper::print_warning("Open stream detected! Incomplete file can not be deleted".to_owned());
|
|
||||||
}
|
|
||||||
|
|
||||||
return Err(cmd_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We encoded the file to a temporary buffer and now need to write it
|
|
||||||
if cmd.compress_lz4 {
|
|
||||||
let buffer = tool_helper::compress::psx_default::lz4(&buffer)?;
|
|
||||||
output_file.write(&buffer)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
match CommandLine::try_parse() {
|
match CommandLine::try_parse() {
|
||||||
Ok(cmd) => {
|
Ok(cmd) => {
|
||||||
if let Err(error) = run_main(cmd) {
|
if let Err(error) = run_subcommand(cmd.compress_lz4, cmd.input_file, cmd.output_file, cmd.sub_command) {
|
||||||
exit_with_error(error);
|
exit_with_error(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
use crate::images::args::{Arguments, ClutAlignment, ColorType};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tool_helper::{Error, Input};
|
||||||
|
use tim_tool::logic::{tim::types::Encoding, project::*};
|
||||||
|
|
||||||
|
pub fn run_project(input: Input, input_path: Option<PathBuf>, output_path: &Option<PathBuf>) -> Result<(), Error> {
|
||||||
|
let location_path = if let Some(input_path) = input_path {input_path} else {PathBuf::from(".")};
|
||||||
|
let output_path = if let Some(output_path) = &output_path {
|
||||||
|
let mut output_path = output_path.clone();
|
||||||
|
if output_path.is_file() {
|
||||||
|
output_path.pop();
|
||||||
|
}
|
||||||
|
output_path
|
||||||
|
} else {PathBuf::from(".")};
|
||||||
|
let project = serde_json::from_reader::<Input, Project>(input).map_err(|error|{Error::from_text(format!("Reading project failed: {}", error))})?;
|
||||||
|
|
||||||
|
for job in project.jobs {
|
||||||
|
let args = to_arguments(&job)?;
|
||||||
|
let output_path = {
|
||||||
|
let mut path = output_path.clone();
|
||||||
|
|
||||||
|
path.push(job.name);
|
||||||
|
path.set_extension("img");
|
||||||
|
path
|
||||||
|
};
|
||||||
|
|
||||||
|
let sub_command = crate::SubCommands::SimpleTIM(args);
|
||||||
|
crate::run_subcommand(job.settings.compress, Some(Job::create_file_path(job.file_path, &location_path)), Some(output_path), sub_command)?;
|
||||||
|
// Create .cpp file
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_arguments(job: &Job) -> Result<Arguments, Error> {
|
||||||
|
let (semi_transparent, transparent_palette) = get_transparency(&job.settings.transparency);
|
||||||
|
|
||||||
|
return Ok(Arguments {
|
||||||
|
color_depth: get_encoding(&job.settings.encoding),
|
||||||
|
clut_align: get_palette_rect(&job.palette_rect)?,
|
||||||
|
semi_transparent,
|
||||||
|
transparent_palette,
|
||||||
|
});
|
||||||
|
|
||||||
|
fn get_transparency(transparency: &Transparency) -> (bool, bool) {
|
||||||
|
match transparency {
|
||||||
|
Transparency::None => (false, false),
|
||||||
|
Transparency::FirstColor => (false, true),
|
||||||
|
Transparency::PSXSemi => (true, false),
|
||||||
|
Transparency::Both => (true, true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_encoding(encoding: &Encoding) -> ColorType {
|
||||||
|
match encoding {
|
||||||
|
Encoding::FourBit => ColorType::Clut4,
|
||||||
|
Encoding::EightBit => ColorType::Clut8,
|
||||||
|
Encoding::FullColor => ColorType::Full16,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_palette_rect(rect: &Option<PaletteRect>) -> Result<ClutAlignment, Error> {
|
||||||
|
if let Some(rect) = rect {
|
||||||
|
if rect.size.height == 1 {
|
||||||
|
return Ok(ClutAlignment::Linear);
|
||||||
|
}
|
||||||
|
|
||||||
|
if rect.size.width%16 == 0 {
|
||||||
|
return Ok(ClutAlignment::Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::from_text(format!("psxfileconv currently only supports linear or block CLUTs with a width of 16px")));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ClutAlignment::None)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue