diff options
author | Ben Bridle <bridle.benjamin@gmail.com> | 2024-09-30 12:28:24 +1300 |
---|---|---|
committer | Ben Bridle <bridle.benjamin@gmail.com> | 2024-09-30 15:00:01 +1300 |
commit | f4f129a75208ccf5d6a19b1cb81c56d4d95fd61f (patch) | |
tree | b3b95f78edeb2cc48ccf207069631468b2705d55 /src/program_memory.rs | |
parent | f5986d0a37dd8c2526432e5e5e3af7083840447d (diff) | |
download | bedrock-core-f4f129a75208ccf5d6a19b1cb81c56d4d95fd61f.zip |
Make Bedrock parametric over devices
The core Bedrock struct is now parametric over individual Device
structs, rather than over a single DeviceBus. This change was made so
that devices can be implemented separately to one another.
The implementation of the evaluate method has also been changed to make
it potentially slightly more efficient, by replacing pop-then-push
combinations with get operations.
Diffstat (limited to 'src/program_memory.rs')
-rw-r--r-- | src/program_memory.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/program_memory.rs b/src/program_memory.rs new file mode 100644 index 0000000..7ffdb17 --- /dev/null +++ b/src/program_memory.rs @@ -0,0 +1,56 @@ +pub struct ProgramMemory { + pub mem: [u8; 65536], + pub pc: u16, +} + +impl ProgramMemory { + pub fn new() -> Self { + Self { + mem: [0; 65536], + pc: 0, + } + } + + pub fn reset(&mut self) { + self.mem.fill(0); + self.pc = 0; + } + + pub fn load_program(&mut self, bytecode: &[u8]) { + let length = std::cmp::min(bytecode.len(), 65536); + self.mem[..length].copy_from_slice(&bytecode[..length]); + self.mem[length..65536].fill(0); + } + + pub fn read_u8(&self, addr: u16) -> u8 { + self.mem[addr as usize] + } + + pub fn write_u8(&mut self, val: u8, addr: u16) { + self.mem[addr as usize] = val; + } + + pub fn read_u8_next(&mut self) -> u8 { + let byte = self.mem[self.pc as usize]; + self.pc = self.pc.wrapping_add(1); + byte + } + + pub fn read_u16(&self, addr: u16) -> u16 { + let byte_high = self.read_u8(addr); + let byte_low = self.read_u8(addr.wrapping_add(1)); + u16::from_be_bytes([byte_high, byte_low]) + } + + pub fn write_u16(&mut self, val: u16, addr: u16) { + let [byte_high, byte_low] = val.to_be_bytes(); + self.write_u8(byte_high, addr); + self.write_u8(byte_low, addr.wrapping_add(1)); + } + + pub fn read_u16_next(&mut self) -> u16 { + let byte_high = self.read_u8_next(); + let byte_low = self.read_u8_next(); + u16::from_be_bytes([byte_high, byte_low]) + } +} |