summaryrefslogtreecommitdiff
path: root/src/devices/memory.rs
diff options
context:
space:
mode:
authorBen Bridle <bridle.benjamin@gmail.com>2024-04-16 10:51:13 +1200
committerBen Bridle <bridle.benjamin@gmail.com>2024-04-16 10:51:26 +1200
commit6b3796c9a0d3a2f1422bcbde4790c43417659722 (patch)
tree6429a5fa2f8c4d3b26790775e07e46e6338b61d3 /src/devices/memory.rs
parent28101de56231252ca0cfa6a9f107b75112c9acad (diff)
downloadbedrock-pc-6b3796c9a0d3a2f1422bcbde4790c43417659722.zip
Update devices to match new specifications
Diffstat (limited to 'src/devices/memory.rs')
-rw-r--r--src/devices/memory.rs89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/devices/memory.rs b/src/devices/memory.rs
new file mode 100644
index 0000000..1d33f64
--- /dev/null
+++ b/src/devices/memory.rs
@@ -0,0 +1,89 @@
+macro_rules! then_inc { ($v:expr) => {{ $v = $v.wrapping_add(1); $v as usize }}; }
+
+type Page = [u8; 65536];
+fn new_blank_page() -> [u8; 65536] { [0; 65536] }
+
+
+pub struct MemoryDevice {
+ pages: Vec<Page>,
+ pub page_limit: u16,
+ pub page_1: u16,
+ pub address_1: u16,
+ pub page_2: u16,
+ pub address_2: u16,
+ pub copy_length: u16,
+}
+
+impl MemoryDevice {
+ pub fn new() -> Self {
+ Self {
+ pages: Vec::new(),
+ page_limit: 0,
+ page_1: 0,
+ address_1: 0,
+ page_2: 0,
+ address_2: 0,
+ copy_length: 0,
+ }
+ }
+
+ pub fn page_count(&self) -> u16 {
+ self.pages.len() as u16
+ }
+
+ pub fn copy(&mut self) {
+ // Return if at least one page is out-of-bounds
+ if self.page_1 as usize >= self.pages.len()
+ || self.page_2 as usize >= self.pages.len() {
+ return
+ }
+ let p1 = self.page_1 as usize;
+ let p2 = self.page_2 as usize;
+ let a1 = self.address_1;
+ let a2 = self.address_2;
+
+ for i in 0..=self.copy_length {
+ let byte = self.pages[p2][a2.wrapping_add(i) as usize];
+ self.pages[p1][a1.wrapping_add(i) as usize] = byte;
+ }
+ }
+
+ pub fn expand_memory(&mut self) {
+ let size = std::cmp::max(self.page_1, self.page_2) as usize + 1;
+ if size < self.page_limit as usize {
+ self.pages.resize_with(size, new_blank_page);
+ }
+ }
+
+ pub fn read_from_head_1(&mut self) -> u8 {
+ let address = then_inc!(self.address_1);
+ if let Some(page) = self.pages.get(self.page_1 as usize) {
+ page[address]
+ } else {
+ 0x00
+ }
+ }
+
+ pub fn read_from_head_2(&mut self) -> u8 {
+ let address = then_inc!(self.address_2);
+ if let Some(page) = self.pages.get(self.page_2 as usize) {
+ page[address]
+ } else {
+ 0x00
+ }
+ }
+
+ pub fn write_to_head_1(&mut self, byte: u8) {
+ let address = then_inc!(self.address_1);
+ if let Some(page) = self.pages.get_mut(self.page_1 as usize) {
+ page[address] = byte;
+ }
+ }
+
+ pub fn write_to_head_2(&mut self, byte: u8) {
+ let address = then_inc!(self.address_2);
+ if let Some(page) = self.pages.get_mut(self.page_2 as usize) {
+ page[address] = byte;
+ }
+ }
+}