void IClockSink.OnPowerUp() { _nextOpCodeStatus = OpCodeStatus.None; _nextMicroCode = MicroCode.None; // see also: https://wiki.nesdev.com/w/index.php/CPU_power_up_state Status.Value = 0x34; Registers.A = 0; Registers.X = 0; Registers.Y = 0; Registers.S = 0xFD; // _masterClient.Value = 0; // _masterClient.Write(0x4017); // frame irq enabled // _masterClient.Write(0x4015); // all channels disabled // $4000 -$400F = $00 // for (ushort i = 0x4000; i <= 0x400F; i++) // _masterClient.Write(i); // TODO: // All 15 bits of noise channel LFSR = $0000[3].The first time the LFSR is clocked from the all-0s state, it will shift in a 1. Interrupt(InterruptType.Reset); }
protected override void dispose(bool disposeManagedResources) { if (!IsDisposed) { if (disposeManagedResources) { // have to call this here reather than in Resource destructor // since calling virtual methods in base destructors causes crash if (IsLoaded) { unload(); MicroCode.SafeDispose(); this.constTable.SafeDispose(); } else { UnloadHighLevel(); } } // There are no unmanaged resources to release, but // if we add them, they need to be released here. } // If it is available, make the call to the // base class's Dispose(Boolean) method base.dispose(disposeManagedResources); }
protected override void UnloadHighLevelImpl() { MicroCode.SafeDispose(); MicroCode = null; this.constTable.SafeDispose(); this.constTable = null; }
private MicroCode ExecuteMicroCode(MicroCode code) { switch (code) { case MicroCode.Nop: return(MicroCode.None); case MicroCode.Addressing: DispatchAddressing(); return(MicroCode.None); case MicroCode.Immediate: _addressState.MemoryAddress = Registers.PC++; DispatchAddressing(); return(MicroCode.None); case MicroCode.Relative: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress = (ushort)(Registers.PC + (sbyte)_masterClient.Value); DispatchAddressing(); return(MicroCode.None); case MicroCode.Absolute_1: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress = _masterClient.Value; return(MicroCode.Absolute_2); case MicroCode.Absolute_2: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress |= (ushort)(_masterClient.Value << 8); return(MicroCode.Absolute_3); case MicroCode.Absolute_3: DispatchAddressing(); return(MicroCode.None); case MicroCode.ZeroPage_1: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress = _masterClient.Value; return(MicroCode.ZeroPage_2); case MicroCode.ZeroPage_2: DispatchAddressing(); return(MicroCode.None); case MicroCode.ZeroPageX_1: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress = _masterClient.Value; return(MicroCode.ZeroPageX_2); case MicroCode.ZeroPageX_2: _addressState.MemoryAddress = (byte)(_addressState.MemoryAddress + Registers.X); return(MicroCode.ZeroPageX_3); case MicroCode.ZeroPageX_3: DispatchAddressing(); return(MicroCode.None); case MicroCode.AbsoluteX_1: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress = _masterClient.Value; return(MicroCode.AbsoluteX_2); case MicroCode.AbsoluteX_2: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress |= (ushort)(_masterClient.Value << 8); return(MicroCode.AbsoluteX_3); case MicroCode.AbsoluteX_3: _addressState.MemoryAddress += Registers.X; DispatchAddressing(); return(MicroCode.None); case MicroCode.AbsoluteY_1: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress = _masterClient.Value; return(MicroCode.AbsoluteX_2); case MicroCode.AbsoluteY_2: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress |= (ushort)(_masterClient.Value << 8); return(MicroCode.AbsoluteX_3); case MicroCode.AbsoluteY_3: _addressState.MemoryAddress += Registers.Y; DispatchAddressing(); return(MicroCode.None); case MicroCode.IndirectY_1: _masterClient.Read(Registers.PC++); _addressState.MemoryAddress8 = _masterClient.Value; return(MicroCode.IndirectY_2); case MicroCode.IndirectY_2: _masterClient.Read(_addressState.MemoryAddress8); _addressState.MemoryAddress = _masterClient.Value; return(MicroCode.IndirectY_3); case MicroCode.IndirectY_3: _masterClient.Read((byte)(_addressState.MemoryAddress8 + 1)); _addressState.MemoryAddress |= (ushort)(_masterClient.Value << 8); return(MicroCode.IndirectY_4); case MicroCode.IndirectY_4: _addressState.MemoryAddress += Registers.Y; DispatchAddressing(); return(MicroCode.None); /* * case MicroCode.ZeroPage_1: * _masterClient.Read(Registers.PC++); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.ZeroPage_2; * break; * case MicroCode.ZeroPage_2: * _masterClient.Read(_addressResult); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.None; * break; * case MicroCode.ZeroPageY_1: * _masterClient.Read(Registers.PC++); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.ZeroPageY_2; * break; * case MicroCode.ZeroPageY_2: * _addressResult += Registers.Y; * _nextMicroCode = MicroCode.ZeroPageY_3; * break; * case MicroCode.ZeroPageY_3: * _masterClient.Read(_addressResult); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.None; * break; * case MicroCode.Absolute_1: * _masterClient.Read(Registers.PC++); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.Absolute_2; * break; * case MicroCode.Absolute_2: * _masterClient.Read(Registers.PC++); * _addressResult2 = _masterClient.Value; * _nextMicroCode = MicroCode.Absolute_3; * break; * case MicroCode.Absolute_3: * _masterClient.Read((ushort)(_addressResult | _addressResult2 << 8)); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.None; * break; * case MicroCode.IndirectX_1: * _masterClient.Read(Registers.PC++); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.IndirectX_2; * break; * case MicroCode.IndirectX_2: * _addressResult = (byte)(_addressResult + Registers.X); * _addressResult2 = (byte)(_addressResult + 1); * _nextMicroCode = MicroCode.IndirectX_3; * break; * case MicroCode.IndirectX_3: * _masterClient.Read(_addressResult); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.IndirectX_4; * break; * case MicroCode.IndirectX_4: * _masterClient.Read(_addressResult2); * _addressResult2 = _masterClient.Value; * _nextMicroCode = MicroCode.IndirectX_5; * break; * case MicroCode.IndirectX_5: * _masterClient.Read((ushort)(_addressResult | _addressResult2 << 8)); * _addressResult = _masterClient.Value; * _nextMicroCode = MicroCode.None; * break; * case MicroCode.ADC: * { * var result = (ushort)(Registers.A + _addressResult + Status.C); * UpdateCVN(Registers.A, _addressResult, result); * Registers.A = (byte)result; * _nextMicroCode = MicroCode.None; * } * * break; */ case MicroCode.Push: _masterClient.Value = _addressState.ResultA; _masterClient.Write((ushort)(0x100u + Registers.S--)); return(MicroCode.None); case MicroCode.Pop: _masterClient.Read((ushort)(0x100u + ++Registers.S)); _addressState.ResultA = _masterClient.Value; return(MicroCode.None); case MicroCode.SEI: Status.I = true; return(MicroCode.None); case MicroCode.CLC: Status.C = false; return(MicroCode.None); case MicroCode.CLD: Status.D = false; return(MicroCode.None); default: throw new InvalidProgramException($"invalid micro code: 0x{code:X}."); } }