Example #1
0
        private void initOpCodes()
        {
            // ----------------------------------------------------------------------------------------------
            // reinitialize OpCode table for additional 4 Z80 prefixes - none, CB, DD, ED, FD
            //                                                         - combinations DD, FD, CB
            m_OpCodes          = new OperationCode[0x100 * 7];
            m_dictOpCodePrefix = new Dictionary <int, int>(6);
            m_dictOpCodePrefix.Add(0xCB, 0x100);
            m_dictOpCodePrefix.Add(0xDD, 0x200);
            m_dictOpCodePrefix.Add(0xED, 0x300);
            m_dictOpCodePrefix.Add(0xFD, 0x400);
            m_dictOpCodePrefix.Add(0xDDCB, 0x500);
            m_dictOpCodePrefix.Add(0xFDCB, 0x600);

            // ----------------------------------------------------------------------------------------------
            // OpCode initialization (ordered according to Zilog Z80 CPU Specifications by Sean Young)

            initOpCodes8BitLoadGroup();         // 8 bit Load group
            initOpCodes16BitLoadGroup();        // 16 bit Load group
            initOpCodesExchangeGroup();         // Exchange group
            initOpCodesBlockTransferGroup();    // Block Transfer group
            initOpCodesSearchGroup();           // Search group
            initOpCodes8BitArithLogGroup();     // 8 bit Arithmetic & Logical group
            initOpCodes16BitArithLogGroup();    // 16 bit Arithmetic & Logical group
            initOpCodesJumpGroup();             // Jump group
            initOpCodesCallAndReturnGroup();    // Call and Return group
            initOpCodesGenPurposeArithGroup();  // General Purpose Arithmetic group
            initOpCodesRotateAndShiftGroup();   // Rotate and Shift group
            initOpCodesCPUControlGroup();       // CPU control group
            initOpCodesBITManipulationGroup();  // Bit Manipulation group
            initOpCodesInputAndOutputGroup();   // Input and Output group
        }
