From f133b26283c937b4ce6629e2c114dafd13b8178b Mon Sep 17 00:00:00 2001 From: jaby Date: Wed, 14 Aug 2024 16:07:17 -0500 Subject: [PATCH] Prototype implementation of TMD license --- src/Tools/psxcdgen_ex/src/encoder/cd.rs | 96 +++++++++++++++++-------- 1 file changed, 68 insertions(+), 28 deletions(-) diff --git a/src/Tools/psxcdgen_ex/src/encoder/cd.rs b/src/Tools/psxcdgen_ex/src/encoder/cd.rs index 8e75ab02..f6b75098 100644 --- a/src/Tools/psxcdgen_ex/src/encoder/cd.rs +++ b/src/Tools/psxcdgen_ex/src/encoder/cd.rs @@ -163,11 +163,32 @@ pub fn encode_image(cd_desc: &CDDesc, sec_writer: &mut dyn SectorWriter) -> Resu } fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { - fn write_license_file(sec_writer: &mut dyn SectorWriter, mut license_file: BufferedInputFile) -> Result<(), Error> { - fn write_data_zeros(sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { - write_dummy(sec_writer, 4) - } + fn write_data_zeros(sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { + write_dummy(sec_writer, 4) + } + fn write_audio_zeros(sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { + for _ in 0..4 { + let sector = { + let mut sector = builder::create_xa_audio_zero(0); + + sector.sub_header.sub_mode.clear_audio(); + sector + }; + sec_writer.write_cd_xa_audio(sector)?; + } + + Ok(()) + } + + fn write_license_string_raw(sec_writer: &mut dyn SectorWriter, data: &[u8; Mode2Form1::DATA_SIZE]) -> Result { + let sub_mode = SubModeBuilder::new_mode1().create(); + let sector = builder::create_xa_data_for_raw(sub_mode, data); + + sec_writer.write_cd_xa_data(sector) + } + + fn write_license_file(sec_writer: &mut dyn SectorWriter, mut license_file: BufferedInputFile) -> Result<(), Error> { fn write_license_string(sec_writer: &mut dyn SectorWriter, license_file: &mut BufferedInputFile) -> Result<(), Error> { const LICENSE_STRING_START:u64 = 0x2488; @@ -179,11 +200,8 @@ fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWrit license_file.seek(SeekFrom::Start(LICENSE_STRING_START))?; license_file.read(&mut license_string_buffer)?; - - let sub_mode = SubModeBuilder::new_mode1().create(); - let sector = builder::create_xa_data_for_raw(sub_mode, &license_string_buffer); - sec_writer.write_cd_xa_data(sector)?; + write_license_string_raw(sec_writer, &license_string_buffer)?; Ok(()) } @@ -211,28 +229,49 @@ fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWrit Ok(()) } - fn write_audio_zeros(sec_writer: &mut dyn SectorWriter) -> Result<(), Error> { - for _ in 0..4 { - let sector = { - let mut sector = builder::create_xa_audio_zero(0); - - sector.sub_header.sub_mode.clear_audio(); - sector - }; - sec_writer.write_cd_xa_audio(sector)?; - } - - Ok(()) - } - format_if_error!(write_data_zeros(sec_writer), "Writing license data zeros failed with: {error_text}")?; format_if_error!(write_license_string(sec_writer, &mut license_file), "Writing license string from file failed with: {error_text}")?; format_if_error!(write_license_logo(sec_writer, &mut license_file), "Writing license logo from file failed with: {error_text}")?; - format_if_error!(write_audio_zeros(sec_writer), "Writing license audio zeros failed with: {error_text}")?; - - Ok(()) + format_if_error!(write_audio_zeros(sec_writer), "Writing license audio zeros failed with: {error_text}") } + fn write_tmd_file(sec_writer: &mut dyn SectorWriter, tmd_file: BufferedInputFile) -> Result<(), Error> { + fn write_license_string(sec_writer: &mut dyn SectorWriter, text: &str) -> Result<(), Error> { + let mut license_string_buffer = [0u8; Mode2Form1::DATA_SIZE]; + + license_string_buffer[..Mode2Form1::DATA_SIZE].copy_from_slice(text[0..text.len()].as_bytes()); + write_license_string_raw(sec_writer, &license_string_buffer)?; + Ok(()) + } + + fn write_license_logo(sec_writer: &mut dyn SectorWriter, mut tmd_file: BufferedInputFile) -> Result<(), Error> { + let bytes = { + let mut bytes = vec![]; + tmd_file.read_to_end(&mut bytes)?; + bytes + }; + let mut sectors = builder::create_xa_data_for_vec(Some(SubModeBuilder::new_mode1().create()), &bytes); + // TODO: Buhu magic number!! + if sectors.len() > 8 { + return Err(Error::from_str("Provided TMD file for alt-license is larger then 8 sectors of data")); + } + + while sectors.len() < 8 { + sectors.push(builder::create_xa_data_zero()); + } + + for sector in sectors { + sec_writer.write_cd_xa_data(sector)?; + } + Ok(()) + } + + format_if_error!(write_data_zeros(sec_writer), "Writing alt-license data zeros failed with: {error_text}")?; + format_if_error!(write_license_string(sec_writer, "Not licensed by Sony"), "Writing alt-license string from file failed with: {error_text}")?; + format_if_error!(write_license_logo(sec_writer, tmd_file), "Writing alt-license logo from file failed with: {error_text}")?; + format_if_error!(write_audio_zeros(sec_writer), "Writing alt-license audio zeros failed with: {error_text}") + } + let system_area_lba = system_area.lba.get_track_relative(); if system_area_lba != 0 { return Err(Error::from_text(format!("System Area required to start at sector 0 of Track - found LBA: {}", system_area_lba))); @@ -243,10 +282,11 @@ fn process_system_area(system_area: &SystemArea, sec_writer: &mut dyn SectorWrit let license_file = format_if_error!(open_input_file_buffered(license_path), "Loading license file from {} failed with: {error_text}", license_path.to_string_lossy())?; write_license_file(sec_writer, license_file) }, - LicenseFile::TMD(_) => { - Err(Error::from_str("Support of TMD not supported yet")) + LicenseFile::TMD(tmd_path) => { + let tmd_file = format_if_error!(open_input_file_buffered(tmd_path), "Loading TMD file from {} failed with: {error_text}", tmd_path.to_string_lossy())?; + write_tmd_file(sec_writer, tmd_file) }, - LicenseFile::None => { + LicenseFile::None => { // No license specified - filling it with zeros print_warning("WARNING: No license file provided. Some emulators (like No$PSX) will not boot this CD.".to_owned()); write_dummy(sec_writer, size_of::SYSTEM_AREA_SECTOR_COUNT)