#![no_std]
#![cfg_attr(feature = "aeabi_mem_fns", feature(naked_functions))]
#![allow(unused_mut)]
#![allow(unused_imports)]
#![allow(clippy::let_and_return)]
#![allow(clippy::result_unit_err)]
#![warn(clippy::missing_inline_in_public_items)]
#![cfg_attr(test, feature(custom_test_frameworks))]
#![cfg_attr(test, test_runner(test_harness::test_runner))]
#![cfg_attr(test, no_main)]
#![cfg_attr(test, reexport_test_harness_main = "test_main")]
#[cfg(feature = "on_gba")]
use prelude::{GbaCell, IrqFn};
mod macros;
#[cfg(test)]
mod test_harness;
#[cfg(feature = "on_gba")]
mod asm_runtime;
#[cfg(feature = "on_gba")]
pub mod bios;
pub mod builtin_art;
#[cfg(feature = "critical-section")]
mod critical_section;
#[cfg(feature = "on_gba")]
pub mod dma;
pub mod fixed;
#[cfg(feature = "on_gba")]
pub mod gba_cell;
pub mod interrupts;
pub mod keys;
pub mod mem;
#[cfg(feature = "on_gba")]
pub mod mgba;
#[cfg(feature = "on_gba")]
pub mod mmio;
pub mod prelude;
pub mod random;
pub mod sound;
pub mod timers;
pub mod video;
#[cfg(feature = "on_gba")]
pub static RUST_IRQ_HANDLER: GbaCell<Option<IrqFn>> = GbaCell::new(None);
#[derive(Debug)]
#[repr(C, align(4))]
pub struct Align4<T>(pub T);
impl<const N: usize> Align4<[u8; N]> {
#[inline]
#[must_use]
pub const fn as_u32_slice(&self) -> &[u32] {
self.as_slice()
}
#[inline]
#[must_use]
pub const fn as_u16_slice(&self) -> &[u16] {
self.as_slice()
}
#[inline]
#[must_use]
pub const fn as_slice<T: Sized>(&self) -> &[T] {
const {
assert!(N % (size_of::<T>() + (size_of::<T>() % align_of::<T>())) == 0);
assert!(
align_of::<T>() == 4 || align_of::<T>() == 2 || align_of::<T>() == 1
);
}
let data: *const u8 = self.0.as_ptr();
let len = const { N / size_of::<T>() };
unsafe { core::slice::from_raw_parts(data.cast::<T>(), len) }
}
}
#[macro_export]
macro_rules! include_aligned_bytes {
($file:expr $(,)?) => {{
Align4(*include_bytes!($file))
}};
}
#[cfg(test)]
mod test {
use super::Align4;
#[test_case]
fn align4_as_u16_u32_slice() {
let a = Align4([0u8, 1u8, 2u8, 3u8]);
assert_eq!(a.as_u16_slice(), &[0x100_u16.to_le(), 0x302_u16.to_le()]);
assert_eq!(a.as_u32_slice(), &[0x3020100_u32.to_le()]);
}
#[test_case]
fn align4_as_generic() {
#[repr(C, align(4))]
#[derive(PartialEq, Debug)]
struct FiveByte([u8; 5]);
assert_eq!(
Align4(*b"hello...world...").as_slice::<FiveByte>(),
&[FiveByte(*b"hello"), FiveByte(*b"world")]
);
#[repr(C, align(2))]
#[derive(PartialEq, Debug)]
struct ThreeHalfWords(u16, u16, u16);
assert_eq!(
Align4([
0x11u8, 0x11u8, 0x22u8, 0x22u8, 0x33u8, 0x33u8, 0x44u8, 0x44u8, 0x55u8,
0x55u8, 0x66u8, 0x66u8
])
.as_slice::<ThreeHalfWords>(),
&[
ThreeHalfWords(0x1111, 0x2222, 0x3333),
ThreeHalfWords(0x4444, 0x5555, 0x6666)
]
);
}
}