Example #2
0
        public void emulateCycle()
        {
            if (m_Interrupt != InterruptSignal.None)
            {
                m_State = CPUState.interrupt;
            }

            switch (m_State)
            {
            case CPUState.fetchopcode:
                m_PC_Start         = m_PC;
                m_Cycle            = 1;
                m_ExtraCycles      = false;
                m_byteDisplacement = 0;

                m_OpCodePrefix = 0;
                m_OpCodeIndex  = getNextMemByte();
                m_oc           = m_OpCodes[m_OpCodeIndex];

                int iIndexOffset = 0;

                if (m_OpCodeIndex == 0xCB ||       // evaluate prefix
                    m_OpCodeIndex == 0xDD ||
                    m_OpCodeIndex == 0xED ||
                    m_OpCodeIndex == 0xFD)
                {
                    m_OpCodePrefix = m_OpCodeIndex;
                    iIndexOffset   = m_dictOpCodePrefix[m_OpCodePrefix];
                    m_OpCodeIndex  = getNextMemByte();

                    if (m_OpCodeIndex == 0xCB)    // DD CB or FD CB combination
                    {
                        m_OpCodePrefix   <<= 8;
                        m_OpCodePrefix    |= m_OpCodeIndex;
                        iIndexOffset       = m_dictOpCodePrefix[m_OpCodePrefix];
                        m_byteDisplacement = getNextMemByte();     // contains displacement before OpCode
                        m_OpCodeIndex      = getNextMemByte();
                    }

                    m_oc = m_OpCodes[iIndexOffset + m_OpCodeIndex];
                }

                // check if OpCode is defined
                if (String.IsNullOrEmpty(m_oc.OpCode) || m_oc.executeOperation == null)
                {
                    string sMessage;
                    if (m_OpCodePrefix > 0)
                    {
                        sMessage = String.Format("PC {0:X4} : OpCode {1:X2} {2:X2} unknown!!!",
                                                 m_PC_Start, (byte)m_OpCodePrefix, (byte)m_OpCodeIndex);
                    }
                    else
                    {
                        sMessage = String.Format("PC {0:X4} : OpCode {1:X2} unknown!!!",
                                                 m_PC_Start, (byte)m_OpCodeIndex);
                    }
                    throw new NotImplementedException(sMessage);
                }

#if CPU_TRACE
                m_ei.Counter++;
                m_ei.PC    = m_PC_Start;
                m_ei.Bytes = "";
                if (m_OpCodePrefix != 0)
                {
                    m_ei.Bytes += String.Format("{0:X2} ", m_OpCodePrefix);
                }
                m_ei.Bytes += String.Format("{0:X2} ", m_OpCodeIndex);
                m_ei.OpCode = m_oc.OpCode;
                m_ei.Op1    = "";
                m_ei.Op2    = "";
#endif
                // increase R register (only bits 6-0)
                m_reg_R = (byte)((m_reg_R & 0x80) | ((m_reg_R + 1) & 0x7F));

                // set for next processing state
                m_wordValue = 0;
                m_byteValue = 0;
#if NO_CYCLE_FILLUP
                m_MaxCycles = m_PC - m_PC_Start;
#else
                m_MaxCycles = m_oc.Cycles;
#endif
                m_State = CPUState.addressing;
                break;

            case CPUState.interrupt:     // interrupt
                switch (m_Interrupt)
                {
                case InterruptSignal.NMI:
                    // perform a RST 66h
                    m_reg_SP -= 2;;
                    writeMemWord(m_reg_SP, m_PC);
                    m_PC        = 0x0066;
                    m_State     = CPUState.fetchopcode;
                    m_Interrupt = InterruptSignal.None;
                    break;

                case InterruptSignal.IRQ:
                    switch (m_IM)
                    {
                    case 0:
                        // TODO Z80 implement IM 0
                        throw new NotImplementedException("Z80 IM 0 not implemented!");

                    case 1:             // IM 1 - perform a RST 38h
                        m_reg_SP -= 2;;
                        writeMemWord(m_reg_SP, m_PC);
                        m_PC        = 0x0038;
                        m_State     = CPUState.fetchopcode;
                        m_Interrupt = InterruptSignal.None;
                        break;

                    case 2:             // IM 2 - jump to interrupt vector
                        m_reg_SP -= 2;;
                        writeMemWord(m_reg_SP, m_PC);
                        m_PC        = m_reg_I;
                        m_State     = CPUState.fetchopcode;
                        m_Interrupt = InterruptSignal.None;
                        break;
                    }
                    break;
                }
                break;

            case CPUState.addressing:     // addressing
                m_Cycle++;
                m_oc.executeAddressing();

                break;

            case CPUState.operation:
                if (m_Cycle >= m_MaxCycles)     // emulate cycle exactness by making operation effective on last cycle
                {
                    m_oc.executeOperation();
                    if (m_Cycle < m_MaxCycles)
                    {
                        m_Cycle++;     // operation executed induced another cycle (e.g. branch operations)
                    }
                    else
                    {
                        m_State = CPUState.fetchopcode;      // operation finished -> get next opcode
                    }
#if CPU_TRACE
                    //if (m_PC_Start == 0x188) { m_TraceActive = true; m_ei.Counter = 1; }
                    //if (m_PC_Start == 0x18B) m_TraceActive = false;

                    if (m_State == CPUState.fetchopcode && m_TraceActive)
                    {
                        StringBuilder sb = new StringBuilder();

                        if ((m_ei.Counter % 20) == 1)
                        {
                            sb.Clear();
                            sb.Append("PC-- ");
                            sb.Append("----------- OpCo Op1,Op2---|");
                            sb.Append("A  F  B  C  D  E  H  L  ");
                            //sb.Append("A' F' B' C' D' E' H' L' ");
                            sb.Append("IX   IY   SP   I  R  |");
                            sb.Append("SZ5H3vNC|");
                            sb.Append("Disassembly Check---|");
                            sb.Append("STACK ---------------");
                            Debug.WriteLine(sb.ToString());
                        }
                        sb.Clear();
                        sb.AppendFormat("{0:X4} ", m_ei.PC);
                        sb.Append(m_ei.Bytes.PadRight(12));
                        sb.Append(m_ei.OpCode.PadRight(5));
                        if (!String.IsNullOrEmpty(m_ei.Op1) && !String.IsNullOrEmpty(m_ei.Op2))
                        {
                            sb.Append((m_ei.Op1 + "," + m_ei.Op2).PadRight(10));
                        }
                        else
                        {
                            sb.Append((m_ei.Op1 + m_ei.Op2).PadRight(10));
                        }
                        sb.Append("|");

                        sb.AppendFormat("{0:X2} ", m_reg_A);
                        sb.AppendFormat("{0:X2} ", Flags);
                        sb.AppendFormat("{0:X2} ", m_reg_B);
                        sb.AppendFormat("{0:X2} ", m_reg_C);
                        sb.AppendFormat("{0:X2} ", m_reg_D);
                        sb.AppendFormat("{0:X2} ", m_reg_E);
                        sb.AppendFormat("{0:X2} ", m_reg_H);
                        sb.AppendFormat("{0:X2} ", m_reg_L);

                        //sb.AppendFormat("{0:X2} ", m_reg_A_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_Flags_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_B_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_C_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_D_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_E_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_H_Alt);
                        //sb.AppendFormat("{0:X2} ", m_reg_L_Alt);

                        sb.AppendFormat("{0:X4} ", m_reg_IX);
                        sb.AppendFormat("{0:X4} ", m_reg_IY);
                        sb.AppendFormat("{0:X4} ", m_reg_SP);
                        sb.AppendFormat("{0:X2} ", m_reg_I);
                        sb.AppendFormat("{0:X2} ", m_reg_R);
                        sb.Append("|");

                        sb.Append(Convert.ToString(Flags, 2).PadLeft(8, '0'));
                        sb.Append("|");

                        string strDisassemblyCheck = m_dis.Disassemble(() => readMemByte(m_ei.PC++));
                        sb.Append(strDisassemblyCheck.PadRight(20));
                        sb.Append("|");

                        for (int spDump = m_reg_SP; spDump <= m_reg_SP + 5; spDump++)
                        {
                            sb.AppendFormat("{0:X2} ", readMemByte((UInt16)spDump));
                        }

                        Debug.WriteLine(sb.ToString());
                        sb = null;
                    }
#endif
                }
                else
                {
                    m_Cycle++;
                }
                break;
            }
        }
