use std::{mem::offset_of, sync::{mpsc, Arc}}; use bitfield_struct::bitfield; use zerocopy::{ little_endian::{U32, U64}, FromBytes, IntoBytes, KnownLayout, }; use crate::{component_name, core::CoreMessage, overlapping, unsync_cell::UnsyncCell}; use super::Component; #[derive(Clone, Copy, FromBytes, IntoBytes, KnownLayout)] #[repr(C)] pub struct Registers { pub reset_address: U64, pub flags: U32, } #[bitfield(u32)] pub struct Flags { should_reset: bool, #[bits(31)] _reserved: u32, } pub struct CoreComponent { registers: Arc>, message_sender: mpsc::Sender, } impl CoreComponent { pub fn new(registers: Arc>, message_sender: mpsc::Sender) -> Self { Self { registers, message_sender, } } } impl Component for CoreComponent { fn name() -> [u8; 0x30] { component_name!(b"core") } fn memory_map_size(&self) -> u64 { size_of::() as u64 } fn read(&self, _: &mut jni::JNIEnv, offset: u64, data: &mut [u8]) { assert!((offset + data.len() as u64) < self.memory_map_size() as u64); self.registers.read_into_byte_slice(offset as usize, data); } fn write(&self, _: &mut jni::JNIEnv, offset: u64, data: &[u8]) { assert!((offset + data.len() as u64) < self.memory_map_size() as u64); self.registers.write_from_byte_slice(offset as usize, data); if overlapping( &(offset..offset + data.len() as u64), &(offset_of!(Registers, flags) as u64..size_of::() as u64), ) { let mut registers = self.registers.read(); let flags = Flags::from_bits(registers.flags.get()); if flags.should_reset() { let _ = self.message_sender.send(CoreMessage::Reset); registers.flags.set(flags.with_should_reset(false).into_bits()); self.registers.write(registers); } } } }