pub mod mmio; use std::{ cell::RefCell, mem::offset_of, ops::{Deref, DerefMut, Range, RangeBounds}, pin::Pin, rc::Rc, sync::{ atomic::{AtomicBool, Ordering}, mpsc, Arc, LazyLock, Mutex, }, }; use bitfield_struct::bitfield; use jni::objects::GlobalRef; use unicorn_engine::Unicorn; use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout}; use crate::{ core::CpuContext, memory_map::RAM_START, overlapping, range_of_field, subtract_range, unsync_cell::UnsyncCell, unsync_read, }; #[derive(Default)] pub enum Component { #[default] Empty, Populated { own_index: usize, java_component: GlobalRef, read_transfer_active: AtomicBool, write_transfer_active: AtomicBool, info: ComponentInfo, interface: UnsyncCell, }, } #[derive(Clone, Copy, Default, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C)] pub struct ComponentInterface { // read only pub info: ComponentInfo, // read-write control: ComponentControl, _restart_device: u8, _reserved: [u8; 6], read_dma: ComponentDma, write_dma: ComponentDma, } #[bitfield(u8)] #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)] pub struct ComponentControl { interrupt_when_added: bool, interrupt_when_removed: bool, #[bits(2)] _reserved: u8, #[bits(4)] interrupt_firing_core: u8, } #[derive(Clone, Copy, Default, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C)] pub struct ComponentDma { pub upper_word: ComponentDmaUpper, pub address: u64, } impl Deref for ComponentDma { type Target = ComponentDmaUpper; fn deref(&self) -> &Self::Target { &self.upper_word } } impl DerefMut for ComponentDma { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.upper_word } } #[bitfield(u64)] #[derive(FromBytes, IntoBytes, Immutable, KnownLayout)] pub struct ComponentDmaUpper { dma_enabled: bool, #[bits(3)] _reserved: u8, /// read-write, indicates the core to fire interrupts on. indicating an invalid core means no core will receive the interrupt #[bits(4)] interrupt_firing_core: u8, #[bits(56)] size: u64, } #[derive(Clone, Copy, FromBytes, IntoBytes, Immutable, KnownLayout)] #[repr(C)] pub struct ComponentInfo { /// a null terminated string, the type name of the component pub type_name: [u8; 256], /// a null terminated string, the protocol identifier for how to talk to the component pub protocol: [u8; 256], pub bytes_per_tick: u32, pub version: u32, } impl Default for ComponentInfo { fn default() -> Self { Self { type_name: [0; 256], protocol: [0; 256], bytes_per_tick: 0, version: 0, } } }