cpclib_asm/assembler/
save_command.rs1use 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#[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 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 let data = env.get_memory(from as _, size as _);
69
70 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}