Пример #1
0
        //start from 0x8E19
        private void RunMainLoop()
        {
            byte nextInstruction;

            while (!m_exitMainLoop)
            {
                m_sync.WaitForClockB();

                CheckForInterrupts();

                nextInstruction = Memory[ProgramCounter++];

                switch (nextInstruction)
                {
                case 0x00: //BRK
                {
                    if (!InterruptSet)
                    {
                        ProgramCounter++;
                        Interrupt(IrqVectorAddressLow, true);
                        Clock += 7;
                    }
                } break;

                case 0x01: //ORA pre-indexed indirect
                {
                    ORA(Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0x05: //ORA zero page
                {
                    ORA(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0x06: //ASL zero page
                {
                    ushort address = ZeroPage();
                    Memory[address] = ASL(Memory[address]);
                    Clock          += 5;
                } break;

                case 0x08: //PHP
                {
                    Push(Status);
                    Clock += 3;
                } break;

                case 0x09: //ORA immediate
                {
                    ORA(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0x0A: //ASL accumulator
                {
                    Accumulator = ASL(Accumulator);
                    Clock      += 2;
                } break;

                case 0x0D: //ORA absolute
                {
                    ORA(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0x0E: //ASL absolute
                {
                    ushort address = Absolute();
                    Memory[address] = ASL(Memory[address]);
                    Clock          += 6;
                } break;

                case 0x10: //BPL
                {
                    byte offset = Memory[Immediate()];
                    if (!NegativeSet)
                    {
                        Branch(offset);
                    }
                    else
                    {
                        Console.WriteLine("rawr!");
                    }
                    Clock += 2;
                } break;

                case 0x11: //ORA post-indexed indirect
                {
                    ORA(Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0x15: //ORA zero page X
                {
                    ORA(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0x16: //ASL zero page X
                {
                    ushort address = ZeroPageX();
                    Memory[address] = ASL(Memory[address]);
                    Clock          += 6;
                } break;

                case 0x18: //CLC
                {
                    CarrySet = false;
                    Clock   += 2;
                } break;

                case 0x19: //ORA absolute Y
                {
                    ORA(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0x1D: //ORA absolute X
                {
                    ORA(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0x1E: //ASL absolute X
                {
                    ushort address = AbsoluteX();
                    Memory[address] = ASL(Memory[address]);
                    Clock          += 7;
                } break;

                case 0x20: //JSR
                {
                    ushort jumpAddress   = Absolute();
                    int    returnAddress = ProgramCounter - 1;
                    Push((byte)((returnAddress >> 8) & 0xFF));
                    Push((byte)(returnAddress & 0xFF));
                    ProgramCounter = jumpAddress;
                    Clock         += 6;
                } break;

                case 0x21: //AND pre-indexed indirect
                {
                    AND(Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0x24: //BIT zero page
                {
                    BIT(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0x25: //AND zero page
                {
                    AND(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0x26: //ROL zero page
                {
                    ushort address = ZeroPage();
                    Memory[address] = ROL(Memory[address]);
                    Clock          += 5;
                    break;
                }

                case 0x28: //PLP
                {
                    Status = Pull();
                    Clock += 4;
                } break;

                case 0x29: //AND immediate
                {
                    AND(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0x2A: //ROL accumulator
                {
                    Accumulator = ROL(Accumulator);
                    Clock      += 2;
                    break;
                }

                case 0x2C: //BIT absolute
                {
                    BIT(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0x2D: //AND absolute
                {
                    AND(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0x2E: //ROL absolute
                {
                    ushort address = Absolute();
                    Memory[address] = ROL(Memory[address]);
                    Clock          += 6;
                    break;
                }

                case 0x30: //BMI
                {
                    byte offset = Memory[Immediate()];
                    if (NegativeSet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0x31: //AND post-indexed indirect
                {
                    AND(Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0x35: //AND zero page X
                {
                    AND(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0x36: //ROL zero page X
                {
                    ushort address = ZeroPageX();
                    Memory[address] = ROL(Memory[address]);
                    Clock          += 6;
                    break;
                }

                case 0x38: //SEC
                {
                    CarrySet = true;
                    Clock   += 2;
                } break;

                case 0x39: //AND absolute Y
                {
                    AND(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0x3D: //AND absolute X
                {
                    AND(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0x3E: //ROL absolute X
                {
                    ushort address = AbsoluteX();
                    Memory[address] = ROL(Memory[address]);
                    Clock          += 7;
                    break;
                }

                case 0x40: //RTI
                {
                    Status         = Pull();
                    Status        &= (byte)~BreakFlag;
                    ProgramCounter = (ushort)(Pull() | (Pull() << 8));
                    Clock         += 6;
                } break;

                case 0x41: //EOR pre-indexed indirect
                {
                    EOR(Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0x45: //EOR zero page
                {
                    EOR(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0x46: //LSR zero page
                {
                    ushort address = ZeroPage();
                    Memory[address] = LSR(Memory[address]);
                    Clock          += 5;
                } break;

                case 0x48: //PHA
                {
                    Push(Accumulator);
                    Clock += 3;
                } break;

                case 0x49: //EOR immediate
                {
                    EOR(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0x4A: //LSR accumulator
                {
                    Accumulator = LSR(Accumulator);
                    Clock      += 2;
                } break;

                case 0x4C: //JMP absolute
                {
                    ProgramCounter = Memory[Absolute()];
                    Clock         += 3;
                } break;

                case 0x4D: //EOR absolute
                {
                    EOR(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0x4E: //LSR absolute
                {
                    ushort address = Absolute();
                    Memory[address] = LSR(Memory[address]);
                    Clock          += 6;
                } break;

                case 0x50: //BVC
                {
                    byte offset = Memory[Immediate()];
                    if (!OverflowSet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0x51: //EOR post-indexed indirect
                {
                    EOR(Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0x55: //EOR zero page X
                {
                    EOR(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0x56: //LSR zero page X
                {
                    ushort address = ZeroPageX();
                    Memory[address] = LSR(Memory[address]);
                    Clock          += 6;
                } break;

                case 0x58: //CLI
                {
                    InterruptSet = false;
                    Clock       += 2;
                } break;

                case 0x59: //EOR absolute Y
                {
                    EOR(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 3;
                } break;

                case 0x5D: //EOR absolute X
                {
                    EOR(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 3;
                } break;

                case 0x5E: //LSR absolute X
                {
                    ushort address = AbsoluteX();
                    Memory[address] = LSR(Memory[address]);
                    Clock          += 7;
                } break;

                case 0x60: //RTS
                {
                    ProgramCounter = (ushort)(Pull() | (Pull() << 8));
                    ProgramCounter++;
                    Clock += 6;
                } break;

                case 0x61: //ADC pre-indexed indirect
                {
                    ADC(Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0x65: //ADC zero page
                {
                    ADC(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0x66: //ROR zero page
                {
                    ushort address = ZeroPage();
                    Memory[address] = ROR(Memory[address]);
                    Clock          += 5;
                    break;
                }

                case 0x68: //PLA
                {
                    Accumulator = Pull();
                    ZeroSet     = Accumulator == 0;
                    NegativeSet = (Accumulator & 0x80) == 0x80;
                    Clock      += 4;
                } break;

                case 0x69: //ADC immediate
                {
                    ADC(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0x6A: //ROR accumulator
                {
                    Accumulator = ROR(Accumulator);
                    Clock      += 2;
                } break;

                case 0x6C: //JMP indirect
                {
                    ProgramCounter = Indirect();
                    Clock         += 5;
                } break;

                case 0x6D: //ADC absolute
                {
                    ADC(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0x6E: //ROR absolute
                {
                    ushort address = Absolute();
                    Memory[address] = ROR(Memory[address]);
                    Clock          += 6;
                    break;
                }

                case 0x70: //BVS
                {
                    byte offset = Memory[Immediate()];
                    if (OverflowSet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0x71: //ADC post-indexed indirect
                {
                    ADC(Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0x75: //ADC zero page X
                {
                    ADC(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0x76: //ROR zero page X
                {
                    ushort address = ZeroPageX();
                    Memory[address] = ROR(Memory[address]);
                    Clock          += 6;
                    break;
                }

                case 0x78: //SEI
                {
                    InterruptSet = true;
                    Clock       += 2;
                } break;

                case 0x79: //ADC absolute Y
                {
                    ADC(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0x7D: //ADC absolute X
                {
                    ADC(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0x7E: //ROR absolute X
                {
                    ushort address = AbsoluteX();
                    Memory[address] = ROR(Memory[address]);
                    Clock          += 7;
                    break;
                }

                case 0x81: //STA pre-indexed indirect
                {
                    Memory[PreIndexedIndirect()] = Accumulator;
                    Clock += 6;
                } break;

                case 0x84: //STY zero page
                {
                    Memory[ZeroPage()] = IndexY;
                    Clock += 3;
                } break;

                case 0x85: //STA zero page
                {
                    Memory[ZeroPage()] = Accumulator;
                    Clock += 3;
                } break;

                case 0x86: //STX zero page
                {
                    Memory[ZeroPage()] = IndexX;
                    Clock += 3;
                } break;

                case 0x88: //DEY
                {
                    IndexY = Decrement(IndexY);
                    Clock += 2;
                } break;

                case 0x8A: //TXA
                {
                    Accumulator = IndexX;
                    ZeroSet     = Accumulator == 0;
                    NegativeSet = (Accumulator & 0x80) == 0x80;
                    Clock      += 2;
                } break;

                case 0x8C: //STY absolute
                {
                    Memory[Absolute()] = IndexY;
                    Clock += 4;
                } break;

                case 0x8D: //STA absolute
                {
                    Memory[Absolute()] = Accumulator;
                    Clock += 4;
                } break;

                case 0x8E: //STX absolute
                {
                    Memory[Absolute()] = IndexX;
                    Clock += 4;
                } break;

                case 0x90: //BCC
                {
                    byte offset = Memory[Immediate()];
                    if (!CarrySet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0x91: //STA post-indexed indirect
                {
                    Memory[PostIndexedIndirect()] = Accumulator;
                    Clock += 6;
                } break;

                case 0x94: //STY zero page X
                {
                    Memory[ZeroPageX()] = IndexY;
                    Clock += 4;
                } break;

                case 0x95: //STA zero page X
                {
                    Memory[ZeroPageX()] = Accumulator;
                    Clock += 4;
                } break;

                case 0x96: //STX zero page Y
                {
                    Memory[ZeroPageY()] = IndexX;
                    Clock += 4;
                } break;

                case 0x98: //TYA
                {
                    Accumulator = IndexY;
                    ZeroSet     = Accumulator == 0;
                    NegativeSet = (Accumulator & 0x80) == 0x80;
                    Clock      += 2;
                } break;

                case 0x99: //STA absolute Y
                {
                    Memory[AbsoluteY()] = Accumulator;
                    Clock += 5;
                } break;

                case 0x9A: //TXS
                {
                    StackPointer = IndexX;
                    Clock       += 2;
                } break;

                case 0x9D: //STA absolute X
                {
                    Memory[AbsoluteX()] = Accumulator;
                    Clock += 4;
                } break;

                case 0xA0: //LDY immediate
                {
                    LDY(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xA1: //LDA pre-indexed indirect
                {
                    LDA(Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0xA2: //LDX immediate
                {
                    LDX(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xA4: //LDY zero page
                {
                    LDY(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xA5: //LDA zero page
                {
                    LDA(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xA6: //LDX zero page
                {
                    LDX(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xA8: //TAY
                {
                    IndexY      = Accumulator;
                    ZeroSet     = IndexY == 0;
                    NegativeSet = (IndexY & 0x80) == 0x80;
                    Clock      += 2;
                } break;

                case 0xA9: //LDA immediate
                {
                    LDA(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xAA: //TAX
                {
                    IndexX      = Accumulator;
                    ZeroSet     = IndexX == 0;
                    NegativeSet = (IndexX & 0x80) == 0x80;
                    Clock      += 2;
                } break;

                case 0xAC: //LDY absolute
                {
                    LDY(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xAD: //LDA absolute
                {
                    LDA(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xAE: //LDX absolute
                {
                    LDX(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xB0: //BCS
                {
                    byte offset = Memory[Immediate()];
                    if (CarrySet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0xB1: //LDA post-indexed indirect
                {
                    LDA(Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0xB4: //LDY zero page X
                {
                    LDY(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0xB5: //LDA zero page X
                {
                    LDA(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0xB6: //LDX zero page Y
                {
                    LDX(Memory[ZeroPageY()]);
                    Clock += 4;
                } break;

                case 0xB8: //CLV
                {
                    OverflowSet = false;
                    Clock      += 2;
                } break;

                case 0xB9: //LDA absolute Y
                {
                    LDA(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xBA: //TSX
                {
                    IndexX      = StackPointer;
                    ZeroSet     = IndexX == 0;
                    NegativeSet = (IndexX & 0x80) == 0x80;
                    Clock      += 2;
                } break;

                case 0xBC: //LDY absolute X
                {
                    LDY(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xBD: //LDA absolute X
                {
                    LDA(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xBE: //LDX absolute Y
                {
                    LDX(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xC0: //CPY immediate
                {
                    Compare(IndexY, Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xC1: //CMP pre-indexed indirect
                {
                    Compare(Accumulator, Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0xC4: //CPY zero page
                {
                    Compare(IndexY, Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xC5: //CMP zero page
                {
                    Compare(Accumulator, Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xC6: //DEC zero page
                {
                    ushort address = ZeroPage();
                    Memory[address] = Decrement(Memory[address]);
                    Clock          += 5;
                } break;

                case 0xC8: //INY
                {
                    IndexY = Increment(IndexY);
                    Clock += 2;
                } break;

                case 0xC9: //CMP immediate
                {
                    Compare(Accumulator, Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xCA: //DEX
                {
                    IndexX = Decrement(IndexX);
                    Clock += 2;
                } break;

                case 0xCC: //CPY absolute
                {
                    Compare(IndexY, Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xCD: //CMP absolute
                {
                    Compare(Accumulator, Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xCE: //DEC absolute
                {
                    ushort address = Absolute();
                    Memory[address] = Decrement(Memory[address]);
                    Clock          += 6;
                } break;

                case 0xD0: //BNE
                {
                    byte offset = Memory[Immediate()];
                    if (!ZeroSet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0xD1: //CMP post-indexed indirect
                {
                    Compare(Accumulator, Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0xD5: //CMP zero page X
                {
                    Compare(Accumulator, Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0xD6: //DEC zero page X
                {
                    ushort address = ZeroPageX();
                    Memory[address] = Decrement(Memory[address]);
                    Clock          += 5;
                } break;

                case 0xD8: //CLD
                {
                    DecimalSet = false;
                    Clock     += 2;
                } break;

                case 0xD9: //CMP absolute Y
                {
                    Compare(Accumulator, Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xDD: //CMP absolute X
                {
                    Compare(Accumulator, Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xDE: // DEC absolute X
                {
                    ushort address = AbsoluteX();
                    Memory[address] = Decrement(Memory[address]);
                    Clock          += 7;
                } break;

                case 0xE0: //CPX immediate
                {
                    Compare(IndexX, Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xE1: //SBC pre-indexed indirect
                {
                    SBC(Memory[PreIndexedIndirect()]);
                    Clock += 6;
                } break;

                case 0xE4: //CPX zero page
                {
                    Compare(IndexX, Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xE5: //SBC zero page
                {
                    SBC(Memory[ZeroPage()]);
                    Clock += 3;
                } break;

                case 0xE6: //INC zero page
                {
                    ushort address = ZeroPage();
                    Memory[address] = Increment(Memory[address]);
                    Clock          += 5;
                } break;

                case 0xE8: //INX
                {
                    IndexX = Increment(IndexX);
                    Clock += 2;
                } break;

                case 0xE9: //SBC immediate
                {
                    SBC(Memory[Immediate()]);
                    Clock += 2;
                } break;

                case 0xEA: //NOP
                {
                    Clock += 2;
                } break;

                case 0xEC: //CPX absolute
                {
                    Compare(IndexX, Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xED: //SBC absolute
                {
                    SBC(Memory[Absolute()]);
                    Clock += 4;
                } break;

                case 0xEE: //INC absolute
                {
                    ushort address = Absolute();
                    Memory[address] = Increment(Memory[address]);
                    Clock          += 6;
                } break;

                case 0xF0: //BEQ
                {
                    byte offset = Memory[Immediate()];
                    if (ZeroSet)
                    {
                        Branch(offset);
                    }
                    Clock += 2;
                } break;

                case 0xF1: //SBC post-indexed indirect
                {
                    SBC(Memory[PostIndexedIndirectWithBoundaryCheck()]);
                    Clock += 5;
                } break;

                case 0xF5: //SBC zero page X
                {
                    SBC(Memory[ZeroPageX()]);
                    Clock += 4;
                } break;

                case 0xF6: //INC zero page X
                {
                    ushort address = ZeroPageX();
                    Memory[address] = Increment(Memory[address]);
                    Clock          += 6;
                } break;

                case 0xF8: //SED
                {
                    DecimalSet = true;
                    Clock     += 2;
                } break;

                case 0xF9: //SBC absolute Y
                {
                    SBC(Memory[AbsoluteYWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xFD: //SBC absolute X
                {
                    SBC(Memory[AbsoluteXWithBoundaryCheck()]);
                    Clock += 4;
                } break;

                case 0xFE: //INC absolute X
                {
                    ushort address = AbsoluteX();
                    Memory[address] = Increment(Memory[address]);
                    Clock          += 7;
                } break;

                case 0xFF:
                {
                    m_exitMainLoop = true;
                } break;

                default:
                {
                    throw new InvalidOperationException(
                              string.Format("instruction {0} not supported",
                                            Convert.ToString(nextInstruction, 16)));
                }
                }
            }
        }