static void Main(string[] args) { // Console Initialization Display.Text.TextDisplay.Setup(); Interpreter.Memory memory = new Interpreter.Memory(0x1000); Display.Text.TextDisplay display = new Display.Text.TextDisplay(memory); // Launch Execute Thread Thread executeThread = new Thread(new ParameterizedThreadStart(ExecuteThread)); executeThread.Start(memory); // alive.asm memory.Set(0x600, new List<byte> { 0xa9, 0xf, 0x85, 0x0, 0x85, 0x1, 0xa5, 0xfe, 0x29, 0x3, 0xc9, 0x0, 0xf0, 0x2f, 0xc9, 0x1, 0xf0, 0x30, 0xc9, 0x2, 0xf0, 0x22, 0xc6, 0x1, 0xa5, 0x1, 0x29, 0x1f, 0xa, 0xaa, 0xbd, 0x47, 0x6, 0x85, 0x2, 0xe8, 0xbd, 0x47, 0x6, 0x85, 0x3, 0xa5, 0x0, 0x29, 0x1f, 0xa8, 0xb1, 0x2, 0xaa, 0xe8, 0x8a, 0x91, 0x2, 0x4c, 0x6, 0x6, 0xe6, 0x1, 0x4c, 0x18, 0x6, 0xc6, 0x0, 0x4c, 0x18, 0x6, 0xe6, 0x0, 0x4c, 0x18, 0x6, 0x0, 0x2, 0x20, 0x2, 0x40, 0x2, 0x60, 0x2, 0x80, 0x2, 0xa0, 0x2, 0xc0, 0x2, 0xe0, 0x2, 0x0, 0x3, 0x20, 0x3, 0x40, 0x3, 0x60, 0x3, 0x80, 0x3, 0xa0, 0x3, 0xc0, 0x3, 0xe0, 0x3, 0x0, 0x4, 0x20, 0x4, 0x40, 0x4, 0x60, 0x4, 0x80, 0x4, 0xa0, 0x4, 0xc0, 0x4, 0xe0, 0x4, 0x0, 0x5, 0x20, 0x5, 0x40, 0x5, 0x60, 0x5, 0x80, 0x5, 0xa0, 0x5, 0xc0, 0x5, 0xe0, 0x5 }); // disco.asm //memory.Set(0x600, new List<byte> { 0xe8, 0x8a, 0x99, 0x0, 0x2, 0x99, 0x0, 0x3, 0x99, 0x0, 0x4, 0x99, 0x0, 0x5, 0xc8, 0x98, 0xc5, 0x10, 0xd0, 0x4, 0xc8, 0x4c, 0x0, 0x6, 0xc8, 0xc8, 0xc8, 0xc8, 0x4c, 0x0, 0x6 }); for (; ; ) { display.Render(); if (Interpreter.DisplaySettings.LimitGraphicsSpeed) Thread.Sleep(1000 / Interpreter.DisplaySettings.RenderFrequency); } }
static void Main(string[] args) { // Console Initialization Display.Text.TextDisplay.Setup(); Interpreter.Memory memory = new Interpreter.Memory(0x1000); Display.Text.TextDisplay display = new Display.Text.TextDisplay(memory); // Launch Execute Thread Thread executeThread = new Thread(new ParameterizedThreadStart(ExecuteThread)); executeThread.Start(memory); // alive.asm memory.Set(0x600, new List <byte> { 0xa9, 0xf, 0x85, 0x0, 0x85, 0x1, 0xa5, 0xfe, 0x29, 0x3, 0xc9, 0x0, 0xf0, 0x2f, 0xc9, 0x1, 0xf0, 0x30, 0xc9, 0x2, 0xf0, 0x22, 0xc6, 0x1, 0xa5, 0x1, 0x29, 0x1f, 0xa, 0xaa, 0xbd, 0x47, 0x6, 0x85, 0x2, 0xe8, 0xbd, 0x47, 0x6, 0x85, 0x3, 0xa5, 0x0, 0x29, 0x1f, 0xa8, 0xb1, 0x2, 0xaa, 0xe8, 0x8a, 0x91, 0x2, 0x4c, 0x6, 0x6, 0xe6, 0x1, 0x4c, 0x18, 0x6, 0xc6, 0x0, 0x4c, 0x18, 0x6, 0xe6, 0x0, 0x4c, 0x18, 0x6, 0x0, 0x2, 0x20, 0x2, 0x40, 0x2, 0x60, 0x2, 0x80, 0x2, 0xa0, 0x2, 0xc0, 0x2, 0xe0, 0x2, 0x0, 0x3, 0x20, 0x3, 0x40, 0x3, 0x60, 0x3, 0x80, 0x3, 0xa0, 0x3, 0xc0, 0x3, 0xe0, 0x3, 0x0, 0x4, 0x20, 0x4, 0x40, 0x4, 0x60, 0x4, 0x80, 0x4, 0xa0, 0x4, 0xc0, 0x4, 0xe0, 0x4, 0x0, 0x5, 0x20, 0x5, 0x40, 0x5, 0x60, 0x5, 0x80, 0x5, 0xa0, 0x5, 0xc0, 0x5, 0xe0, 0x5 }); // disco.asm //memory.Set(0x600, new List<byte> { 0xe8, 0x8a, 0x99, 0x0, 0x2, 0x99, 0x0, 0x3, 0x99, 0x0, 0x4, 0x99, 0x0, 0x5, 0xc8, 0x98, 0xc5, 0x10, 0xd0, 0x4, 0xc8, 0x4c, 0x0, 0x6, 0xc8, 0xc8, 0xc8, 0xc8, 0x4c, 0x0, 0x6 }); for (; ;) { display.Render(); if (Interpreter.DisplaySettings.LimitGraphicsSpeed) { Thread.Sleep(1000 / Interpreter.DisplaySettings.RenderFrequency); } } }
public GraphicsDisplay() { InitializeComponent(); this.Paint += new PaintEventHandler(GraphicsDisplay_Paint); this.FormClosed += new FormClosedEventHandler(GraphicsDisplay_FormClosing); _memory = new Memory(0xFFFF); _processor = new Processor(_memory, 0x600); // alive.asm //_memory.Set(0x600, new List<byte> { 0xa9, 0xf, 0x85, 0x0, 0x85, 0x1, 0xa5, 0xfe, 0x29, 0x3, 0xc9, 0x0, 0xf0, 0x2f, 0xc9, 0x1, 0xf0, 0x30, 0xc9, 0x2, 0xf0, 0x22, 0xc6, 0x1, 0xa5, 0x1, 0x29, 0x1f, 0xa, 0xaa, 0xbd, 0x47, 0x6, 0x85, 0x2, 0xe8, 0xbd, 0x47, 0x6, 0x85, 0x3, 0xa5, 0x0, 0x29, 0x1f, 0xa8, 0xb1, 0x2, 0xaa, 0xe8, 0x8a, 0x91, 0x2, 0x4c, 0x6, 0x6, 0xe6, 0x1, 0x4c, 0x18, 0x6, 0xc6, 0x0, 0x4c, 0x18, 0x6, 0xe6, 0x0, 0x4c, 0x18, 0x6, 0x0, 0x2, 0x20, 0x2, 0x40, 0x2, 0x60, 0x2, 0x80, 0x2, 0xa0, 0x2, 0xc0, 0x2, 0xe0, 0x2, 0x0, 0x3, 0x20, 0x3, 0x40, 0x3, 0x60, 0x3, 0x80, 0x3, 0xa0, 0x3, 0xc0, 0x3, 0xe0, 0x3, 0x0, 0x4, 0x20, 0x4, 0x40, 0x4, 0x60, 0x4, 0x80, 0x4, 0xa0, 0x4, 0xc0, 0x4, 0xe0, 0x4, 0x0, 0x5, 0x20, 0x5, 0x40, 0x5, 0x60, 0x5, 0x80, 0x5, 0xa0, 0x5, 0xc0, 0x5, 0xe0, 0x5 }); // disco.asm _memory.Set(0x600, new List<byte> { 0xe8, 0x8a, 0x99, 0x0, 0x2, 0x99, 0x0, 0x3, 0x99, 0x0, 0x4, 0x99, 0x0, 0x5, 0xc8, 0x98, 0xc5, 0x10, 0xd0, 0x4, 0xc8, 0x4c, 0x0, 0x6, 0xc8, 0xc8, 0xc8, 0xc8, 0x4c, 0x0, 0x6 }); }
/// <summary> /// Core of the intepreter, executes a single instruction. /// </summary> public void Execute() { //Thread.Sleep(1); if (!_programRunning) { return; } int a = 0; if (LimitProcessorSpeed) { for (int i = 0; i < SpinWait; i++) { a += 2; } } byte opcode = PopByte(); // Console.WriteLine("0x" + opcode.ToString("X")); switch (opcode) { case 0x00: // BRK _breakFlag = true; _programRunning = false; break; case 0x01: // Logical OR, Indirect, X value1 = PopByte(); _accumulator |= _memory.Read(value1 + _indexX); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x05: // Logical OR, Zero-paged value1 = PopByte(); _accumulator |= _memory.Read(value1); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x06: // Arithmetic shift left, Zero-paged _carryFlag = (_accumulator & 0x80) != 0; value1 = PopByte(); _memory.Set(value1, Convert.ToByte(_memory.Read(value1) << 1)); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x08: break; case 0x09: // Logical OR, Immediate value1 = PopByte(); _accumulator |= value1; _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x0A: // Arithmetic shift left, Accumulator // Note: actually logical shift left _carryFlag = (_accumulator & 0x80) != 0; _accumulator = Convert.ToByte((_accumulator * 2) & 0xFF); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x0D: // Logical OR, Absolute value1 = PopByte(); value2 = PopByte(); _accumulator |= _memory.Read(value2 * 0x100 + value1); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x0E: // Arithmetic shift left, Absolute _carryFlag = (_accumulator & 0x80) != 0; value1 = PopByte(); value2 = PopByte(); _memory.Set(value2 * 0x100 + value1, Convert.ToByte(2 * _memory.Read(value1 * 0x100 + value2))); _zeroFlag = _accumulator == 0; break; case 0x10: break; case 0x11: break; case 0x15: break; case 0x16: break; case 0x18: break; case 0x19: break; case 0x1D: break; case 0x1E: break; case 0x20: break; case 0x21: break; case 0x24: break; case 0x25: break; case 0x26: break; case 0x28: break; case 0x29: // Logical AND, Immediate value1 = PopByte(); _accumulator &= value1; _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x2A: break; case 0x2C: break; case 0x2D: break; case 0x2E: break; case 0x30: break; case 0x31: break; case 0x35: break; case 0x36: break; case 0x38: break; case 0x39: break; case 0x3D: break; case 0x3E: break; case 0x40: break; case 0x41: break; case 0x45: break; case 0x46: break; case 0x48: break; case 0x49: break; case 0x4A: // Logical shift right break; case 0x4C: // Jump, Absolute value1 = PopByte(); value2 = PopByte(); _programCounter = Convert.ToUInt16(value2 * 0x100 + value1); break; case 0x4D: break; case 0x4E: break; case 0x50: break; case 0x51: break; case 0x55: break; case 0x56: break; case 0x58: break; case 0x59: break; case 0x5D: break; case 0x5E: break; case 0x60: break; case 0x61: // Add with Carry, Indirect, X value1 = PopByte(); sum = _accumulator + _memory.Read(value1 + _indexX); if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); break; case 0x65: // Add with Carry, Zero-paged value1 = PopByte(); sum = _accumulator + _memory.Read(value1); if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); break; case 0x66: break; case 0x68: break; case 0x69: // Add with Carry, Immediate value1 = PopByte(); sum = _accumulator + value1; if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); break; case 0x6A: break; case 0x6C: // Jump, Indirect value1 = PopByte(); value2 = PopByte(); _programCounter = Convert.ToUInt16(_memory.Read(value2 * 0x100 + value1 + 1) * 0x100 + _memory.Read(value2 * 0x100 + value1)); break; case 0x6D: // Add with Carry, Absolute value1 = PopByte(); value2 = PopByte(); sum = _accumulator + _memory.Read(value2 * 0x100 + value1); if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); break; case 0x6E: break; case 0x70: break; case 0x71: break; case 0x75: // Add with Carry, Zero-paged, X value1 = PopByte(); sum = _accumulator + _memory.Read((value1 + _indexX) % 0xFF); if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); _programCounter++; break; case 0x76: break; case 0x78: break; case 0x79: // Add with Carry, Absolute, Y value1 = PopByte(); value2 = PopByte(); sum = _accumulator + _memory.Read(value2 * 0x100 + value1 + _indexY); if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); break; case 0x7D: // Add with Carry, Absolute, X value1 = PopByte(); value2 = PopByte(); sum = _accumulator + _memory.Read(value2 * 0x100 + value1 + _indexX); if (_carryFlag) { sum++; } _carryFlag = sum > 0xFF; _accumulator = Convert.ToByte(sum % 0xFF); break; case 0x7E: break; case 0x81: // Store accumulator, Indirect, X value1 = PopByte(); _memory.Set((value1 + _indexX) % 0xFFFF, _accumulator); break; case 0x84: break; case 0x85: // Store accumulator, Zero-paged value1 = PopByte(); _memory.Set(value1, _accumulator); break; case 0x86: // Store X, Zero-paged value1 = PopByte(); _memory.Set(value1, _indexX); break; case 0x88: break; case 0x8A: // Transfer X to A, Implied _accumulator = _indexX; _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x8C: break; case 0x8D: // Store accumulator, Absolute value1 = PopByte(); value2 = PopByte(); _memory.Set(value2 * 0x100 + value1, _accumulator); break; case 0x8E: break; case 0x90: break; case 0x91: // Store accumulator, Indirect, Y value1 = PopByte(); value2 = _memory.Read(value1); value1 = _memory.Read(value1 + 1); _memory.Set((value1 * 0x100 + value2 + _indexY) & 0xFFFF, _accumulator); break; case 0x94: break; case 0x95: // Store accumulator, Zero-paged, X value1 = PopByte(); _memory.Set((value1 + _indexX) % 0xFF, _accumulator); break; case 0x96: break; case 0x98: // Transfer Y to A, Implied _accumulator = _indexY; _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0x99: // Store accumulator, Absolute, Y value1 = PopByte(); value2 = PopByte(); _memory.Set(value2 * 0x100 + value1 + _indexY, _accumulator); break; case 0x9A: break; case 0x9D: break; case 0xA0: break; case 0xA1: // Load accumulator, Indirect, X value1 = PopByte(); _accumulator = _memory.Read((value1 + _indexX) % 0xFFFF); // wraps around _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xA2: // Load X, Immediate _indexX = PopByte(); _zeroFlag = _indexX == 0; _negativeFlag = (_indexX & 0x80) != 0; break; case 0xA4: break; case 0xA5: // Load accumulator, Zero-paged value1 = PopByte(); _accumulator = _memory.Read(value1); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xA6: // Load X, Zero-paged value1 = PopByte(); _indexX = _memory.Read(value1); _zeroFlag = _indexX == 0; _negativeFlag = (_indexX & 0x80) != 0; break; case 0xA8: // Transfer A to Y, Implied _indexY = _accumulator; _zeroFlag = _indexY == 0; _negativeFlag = (_indexY & 0x80) != 0; break; case 0xA9: // Load accumulator, Immediate value1 = PopByte(); _accumulator = value1; _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xAA: // Transfer A to X, Implied _indexX = _accumulator; _zeroFlag = _indexX == 0; _negativeFlag = (_indexX & 0x80) != 0; break; case 0xAC: break; case 0xAD: // Load accumulator, Absolute value1 = PopByte(); value2 = PopByte(); _accumulator = _memory.Read(value2 * 0x100 + value1); break; case 0xAE: break; case 0xB0: break; case 0xB1: // Load accumulator, Indirect, Y value1 = PopByte(); value2 = _memory.Read(value1); value1 = _memory.Read(value1 + 1); _accumulator = _memory.Read((value1 * 0x100 + value2 + _indexY) & 0xFFFF); // wraps around _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xB4: break; case 0xB5: // Load accumulator, Zero-paged, X value1 = PopByte(); _accumulator = _memory.Read((value1 + _indexX) & 0xFF); // wraps around break; case 0xB6: break; case 0xB8: break; case 0xB9: // Load accumulator, Absolute, Y value1 = PopByte(); value2 = PopByte(); _accumulator = _memory.Read(value2 * 0x100 + value1 + _indexY); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xBA: break; case 0xBC: break; case 0xBD: // Load accumulator, Absolute, X value1 = PopByte(); value2 = PopByte(); _accumulator = _memory.Read(value2 * 0x100 + value1 + _indexX); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xBE: break; case 0xC0: break; case 0xC1: break; case 0xC4: break; case 0xC5: // Compare, Zero-paged value1 = PopByte(); _carryFlag = _accumulator >= _memory.Read(value1); _accumulator -= _memory.Read(value1); _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xC6: // Decrement memory, Zero Paged value1 = PopByte(); if (_memory.Read(value1) - 1 == -1) { value2 = Convert.ToByte(0xFF); } else { value2 = Convert.ToByte(_memory.Read(value1) - 1); } _memory.Set(value1, value2); _negativeFlag = (value2 & 0x80) != 0; _zeroFlag = value2 == 0; break; case 0xC8: // Increment Y, Implied _indexY = Convert.ToByte((_indexY + 1) & 0xFF); _zeroFlag = _indexY == 0; _negativeFlag = (_indexY & 0x80) != 0; break; case 0xC9: // Compare, Immediate value1 = PopByte(); _carryFlag = _accumulator >= value1; _accumulator -= value1; _zeroFlag = _accumulator == 0; _negativeFlag = (_accumulator & 0x80) != 0; break; case 0xCA: break; case 0xCC: break; case 0xCD: break; case 0xCE: break; case 0xD0: // Branch if not equal value1 = PopByte(); if (!_zeroFlag) { JumpRelative(value1); } break; case 0xD1: break; case 0xD5: break; case 0xD6: break; case 0xD8: break; case 0xD9: break; case 0xDD: break; case 0xDE: break; case 0xE0: break; case 0xE1: break; case 0xE4: break; case 0xE5: break; case 0xE6: // Increment memory, Zero Paged value1 = PopByte(); value2 = Convert.ToByte((_memory.Read(value1) + 1) & 0xFF); _memory.Set(value1, value2); _negativeFlag = (value2 & 0x80) != 0; _zeroFlag = value2 == 0; break; case 0xE8: // Increment X, Implied _indexX = Convert.ToByte((_indexX + 1) & 0xFF); _zeroFlag = _indexX == 0; _negativeFlag = (_indexX & 0x80) != 0; break; case 0xE9: break; case 0xEA: // No-op return; case 0xEB: break; case 0xEC: break; case 0xED: break; case 0xEE: // Increment memory, Absolute value1 = PopByte(); value2 = PopByte(); sum = _memory.Read(value1 * 0x100 + value2) + 1; _memory.Set(value2 * 0x100 + value1, Convert.ToByte(sum)); _negativeFlag = (sum & 0x80) != 0; _zeroFlag = sum == 0; break; case 0xF0: // Branch if equal value1 = PopByte(); if (_zeroFlag) { JumpRelative(value1); } break; case 0xF1: break; case 0xF5: break; case 0xF6: // Increment memory, Zero Paged, X value1 = PopByte(); value2 = Convert.ToByte(_memory.Read((value1 + _indexX) & 0xFF) + 1); _memory.Set((value1 + _indexX) & 0xFF, value2); _negativeFlag = (value2 & 0x80) != 0; _zeroFlag = value2 == 0; break; case 0xF8: break; case 0xF9: break; case 0xFD: break; case 0xFE: // Increment memory, Absolute, X value1 = PopByte(); value2 = PopByte(); sum = _memory.Read(value2 * 0x100 + value1) + 1; _memory.Set(value2 * 0x100 + value1, Convert.ToByte(sum)); _negativeFlag = (sum & 0x80) != 0; _zeroFlag = sum == 0; break; default: throw new Exceptions.InvalidOpCodeException("Opcode 0x" + opcode.ToString("X") + " is invalid."); } }