Moved psxcdgen files to tools folder

This commit is contained in:
2022-08-21 13:20:53 +02:00
parent 69074600cc
commit 37a7c582e7
41 changed files with 0 additions and 84 deletions

View File

@@ -0,0 +1,9 @@
[package]
name = "psxcdread"
version = "0.5.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cdtypes = {path = "../cdtypes"}

View File

@@ -0,0 +1,137 @@
use cdtypes::{Error, cd::{sector::Sector, CD}};
pub fn check_edc(cd: &CD, sector_id: usize) -> Result<(), Error> {
if let Some(sector) = cd.get_sector(sector_id) {
if let Some((edc, _)) = sector.get_error_correction() {
let mut sector = (*sector).clone();
sector.calculate_edc();
if let Some(calc_edc) = sector.get_edc() {
println!("ISO EDC is: {}", edc);
println!("Calculated EDC is: {}", calc_edc);
}
}
else {
println!("No EDC");
}
Ok(())
}
else {
Err(Error::GenericError(format!("Sector {} not found", sector_id)))
}
}
pub fn check_ecc(cd: &CD, sector_id: usize) -> Result<(), Error> {
if let Some(sector) = cd.get_sector(sector_id) {
if let Some((_, Some(ecc))) = sector.get_error_correction() {
let mut sector = (*sector).clone();
sector.calculate_ecc();
if let Some(calc_ecc) = sector.get_ecc() {
if ecc == calc_ecc {
println!("ECC is same");
}
else {
println!("ECC is different");
}
}
}
else {
println!("No ECC");
}
Ok(())
}
else {
Err(Error::GenericError(format!("Sector {} not found", sector_id)))
}
}
pub fn dump(cd: &CD) -> Result<(), Error> {
println!("{}", cd.get_primary_volume_descriptor()?);
Ok(())
}
pub fn dump_root_dir_rec(cd: &CD, detailed: bool) -> Result<(), Error> {
let root_dir = cd.get_primary_volume_descriptor()?.get_root_dir_record();
dump_dir_rec(cd, root_dir.data_block_number.read_any() as usize, detailed)
}
pub fn dump_dir_rec(cd: &CD, sector_id: usize, detailed: bool) -> Result<(), Error> {
for entry in cd.directory_record_iter(sector_id) {
if detailed {
println!("{}", entry)
}
else {
let type_name = {
if entry.is_file() {
"File"
}
else {
"Directory"
}
};
println!("{}: {} @{}", type_name, entry.get_name(), entry.data_block_number.read_any());
}
}
Ok(())
}
pub fn dump_path_table(cd: &CD) -> Result<(), Error> {
let mut number = 1usize;
for entry in cd.path_table_iter() {
println!("{}.) {}", number, entry);
number += 1;
}
Ok(())
}
pub fn dump_stats(cd: &CD) -> Result<(), Error> {
let mut audio_count = 0;
let mut mode0_count = 0;
let mut mode1_count = 0;
let mut mode2form1_count = 0;
let mut mode2form2_count = 0;
for sector in cd.sector_iter() {
match sector {
Sector::Audio(_) => audio_count += 1,
Sector::Empty(_) => mode0_count += 1,
Sector::CDData(_) => mode1_count += 1,
Sector::CDXAData(_) => mode2form1_count += 1,
Sector::CDXAAudio(_) => mode2form2_count += 1,
}
}
println!("Audio: {}\nMode0: {}\nMode1: {}\nMode2Form1: {}\nMode2Form2: {}", audio_count, mode0_count, mode1_count, mode2form1_count, mode2form2_count);
Ok(())
}
pub fn dump_tracks(cd: &CD) -> Result<(), Error> {
if cd.has_tracks() {
let mut track_count = 1;
for track_info in cd.track_info_iter() {
println!("Track {:02}: {:<10} @{}", track_count, track_info.r#type, track_info.start);
track_count += 1;
}
}
else {
println!("Track 01");
}
Ok(())
}

View File

@@ -0,0 +1 @@
pub mod complex_dump;

View File

@@ -0,0 +1,379 @@
use psxcdread::{*};
use cdtypes::{Error, cd::CD, types::{cue, sector::SECTOR_SIZE}};
use std::{fs::OpenOptions, io::{stdin, stdout, Write}, path::{Path, PathBuf}};
fn open_file(path: &Path, write_access: bool) -> Result<std::fs::File, Error> {
match OpenOptions::new().read(true).write(write_access).create(write_access).open(path) {
Ok(file) => Ok(file),
Err(error) => {
let path = {
if let Some(path) = path.to_str() {
path.to_owned()
}
else {
"<Invalid encoded file path>".to_owned()
}
};
Err(Error::IOError(Some(path), error))
}
}
}
fn open_cue(file: std::fs::File, cue_path: &Path) -> Result<CD, Error> {
fn get_bin_path(specifier: &Vec<cue::Specifier>, cue_path: &Path) -> Result<Option<PathBuf>, Error> {
for specifier in specifier {
match specifier {
cue::Specifier::File{path, format} => {
if matches!(format, cue::Format::Binary) {
let mut bin_path = cue_path.to_path_buf();
if let Some(_) = bin_path.file_name() {
bin_path.pop();
}
bin_path.push(path);
return Ok(Some(bin_path));
}
else {
return Err(Error::GenericError("Only binary CUE files are supported".to_owned()));
}
},
_ => ()
}
}
Ok(None)
}
let specifier = cue::read::read(file)?;
if let Some(bin_path) = get_bin_path(&specifier, cue_path)? {
Ok(CD::from_file(open_file(bin_path.as_path(), false)?, Some(specifier))?)
}
else {
Err(Error::GenericError("No binary file specified".to_owned()))
}
}
fn open_cd(path: &str) -> Result<CD, Error> {
fn is_cue(path: &Path) -> bool {
if let Some(extension) = path.extension() {
extension == "cue"
}
else {
false
}
}
let path = Path::new(path);
let file = open_file(path, false)?;
if is_cue(&path) {
open_cue(file, &path)
}
else {
Ok(CD::from_file(file, None)?)
}
}
fn read_input(cd: &CD, cur_sec: usize) -> Result<String, std::io::Error> {
println!("Current Sector: [{}/{}]", cur_sec, cd.last_sector_idx());
stdout().write("> ".as_bytes())?;
stdout().flush()?;
let mut input = String::new();
stdin().read_line(&mut input)?;
Ok(input)
}
enum ChangeSectorNumMode {
Increment,
Decrement,
Absolute
}
fn get_number_from_str(number_str: &str) -> Option<usize> {
let (number, base) = {
if number_str.starts_with("0x") {
(number_str.trim_start_matches("0x"), 16)
}
else {
(number_str, 10)
}
};
if let Ok(number) = usize::from_str_radix(number, base) {
Some(number)
}
else {
None
}
}
fn change_sector_number(mode: ChangeSectorNumMode, cd: &CD, mut cur_sec: usize, mut iter: std::str::Split<&str>) -> usize {
if let Some(number) = iter.next() {
let last_sec = cd.last_sector_idx();
if let Some(number) = get_number_from_str(number) {
let new_sec = {
match mode {
ChangeSectorNumMode::Increment => cur_sec + number,
ChangeSectorNumMode::Decrement => cur_sec - number,
ChangeSectorNumMode::Absolute => number
}
};
if new_sec <= last_sec {
cur_sec = new_sec;
}
else {
println!("{} is higher then last valid index which is {}", new_sec, last_sec);
}
}
else {
println!("{} is no valid number", number);
}
}
cur_sec
}
fn write_data(cd: &CD, cur_sec: usize, mut iter: std::str::Split<&str>) -> Result<(), Error> {
if let Some(number_str) = iter.next() {
let file_name = {
let mut file_name = String::new();
for str_part in iter {
file_name.push_str(str_part);
file_name.push(' ');
}
file_name
};
if !file_name.is_empty() {
if let Some(number) = get_number_from_str(number_str) {
let mut file = open_file(Path::new(file_name.as_str()), true)?;
for i in 0..number {
if let Some(sector) = cd.get_sector(cur_sec + i) {
file.write(sector.get_data())?;
}
else {
return Err(Error::GenericError(format!("Failed writing sector {} - data incomplete", (cur_sec + i))));
}
}
Ok(())
}
else {
Err(Error::GenericError(format!("{} is not a valid number", number_str)))
}
}
else {
Err(Error::GenericError(format!("No output file specified")))
}
}
else {
Err(Error::GenericError(format!("Sector count not specified")))
}
}
fn dump(cd: &CD, cur_sec: usize, dump_ecc: bool) {
if let Some(sector) = cd.get_sector(cur_sec) {
let header: &dyn std::fmt::Display = {
if let Some(header) = sector.get_header() {
header
}
else {
&"<No Header>"
}
};
let sub_header = sector.get_sub_header();
println!("{}:", sector.get_friendly_name());
println!("Header: {}", header);
match sub_header {
Some(sub_header) => println!("SubHeader: {}", sub_header),
None => println!("SubHeader: <None>")
}
let (data_offset, data_size) = sector.get_data_offset_with_size();
let data_start = (cur_sec*SECTOR_SIZE) + data_offset;
println!("Data: at 0x{:X} - 0x{:x} ({} Bytes)", data_start, (data_start + data_size - 1), data_size);
let (edc, ecc) = {
if let Some(error_cor) = sector.get_error_correction() {
(Some(error_cor.0), error_cor.1)
}
else {
(None, None)
}
};
println!("EDC: {}\nECC:\n{}", {
if let Some(edc) = &edc {
edc
}
else {
&"<none>" as &dyn std::fmt::Display
}
}, {
if dump_ecc {
if let Some(ecc) = &ecc {
ecc
}
else {
&"<none>" as &dyn std::fmt::Display
}
}
else {
&"<run \"d ecc\">" as &dyn std::fmt::Display
}
});
}
}
fn handle_complex(cd: &CD, cur_sec: usize, mut iter: std::str::Split<&str>) -> Result<(), Error> {
let handle_dir_parms = |iter| {
let mut dump_root = false;
let mut dump_detail = false;
for cmd in iter {
match cmd {
"root" => dump_root = true,
"-d" => dump_detail = true,
_ => return Err(Error::GenericError(format!("Unkown option {}", cmd)))
}
}
Ok((dump_root, dump_detail))
};
if let Some(cmd) = iter.next() {
match cmd {
"pvd" => complex_dump::dump(&cd),
"dir" => {
let (dump_root, dump_detail) = handle_dir_parms(iter)?;
if dump_root {
complex_dump::dump_root_dir_rec(&cd, dump_detail)
}
else {
complex_dump::dump_dir_rec(&cd, cur_sec, dump_detail)
}
},
"path" => {
complex_dump::dump_path_table(&cd)
},
"edc" => complex_dump::check_edc(&cd, cur_sec),
"ecc" => complex_dump::check_ecc(&cd, cur_sec),
"stats" => complex_dump::dump_stats(&cd),
"tracks" => complex_dump::dump_tracks(&cd),
"?" => {
println!("pvd Dump Primary Volume Descriptor");
println!("dir [root] [-d] Dumps current sector as Directory Record or the Root Directory Record");
println!("path Dumps any PathTable");
println!("edc ");
println!("ecc ");
println!("stats Lists statistics about all sectors");
println!("tracks Lists all the tracks of this CD");
return Ok(());
},
_ => {
println!("Unkown command {} - try cplx ?", cmd);
return Ok(());
}
}
}
else {
Err(Error::GenericError("No command found".to_string()))
}
}
fn main() {
let file = {
match std::env::args().skip(1).next()
{
Some(file) => file,
None => {
println!("psxcdread <path fo file>");
return;
}
}
};
let mut sec_idx = 0;
let cd = {
match open_cd(file.as_str()) {
Ok(cd) => cd,
Err(error) => {
println!("Readin CD failed with: {}", error);
return;
}
}
};
loop {
match read_input(&cd, sec_idx) {
Ok(input) => {
let mut iter = input.trim().split(" ");
if let Some(cmd) = iter.next() {
match cmd {
"" => (),
">" => sec_idx = change_sector_number(ChangeSectorNumMode::Increment, &cd, sec_idx, iter),
"<" => sec_idx = change_sector_number(ChangeSectorNumMode::Decrement, &cd, sec_idx, iter),
"!" => sec_idx = change_sector_number(ChangeSectorNumMode::Absolute, &cd, sec_idx, iter),
"d" => dump(&cd, sec_idx, {
if let Some(cmd) = iter.next() {
cmd == "ecc"
}
else {
false
}
}),
"w" => {
if let Err(txt) = write_data(&cd, sec_idx, iter) {
println!("{}", txt);
}
},
"cplx" => {
if let Err(txt) = handle_complex(&cd, sec_idx, iter) {
println!("{}", txt);
}
}
"q" => return,
"?" => {
println!("> <number> move number sectors forward");
println!("< <number> move number sectors backward");
println!("! <number> move to sector number");
println!("d dump current sector");
println!("cplx <sub command> dumps extended infos");
println!("w <sector count> <file path> writes the data of the sectos to a file");
println!("q exit programm");
},
_ => println!("Unkown CMD: \"{}\"", cmd)
}
}
},
Err(error) => {
println!("Reading input failed with: {}", error);
return;
}
}
}
}