public int Execute(CpuState cpuState, IMemory memory) { int cycles = 3; ushort dest = memory.ReadShort(cpuState.Pc + 1); if (Variants[memory[cpuState.Pc]] == AddressingMode.Indirect) { dest = memory.ReadShort(dest); cycles = 5; } cpuState.Pc = dest; return cycles; }
public int Execute(CpuState cpuState, IMemory memory) { var ret = cpuState.Pc + 2; cpuState.PushStack((byte)((ret & 0xFF00) >> 8), memory); cpuState.PushStack((byte) (ret & 0xFF), memory); cpuState.Pc = memory.ReadShort(cpuState.Pc + 1); return 6; }
public void Interrupt(int interruptAddress, IMemory mem) { PushStack((byte)(Pc >> 8), mem); PushStack((byte)(Pc & 0xFF), mem); PushStack(StatusRegister, mem); SetFlag(Flags.InterruptDisable, true); Pc = mem.ReadShort(interruptAddress); }
public int Execute(CpuState cpuState, IMemory memory) { int cycles = 3; ushort dest = memory.ReadShort(cpuState.Pc + 1); if (Variants[memory[cpuState.Pc]] == AddressingMode.Indirect) { // Reading the address cannot page wrap var secondByte = (dest + 1) & 0xFF; secondByte |= dest & 0xFF00; dest = (ushort) (memory[dest] | (memory[secondByte] << 8)); cycles = 5; } cpuState.Pc = dest; return cycles; }
public static string Disassemble(this IInstruction instruction, byte[] args, IMemory memory, CpuState cpuState) { switch (instruction.Variants[args[0]]) { case AddressingMode.Accumulator: return string.Format("{0} A", instruction.Mnemonic); case AddressingMode.Absolute: if (instruction is JMP || instruction is JSR) { return string.Format("{0} ${1:X2}{2:X2}", instruction.Mnemonic, args[2], args[1]); } else { return string.Format("{0} ${1:X2}{2:X2} = {3:X2}", instruction.Mnemonic, args[2], args[1], memory[(args[2] << 8) | args[1]]); } case AddressingMode.AbsoluteX: { ushort addr = (ushort) ((args[2] << 8) | args[1]); addr += cpuState.X; return string.Format("{0} ${1:X2}{2:X2},X @ {3:X4} = {4:X2}", instruction.Mnemonic, args[2], args[1], addr, memory[addr]); } case AddressingMode.AbsoluteY: { ushort addr = (ushort) ((args[2] << 8) | args[1]); addr += cpuState.Y; return string.Format("{0} ${1:X2}{2:X2},Y @ {3:X4} = {4:X2}", instruction.Mnemonic, args[2], args[1], addr, memory[addr]); } case AddressingMode.Immediate: return string.Format("{0} #${1:X2}", instruction.Mnemonic, args[1]); case AddressingMode.Implied: return instruction.Mnemonic; case AddressingMode.Indirect: return string.Format("{0} (${1:X2}{2:X2}) = {3:X4}", instruction.Mnemonic, args[2], args[1], memory.ReadShort((args[2] << 8) | args[1])); case AddressingMode.XIndexedIndirect: { byte addr = (byte) (args[1] + cpuState.X); var finalAddr = memory.ReadZeroPageShort(addr); return string.Format("{0} (${1:X2},X) @ {2:X2} = {3:X4} = {4:X2}", instruction.Mnemonic, args[1], addr, finalAddr, memory[finalAddr]); } case AddressingMode.IndirectYIndexed: { ushort addr = memory.ReadZeroPageShort(args[1]); ushort finalAddr = (ushort) (addr + cpuState.Y); return string.Format("{0} (${1:X2}),Y = {2:X4} @ {3:X4} = {4:X2}", instruction.Mnemonic, args[1], addr, finalAddr, memory[finalAddr]); } case AddressingMode.Relative: { ushort newPc; if ((args[1] & 0x80) != 0) { newPc = (ushort)(cpuState.Pc - (0x100 - args[1])); } else { newPc = (ushort)(cpuState.Pc + args[1]); } return string.Format("{0} ${1:X4}", instruction.Mnemonic, newPc + 2); } case AddressingMode.ZeroPage: return string.Format("{0} ${1:X2} = {2:X2}", instruction.Mnemonic, args[1], memory[args[1]]); case AddressingMode.ZeroPageXIndexed: return string.Format("{0} ${1:X2},X", instruction.Mnemonic, args[1]); case AddressingMode.ZeroPageYIndexed: return string.Format("{0} ${1:X2},Y", instruction.Mnemonic, args[1]); default: throw new Exception("Disassembly for addressing mode is unimplemented"); } }
private static byte GetAbsoluteOffsetArg(CpuState cpuState, IMemory memory, byte offset, out int cycles) { byte arg; var address = memory.ReadShort(cpuState.Pc + 1); var offsetAddress = address + offset; arg = memory[offsetAddress]; cycles = 4; if ((offsetAddress & 0xFF00) != (address & 0xFF00)) { ++cycles; } return arg; }
public int Execute(CpuState cpuState, IMemory memory) { var addressMode = Variants[memory[cpuState.Pc]]; byte arg; int cycles; switch (addressMode) { case AddressingMode.Implied: cycles = 2; arg = 0; // Not used break; case AddressingMode.Immediate: arg = memory[cpuState.Pc + 1]; cycles = 2; break; case AddressingMode.Absolute: arg = memory[memory.ReadShort(cpuState.Pc + 1)]; cycles = 4; break; case AddressingMode.ZeroPage: arg = memory[memory[cpuState.Pc + 1]]; cycles = 3; break; case AddressingMode.ZeroPageXIndexed: arg = memory[(memory[cpuState.Pc + 1] + cpuState.X) & 0xFF]; cycles = 4; break; case AddressingMode.ZeroPageYIndexed: arg = memory[(memory[cpuState.Pc + 1] + cpuState.Y) & 0xFF]; cycles = 4; break; case AddressingMode.AbsoluteX: arg = GetAbsoluteOffsetArg(cpuState, memory, cpuState.X, out cycles); break; case AddressingMode.AbsoluteY: arg = GetAbsoluteOffsetArg(cpuState, memory, cpuState.Y, out cycles); break; case AddressingMode.XIndexedIndirect: arg = memory[memory.ReadShort((memory[cpuState.Pc + 1] + cpuState.X) & 0xFF)]; cycles = 6; break; case AddressingMode.IndirectYIndexed: var addrPreOffset = memory.ReadShort(memory[cpuState.Pc + 1]); var addrPostOffset = addrPreOffset + cpuState.Y; cycles = 5; arg = memory[addrPostOffset]; if ((addrPostOffset & 0xFF00) != (addrPreOffset & 0xFF00)) { ++cycles; } break; default: throw new Exception("Unimplemented addressing mode"); } InternalExecute(cpuState, memory, arg, ref cycles); cpuState.Pc += addressMode.InstructionSize(); return cycles; }
public int Execute(CpuState cpuState, IMemory memory) { var addressMode = Variants[memory[cpuState.Pc]]; int cycles; Action<byte> write; switch (addressMode) { case AddressingMode.Accumulator: write = b => cpuState.A = b; cycles = 2; break; case AddressingMode.Implied: cycles = 2; write = b => { }; break; case AddressingMode.Immediate: { var addr = cpuState.Pc + 1; write = b => memory[addr] = b; cycles = 2; break; } case AddressingMode.Absolute: { var addr = memory.ReadShort(cpuState.Pc + 1); write = b => memory[addr] = b; cycles = 4; break; } case AddressingMode.ZeroPage: { var addr = memory[cpuState.Pc + 1]; write = b => memory[addr] = b; cycles = 3; break; } case AddressingMode.ZeroPageXIndexed: { var addr = (memory[cpuState.Pc + 1] + cpuState.X) & 0xFF; write = b => memory[addr] = b; cycles = 4; break; } case AddressingMode.ZeroPageYIndexed: { var addr = (memory[cpuState.Pc + 1] + cpuState.Y) & 0xFF; write = b => memory[addr] = b; cycles = 4; break; } case AddressingMode.AbsoluteX: GetAbsoluteOffsetArg(cpuState, memory, cpuState.X, out cycles, out write); break; case AddressingMode.AbsoluteY: GetAbsoluteOffsetArg(cpuState, memory, cpuState.Y, out cycles, out write); break; case AddressingMode.XIndexedIndirect: { var addr = memory.ReadZeroPageShort((byte) ((memory[cpuState.Pc + 1] + cpuState.X) & 0xFF)); write = b => memory[addr] = b; cycles = 6; break; } case AddressingMode.IndirectYIndexed: var addrPreOffset = memory.ReadZeroPageShort(memory[cpuState.Pc + 1]); var addrPostOffset = addrPreOffset + cpuState.Y; cycles = 5; if ((addrPostOffset & 0xFF00) != (addrPreOffset & 0xFF00)) { ++cycles; } write = b => memory[addrPostOffset] = b; break; default: throw new Exception("Unimplemented addressing mode"); } InternalExecute(cpuState, memory, write, ref cycles); cpuState.Pc += addressMode.InstructionSize(); return cycles; }
private static void GetAbsoluteOffsetArg(CpuState cpuState, IMemory memory, byte offset, out int cycles, out Action<byte> write) { var address = memory.ReadShort(cpuState.Pc + 1); var offsetAddress = address + offset; cycles = 4; if ((offsetAddress & 0xFF00) != (address & 0xFF00)) { ++cycles; } write = b => memory[offsetAddress] = b; }
private static byte GetAbsoluteOffsetArg(CpuState cpuState, IMemory memory, byte offset, out int cycles, out Action<byte> write ) { byte arg; var address = memory.ReadShort(cpuState.Pc + 1); ushort offsetAddress = (ushort) (address + offset); arg = memory[offsetAddress]; cycles = 4; if ((offsetAddress & 0xFF00) != (address & 0xFF00)) { ++cycles; } write = b => memory[offsetAddress] = b; return arg; }