use crate::gpu::Color;
use crate::sys::kernel;
use core::mem::size_of;
use core::slice;
pub struct Rng(());
impl Rng {
pub fn new(seed: u32) -> Self {
unsafe { kernel::psx_srand(seed) }
Rng(())
}
pub fn reseed(&mut self, seed: u32) {
unsafe { kernel::psx_srand(seed) }
}
pub fn step(&self) -> u16 {
unsafe { kernel::psx_rand() }
}
pub fn rand<T: From<u8>>(&self) -> T {
let mut res = T::from(0);
let ptr = &mut res as *mut T as *mut u8;
let slice = unsafe { slice::from_raw_parts_mut(ptr, size_of::<T>()) };
for n in 0..slice.len() {
slice[n] = self.step() as u8;
}
res
}
pub fn rand_color(&self) -> Color {
let x = ((self.step() as u32) << 15) | (self.step() as u32);
Color::new(x as u8, (x >> 8) as u8, (x >> 16) as u8)
}
}
#[test_case]
fn rng_size() {
fuzz!(|seed: u32| {
let rng = Rng::new(seed);
let rand = rng.step();
assert!(rand < (1 << 15));
});
}
#[test_case]
fn rng_state() {
fuzz!(|seed: u32, steps: u8| {
let rng = Rng::new(seed);
let mut state = seed;
for _ in 0..steps {
let x = rng.step() as u32;
state = state * 0x41C6_4E6D + 0x3039;
let expected = (state / 0x1_0000) & 0x7F_FF;
assert!(x == expected);
}
});
}