1use crate::utils::{check_for_overwrite, has_extension, iter_files};
4use anyhow::{Context, Error, Result};
5use clap::Args;
6use lsdj::{
7 fs::{File, Filesystem, Index},
8 lsdsng::LsdSng,
9 name::Name,
10 serde::CompressBlockError,
11 song::SongMemory,
12 sram::SRam,
13};
14use std::path::PathBuf;
15
16#[derive(Args)]
18#[clap(author, version, about = "Import .lsdsng's into a .sav file", long_about = None)]
19pub struct ImportArgs {
20 song: Vec<PathBuf>,
22
23 #[clap(short, long)]
25 output: PathBuf,
26}
27
28pub fn import(args: ImportArgs) -> Result<()> {
30 let mut index = 0u8;
31 let mut sram = SRam::new();
32
33 for entry in iter_files(&args.song, true, &["lsdsng", "sav"]) {
34 let path = entry.path();
35
36 if index == Filesystem::FILES_CAPACITY as u8 {
37 return Err(Error::msg(
38 "Reached the maximum file limit. Aborting import.",
39 ));
40 }
41
42 if has_extension(path, "lsdsng") {
43 let lsdsng = LsdSng::from_path(path).context("Could not load {path}")?;
44 let song = lsdsng
45 .decompress()
46 .context(format!("Could not decompress {}", path.to_string_lossy()))?;
47
48 insert(&mut sram, index, &lsdsng.name()?, lsdsng.version(), &song)?;
49
50 println!("{:02} => {}", index, path.to_string_lossy());
51
52 index += 1;
53 } else if has_extension(path, "sav") {
54 let sav = SRam::from_path(path)
55 .context(format!("Could not open {}", path.to_string_lossy()))?;
56
57 for (source_index, file) in sav.filesystem.files().enumerate() {
58 if let Some(file) = file {
59 let song = file.decompress().context(format!(
60 "Could not decompress file {} from {}",
61 source_index,
62 path.to_string_lossy()
63 ))?;
64
65 let name = file.name()?;
66
67 insert(&mut sram, index, &name, file.version(), &song)?;
68
69 println!(
70 "{:02} => {} - {}",
71 index,
72 path.to_string_lossy(),
73 name.as_str(),
74 );
75
76 index += 1;
77 }
78 }
79 }
80 }
81
82 if check_for_overwrite(&args.output)? {
83 sram.to_path(&args.output).context(format!(
84 "Could not write SRAM to {}",
85 args.output.to_string_lossy()
86 ))?;
87
88 println!("Wrote {}", args.output.to_string_lossy());
89 }
90
91 Ok(())
92}
93
94fn insert(
95 sram: &mut SRam,
96 index: u8,
97 name: &Name<8>,
98 version: u8,
99 song: &SongMemory,
100) -> Result<()> {
101 match sram
102 .filesystem
103 .insert_file(Index::new(index), name, version, song)
104 {
105 Err(CompressBlockError::NoBlockLeft) => {
106 Err(Error::msg("Ran out of space in the SRAM memory"))
107 }
108 result => {
109 result.context("Could not insert song")?;
110 Ok(())
111 }
112 }
113}