two-bit/minecraft-machine.ts

66 lines
2.8 KiB
TypeScript

import bit from "./bit";
import { memory } from "./memory";
import { Ram, ram } from "./ram";
import { Word, emptyWord, wordFromNumber, wordFromString } from "./word";
const bank1GeneralAddressesStart = wordFromString("0010") as Word<4>
const bank2GeneralAddressesStart = wordFromString("0101") as Word<4>
const addressRegisterAddress = wordFromString("0000") as Word<4>
const extendedAddressRegisterAddress = wordFromString("0001") as Word<4>
const programCounterAddress = wordFromString("0010") as Word<4>
const overflowFlagAddress = wordFromString("0011") as Word<4>
const inputPinAddress = wordFromString("0100") as Word<4>
export function minecraftMachine(initialBank1Values: Word<4>[], initialBank2Values: Word<4>[], instructions: Word<4>[]) {
const bank1Ram = ram({ size: 16, width: 4 })
const bank2Ram = ram({ size: 16, width: 4 })
const stack = ram({ size: 4, width: 4 })
const stackPointer = memory(wordFromString("00"))
const instructionPointer = memory(wordFromString("0"))
initialBank1Values.forEach((value, index) => bank1Ram.write(value, wordFromNumber(index).plus(bank1GeneralAddressesStart).sum))
initialBank2Values.forEach((value, index) => bank2Ram.write(value, wordFromNumber(index).plus(bank2GeneralAddressesStart).sum))
const addressRegister = bank1Ram.get(addressRegisterAddress)
const extendedAddressRegister = bank1Ram.get(extendedAddressRegisterAddress)
addressRegister.set(wordFromNumber(2, 4) as Word<4>)
bank2Ram.write(addressRegister.value(), addressRegisterAddress)
bank2Ram.write(extendedAddressRegister.value(), extendedAddressRegisterAddress)
const programCounter = bank2Ram.get(programCounterAddress)
const overflowFlag = bank2Ram.get(overflowFlagAddress)
const inputPin = bank2Ram.get(inputPinAddress)
function tick() {
incrementInstruction()
stack.write(readCurrent(), stackPointer.value())
if (!stackPointer.value().equals(wordFromString("11"))) {
stackPointer.set(stackPointer.value().plus(wordFromString("01")).sum)
}
addressRegister.set(addressRegister.value().plus(wordFromNumber(1, 4)).sum)
}
function incrementInstruction() {
if (instructionPointer.value().equals(wordFromString("1"))) {
programCounter.set(programCounter.value().plus(wordFromNumber(1, 4)).sum)
}
instructionPointer.set(instructionPointer.value().plus(wordFromString("1")).sum)
}
function readCurrent() {
const currentBank = extendedAddressRegister.value().toString() === "0000" ? bank1Ram : bank2Ram
return currentBank.read(addressRegister.value())
}
return { programCounter, instructionPointer, addressRegister, extendedAddressRegister, stack, stackPointer, tick, bank1Ram, bank2Ram }
}