import ROM from 'js/roms/rom'; import { bit, byte } from 'js/types'; import { debug } from '../util'; const PATTERN = [ 0xC5, 0x3A, 0xA3, 0x5C, 0xC5, 0x3A, 0xA3, 0x5C ]; const A0 = 0x01; const A2 = 0x04; export default class NoSlotClock { bits: bit[] = []; pattern = new Array(64); patternIdx: number = 0; constructor(private rom: ROM) { debug('NoSlotClock'); } private patternMatch() { for (let idx = 0; idx < 8; idx++) { let byte = 0; for (let jdx = 0; jdx < 8; jdx++) { byte >>= 1; byte |= this.pattern.shift() ? 0x80 : 0x00; } if (byte !== PATTERN[idx]) { return false; } } return true; } private calcBits() { const shift = (val: byte) => { for (let idx = 0; idx < 4; idx++) { this.bits.push(val & 0x08 ? 0x01 : 0x00); val <<= 1; } }; const shiftBCD = (val: byte) => { shift(Math.floor(val / 10)); shift(Math.floor(val % 10)); }; const now = new Date(); const year = now.getFullYear() % 100; const day = now.getDate(); const weekday = now.getDay() + 1; const month = now.getMonth() + 1; const hour = now.getHours(); const minutes = now.getMinutes(); const seconds = now.getSeconds(); const hundredths = (now.getMilliseconds() / 10); this.bits = []; shiftBCD(year); shiftBCD(month); shiftBCD(day); shiftBCD(weekday); shiftBCD(hour); shiftBCD(minutes); shiftBCD(seconds); shiftBCD(hundredths); } access(off: byte) { if (off & A2) { this.patternIdx = 0; } else { const bit = off & A0; this.pattern[this.patternIdx++] = bit; if (this.patternIdx === 64) { if (this.patternMatch()) { this.calcBits(); } this.patternIdx = 0; } } } start() { return this.rom.start(); } end() { return this.rom.end(); } read(page: byte, off: byte) { if (this.bits.length > 0) { const bit = this.bits.pop(); return bit; } else { this.access(off); } return this.rom.read(page, off); } write(_page: byte, off: byte, _val: byte) { this.access(off); this.rom.write(); } getState() { return {}; } setState(_: unknown) { // Setting the state makes no sense. } }