Skip to content
Snippets Groups Projects
Verified Commit 2bbb0a04 authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

chore: initial state management for timer

parent 4412e07f
No related branches found
No related tags found
1 merge request!59`StateComponent` creation and implementation
use std::io::{Cursor, Read};
use crate::error::Error;
#[inline(always)]
pub fn read_u8(data: &mut Cursor<&[u8]>) -> Result<u8, Error> {
let mut buffer = [0x00; size_of::<u8>()];
data.read_exact(&mut buffer)?;
Ok(u8::from_le_bytes(buffer))
}
#[inline(always)]
pub fn read_u16(data: &mut Cursor<&[u8]>) -> Result<u16, Error> {
let mut buffer = [0x00; size_of::<u16>()];
data.read_exact(&mut buffer)?;
Ok(u16::from_le_bytes(buffer))
}
#[inline(always)]
pub fn read_u32(data: &mut Cursor<&[u8]>) -> Result<u32, Error> {
let mut buffer = [0x00; size_of::<u32>()];
data.read_exact(&mut buffer)?;
Ok(u32::from_le_bytes(buffer))
}
pub mod bench; pub mod bench;
pub mod data;
pub mod error; pub mod error;
pub mod util; pub mod util;
......
//! Timer functions and structures. //! Timer functions and structures.
use std::io::{Cursor, Write};
use boytacean_common::{
data::{read_u16, read_u8},
error::Error,
};
use crate::{ use crate::{
consts::{DIV_ADDR, TAC_ADDR, TIMA_ADDR, TMA_ADDR}, consts::{DIV_ADDR, TAC_ADDR, TIMA_ADDR, TMA_ADDR},
mmu::BusComponent, mmu::BusComponent,
panic_gb, warnln, panic_gb,
state::StateComponent,
warnln,
}; };
pub struct Timer { pub struct Timer {
...@@ -161,8 +170,75 @@ impl BusComponent for Timer { ...@@ -161,8 +170,75 @@ impl BusComponent for Timer {
} }
} }
impl StateComponent for Timer {
fn state(&self) -> Result<Vec<u8>, Error> {
let mut cursor = Cursor::new(vec![]);
cursor.write(&self.div.to_le_bytes())?;
cursor.write(&self.tima.to_le_bytes())?;
cursor.write(&self.tma.to_le_bytes())?;
cursor.write(&self.tac.to_le_bytes())?;
cursor.write(&self.div_clock.to_le_bytes())?;
cursor.write(&self.tima_clock.to_le_bytes())?;
cursor.write(&(self.tima_enabled as u8).to_le_bytes())?;
cursor.write(&self.tima_ratio.to_le_bytes())?;
cursor.write(&(self.int_tima as u8).to_le_bytes())?;
Ok(cursor.into_inner())
}
fn set_state(&mut self, data: &[u8]) -> Result<(), boytacean_common::error::Error> {
let mut cursor = Cursor::new(data);
self.div = read_u8(&mut cursor)?;
self.tima = read_u8(&mut cursor)?;
self.tma = read_u8(&mut cursor)?;
self.tac = read_u8(&mut cursor)?;
self.div_clock = read_u16(&mut cursor)?;
self.tima_clock = read_u16(&mut cursor)?;
self.tima_enabled = read_u8(&mut cursor)? == 1;
self.tima_ratio = read_u16(&mut cursor)?;
self.int_tima = read_u8(&mut cursor)? == 1;
Ok(())
}
}
impl Default for Timer { impl Default for Timer {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
} }
} }
#[cfg(test)]
mod tests {
use super::Timer;
use crate::state::StateComponent;
#[test]
fn test_state_and_set_state() {
let mut timer = Timer::new();
timer.div = 0x12;
timer.tima = 0x34;
timer.tma = 0x56;
timer.tac = 0x78;
timer.div_clock = 0x9abc;
timer.tima_clock = 0xdef0;
timer.tima_enabled = true;
timer.tima_ratio = 0x1234;
timer.int_tima = true;
let state = timer.state().unwrap();
assert_eq!(state.len(), 12);
let mut new_timer = Timer::new();
new_timer.set_state(&state).unwrap();
assert_eq!(timer.div, new_timer.div);
assert_eq!(timer.tima, new_timer.tima);
assert_eq!(timer.tma, new_timer.tma);
assert_eq!(timer.tac, new_timer.tac);
assert_eq!(timer.div_clock, new_timer.div_clock);
assert_eq!(timer.tima_clock, new_timer.tima_clock);
assert_eq!(timer.tima_enabled, new_timer.tima_enabled);
assert_eq!(timer.tima_ratio, new_timer.tima_ratio);
assert_eq!(timer.int_tima, new_timer.int_tima);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment