cpclib_asm/assembler/
save_command.rs

1use cpclib_disc::disc::Disc;
2#[cfg(feature = "hfe")]
3use cpclib_disc::hfe::Hfe;
4use cpclib_files::*;
5
6use super::Env;
7use super::report::SavedFile;
8use crate::error::AssemblerError;
9use crate::progress::{self, Progress};
10
11pub type SaveFile = FileAndSupport;
12
13/// Save command information
14/// RMR is already properly set up when executing the instruction
15#[derive(Debug, Clone)]
16pub struct SaveCommand {
17    from: Option<i32>,
18    size: Option<i32>,
19    file: SaveFile,
20    ga_mmr: u8
21}
22
23impl SaveCommand {
24    pub fn new(from: Option<i32>, size: Option<i32>, file: SaveFile, ga_mmr: u8) -> Self {
25        SaveCommand {
26            from,
27            size,
28            file,
29            ga_mmr
30        }
31    }
32
33    pub fn ga_mmr(&self) -> u8 {
34        self.ga_mmr
35    }
36
37    pub fn can_be_saved_in_parallel(&self) -> bool {
38        self.file.in_host()
39    }
40
41    /// Really make the save - Prerequisit : the page is properly selected
42    /// Do not yet handle the ascii format
43    pub fn execute_on(&self, env: &Env) -> Result<SavedFile, AssemblerError> {
44        assert_eq!(env.ga_mmr, self.ga_mmr);
45        if env.options().show_progress() {
46            Progress::progress().add_save(progress::normalize(&self.file.filename()));
47        }
48
49        let from = match self.from {
50            Some(from) => from,
51            None => env.start_address().unwrap() as _
52        };
53
54        let size = match self.size {
55            Some(size) => size,
56            None => {
57                if env.start_address().is_some() {
58                    let stop = env.maximum_address();
59                    (stop - from as u16) as i32 + 1
60                }
61                else {
62                    0
63                }
64            },
65        };
66
67        // get the data from the CPC memory
68        let data = env.get_memory(from as _, size as _);
69
70        // Generate and save the file
71
72        self.file
73            .save(
74                data,
75                Some(from as u16),
76                match env.run_options {
77                    Some((exec_address, _)) if exec_address < from as u16 + size as u16 => {
78                        Some(exec_address)
79                    },
80                    _ => None
81                },
82                Some(env.options().assemble_options().save_behavior())
83            )
84            .map_err(|e| {
85                AssemblerError::AssemblingError {
86                    msg: format!("Error while saving. {e}")
87                }
88            })?;
89
90        if env.options().show_progress() {
91            Progress::progress().remove_save(progress::normalize(&self.file.filename()));
92        }
93
94        Ok(SavedFile {
95            name: self.file.filename().to_owned(),
96            size: size as _
97        })
98    }
99}