use log::{trace,error};
use crate::img::disk35;
use crate::img::{names,DiskKind};
use crate::DYNERR;
pub fn get_phys_interleave(table: &[usize]) -> usize {
let first = table[0];
for rep in 1..table.len() {
if table[rep]==first+1 {
return rep;
}
}
panic!("bad physical skew table");
}
pub const CPM_1_LSEC_TO_PSEC: [u8;26] = [1,7,13,19,25,5,11,17,23,3,9,15,21,2,8,14,20,26,6,12,18,24,4,10,16,22];
pub const CPM_LSEC_TO_NABU_PSEC: [u8;26] = [1,8,15,22,3,10,17,24,5,12,19,26,7,14,21,2,9,16,23,4,11,18,25,6,13,20];
pub const CPM_LSEC_TO_OSB1_PSEC: [u8;10] = [1,3,5,7,9,2,4,6,8,10];
pub const CPM_LSEC_TO_DOS_LSEC: [usize;32] = [0,0,6,6,12,12,3,3,9,9,15,15,14,14,5,5,11,11,2,2,8,8,7,7,13,13,4,4,10,10,1,1];
pub const CPM_LSEC_TO_DOS_PSEC: [usize;32] = [0,0,3,3,6,6,9,9,12,12,15,15,2,2,5,5,8,8,11,11,14,14,1,1,4,4,7,7,10,10,13,13];
pub const CPM_LSEC_TO_DOS_OFFSET: [usize;32] = [0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128,0,128];
pub const D35_PHYSICAL: [[usize;12];5] = [
[0,3,6,9,1,4,7,10,2,5,8,11],
[0,3,6,9,1,4,7,10,2,5,8,0xff],
[0,5,3,8,1,6,4,9,2,7,0xff,0xff],
[0,7,5,3,1,8,6,4,2,0xff,0xff,0xff],
[0,2,4,6,1,3,5,7,0xff,0xff,0xff,0xff],
];
pub const DOS32_PHYSICAL: [usize;13] = [0,10,7,4,1,11,8,5,2,12,9,6,3];
pub const DOS_LSEC_TO_DOS_PSEC: [usize;16] = [0,13,11,9,7,5,3,1,14,12,10,8,6,4,2,15];
pub const DOS_PSEC_TO_DOS_LSEC: [usize;16] = [0,7,14,6,13,5,12,4,11,3,10,2,9,1,8,15];
pub fn prodos_block_from_ts(track: usize,sector: usize) -> Result<(usize,usize),DYNERR> {
let block_offset: [usize;16] = [0,7,6,6,5,5,4,4,3,3,2,2,1,1,0,7];
let byte_offset: [usize;16] = [0,0,256,0,256,0,256,0,256,0,256,0,256,0,256,256];
Ok((8*track + block_offset[sector], byte_offset[sector]))
}
pub fn ts_from_prodos_block(block: usize,kind: &DiskKind) -> Result<Vec<[usize;2]>,DYNERR> {
match *kind {
DiskKind::LogicalSectors(names::A2_DOS33) | names::A2_DOS33_KIND => {
let sector1: [usize;8] = [0,13,11,9,7,5,3,1];
let sector2: [usize;8] = [14,12,10,8,6,4,2,15];
let [track,sec1,sec2] = [block/8,sector1[block%8],sector2[block%8]];
trace!("locate block for 5.25 inch disk: track {}, sectors {},{}",track,sec1,sec2);
Ok(vec![[track,sec1],[track,sec2]])
},
names::A2_400_KIND => {
let zone = match block {
x if x<disk35::ZONE_BOUNDS_1[1] => 0,
x if x<disk35::ZONE_BOUNDS_1[2] => 1,
x if x<disk35::ZONE_BOUNDS_1[3] => 2,
x if x<disk35::ZONE_BOUNDS_1[4] => 3,
x if x<disk35::ZONE_BOUNDS_1[5] => 4,
_ => panic!("illegal block request")
};
let rel_block = block - disk35::ZONE_BOUNDS_1[zone];
let secs_per_track = disk35::ZONED_SECS_PER_TRACK[zone];
let track = 16 * zone + rel_block/secs_per_track;
let sector = rel_block%secs_per_track;
trace!("locate block for 3.5 inch disk: track {}, sector {}",track,sector);
Ok(vec![[track,sector]])
},
names::A2_800_KIND => {
let zone = match block {
x if x<disk35::ZONE_BOUNDS_2[1] => 0,
x if x<disk35::ZONE_BOUNDS_2[2] => 1,
x if x<disk35::ZONE_BOUNDS_2[3] => 2,
x if x<disk35::ZONE_BOUNDS_2[4] => 3,
x if x<disk35::ZONE_BOUNDS_2[5] => 4,
_ => panic!("illegal block request")
};
let rel_block = block - disk35::ZONE_BOUNDS_2[zone];
let secs_per_track = disk35::ZONED_SECS_PER_TRACK[zone];
let track = 32 * zone + rel_block/secs_per_track;
let sector = rel_block%secs_per_track;
trace!("locate block for 3.5 inch disk: track {}, sector {}",track,sector);
Ok(vec![[track,sector]])
},
_ => {
error!("cannot map ProDOS block to {}",*kind);
Err(Box::new(super::Error::IncompatibleDiskKind))
}
}
}