use crate::img;
use crate::bios::Block;
use a2kit_macro::DiskStructError;
use log::{trace,debug,error};
use crate::{STDRESULT,DYNERR};
const SECTOR_SIZE: usize = 256;
const TRACK_SIZE: usize = 13*SECTOR_SIZE;
const MIN_TRACKS: usize = 35;
pub fn file_extensions() -> Vec<String> {
vec!["d13".to_string()]
}
pub struct D13 {
tracks: u16,
data: Vec<u8>
}
impl D13 {
pub fn create(tracks: u16) -> Self {
let mut data: Vec<u8> = Vec::new();
for _i in 0..tracks as usize*13 {
data.append(&mut [0;SECTOR_SIZE].to_vec());
}
Self {
tracks,
data
}
}
}
impl img::DiskImage for D13 {
fn track_count(&self) -> usize {
return self.tracks as usize;
}
fn end_track(&self) -> usize {
return self.tracks as usize;
}
fn num_heads(&self) -> usize {
1
}
fn nominal_capacity(&self) -> Option<usize> {
Some(self.data.len())
}
fn actual_capacity(&mut self) -> Result<usize,DYNERR> {
Ok(self.data.len())
}
fn read_block(&mut self,addr: Block) -> Result<Vec<u8>,DYNERR> {
trace!("read {}",addr);
match addr {
Block::D13([t,s]) => {
let offset = t*TRACK_SIZE + s*SECTOR_SIZE;
Ok(self.data[offset..offset+SECTOR_SIZE].to_vec())
},
_ => Err(Box::new(img::Error::ImageTypeMismatch))
}
}
fn write_block(&mut self, addr: Block, dat: &[u8]) -> STDRESULT {
trace!("write {}",addr);
match addr {
Block::D13([t,s]) => {
let offset = t*TRACK_SIZE + s*SECTOR_SIZE;
let padded = super::quantize_block(dat, SECTOR_SIZE);
self.data[offset..offset+SECTOR_SIZE].copy_from_slice(&padded);
Ok(())
},
_ => Err(Box::new(img::Error::ImageTypeMismatch))
}
}
fn read_sector(&mut self,trk: super::Track,sec: super::Sector) -> Result<Vec<u8>,DYNERR> {
let [cyl,head,sec] = self.get_rzq(trk,sec)?;
if cyl>=self.end_track() || head>0 || sec>12 {
error!("exceeded bounds: maxima are cyl {}, head {}, sector {}",self.end_track()-1,0,12);
return Err(Box::new(img::Error::SectorAccess));
}
let offset = cyl*TRACK_SIZE + sec*SECTOR_SIZE;
Ok(self.data[offset..offset+SECTOR_SIZE].to_vec())
}
fn write_sector(&mut self,trk: super::Track,sec: super::Sector,dat: &[u8]) -> STDRESULT {
let [cyl,head,sec] = self.get_rzq(trk,sec)?;
if cyl>=self.end_track() || head>0 || sec>12 {
error!("exceeded bounds: maxima are cyl {}, head {}, sector {}",self.end_track()-1,0,12);
return Err(Box::new(img::Error::SectorAccess));
}
let offset = cyl*TRACK_SIZE + sec*SECTOR_SIZE;
let padded = super::quantize_block(dat, SECTOR_SIZE);
self.data[offset..offset+SECTOR_SIZE].copy_from_slice(&padded);
Ok(())
}
fn from_bytes(data: &[u8]) -> Result<Self,DiskStructError> {
if data.len()%TRACK_SIZE > 0 || data.len()/TRACK_SIZE < MIN_TRACKS {
return Err(DiskStructError::UnexpectedSize);
}
Ok(Self {
tracks: (data.len()/TRACK_SIZE) as u16,
data: data.to_vec()
})
}
fn what_am_i(&self) -> img::DiskImageType {
img::DiskImageType::D13
}
fn file_extensions(&self) -> Vec<String> {
file_extensions()
}
fn kind(&self) -> img::DiskKind {
img::names::A2_DOS32_KIND
}
fn change_kind(&mut self,kind: img::DiskKind) {
debug!("ignoring change of D13 to {}",kind);
}
fn to_bytes(&mut self) -> Vec<u8> {
return self.data.clone();
}
fn get_track_buf(&mut self,_trk: super::Track) -> Result<Vec<u8>,DYNERR> {
error!("D13 images have no track bits");
return Err(Box::new(img::Error::ImageTypeMismatch));
}
fn set_track_buf(&mut self,_trk: super::Track,_dat: &[u8]) -> STDRESULT {
error!("D13 images have no track bits");
return Err(Box::new(img::Error::ImageTypeMismatch));
}
fn get_track_solution(&mut self,trk: super::Track) -> Result<img::TrackSolution,DYNERR> {
let [c,_] = self.get_rz(trk)?;
let mut addr_map: Vec<[u8;6]> = Vec::new();
for i in 0..13 {
let mut addr = [254,c.try_into()?,crate::bios::skew::DOS32_PHYSICAL[i].try_into()?,0,0,0];
addr[3] = addr[0] ^ addr[1] ^ addr[2];
addr_map.push(addr);
}
return Ok(img::TrackSolution::Solved(img::SolvedTrack {
speed_kbps: 250,
density: None,
flux_code: img::FluxCode::GCR,
addr_code: img::FieldCode::WOZ((4,4)),
data_code: img::FieldCode::WOZ((5,3)),
addr_type: "VTSK".to_string(),
addr_mask: [0,0,255,0,0,0],
addr_map,
size_map: vec![256;13]
}));
}
fn get_track_nibbles(&mut self,_trk: super::Track) -> Result<Vec<u8>,DYNERR> {
error!("D13 images have no track bits");
return Err(Box::new(img::Error::ImageTypeMismatch));
}
fn display_track(&self,_bytes: &[u8]) -> String {
String::from("D13 images have no track bits to display")
}
}