use super::super::FluxCells;
const FAKE_BITS: [u8;32] = [180, 2, 177, 40, 180, 160, 114, 96, 20, 1, 26, 45, 25, 96, 129, 70, 3, 0, 0, 77, 140, 42, 8, 137, 2, 8, 68, 4, 225, 195, 141, 0];
const ROM: [[[[u8;16];2];2];4] = [
[
[
[0x18,0x2d,0x38,0x48,0x58,0x68,0x78,0x88,0x98,0x29,0xbd,0x59,0xd9,0x08,0xfd,0x4d],
[0x18,0x2d,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xcd,0xd9,0xd9,0xd8,0xfd,0xdd]
],
[
[0x18,0x38,0x28,0x48,0x58,0x68,0x78,0x88,0x98,0xa8,0xb8,0xc8,0xa0,0xe8,0xf8,0xe0],
[0x18,0x38,0x08,0x48,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xe8,0xf8,0xe0]
]
],
[
[
[0x18,0x28,0x39,0x48,0x58,0x68,0x78,0x08,0x98,0xa8,0xb9,0xc8,0xd8,0xe8,0xf8,0x88],
[0x18,0x28,0x39,0x48,0x58,0x68,0x78,0x08,0x98,0xa8,0xb9,0xc8,0xd8,0xe8,0xf8,0x88]
],
[
[0x18,0x28,0x39,0x48,0x58,0x68,0x78,0x88,0x98,0xa8,0xb9,0xc8,0xd8,0xe8,0xf8,0x08],
[0x18,0x28,0x39,0x48,0x58,0x68,0x78,0x88,0x98,0xa8,0xb9,0xc8,0xd8,0xe8,0xf8,0x08]
]
],
[
[
[0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a],
[0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a]
],
[
[0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a],
[0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a,0x0a]
]
],
[
[
[0x18,0x28,0x3b,0x48,0x58,0x68,0x78,0x08,0x98,0xa8,0xbb,0xc8,0xd8,0xe8,0xf8,0x88],
[0x18,0x28,0x3b,0x48,0x58,0x68,0x78,0x08,0x98,0xa8,0xbb,0xc8,0xd8,0xe8,0xf8,0x88]
],
[
[0x18,0x28,0x3b,0x48,0x58,0x68,0x78,0x88,0x98,0xa8,0xbb,0xc8,0xd8,0xe8,0xf8,0x08],
[0x18,0x28,0x3b,0x48,0x58,0x68,0x78,0x88,0x98,0xa8,0xbb,0xc8,0xd8,0xe8,0xf8,0x08]
]
]
];
#[derive(Clone)]
pub struct State {
seq: usize,
latch: u8,
c08d: u8,
q6: bool,
q7: bool,
write_protect: bool,
fake_bit_ptr: usize,
last_pulse: u64,
fake_bit_pool: bit_vec::BitVec
}
impl State {
pub fn new() -> Self {
Self {
seq: 0,
latch: 0,
c08d: 0,
q6: false,
q7: false,
write_protect: false,
fake_bit_ptr: (chrono::Local::now().timestamp() % 256) as usize,
last_pulse: 0,
fake_bit_pool: bit_vec::BitVec::from_bytes(&FAKE_BITS)
}
}
pub fn disable_fake_bits(&mut self) {
self.fake_bit_pool = bit_vec::BitVec::from_bytes(&vec![0;32]);
}
pub fn enable_fake_bits(&mut self) {
self.fake_bit_pool = bit_vec::BitVec::from_bytes(&FAKE_BITS);
}
fn mc3470_pulse(&mut self,cells: &mut FluxCells) -> u8 {
let mut pulse = false;
if cells.ptr & cells.fmask == 0 {
let flux_ptr = cells.ptr >> cells.fshift;
let mut new_pulse = cells.stream.get(flux_ptr).unwrap();
if new_pulse {
self.last_pulse = cells.time;
}
if cells.ticks_since(self.last_pulse) > 96 {
self.fake_bit_ptr = (self.fake_bit_ptr + 1) & 0xff;
new_pulse = self.fake_bit_pool[self.fake_bit_ptr];
}
pulse |= new_pulse;
}
cells.fwd(4);
pulse as u8
}
pub fn get_latch(&self) -> u8 {
self.latch
}
pub fn get_critical_state(&self) -> (usize,u64,u8) {
(self.seq,self.last_pulse,self.latch)
}
pub fn restore_critical_state(&mut self,crit: (usize,u64,u8)) {
self.seq = crit.0;
self.last_pulse = crit.1;
self.latch = crit.2;
}
pub fn start_read(&mut self) {
self.q6 = false;
self.q7 = false;
}
pub fn advance(&mut self, ticks: usize, cells: &mut FluxCells) -> bool {
assert!(ticks%4==0);
assert!(cells.fshift > 1);
assert!(cells.ptr & 3 == 0);
let mut touched = false;
let cycles = ticks/4;
for _ in 0..cycles {
let pulse = self.mc3470_pulse(cells);
let q6q7 = self.q6 as usize * 2 + self.q7 as usize;
let neg = 0x80 & self.latch as usize;
let next = ROM[q6q7][neg/0x80][pulse as usize][self.seq];
let next_op = next & 0x0f;
let next_seq = (next & 0xf0) >> 4;
match next_op {
0x00 => self.latch = 0,
0x08 => {},
0x09 => self.latch = self.latch << 1,
0x0a => {
if self.write_protect {
self.latch = 0xff;
} else {
self.latch = self.latch >> 1;
}
},
0x0b => self.latch = self.c08d,
0x0d => self.latch = (self.latch << 1) | 1,
_ => panic!("illegal value in state machine ROM")
};
self.seq = next_seq as usize;
touched |= next_op != 0x08;
}
touched
}
}