Ejemplo n.º 1
0
        public byte GetFlag(FLAGS6502 f)
        {
            byte b = (byte)f;
            byte a = (byte)(status & b);

            return((byte)((a > 0) ? 1 : 0));
        }
Ejemplo n.º 2
0
 private void SetFlag(FLAGS6502 flag, bool value)
 {
     if (value == true)
     {
         StatusRegister |= ToByte((int)flag);
     }
     else
     {
         StatusRegister &= ToByte((int)~flag);
     }
 }
Ejemplo n.º 3
0
 public void SetFlag(FLAGS6502 f, int v)
 {
     if (v > 0)
     {
         status |= (byte)f;
     }
     else
     {
         status &= (byte)(~f);
     }
 }
Ejemplo n.º 4
0
 public void SetFlag(FLAGS6502 f, bool v)
 {
     if (v)
     {
         status |= (byte)f;
     }
     else
     {
         status &= (byte)~f;
     }
 }
Ejemplo n.º 5
0
 private void SetFlag(FLAGS6502 flag, bool v)
 {
     if (v)
     {
         status = (byte)(status | (byte)flag);
     }
     else
     {
         status = (byte)(status & (byte)~flag);
     }
 }
Ejemplo n.º 6
0
        /// <summary>
        /// A Non-Maskable Interrupt cannot be ignored. It behaves in exactly the
        /// same way as a regular IRQ, but reads the new program counter address
        /// form location 0xFFFA.
        /// </summary>
        public void NMI()
        {
            // Push current current PC to the stack (two pushes)
            PushStack((byte)((Pc >> 8) & 0x00FF)); // Store the high byte (& 0x00FF clears the high portion)
            PushStack((byte)(Pc & 0x00FF));        // Store the low byte

            // Then Push the status register to the stack
            Status |= FLAGS6502.B;
            Status |= FLAGS6502.U;
            Status |= FLAGS6502.I;
            PushStack((byte)Status);

            // Read new program counter location from fixed address
            Pc = ReadAsAddress(NMI_PC_START_ADDRESS);

            // NMIs take time
            cycles = NMI_CYCLE_COUNT;
        }
Ejemplo n.º 7
0
        // EXTERNAL EVENTS

        /// <summary>
        /// Forces the 6502 into a known state. This is hard-wired inside the CPU. The
        /// registers are set to 0x00, the status register is cleared except for unused
        /// bit which remains at 1. An absolute address is read from location 0xFFFC
        /// which contains a second address that the program counter is set to. This
        /// allows the programmer to jump to a known and programmable location in the
        /// memory to start executing from. Typically the programmer would set the value
        /// </summary>
        public void Reset(bool hardReset = false)
        {
            // Get address to set program counter to
            // This is stored little indian starting at 0xFFFC
            Pc = ReadAsAddress(PC_START_ADDRESS);

            // Reset registers
            A      = 0;
            X      = 0;
            Y      = 0;
            StkPtr = INITIAL_STACK_POINTER;
            Status = FLAGS6502.U;

            // Clear internals
            addr_abs = 0x0000;
            addr_rel = 0x0000;
            fetched  = 0x00;

            // Reset takes time
            cycles      = RESET_CYCLE_COUNT;
            clock_count = 0;
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Interrupt requests are a complex operation and only happen if the
        /// "disable interrupt" flag is 0. IRQs can happen at any time, but
        /// you dont want them to be destructive to the operation of the running
        /// program. Therefore the current instruction is allowed to finish
        /// (which I facilitate by doing the whole thing when cycles == 0) and
        /// then the current program counter is stored on the stack. Then the
        /// current status register is stored on the stack. When the routine
        /// that services the interrupt has finished, the status register
        /// and program counter can be restored to how they where before it
        /// occurred. This is impemented by the "RTI" instruction. Once the IRQ
        /// has happened, in a similar way to a reset, a programmable address
        /// is read form hard coded location 0xFFFE, which is subsequently
        /// set to the program counter.
        /// </summary>
        public void IRQ()
        {
            // Check if "Disable Interrupts" is set
            if (Status.HasFlag(FLAGS6502.I))
            {
                return;
            }

            // Push current current PC to the stack (two pushes)
            PushPcOnStack();

            // Then Push the status register to the stack
            Status |= FLAGS6502.B;
            Status |= FLAGS6502.U;
            Status |= FLAGS6502.I;
            PushStack((byte)Status);

            // Read new program counter location from fixed address
            Pc = ReadAsAddress(IRQ_PC_START_ADDRESS);

            // IRQs take time
            cycles = IRQ_CYCLE_COUNT;
        }
Ejemplo n.º 9
0
 private void SetFlag(FLAGS6502 flag, int value)
 {
     SetFlag(flag, value != 0);
 }
Ejemplo n.º 10
0
        private byte GetFlag(FLAGS6502 flag)
        {
            var flagValue = ((StatusRegister & ToByte((int)flag)) > 0) ? 1: 0;

            return(ToByte(flagValue));
        }
Ejemplo n.º 11
0
 public bool GetFlag(FLAGS6502 f)
 {
     return((status & (byte)f) > 0);
 }
Ejemplo n.º 12
0
        } = 0x00;                                       // Status Register


        public byte GetFlagByte(FLAGS6502 f)
        {
            return(GetFlag(f) ? (byte)1 : (byte)0);
        }
