/*----------------------------------------------------------------------------*/ /*-- converted from cdrom.inc with https://c2rust.com/ --*/ /*-- Rebuild CD sector fields --*/ /*-- Copyright (C) 2012 CUE --*/ /*-- --*/ /*-- This program is free software: you can redistribute it and/or modify --*/ /*-- it under the terms of the GNU General Public License as published by --*/ /*-- the Free Software Foundation, either version 3 of the License, or --*/ /*-- (at your option) any later version. --*/ /*-- --*/ /*-- This program is distributed in the hope that it will be useful, --*/ /*-- but WITHOUT ANY WARRANTY; without even the implied warranty of --*/ /*-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --*/ /*-- GNU General Public License for more details. --*/ /*-- --*/ /*-- You should have received a copy of the GNU General Public License --*/ /*-- along with this program. If not, see . --*/ /*----------------------------------------------------------------------------*/ #![allow(dead_code, mutable_transmutes, non_camel_case_types, non_snake_case, non_upper_case_globals, unused_assignments, unused_mut)] use libc; /*----------------------------------------------------------------------------*/ #[no_mangle] static mut CDROM_crc: [libc::c_uint; 256] = [0; 256]; #[no_mangle] static mut CDROM_exp: [libc::c_uchar; 256] = [0; 256]; #[no_mangle] static mut CDROM_log: [libc::c_uchar; 256] = [0; 256]; #[no_mangle] static mut CDROM_enabled: libc::c_uint = 0 as libc::c_int as libc::c_uint; /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Init_Tables() { let mut edc: libc::c_uint = 0; let mut ecc: libc::c_uint = 0; let mut i: libc::c_uint = 0; let mut j: libc::c_uint = 0; i = 0 as libc::c_int as libc::c_uint; while i < 0x100 as libc::c_int as libc::c_uint { edc = i; j = 0 as libc::c_int as libc::c_uint; while j < 8 as libc::c_int as libc::c_uint { edc = if edc & 1 as libc::c_int as libc::c_uint != 0 { (edc >> 1 as libc::c_int) ^ 0xd8018001 as libc::c_uint } else { (edc) >> 1 as libc::c_int }; j = j.wrapping_add(1) } CDROM_crc[i as usize] = edc; ecc = if i & 0x80 as libc::c_int as libc::c_uint != 0 { (i << 1 as libc::c_int) ^ 0x11d as libc::c_int as libc::c_uint } else { (i) << 1 as libc::c_int }; CDROM_exp[i as usize] = ecc as libc::c_uchar; CDROM_log[(i ^ ecc) as usize] = i as libc::c_uchar; i = i.wrapping_add(1) } } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_NUM2BCD(mut value: libc::c_char) -> libc::c_char { return ((value as libc::c_int / 10 as libc::c_int) << 4 as libc::c_int | value as libc::c_int % 10 as libc::c_int) as libc::c_char; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_BCD2NUM(mut value: libc::c_char) -> libc::c_char { return ((value as libc::c_int >> 4 as libc::c_int) * 10 as libc::c_int | value as libc::c_int & 0xf as libc::c_int) as libc::c_char; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Update(mut sector: *mut libc::c_char, mut lba: libc::c_int, mut cdmode: libc::c_int, mut flags: libc::c_int, mut check: libc::c_int) -> libc::c_int { if CDROM_enabled == 0 { CDROM_Init_Tables(); CDROM_enabled = 1 as libc::c_int as libc::c_uint } if check != 0 && CDROM_Check(sector, cdmode) != 0 { return 1 as libc::c_int; } match cdmode { 1 => { CDROM_Put_Sync(sector.offset(0 as libc::c_int as isize)); CDROM_Put_Header(sector.offset(0xc as libc::c_int as isize), lba, cdmode); CDROM_Put_Intermediate(sector.offset(0x814 as libc::c_int as isize)); CDROM_Put_EDC(sector.offset(0 as libc::c_int as isize), 0x810 as libc::c_int, sector.offset(0x810 as libc::c_int as isize)); CDROM_Put_ECC_P(sector.offset(0xc as libc::c_int as isize), sector.offset(0x81c as libc::c_int as isize)); CDROM_Put_ECC_Q(sector.offset(0xc as libc::c_int as isize), sector.offset(0x8c8 as libc::c_int as isize)); } 2 => { CDROM_Put_Sync(sector.offset(0 as libc::c_int as isize)); CDROM_Put_Header(sector.offset(0xc as libc::c_int as isize), lba, cdmode); } 21 => { CDROM_Put_Sync(sector.offset(0 as libc::c_int as isize)); //CDROM_Put_Header(sector + POS_HEADER, lba, cdmode); CDROM_Put_SubHeader(sector.offset(0x10 as libc::c_int as isize), flags); CDROM_Put_EDC(sector.offset(0x10 as libc::c_int as isize), 0x808 as libc::c_int, sector.offset(0x818 as libc::c_int as isize)); *(sector.offset(0xc as libc::c_int as isize) as *mut libc::c_uint) = 0 as libc::c_int as libc::c_uint; CDROM_Put_ECC_P(sector.offset(0xc as libc::c_int as isize), sector.offset(0x81c as libc::c_int as isize)); CDROM_Put_ECC_Q(sector.offset(0xc as libc::c_int as isize), sector.offset(0x8c8 as libc::c_int as isize)); CDROM_Put_Header(sector.offset(0xc as libc::c_int as isize), lba, cdmode); } 22 => { CDROM_Put_Sync(sector.offset(0 as libc::c_int as isize)); CDROM_Put_Header(sector.offset(0xc as libc::c_int as isize), lba, cdmode); CDROM_Put_SubHeader(sector.offset(0x10 as libc::c_int as isize), flags); CDROM_Put_EDC(sector.offset(0x10 as libc::c_int as isize), 0x91c as libc::c_int, sector.offset(0x92c as libc::c_int as isize)); } _ => {} } return 0 as libc::c_int; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Check(mut sector: *mut libc::c_char, mut cdmode: libc::c_int) -> libc::c_int { let mut tmp1: libc::c_int = 0; let mut tmp2: libc::c_int = 0; let mut tmp3: libc::c_int = 0; match cdmode { 1 => { if *(sector.offset(0 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff00 as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffffff as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(8 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff as libc::c_int as libc::c_uint { return 1 as libc::c_int; } if *sector.offset(0xf as libc::c_int as isize) as libc::c_int != 1 as libc::c_int { return 1 as libc::c_int; } if *(sector.offset(0x814 as libc::c_int as isize) as *mut libc::c_int) != 0 { return 1 as libc::c_int; } if *(sector.offset(0x814 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_int) != 0 { return 1 as libc::c_int; } } 2 => { if *(sector.offset(0 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff00 as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffffff as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(8 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff as libc::c_int as libc::c_uint { return 1 as libc::c_int; } if *sector.offset(0xf as libc::c_int as isize) as libc::c_int != 2 as libc::c_int { return 1 as libc::c_int; } } 21 => { if *(sector.offset(0 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff00 as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffffff as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(8 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff as libc::c_int as libc::c_uint { return 1 as libc::c_int; } if *sector.offset(0xf as libc::c_int as isize) as libc::c_int != 2 as libc::c_int { return 1 as libc::c_int; } tmp1 = *(sector.offset(0x10 as libc::c_int as isize) as *mut libc::c_int); tmp2 = *(sector.offset(0x10 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_int); tmp3 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x20 as libc::c_int; if tmp1 == 0 || tmp1 != tmp2 || tmp3 != 0 { return 1 as libc::c_int; } tmp1 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x2 as libc::c_int; tmp2 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x4 as libc::c_int; tmp3 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x8 as libc::c_int; if tmp1 != 0 && (tmp2 != 0 || tmp3 != 0) { return 1 as libc::c_int; } if tmp2 != 0 && (tmp3 != 0 || tmp1 != 0) { return 1 as libc::c_int; } if tmp3 != 0 && (tmp1 != 0 || tmp2 != 0) { return 1 as libc::c_int; } } 22 => { if *(sector.offset(0 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff00 as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffffff as libc::c_uint { return 1 as libc::c_int; } if *(sector.offset(0 as libc::c_int as isize).offset(8 as libc::c_int as isize) as *mut libc::c_uint) != 0xffffff as libc::c_int as libc::c_uint { return 1 as libc::c_int; } if *sector.offset(0xf as libc::c_int as isize) as libc::c_int != 2 as libc::c_int { return 1 as libc::c_int; } tmp1 = *(sector.offset(0x10 as libc::c_int as isize) as *mut libc::c_int); tmp2 = *(sector.offset(0x10 as libc::c_int as isize).offset(4 as libc::c_int as isize) as *mut libc::c_int); tmp3 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x20 as libc::c_int; if tmp1 == 0 || tmp1 != tmp2 || tmp3 == 0 { return 1 as libc::c_int; } tmp1 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x2 as libc::c_int; tmp2 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x4 as libc::c_int; tmp3 = *sector.offset(0x12 as libc::c_int as isize) as libc::c_int & 0x8 as libc::c_int; if tmp1 != 0 && (tmp2 != 0 || tmp3 != 0) { return 1 as libc::c_int; } if tmp2 != 0 && (tmp3 != 0 || tmp1 != 0) { return 1 as libc::c_int; } if tmp3 != 0 && (tmp1 != 0 || tmp2 != 0) { return 1 as libc::c_int; } } _ => { return 1 as libc::c_int; } } return 0 as libc::c_int; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_Sync(mut source: *mut libc::c_char) { *(source as *mut libc::c_uint) = 0xffffff00 as libc::c_uint; *(source.offset(4 as libc::c_int as isize) as *mut libc::c_uint) = 0xffffffff as libc::c_uint; *(source.offset(8 as libc::c_int as isize) as *mut libc::c_uint) = 0xffffff as libc::c_int as libc::c_uint; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_Header(mut source: *mut libc::c_char, mut lba: libc::c_int, mut cdmode: libc::c_int) { lba += 150 as libc::c_int; *source = CDROM_NUM2BCD((lba / 75 as libc::c_int / 60 as libc::c_int) as libc::c_char); *source.offset(1 as libc::c_int as isize) = CDROM_NUM2BCD((lba / 75 as libc::c_int % 60 as libc::c_int) as libc::c_char); *source.offset(2 as libc::c_int as isize) = CDROM_NUM2BCD((lba % 75 as libc::c_int) as libc::c_char); *source.offset(3 as libc::c_int as isize) = cdmode as libc::c_char; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_SubHeader(mut source: *mut libc::c_char, mut flags: libc::c_int) { *(source as *mut libc::c_uint) = flags as libc::c_uint; *(source.offset(4 as libc::c_int as isize) as *mut libc::c_uint) = flags as libc::c_uint; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_Intermediate(mut source: *mut libc::c_char) { *(source as *mut libc::c_uint) = 0 as libc::c_int as libc::c_uint; *(source.offset(4 as libc::c_int as isize) as *mut libc::c_uint) = 0 as libc::c_int as libc::c_uint; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_EDC(mut source: *mut libc::c_char, mut length: libc::c_int, mut target: *mut libc::c_char) { let mut edc: libc::c_uint = 0; let mut i: libc::c_uint = 0; edc = 0 as libc::c_int as libc::c_uint; i = 0 as libc::c_int as libc::c_uint; while i < length as libc::c_uint { edc = edc >> 8 as libc::c_int ^ CDROM_crc[((edc ^ *source.offset(i as isize) as libc::c_uint) & 0xff as libc::c_int as libc::c_uint) as usize]; i = i.wrapping_add(1) } *(target as *mut libc::c_uint) = edc; } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_ECC_P(mut source: *mut libc::c_char, mut target: *mut libc::c_char) { let mut table: libc::c_uint = 0; let mut column: libc::c_uint = 0; let mut row: libc::c_uint = 0; let mut index: libc::c_uint = 0; let mut ecc: libc::c_uchar = 0; let mut xor: libc::c_uchar = 0; table = 0 as libc::c_int as libc::c_uint; while table < 2 as libc::c_int as libc::c_uint { column = 0 as libc::c_int as libc::c_uint; while column < 43 as libc::c_int as libc::c_uint { xor = 0 as libc::c_int as libc::c_uchar; ecc = xor; row = 0 as libc::c_int as libc::c_uint; while row < 24 as libc::c_int as libc::c_uint { index = (1 as libc::c_int as libc::c_uint) .wrapping_mul(column) .wrapping_add((43 as libc::c_int as libc::c_uint).wrapping_mul(row)) .wrapping_rem((24 as libc::c_int * 43 as libc::c_int) as libc::c_uint); ecc = (ecc as libc::c_int ^ *source.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(index).wrapping_add(table) as isize) as libc::c_int) as libc::c_uchar; ecc = CDROM_exp[ecc as usize]; xor = (xor as libc::c_int ^ *source.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(index).wrapping_add(table) as isize) as libc::c_int) as libc::c_uchar; row = row.wrapping_add(1) } ecc = CDROM_log[(CDROM_exp[ecc as usize] as libc::c_int ^ xor as libc::c_int) as usize]; *target.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(column).wrapping_add(table) as isize) = ecc as libc::c_char; *target.offset( (2 as libc::c_int as libc::c_uint) .wrapping_mul(column.wrapping_add(43 as libc::c_int as libc::c_uint)) .wrapping_add(table) as isize, ) = (ecc as libc::c_int ^ xor as libc::c_int) as libc::c_char; column = column.wrapping_add(1) } table = table.wrapping_add(1) } } /*----------------------------------------------------------------------------*/ #[no_mangle] unsafe extern "C" fn CDROM_Put_ECC_Q(mut source: *mut libc::c_char, mut target: *mut libc::c_char) { let mut table: libc::c_uint = 0; let mut row: libc::c_uint = 0; let mut column: libc::c_uint = 0; let mut index: libc::c_uint = 0; let mut ecc: libc::c_uchar = 0; let mut xor: libc::c_uchar = 0; table = 0 as libc::c_int as libc::c_uint; while table < 2 as libc::c_int as libc::c_uint { row = 0 as libc::c_int as libc::c_uint; while row < 26 as libc::c_int as libc::c_uint { xor = 0 as libc::c_int as libc::c_uchar; ecc = xor; column = 0 as libc::c_int as libc::c_uint; while column < 43 as libc::c_int as libc::c_uint { index = (43 as libc::c_int as libc::c_uint) .wrapping_mul(row) .wrapping_add(((1 as libc::c_int + 43 as libc::c_int) as libc::c_uint).wrapping_mul(column)) .wrapping_rem((26 as libc::c_int * 43 as libc::c_int) as libc::c_uint); ecc = (ecc as libc::c_int ^ *source.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(index).wrapping_add(table) as isize) as libc::c_int) as libc::c_uchar; ecc = CDROM_exp[ecc as usize]; xor = (xor as libc::c_int ^ *source.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(index).wrapping_add(table) as isize) as libc::c_int) as libc::c_uchar; column = column.wrapping_add(1) } ecc = CDROM_log[(CDROM_exp[ecc as usize] as libc::c_int ^ xor as libc::c_int) as usize]; *target.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(row).wrapping_add(table) as isize) = ecc as libc::c_char; *target.offset((2 as libc::c_int as libc::c_uint).wrapping_mul(row.wrapping_add(26 as libc::c_int as libc::c_uint)).wrapping_add(table) as isize) = (ecc as libc::c_int ^ xor as libc::c_int) as libc::c_char; row = row.wrapping_add(1) } table = table.wrapping_add(1) } } #[no_mangle] unsafe extern "C" fn Check_Image(mut sector: &[u8], mut length: *mut libc::c_int, mut offset: *mut libc::c_int, mut position: *mut libc::c_int) -> libc::c_int { let mut buffer: [u8; 8192] = [0; 8192]; let mut i: libc::c_int = 0; let mut n: libc::c_int = 0; let mut tabla: [[libc::c_int; 3]; 8] = [ [0 as libc::c_int, 0x800 as libc::c_int, 0 as libc::c_int], [1 as libc::c_int, 0x930 as libc::c_int, 0x10 as libc::c_int], [21 as libc::c_int, 0x930 as libc::c_int, 0x18 as libc::c_int], [1 as libc::c_int, 0x990 as libc::c_int, 0x10 as libc::c_int], [21 as libc::c_int, 0x990 as libc::c_int, 0x18 as libc::c_int], [1 as libc::c_int, 0x940 as libc::c_int, 0x10 as libc::c_int], [21 as libc::c_int, 0x940 as libc::c_int, 0x18 as libc::c_int], [-(1 as libc::c_int), -(1 as libc::c_int), -(1 as libc::c_int)], ]; n = 0 as libc::c_int; while n < 2 as libc::c_int { i = 0 as libc::c_int; while tabla[i as usize][0 as libc::c_int as usize] != -(1 as libc::c_int) { *length = tabla[i as usize][1 as libc::c_int as usize]; *position = tabla[i as usize][2 as libc::c_int as usize]; loop { *offset = *length * 150 as libc::c_int * n; //fseek(fp, *offset + 0x000010 * *length, SEEK_SET); //if (fread(buffer, 2, *length, fp) != *length) return -1; // manually implement above fseek+fread { let copy_start = (*offset + 0x000010 * *length) as usize; let copy_end = copy_start + (2 * *length) as usize; if copy_start >= sector.len() || copy_end >= sector.len() { return -1; } let src = §or[copy_start..copy_end]; &buffer[0..src.len()].copy_from_slice(src); } if *(buffer.as_mut_ptr().offset(*position as isize) as *mut libc::c_int) == 0x30444301 as libc::c_int { if *(buffer.as_mut_ptr().offset(*position as isize).offset(4 as libc::c_int as isize) as *mut libc::c_int) == 0x13130 as libc::c_int { if *(buffer.as_mut_ptr().offset(*position as isize).offset(*length as isize).offset(1 as libc::c_int as isize) as *mut libc::c_int) == 0x30304443 as libc::c_int { return tabla[i as usize][0 as libc::c_int as usize]; } } } if *position < 0x10 as libc::c_int { break; } *length -= 0x10 as libc::c_int; *position -= 0x10 as libc::c_int } i += 1 } n += 1 } return -(1 as libc::c_int); } /*----------------------------------------------------------------------------*/ /*-- EOF Copyright (C) 2012 CUE --*/ /*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ // above as you can see was roughly and unsafely converted from C, until I get around to cleaning that // mess up, write some slightly nicer and rustier APIs to use use anyhow::{bail, Result}; pub struct CDRomImage { mode: i32, length: usize, offset: usize, position: usize, } impl CDRomImage { pub fn new(bytes: &[u8]) -> Result { let mode: i32; let mut length = 0; let mut offset = 0; let mut position = 0; unsafe { mode = Check_Image(&bytes, &mut length, &mut offset, &mut position); } if mode == -1 { bail!("File not supported or invalid"); } Ok(CDRomImage { mode, length: length as usize, offset: offset as usize, position: position as usize, }) } pub fn update_sectors(&self, bytes: &mut [u8]) { unsafe { CDROM_Update(bytes.as_mut_ptr() as *mut i8, 0, self.mode, 0, 0); CDROM_Update(bytes[self.length..].as_mut_ptr() as *mut i8, 1, self.mode, 0, 0); } } pub fn debug(&self) { println!("mode: {}, length: {}, offset: {}, position: {}", self.mode, self.length, self.offset, self.position); } }