All pastes #830423 Raw Edit

Unnamed

public text v1 · immutable
#830423 ·published 2007-12-23 23:19 UTC
rendered paste body
using System;
using System.Runtime.InteropServices;

namespace NXSNES {
    public class Ricoh5A22 : ICyclic {
        private IMemory mem;

        [Flags]
        public enum Status : int {
            C   = 0x001,
            Z   = 0x002,
            I   = 0x004,
            D   = 0x008,
            X   = 0x010,
            M   = 0x020,
            V   = 0x040,
            N   = 0x080,
            E   = 0x100
        };

        /* FIXME: not portable to big-endian systems */
        [StructLayout(LayoutKind.Explicit)]
        public struct Registers {
            [FieldOffset(0)]    public ushort A;
            [FieldOffset(0)]    public byte AL;
            [FieldOffset(1)]    public byte AH;

            [FieldOffset(2)]    public byte DB;     /* Data Bank Register */

            [FieldOffset(4)]    public ushort X;
            [FieldOffset(4)]    public byte XL;
            [FieldOffset(5)]    public byte XH;

            [FieldOffset(6)]    public ushort Y;
            [FieldOffset(6)]    public byte YL;
            [FieldOffset(7)]    public byte YH;

            [FieldOffset(8)]    public ushort D;    /* Direct Page Pointer */
            [FieldOffset(8)]    public byte DL;
            [FieldOffset(9)]    public byte DH;
            
            [FieldOffset(10)]   public ushort SP;   /* Stack Pointer */

            [FieldOffset(12)]   public int PL;      /* Program Counter Long */
            [FieldOffset(12)]   public ushort PC;   /* Program Counter */
            [FieldOffset(14)]   public byte PB;     /* Program Bank */

            [FieldOffset(16)]   public Status S;    /* Status */
        }

        public Registers R;

        private long nextClock = 0;
        private const long OneCycle = 6;

        /* Prototype for one micro-op. Returns the index of the next micro-op
         * to execute for the current instruction, or null if this is the last
         * micro-op to execute. */
        private delegate int? Microcode(out long accessTime);

        /* A jagged array consisting of the microcode to execute for each
         * instruction. The opcode fetch-and-decode micro-op is *not* included;
         * this is automatically added. */
        private Microcode[][] microcode = new Microcode[256][];

        private int operand;

        public static class EmulationVectors {
            public const int IRQBRK  = 0xfffe;
            public const int Reset   = 0xfffc;
            public const int NMI     = 0xfffa;
            public const int Abort   = 0xfff8;
            public const int COP     = 0xfff4;
        }
        public static class NativeVectors {
            public const int IRQ     = 0xffee;
            public const int NMI     = 0xffea;
            public const int Abort   = 0xffe8;
            public const int BRK     = 0xffe6;
            public const int COP     = 0xffe5;
        }

/* ----------------------------------------------------------------------------
 *   Opcode archetypes 
 * ------------------------------------------------------------------------- */
      
#if XXX

        private void SetZN(ushort x)
        {
            if (x == 0)
                R.S |= Status.Z;
            else
                R.S &= ~Status.Z;

            if ((x & 0x8000) == 0x8000)
                R.S |= Status.N;
            else
                R.S &= ~Status.N;
        }

        private void ADC(ushort d)
        {
            d += (ushort)(R.S & Status.C);
            uint r = (uint)(R.A + d);

            if ((r & 0xffff0000) != 0)
                R.S |= Status.C;
            else
                R.S &= ~Status.C;

            if (((R.A & d & 0x8000) != 0 && (r & 0x8000) == 0) ||
                    ((R.A & 0x8000) == 0 && (d & 0x8000) == 0 &&
                     (r & 0x8000) != 0))
                R.S |= Status.V;
            else
                R.S &= ~Status.V;

            R.A = (ushort)r;
            SetZN(R.A);
        }
#endif

/* ----------------------------------------------------------------------------
 *   Addressing modes 
 * ------------------------------------------------------------------------- */

        private Microcode[] Immediate, DirectRead;
        private int offset;

        private void CreateAddressingModes()
        {
            Immediate = new Microcode[] {
                (out long time) => {   /* 0: IDL */
                    operand = mem.GetByte(R.PC++, out time);
                    if ((R.S & Status.M) == 0)
                        return 1;
                    else
                        return null;
                },
                (out long time) => {   /* 1: IDH */
                    operand |= ((int)(mem.GetByte(R.PC++, out time)) << 8);
                    return null;
                }
            };

            DirectRead = new Microcode[] {
                (out long time) => {   /* 0: DO */
                    offset = mem.GetByte(R.PC, out time);
                    if (R.DL != 0)
                        return 1;   /* One extra cycle, below. */
                    else {
                        R.PC++;
                        return 2;   /* Don't need the extra cycle. */
                    }
                },
                (out long time) => {   /* 1: IO */
                    R.PC++;
                    time = OneCycle;
                    return 2;
                },
                (out long time) => {   /* 2: Data Low */
                    operand = mem.GetByte(R.DL + offset, out time);
                    if ((R.S & Status.M) == 0)
                        return 3;
                    else
                        return null;
                },
                (out long time) => {   /* 3: Data High */
                    operand |= ((int)(mem.GetByte(R.DL + offset + 1, out time))
                            << 8);
                    return null;
                }
            };
        }


/* ----------------------------------------------------------------------------
 *   Opcode implementations
 * ------------------------------------------------------------------------- */

        /*private void ADCImmediate16()
        {
            ADC(Immediate16());
        }*/

/* ----------------------------------------------------------------------------
 *   Initialization and interrupts
 * ------------------------------------------------------------------------- */

        public Ricoh5A22(IMemory m)
        {
            CreateAddressingModes();

            microcode[0x69] = new Microcode[] {
                
            };
            //OpcodesN16[0x69] = ADCImmediate16;

            mem = m;
        }

        public void Reset()
        {
            R.S  = Status.E;
            // R.PC = mem.GetWord(EmulationVectors.Reset);
            R.PB = 0;
        }

/* ----------------------------------------------------------------------------
 *   The main run loop
 * ------------------------------------------------------------------------- */

#if XXX
        public void Step()
        {
            int op = mem.GetByte(R.PL); R.PC++;
            
            if ((R.S & Status.E) == 0) {
                if ((R.S & Status.M) == 0)
                    OpcodesN16[op]();
                else
                    OpcodesN8[op]();
            } else {
                if ((R.S & Status.M) == 0)
                    OpcodesE16[op]();
                else
                    OpcodesE8[op]();
            }
            
        }
#endif

        public long Step(long clock)
        {
            return clock + 6;
        }

    }
}