Example #3
0
        private StringBuilder m_sbDebug;  // build operations debug string
#endif

        public MOS6502() : base()
        {
            // initialize OpCode table
            // reference see http://homepage.ntlworld.com/cyborgsystems/CS_Main/6502/6502.htm
            m_OpCodes[0x00] = new OperationCode("BRK", 1, 7, _ADDR_IMP, _BRK);
            m_OpCodes[0x01] = new OperationCode("ORA", 2, 6, _ADDR_INDX_1, _ORA);
            m_OpCodes[0x05] = new OperationCode("ORA", 2, 3, _ADDR_ZP, _ORA);
            m_OpCodes[0x06] = new OperationCode("ASL", 2, 5, _ADDR_ZP, _ASL);
            m_OpCodes[0x08] = new OperationCode("PHP", 1, 3, _ADDR_IMP, _PHP);
            m_OpCodes[0x09] = new OperationCode("ORA", 2, 2, _ADDR_IMM, _ORA);
            m_OpCodes[0x0a] = new OperationCode("ASL", 1, 2, _ADDR_ACC, _ASL);
            m_OpCodes[0x0d] = new OperationCode("ORA", 3, 4, _ADDR_ABS, _ORA);
            m_OpCodes[0x0e] = new OperationCode("ASL", 3, 6, _ADDR_ABS, _ASL);
            m_OpCodes[0x10] = new OperationCode("BPL", 2, 2, _ADDR_REL_1, _BPL);
            m_OpCodes[0x11] = new OperationCode("ORA", 2, 5, _ADDR_INDY_1, _ORA);
            m_OpCodes[0x15] = new OperationCode("ORA", 2, 4, _ADDR_ZPX_1, _ORA);
            m_OpCodes[0x16] = new OperationCode("ASL", 2, 6, _ADDR_ZPX_1, _ASL);
            m_OpCodes[0x18] = new OperationCode("CLC", 1, 2, _ADDR_IMP, _CLC);
            m_OpCodes[0x19] = new OperationCode("ORA", 3, 4, _ADDR_ABSY_1, _ORA);
            m_OpCodes[0x1d] = new OperationCode("ORA", 3, 4, _ADDR_ABSX_1, _ORA);
            m_OpCodes[0x1e] = new OperationCode("ASL", 3, 7, _ADDR_ABSX_1, _ASL);
            m_OpCodes[0x20] = new OperationCode("JSR", 3, 6, _ADDR_ABS, _JSR);
            m_OpCodes[0x21] = new OperationCode("AND", 2, 6, _ADDR_INDX_1, _AND);
            m_OpCodes[0x24] = new OperationCode("BIT", 2, 3, _ADDR_ZP, _BIT);
            m_OpCodes[0x25] = new OperationCode("AND", 2, 3, _ADDR_ZP, _AND);
            m_OpCodes[0x26] = new OperationCode("ROL", 2, 5, _ADDR_ZP, _ROL);
            m_OpCodes[0x28] = new OperationCode("PLP", 1, 4, _ADDR_IMP, _PLP);
            m_OpCodes[0x29] = new OperationCode("AND", 2, 2, _ADDR_IMM, _AND);
            m_OpCodes[0x2a] = new OperationCode("ROL", 1, 2, _ADDR_ACC, _ROL);
            m_OpCodes[0x2c] = new OperationCode("BIT", 3, 4, _ADDR_ABS, _BIT);
            m_OpCodes[0x2d] = new OperationCode("AND", 3, 4, _ADDR_ABS, _AND);
            m_OpCodes[0x2e] = new OperationCode("ROL", 3, 6, _ADDR_ABS, _ROL);
            m_OpCodes[0x30] = new OperationCode("BMI", 2, 2, _ADDR_REL_1, _BMI);
            m_OpCodes[0x31] = new OperationCode("AND", 2, 5, _ADDR_INDY_1, _AND);
            m_OpCodes[0x35] = new OperationCode("AND", 2, 4, _ADDR_ZPX_1, _AND);
            m_OpCodes[0x36] = new OperationCode("ROL", 2, 6, _ADDR_ZPX_1, _ROL);
            m_OpCodes[0x38] = new OperationCode("SEC", 1, 2, _ADDR_IMP, _SEC);
            m_OpCodes[0x39] = new OperationCode("AND", 3, 4, _ADDR_ABSY_1, _AND);
            m_OpCodes[0x3d] = new OperationCode("AND", 3, 4, _ADDR_ABSX_1, _AND);
            m_OpCodes[0x3e] = new OperationCode("ROL", 3, 7, _ADDR_ABSX_1, _ROL);
            m_OpCodes[0x40] = new OperationCode("RTI", 1, 6, _ADDR_IMP, _RTI);
            m_OpCodes[0x41] = new OperationCode("EOR", 2, 6, _ADDR_INDX_1, _EOR);
            m_OpCodes[0x45] = new OperationCode("EOR", 2, 3, _ADDR_ZP, _EOR);
            m_OpCodes[0x46] = new OperationCode("LSR", 2, 5, _ADDR_ZP, _LSR);
            m_OpCodes[0x48] = new OperationCode("PHA", 1, 3, _ADDR_IMP, _PHA);
            m_OpCodes[0x49] = new OperationCode("EOR", 2, 2, _ADDR_IMM, _EOR);
            m_OpCodes[0x4a] = new OperationCode("LSR", 1, 2, _ADDR_ACC, _LSR);
            m_OpCodes[0x4c] = new OperationCode("JMP", 3, 3, _ADDR_ABS, _JMP);
            m_OpCodes[0x4d] = new OperationCode("EOR", 3, 4, _ADDR_ABS, _EOR);
            m_OpCodes[0x4e] = new OperationCode("LSR", 3, 6, _ADDR_ABS, _LSR);
            m_OpCodes[0x50] = new OperationCode("BVC", 2, 2, _ADDR_REL_1, _BVC);
            m_OpCodes[0x51] = new OperationCode("EOR", 2, 5, _ADDR_INDY_1, _EOR);
            m_OpCodes[0x55] = new OperationCode("EOR", 2, 4, _ADDR_ZPX_1, _EOR);
            m_OpCodes[0x56] = new OperationCode("LSR", 2, 6, _ADDR_ZPX_1, _LSR);
            m_OpCodes[0x58] = new OperationCode("CLI", 1, 2, _ADDR_IMP, _CLI);
            m_OpCodes[0x59] = new OperationCode("EOR", 3, 4, _ADDR_ABSY_1, _EOR);
            m_OpCodes[0x5d] = new OperationCode("EOR", 3, 4, _ADDR_ABSX_1, _EOR);
            m_OpCodes[0x5e] = new OperationCode("LSR", 3, 7, _ADDR_ABSX_1, _LSR);
            m_OpCodes[0x60] = new OperationCode("RTS", 1, 6, _ADDR_IMP, _RTS);
            m_OpCodes[0x61] = new OperationCode("ADC", 2, 6, _ADDR_INDX_1, _ADC);
            m_OpCodes[0x65] = new OperationCode("ADC", 2, 3, _ADDR_ZP, _ADC);
            m_OpCodes[0x66] = new OperationCode("ROR", 2, 5, _ADDR_ZP, _ROR);
            m_OpCodes[0x68] = new OperationCode("PLA", 1, 4, _ADDR_IMP, _PLA);
            m_OpCodes[0x69] = new OperationCode("ADC", 2, 2, _ADDR_IMM, _ADC);
            m_OpCodes[0x6a] = new OperationCode("ROR", 1, 2, _ADDR_ACC, _ROR);
            m_OpCodes[0x6c] = new OperationCode("JMP", 3, 5, _ADDR_IND_1, _JMP);
            m_OpCodes[0x6d] = new OperationCode("ADC", 3, 4, _ADDR_ABS, _ADC);
            m_OpCodes[0x6e] = new OperationCode("ROR", 3, 6, _ADDR_ABS, _ROR);
            m_OpCodes[0x70] = new OperationCode("BVS", 2, 2, _ADDR_REL_1, _BVS);
            m_OpCodes[0x71] = new OperationCode("ADC", 2, 5, _ADDR_INDY_1, _ADC);
            m_OpCodes[0x75] = new OperationCode("ADC", 2, 4, _ADDR_ZPX_1, _ADC);
            m_OpCodes[0x76] = new OperationCode("ROR", 2, 6, _ADDR_ZPX_1, _ROR);
            m_OpCodes[0x78] = new OperationCode("SEI", 1, 2, _ADDR_IMP, _SEI);
            m_OpCodes[0x79] = new OperationCode("ADC", 3, 4, _ADDR_ABSY_1, _ADC);
            m_OpCodes[0x7d] = new OperationCode("ADC", 3, 4, _ADDR_ABSX_1, _ADC);
            m_OpCodes[0x7e] = new OperationCode("ROR", 3, 7, _ADDR_ABSX_1, _ROR);
            m_OpCodes[0x81] = new OperationCode("STA", 2, 6, _ADDR_INDX_1, _STA);
            m_OpCodes[0x84] = new OperationCode("STY", 2, 3, _ADDR_ZP, _STY);
            m_OpCodes[0x85] = new OperationCode("STA", 2, 3, _ADDR_ZP, _STA);
            m_OpCodes[0x86] = new OperationCode("STX", 2, 3, _ADDR_ZP, _STX);
            m_OpCodes[0x88] = new OperationCode("DEY", 1, 2, _ADDR_IMP, _DEY);
            m_OpCodes[0x8a] = new OperationCode("TXA", 1, 2, _ADDR_IMP, _TXA);
            m_OpCodes[0x8c] = new OperationCode("STY", 3, 4, _ADDR_ABS, _STY);
            m_OpCodes[0x8d] = new OperationCode("STA", 3, 4, _ADDR_ABS, _STA);
            m_OpCodes[0x8e] = new OperationCode("STX", 3, 4, _ADDR_ABS, _STX);
            m_OpCodes[0x90] = new OperationCode("BCC", 2, 2, _ADDR_REL_1, _BCC);
            m_OpCodes[0x91] = new OperationCode("STA", 2, 6, _ADDR_INDY_1, _STA);
            m_OpCodes[0x94] = new OperationCode("STY", 2, 4, _ADDR_ZPX_1, _STY);
            m_OpCodes[0x95] = new OperationCode("STA", 2, 4, _ADDR_ZPX_1, _STA);
            m_OpCodes[0x96] = new OperationCode("STX", 2, 4, _ADDR_ZPY_1, _STX);
            m_OpCodes[0x98] = new OperationCode("TYA", 1, 2, _ADDR_IMP, _TYA);
            m_OpCodes[0x99] = new OperationCode("STA", 3, 5, _ADDR_ABSY_1, _STA);
            m_OpCodes[0x9a] = new OperationCode("TXS", 1, 2, _ADDR_IMP, _TXS);
            m_OpCodes[0x9d] = new OperationCode("STA", 3, 5, _ADDR_ABSX_1, _STA);
            m_OpCodes[0xa0] = new OperationCode("LDY", 2, 2, _ADDR_IMM, _LDY);
            m_OpCodes[0xa1] = new OperationCode("LDA", 2, 6, _ADDR_INDX_1, _LDA);
            m_OpCodes[0xa2] = new OperationCode("LDX", 2, 2, _ADDR_IMM, _LDX);
            m_OpCodes[0xa4] = new OperationCode("LDY", 2, 3, _ADDR_ZP, _LDY);
            m_OpCodes[0xa5] = new OperationCode("LDA", 2, 3, _ADDR_ZP, _LDA);
            m_OpCodes[0xa6] = new OperationCode("LDX", 2, 3, _ADDR_ZP, _LDX);
            m_OpCodes[0xa8] = new OperationCode("TAY", 1, 2, _ADDR_IMP, _TAY);
            m_OpCodes[0xa9] = new OperationCode("LDA", 2, 2, _ADDR_IMM, _LDA);
            m_OpCodes[0xaa] = new OperationCode("TAX", 1, 2, _ADDR_IMP, _TAX);
            m_OpCodes[0xac] = new OperationCode("LDY", 3, 4, _ADDR_ABS, _LDY);
            m_OpCodes[0xad] = new OperationCode("LDA", 3, 4, _ADDR_ABS, _LDA);
            m_OpCodes[0xae] = new OperationCode("LDX", 3, 4, _ADDR_ABS, _LDX);
            m_OpCodes[0xB0] = new OperationCode("BCS", 2, 2, _ADDR_REL_1, _BCS);
            m_OpCodes[0xb1] = new OperationCode("LDA", 2, 5, _ADDR_INDY_1, _LDA);
            m_OpCodes[0xb4] = new OperationCode("LDY", 2, 4, _ADDR_ZPX_1, _LDY);
            m_OpCodes[0xb5] = new OperationCode("LDA", 2, 4, _ADDR_ZPX_1, _LDA);
            m_OpCodes[0xb6] = new OperationCode("LDX", 2, 4, _ADDR_ZPY_1, _LDX);
            m_OpCodes[0xb8] = new OperationCode("CLV", 1, 2, _ADDR_IMP, _CLV);
            m_OpCodes[0xb9] = new OperationCode("LDA", 3, 4, _ADDR_ABSY_1, _LDA);
            m_OpCodes[0xba] = new OperationCode("TSX", 1, 2, _ADDR_IMP, _TSX);
            m_OpCodes[0xbc] = new OperationCode("LDY", 3, 4, _ADDR_ABSX_1, _LDY);
            m_OpCodes[0xbd] = new OperationCode("LDA", 3, 4, _ADDR_ABSX_1, _LDA);
            m_OpCodes[0xbe] = new OperationCode("LDX", 3, 4, _ADDR_ABSY_1, _LDX);
            m_OpCodes[0xc0] = new OperationCode("CPY", 2, 2, _ADDR_IMM, _CPY);
            m_OpCodes[0xc1] = new OperationCode("CMP", 2, 6, _ADDR_INDX_1, _CMP);
            m_OpCodes[0xc4] = new OperationCode("CPY", 2, 3, _ADDR_ZP, _CPY);
            m_OpCodes[0xc5] = new OperationCode("CMP", 2, 3, _ADDR_ZP, _CMP);
            m_OpCodes[0xc6] = new OperationCode("DEC", 2, 5, _ADDR_ZP, _DEC);
            m_OpCodes[0xc8] = new OperationCode("INY", 1, 2, _ADDR_IMP, _INY);
            m_OpCodes[0xc9] = new OperationCode("CMP", 2, 2, _ADDR_IMM, _CMP);
            m_OpCodes[0xca] = new OperationCode("DEX", 1, 2, _ADDR_IMP, _DEX);
            m_OpCodes[0xcc] = new OperationCode("CPY", 3, 4, _ADDR_ABS, _CPY);
            m_OpCodes[0xcd] = new OperationCode("CMP", 3, 4, _ADDR_ABS, _CMP);
            m_OpCodes[0xce] = new OperationCode("DEC", 3, 6, _ADDR_ABS, _DEC);
            m_OpCodes[0xD0] = new OperationCode("BNE", 2, 2, _ADDR_REL_1, _BNE);
            m_OpCodes[0xd1] = new OperationCode("CMP", 2, 5, _ADDR_INDY_1, _CMP);
            m_OpCodes[0xd5] = new OperationCode("CMP", 2, 4, _ADDR_ZPX_1, _CMP);
            m_OpCodes[0xd6] = new OperationCode("DEC", 2, 6, _ADDR_ZPX_1, _DEC);
            m_OpCodes[0xd8] = new OperationCode("CLD", 1, 2, _ADDR_IMP, _CLD);
            m_OpCodes[0xd9] = new OperationCode("CMP", 3, 4, _ADDR_ABSY_1, _CMP);
            m_OpCodes[0xdd] = new OperationCode("CMP", 3, 4, _ADDR_ABSX_1, _CMP);
            m_OpCodes[0xde] = new OperationCode("DEC", 3, 7, _ADDR_ABSX_1, _DEC);
            m_OpCodes[0xe0] = new OperationCode("CPX", 2, 2, _ADDR_IMM, _CPX);
            m_OpCodes[0xe1] = new OperationCode("SBC", 2, 6, _ADDR_INDX_1, _SBC);
            m_OpCodes[0xe4] = new OperationCode("CPX", 2, 3, _ADDR_ZP, _CPX);
            m_OpCodes[0xe5] = new OperationCode("SBC", 2, 3, _ADDR_ZP, _SBC);
            m_OpCodes[0xe6] = new OperationCode("INC", 2, 5, _ADDR_ZP, _INC);
            m_OpCodes[0xe8] = new OperationCode("INX", 1, 2, _ADDR_IMP, _INX);
            m_OpCodes[0xe9] = new OperationCode("SBC", 2, 2, _ADDR_IMM, _SBC);
            m_OpCodes[0xea] = new OperationCode("NOP", 1, 2, _ADDR_IMP, _NOP);
            m_OpCodes[0xec] = new OperationCode("CPX", 3, 4, _ADDR_ABS, _CPX);
            m_OpCodes[0xed] = new OperationCode("SBC", 3, 4, _ADDR_ABS, _SBC);
            m_OpCodes[0xee] = new OperationCode("INC", 3, 6, _ADDR_ABS, _INC);
            m_OpCodes[0xF0] = new OperationCode("BEQ", 2, 2, _ADDR_REL_1, _BEQ);
            m_OpCodes[0xf1] = new OperationCode("SBC", 2, 5, _ADDR_INDY_1, _SBC);
            m_OpCodes[0xf5] = new OperationCode("SBC", 2, 4, _ADDR_ZPX_1, _SBC);
            m_OpCodes[0xf6] = new OperationCode("INC", 2, 6, _ADDR_ZPX_1, _INC);
            m_OpCodes[0xf8] = new OperationCode("SED", 1, 2, _ADDR_IMP, _SED);
            m_OpCodes[0xf9] = new OperationCode("SBC", 3, 4, _ADDR_ABSY_1, _SBC);
            m_OpCodes[0xfd] = new OperationCode("SBC", 3, 4, _ADDR_ABSX_1, _SBC);
            m_OpCodes[0xfe] = new OperationCode("INC", 3, 7, _ADDR_ABSX_1, _INC);
        }
