cpclib_disc/
builder.rs

1use crate::cfg::DiscConfig;
2use crate::edsk::{ExtendedDsk, Head};
3
4/// Generate an edsk from the given configuration
5pub fn build_edsk_from_cfg(cfg: &DiscConfig) -> ExtendedDsk {
6    let mut edsk = ExtendedDsk {
7        disc_information_bloc: Default::default(),
8        track_list: Default::default()
9    };
10
11    // Feed the disc info table
12    edsk.disc_information_bloc.creator_name = "RUST CPC - BND".to_string();
13    assert_eq!(edsk.disc_information_bloc.creator_name.len(), 14);
14    edsk.disc_information_bloc.number_of_heads = cfg.nb_heads;
15    edsk.disc_information_bloc.number_of_tracks = cfg.nb_tracks;
16    edsk.disc_information_bloc.track_size_table = cfg
17        .track_idx_iterator()
18        .map(|idx| {
19            let info = cfg
20                .track_information_for_track(*idx.0, idx.1)
21                .unwrap_or_else(|| panic!("Unable to acquire information for track {idx:?}"));
22            let sectors_size = info.sector_size as usize * info.number_of_sectors();
23            let header_size = 256;
24            ((sectors_size + header_size) / 256) as u8
25        })
26        .collect::<Vec<_>>();
27
28    // Create the empty tracks -- to be filled in the next loop
29    for (head, track_idx) in cfg.track_idx_iterator() {
30        let track = edsk.track_list.add_empty_track();
31        track.track_number = track_idx;
32
33        track.head_number = match *head {
34            Head::A | Head::Unspecified => Head::A,
35            Head::B => Head::B
36        }
37        .into();
38        track.track_size =
39            u16::from(edsk.disc_information_bloc.track_size_table[track_idx as usize]) * 256 + 512;
40        // XXX Need to see why I had to add these 512 bytes ...
41    }
42
43    // Update the tracks stuff
44    for (&head, track_idx) in cfg.track_idx_iterator() {
45        let track_info = edsk
46            .get_track_information_mut(head, track_idx)
47            .unwrap_or_else(|| {
48                panic!("Unable to acquire track {track_idx} on head {head:?} on the dsk")
49            });
50        let track_model = cfg.track_information_for_track(head, track_idx).unwrap();
51
52        track_info.track_number = track_idx;
53        track_info.head_number = track_model.head.into();
54        track_info.data_rate = 1.into();
55        track_info.recording_mode = 2.into();
56        track_info.sector_size = track_model.sector_size_dsk_format();
57        track_info.number_of_sectors = track_model.sector_id.len() as _;
58        track_info.gap3_length = track_model.gap3; // TODO ensure a 8buts value is in the cfg
59        track_info.filler_byte = 0xE5;
60        track_info.sector_information_list.fill_with(
61            &track_model.sector_id,
62            &track_model.sector_id_head,
63            track_idx,
64            track_model.sector_size_dsk_format(),
65            track_info.filler_byte
66        )
67    }
68    edsk
69}
70
71#[allow(missing_docs)]
72impl From<DiscConfig> for ExtendedDsk {
73    fn from(config: DiscConfig) -> Self {
74        build_edsk_from_cfg(&config)
75    }
76}
77
78#[allow(missing_docs)]
79impl From<&DiscConfig> for ExtendedDsk {
80    fn from(config: &DiscConfig) -> Self {
81        build_edsk_from_cfg(config)
82    }
83}
84
85/// Generate a standard singled sided amsdos disc
86pub fn single_head_data_dsk() -> ExtendedDsk {
87    DiscConfig::single_head_data_format().into()
88}
89
90/// Generate a double sided amsdos disc
91pub fn single_head_data42_dsk() -> ExtendedDsk {
92    DiscConfig::single_head_data42_format().into()
93}