Ejemplo n.º 13
0
 private byte GetFlag(FLAGS6502 flag) => status;
Ejemplo n.º 14
0
 /// <summary>
 /// Set of unset a flag based on a condition
 /// </summary>
 /// <param name="flag"></param>
 /// <param name="isSet"></param>
 private void SetFlag(FLAGS6502 flag, bool isSet)
 {
     Status = isSet ? Status | flag : Status & ~flag;
 }
Ejemplo n.º 15
0
        /// <summary>
        /// Perform one clock cycles worth of emulation
        /// </summary>
        public void Clock()
        {
            // Non clock cycle accurate emulation
            // The result is calculated immediatly based on an opperation cycle value
            if (cycles == 0)
            {
                if (DebugEnabled)
                {
                    // Init logger
                    logger = logger ??= File.CreateText("cpu.txt");
                    // Log Pc before incrementing
                    logger.WriteLine($"{Pc:X4}  A:{A:X2} X:{X:X2} Y:{Y:X2} P:{(byte)Status:X2} SP:{StkPtr:X2}  CYC:{clock_count}");

                    // Usefull to break at a specific prg location
                    if (DebugBreakPc != 0x0000 && Pc == DebugBreakPc)
                    {
                        Debugger.Break();
                        // Disable further breaks
                        DebugBreakPc = 0;
                        // force push logging buffer to file
                        logger.Flush();
                        // Notify if defined
                        DebugPcHitCallback?.Invoke();
                    }
                }

                // Read next instruction byte. This 8-bit value is used to index
                // the translation table to get the relevant information about
                // how to implement the instruction
                opcode = CpuRead(Pc, false);

                // Always set the unused status flag bit to 1
                Status |= FLAGS6502.U;

                // Increment program counter, we read the opcode byte
                Pc++;

                // Get Starting number of cycles
                cycles = Lookup[opcode].Cycles;

                // Perform fetch of intermmediate data using the
                // required addressing mode
                byte extra_cycles1 = Lookup[opcode].AddressModeFunc();
                // Perform the opperation
                byte extra_cycles2 = Lookup[opcode].OpcodeFunc();

                // The addressmode and opcode may have altered the number
                // of cycles this instruction requires before its completed
                cycles += (byte)(extra_cycles1 & extra_cycles2);

                // Always set the unused status flag bit to 1
                Status |= FLAGS6502.U;
            }

            // Increment global clock count - This is actually unused unless logging is enabled
            // but I've kept it in because its a handy watch variable for debugging
            clock_count++;

            // Decrement the number of cycles remaining for this instruction
            cycles--;
        }