Example #4
0
        protected CPUState m_State;              // current state of the CPU

        public CPU8Bit() : base()
        {
            m_PC = 0x0000;            // Program counter starts at $0

            m_OpCodes = new OperationCode[0x100];
        }
Example #5
0
        public void emulateCycle()
        {
            switch (m_State)
            {
            case CPUState.fetchopcode:

                // check and process Interrupt (only when in OpCode fetch)
                if (m_Interrupt)
                {
                    m_MaxCycles    = 7;
                    m_Cycle        = 1;
                    m_address      = 0;
                    m_addr         = Addressing._not_set_;
                    m_OperandValue = 0;
                    m_State        = CPUState.interrupt;
                    break;
                }

                // save current PC for debugging / tracing
                m_PC_Start = m_PC;

                // get the next byte and then move the program counter forward
                byte opCode = getNextMemByte();


                // get from OpCode table
                m_oc = m_OpCodes[opCode];

                // check if OpCode is defined
                if (String.IsNullOrEmpty(m_oc.OpCode) || m_oc.executeOperation == null || m_oc.executeAddressing == null)
                {
                    string sMessage = String.Format("PC {0:X4} : OpCode {1:X2} unknown!!!", m_PC_Start, opCode);
                    throw new NotImplementedException(sMessage);
                }

#if CPU_TRACE
                m_sbDebug = new StringBuilder();
                m_sbDebug.AppendFormat("{0:X4}:{1:X2} {2} ", m_PC_Start, opCode, m_oc.OpCode);
#endif

                m_MaxCycles    = m_oc.Cycles;
                m_Cycle        = 1;
                m_address      = 0;
                m_addr         = Addressing._not_set_;
                m_OperandValue = 0;
                m_State        = CPUState.addressing;

                break;

            case CPUState.addressing:     // addressing
                m_oc.executeAddressing();
                m_Cycle++;

                break;

            case CPUState.operation:
                if (m_Cycle == m_MaxCycles)     // emulate cycle exactness by making operation effective on last cycle
                {
                    m_oc.executeOperation();
                    if (m_Cycle < m_MaxCycles)
                    {
                        m_Cycle++;     // operation executed induced another cycle (e.g. branch operations)
                    }
                    else
                    {
                        m_State = CPUState.fetchopcode;      // operation finished -> get next opcode
#if CPU_TRACE
                        m_sbDebug.AppendFormat("\tPC:{0:X4} A:{1:X2} X:{2:X2} Y:{3:X2} SP:{4:X4} |{5}| STACK: {6:X2} {7:X2} {8:X2} {9:X2}",
                                               m_PC,
                                               m_reg_A,
                                               m_reg_X,
                                               m_reg_Y,
                                               Reg_SP,
                                               StatusString,
                                               m_ram[m_StackPtr - m_ramOffset],
                                               m_ram[m_StackPtr + 1 - m_ramOffset],
                                               m_ram[m_StackPtr + 2 - m_ramOffset],
                                               m_ram[m_StackPtr + 3 - m_ramOffset]);

                        Debug.WriteLine(m_sbDebug.ToString());
#endif
                    }
                }
                else
                {
                    m_Cycle++;
                }

                break;

            case CPUState.interrupt:
                if (m_Cycle == m_MaxCycles)     // emulate cycle exactness by making operation effective on last cycle
                {
                    push_stack((byte)(m_PC >> 8));
                    push_stack((byte)m_PC);
                    push_stack(m_reg_SR);
                    Flag_I      = true;
                    m_PC        = readMemWord(0xFFFE); // fetch IRQ vector
                    m_State     = CPUState.fetchopcode;
                    m_Interrupt = false;
                }
                else
                {
                    m_Cycle++;
                }
                break;
            }
        }