public void set(BCD10 b) { for (int i = 0; i < DIGITS; i++) { digits[i] = b.digits[i]; } }
private byte toTapeCode(BCD10 bcd10) { byte c = 0; bool isOdd = false; switch (bcd10.digits[8]) { default: break; case 4: c += 1; isOdd = !isOdd; break; case 5: case 6: case 7: case 8: c += 2; isOdd = !isOdd; break; case 9: c += 3; break; } switch (bcd10.digits[9]) { default: break; case 1: case 6: c += 4; isOdd = !isOdd; break; case 2: case 7: c += 8; isOdd = !isOdd; break; case 3: case 8: c += 12; break; } if ((!isOdd && bcd10.digits[9] < 5) || (isOdd && bcd10.digits[9] >= 5)) { c += 16; } return(c); }
public void setNumber(BCD10 b) { if (!b.isEqual(lastDisplayed)) { for (int i = 0; i < 10; i++) { nixies[9 - i].setNumber(b.digits[i]); } } lastDisplayed.set(b); }
public bool isEqual(BCD10 bcd10) { for (int i = 0; i < DIGITS; i++) { if (digits[i] != bcd10.digits[i]) { return(false); } } return(true); }
private void setPC(BCD10 addr) { if (isPrimaryInput) { primaryInputPC = (int)addr.toUInt64(); } else { accumulators[controlRegister].set(addr); } }
private void processOrder0() { BCD10 b; if (accB > 0) { effectiveOperand.add(accumulators[accB]); } if (accA == 0) { accumulators[0].set(controlBoxScript.getKeyboard()); } b = new BCD10(effectiveOperand); if (siriusOpcodeLow >= 5) { b.shiftLeft(4); } switch (siriusOpcodeLow) { case 0: case 5: accumulators[accA].add(b); flagOVR |= BCD10.flagOVR; break; case 1: case 6: accumulators[accA].sub(b); flagOVR |= BCD10.flagOVR; break; case 2: case 7: accumulators[accA].negSub(b); flagOVR |= BCD10.flagOVR; break; case 3: case 8: accumulators[accA].negAdd(b); flagOVR |= BCD10.flagOVR; break; case 4: case 9: accumulators[accA].set(b); break; } }
public void negSub(BCD10 b) { int c = 0; bool wasNegative = isNegative(); for (int i = 0; i < DIGITS; i++) { int n = 20 - digits[i] - b.digits[i] - c; c = 2 - n / 10; digits[i] = (byte)(n % 10); } flagOVR = ((!wasNegative && !b.isNegative() && !isNegative()) || (wasNegative && b.isNegative() && isNegative())); }
public void add(BCD10 b) { int c = 0; bool wasNegative = isNegative(); for (int i = 0; i < DIGITS; i++) { int n = digits[i] + b.digits[i] + c; c = n / 10; digits[i] = (byte)(n % 10); } flagOVR = ((wasNegative && b.isNegative() && !isNegative()) || (!wasNegative && !b.isNegative() && isNegative())); }
public BCD10 getKeyboard() { BCD10 result = new BCD10(); for (int i = 0; i < 10; i++) { int n = pressed[i]; if (n < 0) { n = 0; } result.digits[9 - i] = (byte)n; } return(result); }
// Start is called before the first frame update void Start() { nixies = new NixieScript[10]; nixies[0] = nixieScript0; nixies[1] = nixieScript1; nixies[2] = nixieScript2; nixies[3] = nixieScript3; nixies[4] = nixieScript4; nixies[5] = nixieScript5; nixies[6] = nixieScript6; nixies[7] = nixieScript7; nixies[8] = nixieScript8; nixies[9] = nixieScript9; lastDisplayed = new BCD10(); }
private void updateDisplay() { indicatorPIScript.setState(isPrimaryInput); indicatorOVRScript.setState(flagOVR); indicator99WScript.setState(isStopped99); indicatorKSScript.setState(isStoppedKB); indicator6910Script.setState(isStopped6910); indicatorRBScript.setState(isRBusy); indicatorPBScript.setState(isPBusy); indicatorMSDScript.setState(accumulators[accA].digits[9] != 0); indicatorNZScript.setState(!accumulators[accA].isZero()); indicatorSBScript.setState(accumulators[accA].isNegative()); { int s = speedWheelScript.getValue(); if (s > 5) { indicatorNFSScript.setSpecial(); } else { indicatorNFSScript.setState(s < 5); } } int a = lastDisplayed; if (!isRetryingForFrame) { a = controlBoxScript.selectedAccumulator(); lastDisplayed = a; } BCD10 displayed = new BCD10(); displayed.digits[0] = accB; displayed.digits[1] = accA; displayed.digits[2] = siriusOpcodeLow; displayed.digits[3] = siriusOpcodeHigh; for (int i = 0; i < 6; i++) { displayed.digits[i + 4] = effectiveOperand.digits[i]; } displayScript0.setNumber(displayed); accumulators[0].set(accumulators[a]); displayScript1.setNumber(accumulators[0]); }
private bool division(BCD10 b, BCD10 c, BCD10 d) // Divide (b, c) by d. Return true if the quotient >= 1 { div_remainder = new byte[20]; div_quotient = new byte[10]; for (int i = 0; i < 10; i++) { div_remainder[i + 10] = b.digits[i]; } for (int i = 0; i < 10; i++) { div_remainder[i] = c.digits[i]; } for (int i = 0; i < 10; i++) { div_quotient[i] = 0; } multDivCycles = 22; if (sub20(div_remainder, d.digits, 10)) { return(true); } for (int s = 9; s >= 0; s--) { for (int i = 0; i < 10; i++) { if (sub20(div_remainder, d.digits, s)) { div_quotient[s]++; } else { break; } } } for (int i = 0; i < 10; i++) { multDivCycles += (uint)div_quotient[i] * 2; } return(false); }
private void mult(BCD10 b, BCD10 c, bool negate) { mult_result = new int[20]; int carry; multDivCycles = 22; for (int i = 0; i < 10; i++) { multDivCycles += (uint)b.digits[i] * 2; } for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { mult_result[i + j] += b.digits[i] * c.digits[j]; } } carry = 0; for (int i = 0; i < 20; i++) { mult_result[i] += carry; carry = mult_result[i] / 10; mult_result[i] = mult_result[i] % 10; } if (negate) { carry = 0; for (int i = 0; i < 20; i++) { int n = 10 - mult_result[i] - carry; carry = 1 - n / 10; mult_result[i] = n % 10; } } }
private void processOrder5() { BCD10 a = new BCD10(); if (accA == 0) { a.set(controlBoxScript.getKeyboard()); } else { a.set(accumulators[accA]); } if (accB > 0) { effectiveOperand.add(accumulators[accB]); } switch (siriusOpcodeLow) { case 0: // DUMMY break; case 1: if (a.msd() != 0) { setPC(effectiveOperand); } break; case 2: if (!a.isZero()) { setPC(effectiveOperand); } break; case 3: if (flagOVR) { setPC(effectiveOperand); } flagOVR = false; break; case 4: if (a.isNegative()) { setPC(effectiveOperand); } break; case 5: setPC(effectiveOperand); break; case 6: if (a.msd() == 0) { setPC(effectiveOperand); } break; case 7: if (a.isZero()) { setPC(effectiveOperand); } break; case 8: if (!flagOVR) { setPC(effectiveOperand); } flagOVR = false; break; case 9: if (!a.isNegative()) { setPC(effectiveOperand); } break; } }
public BCD10(BCD10 b) { digits = new byte[DIGITS]; set(b); }
private void processOrder3() { BCD10 b = new BCD10(); bool wasNegative = accumulators[accA].isNegative(); bool shiftOVR; byte msdB; shiftOVR = (accumulators[accA].digits[9] != 0 && accumulators[accA].digits[9] != 9); if (siriusOpcodeLow < 5) { if (accB > 0) { effectiveOperand.add(accumulators[accB]); } b.setHex64(getMainStore(effectiveOperand.toUInt64())); if (accA == 0) { accumulators[0].set(controlBoxScript.getKeyboard()); } flagOVR |= shiftOVR | (wasNegative != accumulators[accA].isNegative()); } else { if (accB == 0) { b.set(controlBoxScript.getKeyboard()); } else { b.set(accumulators[accB]); } } msdB = b.msd(); // in case accA = accB ... for (int i = 9; i > 0; i--) { accumulators[accA].digits[i] = accumulators[accA].digits[i - 1]; } accumulators[accA].digits[0] = 0; switch (siriusOpcodeLow) { case 0: accumulators[accA].add(b); flagOVR |= BCD10.flagOVR; break; case 1: accumulators[accA].sub(b); flagOVR |= BCD10.flagOVR; break; case 2: accumulators[accA].negSub(b); flagOVR |= BCD10.flagOVR; break; case 3: accumulators[accA].negAdd(b); flagOVR |= BCD10.flagOVR; break; case 4: accumulators[accA].digits[0] = msdB; break; case 5: accumulators[accA].add(b); break; case 6: accumulators[accA].sub(b); break; case 7: accumulators[accA].negSub(b); break; case 8: accumulators[accA].negAdd(b); break; case 9: accumulators[accA].digits[0] = msdB; break; } }
private void processOrder2() { BCD10 b; bool wasNegative; if (accB > 0) { effectiveOperand.add(accumulators[accB]); } if (accA == 0) { accumulators[0].set(controlBoxScript.getKeyboard()); } b = new BCD10(effectiveOperand); if (siriusOpcodeLow >= 5) { b.shiftLeft(4); } wasNegative = accumulators[accA].isNegative(); flagOVR |= (accumulators[accA].digits[9] != 0 && accumulators[accA].digits[9] != 9); for (int i = 9; i > 0; i--) { accumulators[accA].digits[i] = accumulators[accA].digits[i - 1]; } accumulators[accA].digits[0] = 0; flagOVR |= (wasNegative != accumulators[accA].isNegative()); switch (siriusOpcodeLow) { case 0: case 5: accumulators[accA].add(b); flagOVR |= BCD10.flagOVR; break; case 1: case 6: accumulators[accA].sub(b); flagOVR |= BCD10.flagOVR; break; case 2: case 7: accumulators[accA].negSub(b); flagOVR |= BCD10.flagOVR; break; case 3: case 8: accumulators[accA].negAdd(b); flagOVR |= BCD10.flagOVR; break; case 4: case 9: accumulators[accA].digits[0] = b.digits[9]; break; } }
// Start is called before the first frame update void Start() { accumulators = new BCD10[10]; // accumulators[0] holds content to be displayed, not 0. for (int i = 0; i < 10; i++) { accumulators[i] = new BCD10(); } currentOrder = new BCD10(); siriusOperand = new BCD6(); effectiveOperand = new BCD10(); mainStore = new UInt64[mainStoreSize]; primaryInputMicroProgram = new UInt64[] { 0x0000007140L, 0x0000065440L, 0x0000001544L, 0x0000001544L, 0x0000003954L, 0x0000005500L, 0x0000006051L, 0x0000010010L, 0x0000007140L, 0x0000025940L, 0x0000009900L }; mask66_68 = new byte[, ] // in the order: N+b, a { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, { 0, 0, 0, 0, 4, 5, 5, 5, 5, 9 }, { 0, 0, 0, 0, 0, 5, 5, 5, 5, 5 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, { 0, 0, 2, 2, 4, 5, 5, 7, 7, 9 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, { 0, 0, 0, 0, 4, 5, 5, 5, 5, 9 } }; mask65_67 = new byte[, ] // in the order: N+b, a { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 2, 3, 0, 0, 1, 2, 3, 0 }, { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 1, 0, 0, 1, 0, 1, 0 }, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 2, 3, 0, 0, 1, 2, 3, 0 } }; cycleTimes = new float[] { 0.00008f, 0.00008f, 0.00008f, 0.00008f, 0.00008f, 0.00008f, 0.00004f, 0.00002f, 0.00001f, 0.000005f, 0.0000025f }; cycleFactors = new uint[] { 4167, 2083, 1042, 100, 10, 1, 1, 1, 1, 1, 1 }; cycleTime = cycleTimes[5]; cycleFactor = cycleFactors[5]; isPrimaryInput = false; isStopped99 = false; isStoppedByError = false; isStoppedKB = false; isStopped6910 = false; isRetrying = false; isRetryingForFrame = false; isWaitingR = false; isWaitingP = false; isRBusy = false; // only when no tape isPBusy = false; // always false flagOVR = false; flagInputAccepted = false; delayLinePos = 0; timeLeft = 0.0f; }
private void processOrder1() { BCD10 b = new BCD10(); if (siriusOpcodeLow < 5) { if (accB > 0) { effectiveOperand.add(accumulators[accB]); } b.setHex64(getMainStore(effectiveOperand.toUInt64())); if (accA == 0) { accumulators[0].set(controlBoxScript.getKeyboard()); } } else { if (accB == 0) { b.set(controlBoxScript.getKeyboard()); } else { b.set(accumulators[accB]); } } switch (siriusOpcodeLow) { case 0: accumulators[accA].add(b); flagOVR |= BCD10.flagOVR; break; case 1: accumulators[accA].sub(b); flagOVR |= BCD10.flagOVR; break; case 2: accumulators[accA].negSub(b); flagOVR |= BCD10.flagOVR; break; case 3: accumulators[accA].negAdd(b); flagOVR |= BCD10.flagOVR; break; case 4: accumulators[accA].set(b); break; case 5: accumulators[accA].add(b); break; case 6: accumulators[accA].sub(b); break; case 7: accumulators[accA].negSub(b); break; case 8: accumulators[accA].negAdd(b); break; case 9: accumulators[accA].set(b); break; } }
private void processOrder7() { BCD10 bcd0, bcd1; bool negate; if (accB > 0) { effectiveOperand.add(accumulators[accB]); } switch (siriusOpcodeLow) { case 1: case 6: readInputChannel(); break; case 2: case 7: writeOutputChannel(); break; case 3: case 8: if (!isRetrying || isWaitingR) { readInputChannel(); } if (!isWaitingR) { writeOutputChannel(); } break; case 4: // accB=0: KB // displayed operand: 0? negate = false; if (accB == 0) { accumulators[accB].set(controlBoxScript.getKeyboard()); } if (accumulators[accB].isNegative()) { bcd0 = new BCD10(0); negate = !negate; bcd0.sub(accumulators[accB]); } else { bcd0 = new BCD10(accumulators[accB]); } mult(bcd0, accumulators[9], negate); for (int i = 0; i < 10; i++) { accumulators[9].digits[i] = (byte)mult_result[i]; } for (int i = 0; i < 10; i++) { accumulators[accA].digits[i] = (byte)mult_result[i + 10]; } break; case 9: // displayed operand: 0? negate = false; if (accB == 0) { accumulators[accB].set(controlBoxScript.getKeyboard()); } if (accumulators[accB].isNegative()) { bcd0 = new BCD10(0); negate = !negate; bcd0.sub(accumulators[accB]); } else { bcd0 = new BCD10(accumulators[accB]); } if (accumulators[9].isNegative()) { bcd1 = new BCD10(0); negate = !negate; bcd1.sub(accumulators[9]); } else { bcd1 = new BCD10(accumulators[9]); } mult(bcd0, bcd1, negate); for (int i = 0; i < 10; i++) { accumulators[9].digits[i] = (byte)mult_result[i]; } for (int i = 0; i < 10; i++) { accumulators[accA].digits[i] = (byte)mult_result[i + 10]; } break; case 0: flagOVR |= division(accumulators[accA], accumulators[9], accumulators[accB]); flagOVR |= (div_quotient[9] >= 5); for (int i = 0; i < 10; i++) { accumulators[9].digits[i] = div_quotient[i]; } for (int i = 0; i < 10; i++) { accumulators[accA].digits[i] = div_remainder[i]; } break; case 5: flagOVR |= division(accumulators[accA], accumulators[9], accumulators[accB]); for (int i = 0; i < 10; i++) { accumulators[9].digits[i] = div_quotient[i]; } for (int i = 0; i < 10; i++) { accumulators[accA].digits[i] = div_remainder[i]; } break; } if (siriusOpcodeLow == 0 || siriusOpcodeLow == 4 || siriusOpcodeLow == 5 || siriusOpcodeLow == 9) { addCycles(multDivCycles * cycleFactor); } }
// Update is called once per frame void Update() { bool flagInterrupt = false; // flagContinue is not reset, as it might be from the end of Primary Input. kbValue = controlBoxScript.getKeyboard(); cycleTime = cycleTimes[speedWheelScript.getValue()]; cycleFactor = cycleFactors[speedWheelScript.getValue()]; if (isPrimaryInput) { timeLeft += Time.deltaTime; isRetryingForFrame = isRetrying; while (isPrimaryInput && timeLeft > 0.0f) { processOneOrder(); } } else { if (controlBoxScript.flagContinueKey) { flagContinue = true; controlBoxScript.flagContinueKey = false; } if (!isRetryingForFrame) { runPressed = controlBoxScript.flagRun; manualPressed = controlBoxScript.flagManual; kbWaitPressed = controlBoxScript.flagKBWait; if (controlBoxScript.flagInterruptKey) { flagInterrupt = true; controlBoxScript.flagInterruptKey = false; } if (controlBoxScript.flagClearControlKey) { controlBoxScript.flagClearControlKey = false; if (!runPressed) { accumulators[controlRegister].setUInt64(0); } } } if (manualPressed) { if (!isRetryingForFrame) { if (controlBoxScript.flagPrimaryInputKey) { controlBoxScript.flagPrimaryInputKey = false; isPrimaryInput = true; primaryInputPC = 0; } if (controlBoxScript.flagAcceptInputKey) { controlBoxScript.flagAcceptInputKey = false; flagInputAccepted = true; acceptedInput = new BCD10(kbValue); } } isRetryingForFrame = isRetrying; if (flagContinue) { flagContinue = false; processOneOrder(); } timeLeft = 0.0f; } else { isRetryingForFrame = isRetrying; if (flagInterrupt) { setMainStore_forced(1, accumulators[controlRegister].toHex64()); accumulators[controlRegister].setUInt64(2); } else { if (flagContinue) { flagContinue = false; if (!runPressed) { processOneOrder(); } isStopped99 = false; isStoppedKB = false; isStopped6910 = false; isStoppedByError = false; timeLeft = 0.0f; } else { if (runPressed) { timeLeft += Time.deltaTime; while ((!isStopped99 && !isStoppedKB && !isStopped6910 && !isStoppedByError) && timeLeft > 0.0f) { processOneOrder(); } } else { timeLeft = 0.0f; } } } } } updateDisplay(); }