Я написал эмулятор Chip-8 на JavaScript (источник) и создал версию для браузера, которую можно воспроизвести здесь .
Содержит HTML-выбор:
<select>
<option value="PONG">PONG</option>
<option value="TETRIS">TETRIS</option>
</select>
, который загружает ПЗУ из файла при каждом его выборе:
document.querySelector('select').addEventListener('change', event => {
const rom = event.target.value
loadRom(rom)
})
Эта loadRom
функция извлекает ПЗУ, преобразует его в полезную форму и загружает в экземпляркласса процессора.У cpu
есть цикл fetch-decode-execute, который вызывается с step()
.Я создал эту cycle
(основную) функцию для вызова себя в setTimeout.
const loadRom = async rom => {
const response = await fetch(`./roms/${rom}`)
const arrayBuffer = await response.arrayBuffer()
const uint8View = new Uint8Array(arrayBuffer);
const romBuffer = new RomBuffer(uint8View)
cpu.interface.clearDisplay()
cpu.load(romBuffer)
let timer = 0
async function cycle() {
timer++
if (timer % 5 === 0) {
cpu.tick()
timer = 0
}
await cpu.step()
setTimeout(cycle, 3)
}
cycle()
}
Это прекрасно работает, пока я не загружу новый ROM с помощью select.Теперь цикл составлен, и игра идет в два раза быстрее.Каждый раз, когда вы загружаете новое ПЗУ, оно снова соединяется и создает новый цикл.
Как я могу создать бесконечный цикл, но остановить его и запустить новый, не смешивая его?