use fon::chan::Ch16;
include!(concat!(env!("OUT_DIR"), "/pink.rs"));
#[inline(always)]
fn pnmask(pncnt: u8) -> u8 {
match pncnt % 16 {
_x if _x % 2 != 0 => 0x80,
_x if _x % 4 != 0 => 0x40,
_x if _x % 8 != 0 => 0x20,
8 => 0x10, _ => match pncnt / 16 {
_x if _x % 2 != 0 => 8,
_x if _x % 4 != 0 => 4,
_x if _x % 8 != 0 => 2,
8 => 1, _ => 0, },
}
}
#[derive(Debug, Copy, Clone)]
pub struct Pink {
lfsr: i32,
inc: i32,
dec: i32,
accu: i32,
pncnt: u8,
which: u8,
bit: i32,
}
impl Default for Pink {
#[inline(always)]
fn default() -> Self {
Self::new()
}
}
impl Pink {
#[inline(always)]
pub fn new() -> Self {
Self {
lfsr: 0x5eed41f5i32,
inc: 0xccc,
dec: 0xccc,
accu: 0,
pncnt: 0,
which: 0,
bit: 0,
}
}
fn a(&mut self) -> i16 {
self.bit = self.lfsr >> 31i32;
self.dec &= !0x800i32;
self.lfsr <<= 1;
self.dec |= self.inc & 0x800i32;
self.inc ^= self.bit & 0x800i32;
self.b()
}
fn b(&mut self) -> i16 {
self.accu += self.inc - self.dec;
self.lfsr ^= self.bit & 0x46000001i32;
(self.accu
+ PFIRA[(self.lfsr & 0x3fi32) as usize]
+ PFIRB[(self.lfsr >> 6i32 & 0x3fi32) as usize]) as i16
}
fn c(&mut self) -> i16 {
self.bit = self.lfsr >> 31i32;
self.dec &= !0x400i32;
self.lfsr <<= 1;
self.dec |= self.inc & 0x400i32;
self.inc ^= self.bit & 0x400i32;
self.b()
}
fn d(&mut self) -> i16 {
self.bit = self.lfsr >> 31i32;
self.dec &= !0x200i32;
self.lfsr <<= 1;
self.dec |= self.inc & 0x200i32;
self.inc ^= self.bit & 0x200i32;
self.b()
}
fn e(&mut self) -> i16 {
self.bit = self.lfsr >> 31i32;
self.dec &= !0x100i32;
self.lfsr <<= 1;
self.dec |= self.inc & 0x100i32;
self.inc ^= self.bit & 0x100i32;
self.b()
}
fn f(&mut self, mask: i32) -> i16 {
self.bit = self.lfsr >> 31i32;
self.dec &= !mask;
self.lfsr <<= 1;
self.dec |= self.inc & mask;
self.inc ^= self.bit & mask;
self.b()
}
#[inline(always)]
pub fn step(&mut self) -> fon::chan::Ch32 {
let pink = match self.which {
_x if _x % 2 != 0 => self.a(), _x if _x % 4 != 0 => self.c(),
_x if _x % 8 != 0 => self.d(),
0 => {
let mask = pnmask(self.pncnt).into();
self.pncnt = self.pncnt.wrapping_add(1);
self.f(mask)
}
8 => self.e(),
_ => unreachable!(),
};
self.which += 1;
self.which %= 16;
Ch16::new(pink).into()
}
}