cpclib_asm/assembler/support/
banks.rs1use std::ops::{Deref, DerefMut};
2
3use cpclib_common::bitvec::vec::BitVec;
4
5use crate::page_info::PageInformation;
6use crate::{AssemblerError, MyDefault};
7
8pub(crate) type Bank = [u8; 0x4000];
9
10type Page = [u8; 0x1_0000];
11impl MyDefault for Page {
12 fn default() -> Page {
13 [0; 0x1_0000]
14 }
15}
16
17#[derive(Clone, Debug)]
18pub struct DecoratedPage((Page, PageInformation, BitVec));
19
20impl Deref for DecoratedPage {
21 type Target = (Page, PageInformation, BitVec);
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28impl DerefMut for DecoratedPage {
29 fn deref_mut(&mut self) -> &mut Self::Target {
30 &mut self.0
31 }
32}
33
34impl Default for DecoratedPage {
35 fn default() -> Self {
36 Self((
37 Page::default(),
38 PageInformation::default(),
39 BitVec::repeat(false, 0x4000 * 4)
40 ))
41 }
42}
43
44impl DecoratedPage {
45 #[inline(always)]
46 fn page(&self) -> &Page {
47 &self.0.0
48 }
49
50 #[inline(always)]
51 fn page_information(&self) -> &PageInformation {
52 &self.0.1
53 }
54
55 #[inline(always)]
56 fn written_bytes(&self) -> &BitVec {
57 &self.0.2
58 }
59
60 pub fn set_byte(&mut self, address: u16, byte: u8) {
62 self.0.0[address as usize] = byte;
63 self.0.2.set(address as _, true);
64 }
65
66 pub fn get_byte(&self, address: u16) -> u8 {
67 self.0.0[address as usize]
68 }
69}
70
71#[derive(Clone, Debug)]
72pub struct DecoratedPages {
73 pub(crate) pages: Vec<DecoratedPage>,
74 pub(crate) selected_index: Option<usize>
75}
76
77impl Default for DecoratedPages {
78 fn default() -> Self {
79 DecoratedPages {
80 pages: Vec::with_capacity(0),
81 selected_index: None
82 }
83 }
84}
85
86impl TryInto<Bank> for &DecoratedPage {
87 type Error = AssemblerError;
88
89 fn try_into(self) -> Result<Bank, Self::Error> {
91 let binary_bloc = self.binary_bloc();
92
93 if binary_bloc.len() > 0x4000 {
94 return Err(AssemblerError::AssemblingError {
95 msg: format!("0x{:X} > 0x4000", binary_bloc.len())
96 });
97 }
98
99 let mut bank: Bank = [0; 0x4000];
101 bank[..binary_bloc.len()].copy_from_slice(binary_bloc);
102 Ok(bank)
103 }
104}
105
106impl DecoratedPage {
107 pub fn binary_bloc(&self) -> &[u8] {
109 if let Some(start) = &self.page_information().startadr {
110 let stop = self.page_information().maxadr as usize;
111 &self.page()[(*start as usize)..=stop]
112 }
113 else {
114 &self.page()[..0]
115 }
116 }
117}
118
119impl DecoratedPages {
120 pub fn selected_index(&self) -> Option<usize> {
121 self.selected_index
122 }
123
124 pub fn selected_written_bytes(&self) -> Option<&BitVec> {
125 self.selected_index.as_ref().map(|&idx| &self.pages[idx].2)
126 }
127
128 pub fn selected_active_page_info_mut(&mut self) -> Option<&mut PageInformation> {
129 self.selected_index
130 .as_ref()
131 .map(|&idx| &mut self.pages[idx].1)
132 }
133
134 pub fn selected_active_page_info(&self) -> Option<&PageInformation> {
135 self.selected_index.as_ref().map(|&idx| &self.pages[idx].1)
136 }
137
138 pub fn page_infos(&self) -> impl Iterator<Item = &PageInformation> {
139 self.pages.iter().map(|d| &d.1)
140 }
141}
142
143impl DecoratedPages {
144 pub fn add_new_and_select(&mut self) {
145 self.selected_index = Some(self.pages.len());
146 self.pages.push(DecoratedPage::default());
147 }
148
149 pub fn select_next(&mut self) -> Result<(), AssemblerError> {
150 self.selected_index = self.selected_index.map(|v| v + 1).or(Some(0));
151
152 if *self.selected_index.as_ref().unwrap() >= self.pages.len() {
153 Err(AssemblerError::AssemblingError {
154 msg: "There were less banks in previous pass".to_owned()
155 })
156 }
157 else {
158 Ok(())
159 }
160 }
161
162 pub fn set_byte(&mut self, address: u16, byte: u8) {
164 if let Some(idx) = &self.selected_index {
165 self.pages[*idx].set_byte(address, byte);
166 }
167 else {
168 todo!()
169 }
170 }
171
172 pub fn get_byte(&self, address: u16) -> Option<u8> {
173 self.selected_index
174 .as_ref()
175 .map(|&idx| self.pages[idx].get_byte(address))
176 }
177
178 pub fn reset_written_bytes(&mut self) {
179 self.pages.iter_mut().for_each(|p| p.2.fill(false));
180 }
181}
182
183impl DecoratedPages {
184 pub fn is_empty(&self) -> bool {
185 self.pages.is_empty()
186 }
187}