Nick Massey avatar Nick Massey committed 9e5a455

Add Text and Graphics2 graphics modes.
Add primitive debugger.
Use more correct colors in PPU palette.
Switch cycle lengths to T-Cycle counts.
Disable video on form.
Untested support for interrupts.
Fix various CPU bugs.
Add very basic gamepad support.

Comments (0)

Files changed (9)

coleco-o-tron/ColecoCore.cs

             IM1,
             IM2
         }
-        private int regA;
-        private int regB;
-        private int regC;
-        private int regD;
-        private int regE;
-        private int regH;
-        private int regL;
-        private int regIXh;
-        private int regIXl;
-        private int regIYh;
-        private int regIYl;
-        private int regSP;
-        private int regPC;
+        private int regA = 0xFF;
+        private int regB = 0xFF;
+        private int regC = 0xFF;
+        private int regD = 0xFF;
+        private int regE = 0xFF;
+        private int regH = 0xFF;
+        private int regL = 0xFF;
+        private int regIXh = 0xFF;
+        private int regIXl = 0xFF;
+        private int regIYh = 0xFF;
+        private int regIYl = 0xFF;
+        public int regSP;
+        public int regPC;
         private int intZ = 1;
-        private bool flagZ
+        public bool flagZ
         {
             get
             {
                     intZ = 1;
             }
         }
-        private bool flagN;
-        private bool flagH;
-        private bool flagC;
-        private bool flagS;
-        private bool flagV;
+        public bool flagN;
+        public bool flagH;
+        public bool flagC;
+        public bool flagS;
+        public bool flagV;
         private int regF
         {
             get
                 flagC = ((value & 0x01) != 0);
             }
         }
-        private int regAF
+        public int regAF
         {
             get
             {
                 regF = (value & 0xFF);
             }
         }
-        private int regBC
+        public int regBC
         {
             get
             {
                 regC = (value & 0xFF);
             }
         }
-        private int regDE
+        public int regDE
         {
             get
             {
                 regE = (value & 0xFF);
             }
         }
-        private int regHL
+        public int regHL
         {
             get
             {
                 regL = (value & 0xFF);
             }
         }
-        private int regIX
+        public int regIX
         {
             get
             {
                 regIXl = (value & 0xFF);
             }
         }
-        private int regIY
+        public int regIY
         {
             get
             {
         }
         private int regI;
         private int regR;
-        private int shadowRegAF;
-        private int shadowRegBC;
-        private int shadowRegDE;
-        private int shadowRegHL;
-        private bool halted;
+        private int shadowRegAF = 0xFFD7;
+        private int shadowRegBC = 0xFFFF;
+        private int shadowRegDE = 0xFFFF;
+        private int shadowRegHL = 0xFFFF;
+        private int interruptDataByte;
         private bool IFF1;
         private bool IFF2;
         private InterruptMode IM;
         byte[] memory = new byte[0x10000];
         int counter;
 
-        PPU ppu = new PPU();
+        public PPU ppu = new PPU();
+        public Input input = new Input();
+        StringBuilder debugBuilder = new StringBuilder();
 
-        public void Run()
+        public Debug debug;
+
+        private int[] opTable;
+        private int[] edOpTable;
+        private long debugCount;
+        public ColecoCore(byte[] rom)
         {
+            debug = new Debug(this);
+            regF = 0xD7;
             var fs = File.OpenRead("coleco.rom");
             for (int i = 0; i < 0x10000 && fs.CanRead; i++)
                 memory[i] = (byte)fs.ReadByte();
-            memory[0x8000] = 0xFF;
-            memory[0x8001] = 0xFF;
-            int[] opTable = OpInfo.GetOps();
-            int[] edOpTable = OpInfo.GetEDOps();
+
+            for (int i = 0x00; i < rom.Length && i < 0x8000; i++)
+            {
+                memory[i + 0x8000] = rom[i];
+            }
+
+            opTable = OpInfo.GetOps();
+            edOpTable = OpInfo.GetEDOps();
+
+            debugCount = -1;
+            File.Delete("log.txt");
+            
+        }
+
+        private bool dbgEnabled = false;
+        public void Run()
+        {
             int op, opCode, source, destination, instruction, cycles, result = 0, data = 0, temp = 0;
 
-            long debugCount = 1000000;
+            emulationRunning = true;
+            while (emulationRunning && !debug.Interrupt)
+            {
+                if(prefix == Prefix.None)
+                    debug.Execute(regPC);
+                opCode = Read();
+                if (debugCount < 100000 && prefix == Prefix.None && (dbgEnabled || regPC == 0x1979))
+                {
+                    dbgEnabled = true;
+                    debugCount++;
+                    debugBuilder.AppendFormat(
+                        "{0:x4} AF:{1:x4} BC:{2:x4} DE:{3:x4} HL:{4:x4} IX:{5:x4} IY:{6:x4}\r\n", regPC - 1, regAF, regBC, regDE, regHL, regIX, regIY);
 
-            File.Delete("log.txt");
-
-            while (emulationRunning)
-            {
-                debugCount++;
-                opCode = Read();
-                if (debugCount < 10000 && prefix == Prefix.None)
-                    File.AppendAllText("log.txt", string.Format("{0:x4} {1:x2} AF:{2:x4} BC:{3:x4} DE:{4:x4} HL:{5:x4} IX:{6:x4} IY:{7:x4}\r\n", regPC - 1, opCode, regAF, regBC, regDE, regHL, regIX, regIY));
+                    if (debugCount == 100000)
+                        File.AppendAllText("log.txt", debugBuilder.ToString());
+                }
                 op = opTable[opCode];
                 instruction = op & 0xFF;
                 destination = (op >> 8) & 0xFF;
                 source = (op >> 16) & 0xFF;
                 cycles = (op >> 24) & 0xFF;
 
-                data = GetSource(source);
+                if (prefix != Prefix.None) //TODO - Wrong Wrong Wrong
+                    cycles += 9;
+
+                data = GetSource(source, opCode);
 
                 switch (instruction)
                 {
                     case OpInfo.InstrLD:
                         result = data;
                         break;
+                    case OpInfo.InstrLDInterrupt:
+                        result = data;
+                        flagS = (result & 0x80) == 0x80;
+                        intZ = result;
+                        flagV = IFF2;
+                        break;
                     case OpInfo.InstrEXDEHL:
                         temp = regDE;
                         regDE = regHL;
                         result = regA + data;
                         flagN = false;
                         flagC = result > 0xFF;
-                        flagV = result > 127;
+                        flagV = (((data ^ regA ^ 0x80) & (data ^ result)) & 0x80) != 0; 
                         flagH = ((regA & 0xF) + (data & 0xF)) > 0xF;
                         flagS = (result & 0x80) == 0x80;
                         result = intZ = result & 0xFF;
                         IFF2 = true;
                         break;
                     case OpInfo.InstrADD:
-                        result = (regHL + data);
+                        if (prefix == Prefix.DD)
+                            temp = regIX;
+                        else if (prefix == Prefix.FD)
+                            temp = regIY;
+                        else
+                            temp = regHL;
+                        result = (temp + data);
                         flagN = false;
-                        flagH = ((regHL ^ data ^ (result & 0xFFFF)) & 0x1000) != 0; //I don't really get how the H flag works here, this is from VBA source.
+                        flagH = ((temp ^ data ^ (result & 0xFFFF)) & 0x1000) != 0; //I don't really get how the H flag works here, this is from VBA source.
                         flagC = result > 0xFFFF;
                         result = result & 0xFFFF;
                         break;
                         break;
                     case OpInfo.PrefixCB:
                         var bitOp = Read();
-                        cycles = 2; //TODO - WRONG WRONG WRONG
+                        cycles = 8; //TODO - WRONG WRONG WRONG
                         switch(bitOp & 0x7)
                         {
                             case 0:
                                 break;
                             case 6:
                                 source = OpInfo.LocAddrHL;
-                                cycles += 2;
+                                cycles += 7;
                                 break;
                             case 7:
                                 source = OpInfo.LocRegA;
                                 break;
                         }
                         destination = source;
-                        data = GetSource(source);
+                        data = GetSource(source, bitOp);
 
                         switch ((bitOp & 0xF8) >> 3)
                         {
                                 flagN = false;
                                 break;
                             case OpInfo.InstrSLA:
-                                result = data << 1;
+                                result = (data << 1) & 0xFF;
                                 flagS = (result & 0x80) == 0x80;
                                 flagC = (data & 0x80) == 0x80;
                                 intZ = result;
                                 flagN = false;
                                 break;
                             case OpInfo.InstrSLL:
-                                result = data << 1;
+                                result = (data << 1) & 0xFF;
                                 flagC = (data & 0x80) == 0x80;
                                 flagS = false;
                                 intZ = result;
                         source = (op >> 16) & 0xFF;
                         cycles = (op >> 24) & 0xFF;
 
-                        data = GetSource(source);
+                        data = GetSource(source, opCode);
 
                         switch (instruction)
                         {
                                 regB = (regB - 1) & 0xFF;
                                 regHL = (regHL + 1) & 0xFFFF;
                                 flagN = true;
-                                flagZ = (regB - 1) == 0;
+                                flagZ = regB == 0;
                                 break;
                             case OpInfo.InstrINIR:
                                 Write(In(regC), regHL);
                                 regB = (regB - 1) & 0xFF;
                                 regHL = (regHL + 1) & 0xFFFF;
                                 flagN = true;
-                                flagZ = (regB - 1) == 0;
+                                flagZ = regB == 0;
                                 break;
                             case OpInfo.InstrOUTIR:
                                 Out(data, regC);
 
                         break;
                     case OpInfo.PrefixDD:
+                        regR = (regR + 1) & 0xFF;
                         prefix = Prefix.DD;
                         continue;
                     case OpInfo.PrefixFD:
+                        regR = (regR + 1) & 0xFF;
                         prefix = Prefix.FD;
                         continue;
 
                         regF = result;
                         break;
                     case OpInfo.LocRegH:
-                        if (prefix == Prefix.DD)
+                        if (prefix == Prefix.DD && opCode != 0x66)
                             regIXh = result;
-                        else if (prefix == Prefix.FD)
+                        else if (prefix == Prefix.FD && opCode != 0x66)
                             regIYh = result;
                         else 
                             regH = result;
                         break;
                     case OpInfo.LocRegL:
-                        if (prefix == Prefix.DD)
+                        if (prefix == Prefix.DD && opCode != 0x6E)
                             regIXl = result;
-                        else if (prefix == Prefix.FD)
+                        else if (prefix == Prefix.FD && opCode != 0x6E)
                             regIYl = result;
                         else
                             regL = result;
                         regR = result;
                         break;
                 }
+                regR = (regR + 1) & 0xFF;
                 ppu.Clock(cycles);
+                if (ppu.frameComplete)
+                {
+                    emulationRunning = false;
+                    ppu.frameComplete = false;
+                }
                 if(ppu.nmi)
                 {
                     PushWordStack(regPC);
                     regPC = 0x0066;
                 }
+                if(IFF1 && false)
+                {
+                    switch(IM)
+                    {
+                        case InterruptMode.IM1:
+                            IFF1 = false;
+                            PushWordStack(regPC);
+                            regPC = 0x0038;
+                            break;
+                        case InterruptMode.IM2:
+                            IFF1 = false;
+                            PushWordStack(regPC);
+                            regPC = ReadWord((regI << 8) | (interruptDataByte & 0xFE));
+                        break;
+                    }
+                }
+
+                if (ppu.frame == 700)
+                    input.keys[1] = true;
+                debug.AddCycles(cycles);
+                if (ppu.frame == 705)
+                    input.keys[1] = false;
                 counter += cycles;
                 prefix = Prefix.None;
             }
 
         private byte Read(int address)
         {
+            debug.Read(address);
             return memory[address & 0xFFFF];
         }
         private byte Read()
         }
         private void Write(int value, int address)
         {
+            debug.Write(address);
+            /*
+            if (address == 0x73fe)
+                debugBuilder.AppendLine("WRITE: " + value.ToString("x2"));
+            if (address == 0x73ff)
+                debugBuilder.AppendLine("WRITE: " + value.ToString("x2"));
+            */
             if(address >= 0x2000 && address < 0x8000)
                 memory[address & 0xFFFF] = (byte)(value & 0xFF);
         }
         private void WriteWord(int value, int address)
         {
             Write(value, address);
-            Write(value >> 1, address + 1);
+            Write(value >> 8, address + 1);
         }
 
         private void Out(int value, int address)
             {
                 ppu.Write((byte)value, address);
             }
+            input.Write((byte)value, address);
         }
         private byte In(int address)
         {
             {
                 return ppu.Read(address);
             }
-            return 0x00;
+
+            return input.Read(address);
         }
         private static bool Parity8(int reg)
         {
             reg &= 0xF;
             return ((0x6996 >> reg) & 1) != 1;
         }
-        private int GetSource(int source)
+        private int GetSource(int source, int opcode)
         {
             switch (source)
             {
                 case OpInfo.LocRegF:
                     return regF;
                 case OpInfo.LocRegH:
-                    if (prefix == Prefix.DD)
+                    if (prefix == Prefix.DD && opcode != 0x74)
                         return regIXh;
-                    if (prefix == Prefix.FD)
+                    if (prefix == Prefix.FD && opcode != 0x74)
                         return regIYh;
                     return regH;
                 case OpInfo.LocRegL:
-                    if (prefix == Prefix.DD)
+                    if (prefix == Prefix.DD && opcode != 0x75)
                         return regIXl;
-                    if (prefix == Prefix.FD)
+                    if (prefix == Prefix.FD && opcode != 0x75)
                         return regIYl;
                     return regL;
                 case OpInfo.Loc8Immediate:

coleco-o-tron/Debug.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace coleco_o_tron
+{
+    class Debug
+    {
+        private ColecoCore core;
+
+        public const byte READ = 1;
+        public const byte WRITE = 2;
+        public const byte EXECUTE = 4;
+        public const byte IN = 8;
+        public const byte OUT = 16;
+
+        public bool Interrupt;
+
+        private int debugCounter;
+
+        public byte[] breakpoints = new byte[0x10000];
+
+        public Queue<string> Log = new Queue<string>(5); 
+
+        public Debug(ColecoCore core)
+        {
+            this.core = core;
+        }
+
+        public void Step()
+        {
+            Interrupt = false;
+            debugCounter = 1;
+        }
+
+        public void Resume()
+        {
+            Interrupt = false;
+            debugCounter = 0;
+        }
+
+        public void AddCycles(int cycles)
+        {
+            if (debugCounter > 0)
+            {
+                debugCounter -= cycles;
+                if (debugCounter <= 0)
+                {
+                    Interrupt = true;
+                }
+            }
+        }
+
+        public void Execute(int address)
+        {
+            if((breakpoints[address] & EXECUTE) != 0)
+            {
+                Interrupt = true;
+                Log.Enqueue(string.Format("Execute at {0:x4}", address));
+            }
+        }
+
+        public void Read(int address)
+        {
+            if ((breakpoints[address] & READ) != 0)
+            {
+                Interrupt = true;
+                Log.Enqueue(string.Format("Read at {0:x4}", address));
+            }
+        }
+
+        public void Write(int address)
+        {
+            if ((breakpoints[address] & WRITE) != 0)
+            {
+                Interrupt = true;
+                Log.Enqueue(string.Format("Write at {0:x4}", address));
+            }
+        }
+
+        public void AddExecuteBreakPoint(int address)
+        {
+            breakpoints[address] |= EXECUTE;
+        }
+
+        public void AddReadBreakPoint(int address)
+        {
+            breakpoints[address] |= READ;
+        }
+
+        public void AddWriteBreakPoint(int address)
+        {
+            breakpoints[address] |= WRITE;
+        }
+
+        public void RemoveExecuteBreakPoint(int address)
+        {
+            breakpoints[address] &= EXECUTE ^ 0xFF;
+        }
+
+        public void RemoveReadBreakPoint(int address)
+        {
+            breakpoints[address] &= READ ^ 0xFF;
+        }
+
+        public void RemoveWriteBreakPoint(int address)
+        {
+            breakpoints[address] &= WRITE ^ 0xFF;
+        }
+
+        public void Reset()
+        {
+            core.regPC = 0x0000;
+            core.ppu.frame = 0;
+        }
+
+        public string DebugStatus()
+        {
+            while(Log.Count > 5)
+                Log.Dequeue();
+
+
+            string logs = "";
+
+            foreach (var line in Log.Reverse())
+            {
+                logs += line + "\r\n";
+            }
+
+            string statusLine = "";
+
+            if (core.flagS)
+                statusLine += 'S';
+            else
+                statusLine += '.';
+
+            if (core.flagZ)
+                statusLine += 'Z';
+            else
+                statusLine += '.';
+
+            statusLine += '.';
+
+            if (core.flagH)
+                statusLine += 'H';
+            else
+                statusLine += '.';
+
+            statusLine += '.';
+
+            if (core.flagV)
+                statusLine += 'V';
+            else
+                statusLine += '.';
+
+            if (core.flagN)
+                statusLine += 'N';
+            else
+                statusLine += '.';
+
+            if (core.flagC)
+                statusLine += 'C';
+            else
+                statusLine += '.';
+
+            return
+                string.Format(
+                    "{9}\r\n\r\nPC: {0:x4}\r\nAF: {1:x4}\r\nBC: {2:x4}\r\nDE: {3:x4}\r\nHL: {4:x4}\r\nIX: {5:x4}\r\nIY: {6:x4}\r\nSP: {7:x4}\r\n\r\n\r\n{8}",
+                    core.regPC, core.regAF, core.regBC, core.regDE, core.regHL, core.regIX, core.regIY, core.regSP, logs, statusLine);
+        }
+    }
+}

coleco-o-tron/Form1.Designer.cs

         /// </summary>
         private void InitializeComponent()
         {
-            this.components = new System.ComponentModel.Container();
+            this.textBox1 = new System.Windows.Forms.TextBox();
+            this.button1 = new System.Windows.Forms.Button();
+            this.button2 = new System.Windows.Forms.Button();
+            this.button3 = new System.Windows.Forms.Button();
+            this.button4 = new System.Windows.Forms.Button();
+            this.textBox2 = new System.Windows.Forms.TextBox();
+            this.button5 = new System.Windows.Forms.Button();
+            this.button6 = new System.Windows.Forms.Button();
+            this.button7 = new System.Windows.Forms.Button();
+            this.SuspendLayout();
+            // 
+            // textBox1
+            // 
+            this.textBox1.Location = new System.Drawing.Point(12, 297);
+            this.textBox1.Name = "textBox1";
+            this.textBox1.Size = new System.Drawing.Size(74, 20);
+            this.textBox1.TabIndex = 0;
+            // 
+            // button1
+            // 
+            this.button1.Location = new System.Drawing.Point(92, 297);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(75, 23);
+            this.button1.TabIndex = 1;
+            this.button1.Text = "Read";
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // button2
+            // 
+            this.button2.Location = new System.Drawing.Point(173, 297);
+            this.button2.Name = "button2";
+            this.button2.Size = new System.Drawing.Size(75, 23);
+            this.button2.TabIndex = 2;
+            this.button2.Text = "Write";
+            this.button2.UseVisualStyleBackColor = true;
+            this.button2.Click += new System.EventHandler(this.button2_Click);
+            // 
+            // button3
+            // 
+            this.button3.Location = new System.Drawing.Point(254, 297);
+            this.button3.Name = "button3";
+            this.button3.Size = new System.Drawing.Size(75, 23);
+            this.button3.TabIndex = 3;
+            this.button3.Text = "Execute";
+            this.button3.UseVisualStyleBackColor = true;
+            this.button3.Click += new System.EventHandler(this.button3_Click);
+            // 
+            // button4
+            // 
+            this.button4.Location = new System.Drawing.Point(254, 326);
+            this.button4.Name = "button4";
+            this.button4.Size = new System.Drawing.Size(75, 23);
+            this.button4.TabIndex = 4;
+            this.button4.Text = "Remove";
+            this.button4.UseVisualStyleBackColor = true;
+            this.button4.Click += new System.EventHandler(this.button4_Click);
+            // 
+            // textBox2
+            // 
+            this.textBox2.AcceptsReturn = true;
+            this.textBox2.AcceptsTab = true;
+            this.textBox2.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+            this.textBox2.Location = new System.Drawing.Point(12, 368);
+            this.textBox2.Multiline = true;
+            this.textBox2.Name = "textBox2";
+            this.textBox2.Size = new System.Drawing.Size(317, 282);
+            this.textBox2.TabIndex = 5;
+            // 
+            // button5
+            // 
+            this.button5.Location = new System.Drawing.Point(92, 326);
+            this.button5.Name = "button5";
+            this.button5.Size = new System.Drawing.Size(75, 23);
+            this.button5.TabIndex = 6;
+            this.button5.Text = "Step";
+            this.button5.UseVisualStyleBackColor = true;
+            this.button5.Click += new System.EventHandler(this.button5_Click);
+            // 
+            // button6
+            // 
+            this.button6.Location = new System.Drawing.Point(173, 326);
+            this.button6.Name = "button6";
+            this.button6.Size = new System.Drawing.Size(75, 23);
+            this.button6.TabIndex = 7;
+            this.button6.Text = "Resume";
+            this.button6.UseVisualStyleBackColor = true;
+            this.button6.Click += new System.EventHandler(this.button6_Click);
+            // 
+            // button7
+            // 
+            this.button7.Location = new System.Drawing.Point(12, 326);
+            this.button7.Name = "button7";
+            this.button7.Size = new System.Drawing.Size(75, 23);
+            this.button7.TabIndex = 8;
+            this.button7.Text = "Reset";
+            this.button7.UseVisualStyleBackColor = true;
+            this.button7.Click += new System.EventHandler(this.button7_Click);
+            // 
+            // Form1
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(341, 662);
+            this.Controls.Add(this.button7);
+            this.Controls.Add(this.button6);
+            this.Controls.Add(this.button5);
+            this.Controls.Add(this.textBox2);
+            this.Controls.Add(this.button4);
+            this.Controls.Add(this.button3);
+            this.Controls.Add(this.button2);
+            this.Controls.Add(this.button1);
+            this.Controls.Add(this.textBox1);
+            this.Name = "Form1";
             this.Text = "Form1";
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
+            this.Shown += new System.EventHandler(this.Form1_Shown);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
         }
 
         #endregion
+
+        private System.Windows.Forms.TextBox textBox1;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Button button2;
+        private System.Windows.Forms.Button button3;
+        private System.Windows.Forms.Button button4;
+        private System.Windows.Forms.TextBox textBox2;
+        private System.Windows.Forms.Button button5;
+        private System.Windows.Forms.Button button6;
+        private System.Windows.Forms.Button button7;
     }
 }
 

coleco-o-tron/Form1.cs

 using System.ComponentModel;
 using System.Data;
 using System.Drawing;
+using System.Drawing.Imaging;
+using System.Globalization;
 using System.Linq;
 using System.Text;
 using System.Windows.Forms;
+using System.IO;
+using System.Threading;
 
 namespace coleco_o_tron
 {
         public Form1()
         {
             InitializeComponent();
-            ColecoCore core = new ColecoCore();
-            core.Run();
+            ThreadPool.QueueUserWorkItem(DebugParse);
+        }
+
+        private void DebugParse(object blah)
+        {
+            var fs = File.OpenRead("goodlog.bin");
+            BinaryReader bs = new BinaryReader(fs);
+            StringBuilder sb = new StringBuilder();
+            while(fs.Position < fs.Length - 20)
+            {
+                var regPC = (GetByte(bs) << 8) | GetByte(bs);
+                var regAF = (GetByte(bs) << 8) | GetByte(bs);
+                var regBC = (GetByte(bs) << 8) | GetByte(bs);
+                var regDE = (GetByte(bs) << 8) | GetByte(bs);
+                var regHL = (GetByte(bs) << 8) | GetByte(bs);
+                var regIX = (GetByte(bs) << 8) | GetByte(bs);
+                var regIY = (GetByte(bs) << 8) | GetByte(bs);
+
+                    sb.AppendFormat(
+                        "{0:x4} AF:{1:x4} BC:{2:x4} DE:{3:x4} HL:{4:x4} IX:{5:x4} IY:{6:x4}\r\n", regPC, regAF, regBC, regDE, regHL, regIX, regIY);
+            }
+            fs.Close();
+            File.WriteAllText("parsedGoodLog.txt", sb.ToString());
+        }
+
+        private byte lastByte = 0;
+        private byte GetByte(BinaryReader bs)
+        {
+            var nextByte = bs.ReadByte();
+            return nextByte;
+        }
+
+        private ColecoCore core;
+
+        private bool closing = false;
+        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            closing = true;
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            core.debug.AddReadBreakPoint(int.Parse(textBox1.Text,NumberStyles.AllowHexSpecifier));
+        }
+
+        private void button2_Click(object sender, EventArgs e)
+        {
+            core.debug.AddWriteBreakPoint(int.Parse(textBox1.Text, NumberStyles.AllowHexSpecifier));
+
+        }
+
+        private void button3_Click(object sender, EventArgs e)
+        {
+
+            core.debug.AddExecuteBreakPoint(int.Parse(textBox1.Text, NumberStyles.AllowHexSpecifier));
+        }
+
+        private void button4_Click(object sender, EventArgs e)
+        {
+            int address = int.Parse(textBox1.Text, NumberStyles.AllowHexSpecifier);
+            core.debug.RemoveExecuteBreakPoint(address);
+            core.debug.RemoveReadBreakPoint(address);
+            core.debug.RemoveWriteBreakPoint(address);
+        }
+
+        private unsafe void Form1_Shown(object sender, EventArgs e)
+        {
+            OpenFileDialog ofd = new OpenFileDialog();
+            ofd.ShowDialog();
+            core = new ColecoCore(File.ReadAllBytes(ofd.FileName));
+            var gfx = this.CreateGraphics();
+            Bitmap imscreen = new Bitmap(284, 243, PixelFormat.Format32bppRgb);
+            while (!closing)
+            {
+                core.Run();
+                var bmd = imscreen.LockBits(new Rectangle(0, 0, 284, 243), ImageLockMode.WriteOnly,
+                                PixelFormat.Format32bppRgb);
+                var ptr = (uint*)bmd.Scan0;
+                for (int i = 0; i < 284 * 243; i++)
+                    ptr[i] = core.ppu.screen[i];
+                imscreen.UnlockBits(bmd);
+                gfx.DrawImageUnscaled(imscreen, 0, 0);
+                textBox2.Text = core.debug.DebugStatus();
+                Thread.Sleep(12);
+                Application.DoEvents();
+            }
+
+
+        }
+
+        private void button6_Click(object sender, EventArgs e)
+        {
+            core.debug.Resume();
+        }
+
+        private void button5_Click(object sender, EventArgs e)
+        {
+            core.debug.Step();
+        }
+
+        private void button7_Click(object sender, EventArgs e)
+        {
+            core.debug.Reset();
         }
     }
 }

coleco-o-tron/Form1.resx

+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

coleco-o-tron/Input.cs

+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace coleco_o_tron
+{
+    class Input
+    {
+        public enum Mode
+        {
+            Keys,
+            Joystick
+        }
+
+        private Mode readMode;
+
+        public bool[] keys = new bool[18];
+
+        public void Write(byte value, int address)
+        {
+            if(address == 0x80)
+            {
+                readMode = Mode.Keys;
+            }
+            else if(address == 0xC0)
+            {
+                readMode = Mode.Joystick;
+            }
+        }
+
+        public byte Read(int address)
+        {
+            if(address != 0xFC)
+                return 0;
+            byte data = 0;
+            switch (readMode)
+            {
+                    case Mode.Keys:
+                    if (keys[0])
+                        return (byte)(data | 0xA);
+                    if (keys[1])
+                        return (byte)(data | 0xD);
+                    if (keys[2])
+                        return (byte)(data | 0x7);
+                    if (keys[3])
+                        return (byte)(data | 0xC);
+                    if (keys[4])
+                        return (byte)(data | 0x2);
+                    if (keys[5])
+                        return (byte)(data | 0x3);
+                    if (keys[6])
+                        return (byte)(data | 0xE);
+                    if (keys[7])
+                        return (byte)(data | 0x5);
+                    if (keys[8])
+                        return (byte)(data | 0x1);
+                    if (keys[9])
+                        return (byte)(data | 0xB);
+                    return (byte)(data | 0xF);
+                    break;
+                    case Mode.Joystick:
+                    return 0xF;
+                    break;
+            }
+            return 0xF;
+        }
+    }
+}

coleco-o-tron/OpInfo.cs

         public const int InstrOUTD = 81;
         public const int InstrOUTDR = 82;
         public const int InstrSLL = 83;
+        public const int InstrLDInterrupt = 84;
 
         public const int PrefixED = 100;
         public const int PrefixCB = 101;
             for (int i = 0; i < 256; i++ )
                 SetEDOp(i, InstrNOP, LocNone, LocNone, 2);
 
-            SetEDOp(0x40, InstrIN, LocRegB, LocNone, 3);
-            SetEDOp(0x50, InstrIN, LocRegD, LocNone, 3);
-            SetEDOp(0x60, InstrIN, LocRegH, LocNone, 3);
-            SetEDOp(0x70, InstrIN, LocNone, LocNone, 3);
-            SetEDOp(0x48, InstrIN, LocRegC, LocNone, 3);
-            SetEDOp(0x58, InstrIN, LocRegE, LocNone, 3);
-            SetEDOp(0x68, InstrIN, LocRegL, LocNone, 3);
-            SetEDOp(0x78, InstrIN, LocRegA, LocNone, 3);
+            SetEDOp(0x40, InstrIN, LocRegB, LocNone, 12);
+            SetEDOp(0x50, InstrIN, LocRegD, LocNone, 12);
+            SetEDOp(0x60, InstrIN, LocRegH, LocNone, 12);
+            SetEDOp(0x70, InstrIN, LocNone, LocNone, 12);
+            SetEDOp(0x48, InstrIN, LocRegC, LocNone, 12);
+            SetEDOp(0x58, InstrIN, LocRegE, LocNone, 12);
+            SetEDOp(0x68, InstrIN, LocRegL, LocNone, 12);
+            SetEDOp(0x78, InstrIN, LocRegA, LocNone, 12);
 
 
-            SetEDOp(0x41, InstrOUT, LocNone, LocRegB, 3);
-            SetEDOp(0x51, InstrOUT, LocNone, LocRegD, 3);
-            SetEDOp(0x61, InstrOUT, LocNone, LocRegH, 3);
-            SetEDOp(0x71, InstrOUT, LocNone, LocNone, 3);
-            SetEDOp(0x49, InstrOUT, LocNone, LocRegC, 3);
-            SetEDOp(0x59, InstrOUT, LocNone, LocRegE, 3);
-            SetEDOp(0x69, InstrOUT, LocNone, LocRegL, 3);
-            SetEDOp(0x79, InstrOUT, LocNone, LocRegA, 3);
+            SetEDOp(0x41, InstrOUT, LocNone, LocRegB, 12);
+            SetEDOp(0x51, InstrOUT, LocNone, LocRegD, 12);
+            SetEDOp(0x61, InstrOUT, LocNone, LocRegH, 12);
+            SetEDOp(0x71, InstrOUT, LocNone, LocNone, 12);
+            SetEDOp(0x49, InstrOUT, LocNone, LocRegC, 12);
+            SetEDOp(0x59, InstrOUT, LocNone, LocRegE, 12);
+            SetEDOp(0x69, InstrOUT, LocNone, LocRegL, 12);
+            SetEDOp(0x79, InstrOUT, LocNone, LocRegA, 12);
 
-            SetEDOp(0x42, InstrSBC, LocRegHL, LocRegBC, 4);
-            SetEDOp(0x52, InstrSBC, LocRegHL, LocRegDE, 4);
-            SetEDOp(0x62, InstrSBC, LocRegHL, LocRegHL, 4);
-            SetEDOp(0x72, InstrSBC, LocRegHL, LocRegSP, 4);
+            SetEDOp(0x42, InstrSBC, LocRegHL, LocRegBC, 15);
+            SetEDOp(0x52, InstrSBC, LocRegHL, LocRegDE, 15);
+            SetEDOp(0x62, InstrSBC, LocRegHL, LocRegHL, 15);
+            SetEDOp(0x72, InstrSBC, LocRegHL, LocRegSP, 15);
 
-            SetEDOp(0x4A, InstrADC, LocRegHL, LocRegBC, 4);
-            SetEDOp(0x5A, InstrADC, LocRegHL, LocRegDE, 4);
-            SetEDOp(0x6A, InstrADC, LocRegHL, LocRegHL, 4);
-            SetEDOp(0x7A, InstrADC, LocRegHL, LocRegSP, 4);
+            SetEDOp(0x4A, InstrADC, LocRegHL, LocRegBC, 15);
+            SetEDOp(0x5A, InstrADC, LocRegHL, LocRegDE, 15);
+            SetEDOp(0x6A, InstrADC, LocRegHL, LocRegHL, 15);
+            SetEDOp(0x7A, InstrADC, LocRegHL, LocRegSP, 15);
 
-            SetEDOp(0x43, InstrLD, Loc16AddrAbsoulute, LocRegBC, 6);
-            SetEDOp(0x53, InstrLD, Loc16AddrAbsoulute, LocRegDE, 6);
-            SetEDOp(0x63, InstrLD, Loc16AddrAbsoulute, LocRegHL, 6);
-            SetEDOp(0x73, InstrLD, Loc16AddrAbsoulute, LocRegSP, 6);
+            SetEDOp(0x43, InstrLD, Loc16AddrAbsoulute, LocRegBC, 20);
+            SetEDOp(0x53, InstrLD, Loc16AddrAbsoulute, LocRegDE, 20);
+            SetEDOp(0x63, InstrLD, Loc16AddrAbsoulute, LocRegHL, 20);
+            SetEDOp(0x73, InstrLD, Loc16AddrAbsoulute, LocRegSP, 20);
 
-            SetEDOp(0x4B, InstrLD, LocRegBC, Loc16AddrAbsoulute, 6);
-            SetEDOp(0x5B, InstrLD, LocRegDE, Loc16AddrAbsoulute, 6);
-            SetEDOp(0x6B, InstrLD, LocRegHL, Loc16AddrAbsoulute, 6);
-            SetEDOp(0x7B, InstrLD, LocRegSP, Loc16AddrAbsoulute, 6);
+            SetEDOp(0x4B, InstrLD, LocRegBC, Loc16AddrAbsoulute, 20);
+            SetEDOp(0x5B, InstrLD, LocRegDE, Loc16AddrAbsoulute, 20);
+            SetEDOp(0x6B, InstrLD, LocRegHL, Loc16AddrAbsoulute, 20);
+            SetEDOp(0x7B, InstrLD, LocRegSP, Loc16AddrAbsoulute, 20);
 
-            SetEDOp(0x44, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x54, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x64, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x74, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x4C, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x5C, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x6C, InstrNEG, LocRegA, LocNone, 2);
-            SetEDOp(0x7C, InstrNEG, LocRegA, LocNone, 2);
+            SetEDOp(0x44, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x54, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x64, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x74, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x4C, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x5C, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x6C, InstrNEG, LocRegA, LocNone, 8);
+            SetEDOp(0x7C, InstrNEG, LocRegA, LocNone, 8);
 
-            SetEDOp(0x45, InstrRETN, LocNone, LocNone, 4);
-            SetEDOp(0x55, InstrRETN, LocNone, LocNone, 4);
-            SetEDOp(0x65, InstrRETN, LocNone, LocNone, 4);
-            SetEDOp(0x75, InstrRETN, LocNone, LocNone, 4);
-            SetEDOp(0x5D, InstrRETN, LocNone, LocNone, 4);
-            SetEDOp(0x6D, InstrRETN, LocNone, LocNone, 4);
-            SetEDOp(0x7D, InstrRETN, LocNone, LocNone, 4);
+            SetEDOp(0x45, InstrRETN, LocNone, LocNone, 14);
+            SetEDOp(0x55, InstrRETN, LocNone, LocNone, 14);
+            SetEDOp(0x65, InstrRETN, LocNone, LocNone, 14);
+            SetEDOp(0x75, InstrRETN, LocNone, LocNone, 14);
+            SetEDOp(0x5D, InstrRETN, LocNone, LocNone, 14);
+            SetEDOp(0x6D, InstrRETN, LocNone, LocNone, 14);
+            SetEDOp(0x7D, InstrRETN, LocNone, LocNone, 14);
 
-            SetEDOp(0x4D, InstrRETI, LocNone, LocNone, 4);
+            SetEDOp(0x4D, InstrRETI, LocNone, LocNone, 14);
 
-            SetEDOp(0x46, InstrIM0, LocNone, LocNone, 2);
-            SetEDOp(0x66, InstrIM0, LocNone, LocNone, 2);
-            SetEDOp(0x4E, InstrIM0, LocNone, LocNone, 2); //Should be illegal im0/1
-            SetEDOp(0x6E, InstrIM0, LocNone, LocNone, 2); //Should be illegal im0/1
+            SetEDOp(0x46, InstrIM0, LocNone, LocNone, 8);
+            SetEDOp(0x66, InstrIM0, LocNone, LocNone, 8);
+            SetEDOp(0x4E, InstrIM0, LocNone, LocNone, 8); //Should be illegal im0/1
+            SetEDOp(0x6E, InstrIM0, LocNone, LocNone, 8); //Should be illegal im0/1
 
-            SetEDOp(0x56, InstrIM1, LocNone, LocNone, 2);
-            SetEDOp(0x76, InstrIM1, LocNone, LocNone, 2);
+            SetEDOp(0x56, InstrIM1, LocNone, LocNone, 8);
+            SetEDOp(0x76, InstrIM1, LocNone, LocNone, 8);
 
-            SetEDOp(0x5E, InstrIM2, LocNone, LocNone, 2);
-            SetEDOp(0x7E, InstrIM2, LocNone, LocNone, 2);
+            SetEDOp(0x5E, InstrIM2, LocNone, LocNone, 8);
+            SetEDOp(0x7E, InstrIM2, LocNone, LocNone, 8);
 
-            SetEDOp(0x47, InstrLD, LocRegI, LocRegA, 2); //TODO - This group should set flags
-            SetEDOp(0x57, InstrLD, LocRegA, LocRegI, 2);
-            SetEDOp(0x4F, InstrLD, LocRegR, LocRegA, 2);
-            SetEDOp(0x5F, InstrLD, LocRegA, LocRegR, 2);
+            SetEDOp(0x47, InstrLD, LocRegI, LocRegA, 9); //TODO - This group should set flags
+            SetEDOp(0x57, InstrLDInterrupt, LocRegA, LocRegI, 9);
+            SetEDOp(0x4F, InstrLD, LocRegR, LocRegA, 9);
+            SetEDOp(0x5F, InstrLDInterrupt, LocRegA, LocRegR, 9);
 
-            SetEDOp(0x67, InstrRRD, LocAddrHL, LocAddrHL, 5);
+            SetEDOp(0x67, InstrRRD, LocAddrHL, LocAddrHL, 18);
 
-            SetEDOp(0x6F, InstrRLD, LocAddrHL, LocAddrHL, 5);
+            SetEDOp(0x6F, InstrRLD, LocAddrHL, LocAddrHL, 18);
 
-            SetEDOp(0xA0, InstrLDI, LocNone, LocNone, 4);
-            SetEDOp(0xB0, InstrLDIR, LocNone, LocNone, 4);
-            SetEDOp(0xA8, InstrLDD, LocNone, LocNone, 4);
-            SetEDOp(0xB8, InstrLDDR, LocNone, LocNone, 4);
+            SetEDOp(0xA0, InstrLDI, LocNone, LocNone, 16);
+            SetEDOp(0xB0, InstrLDIR, LocNone, LocNone, 16);
+            SetEDOp(0xA8, InstrLDD, LocNone, LocNone, 16);
+            SetEDOp(0xB8, InstrLDDR, LocNone, LocNone, 16);
 
-            SetEDOp(0xA1, InstrCPI, LocNone, LocNone, 4);
-            SetEDOp(0xB1, InstrCPIR, LocNone, LocNone, 4);
-            SetEDOp(0xA9, InstrCPD, LocNone, LocNone, 4);
-            SetEDOp(0xB9, InstrCPDR, LocNone, LocNone, 4);
+            SetEDOp(0xA1, InstrCPI, LocNone, LocNone, 16);
+            SetEDOp(0xB1, InstrCPIR, LocNone, LocNone, 16);
+            SetEDOp(0xA9, InstrCPD, LocNone, LocNone, 16);
+            SetEDOp(0xB9, InstrCPDR, LocNone, LocNone, 16);
 
-            SetEDOp(0xA2, InstrINI, LocNone, LocNone, 4);
-            SetEDOp(0xB2, InstrINIR, LocNone, LocNone, 4);
-            SetEDOp(0xAA, InstrIND, LocNone, LocNone, 4);
-            SetEDOp(0xBA, InstrINDR, LocNone, LocNone, 4);
+            SetEDOp(0xA2, InstrINI, LocNone, LocNone, 16);
+            SetEDOp(0xB2, InstrINIR, LocNone, LocNone, 16);
+            SetEDOp(0xAA, InstrIND, LocNone, LocNone, 16);
+            SetEDOp(0xBA, InstrINDR, LocNone, LocNone, 16);
 
-            SetEDOp(0xA3, InstrOUTI, LocNone, LocAddrHL, 4);
-            SetEDOp(0xB3, InstrOUTIR, LocNone, LocAddrHL, 4);
-            SetEDOp(0xAB, InstrOUTD, LocNone, LocAddrHL, 4);
-            SetEDOp(0xBB, InstrOUTDR, LocNone, LocAddrHL, 4);
+            SetEDOp(0xA3, InstrOUTI, LocNone, LocAddrHL, 16);
+            SetEDOp(0xB3, InstrOUTIR, LocNone, LocAddrHL, 16);
+            SetEDOp(0xAB, InstrOUTD, LocNone, LocAddrHL, 16);
+            SetEDOp(0xBB, InstrOUTDR, LocNone, LocAddrHL, 16);
 
         }
 
             SetOp(0xDD, PrefixDD, LocNone, LocNone, 0);
             SetOp(0xFD, PrefixFD, LocNone, LocNone, 0);
 
-            SetOp(0x7F, InstrLD, LocRegA, LocRegA, 1);
-            SetOp(0x78, InstrLD, LocRegA, LocRegB, 1);
-            SetOp(0x79, InstrLD, LocRegA, LocRegC, 1);
-            SetOp(0x7A, InstrLD, LocRegA, LocRegD, 1);
-            SetOp(0x7B, InstrLD, LocRegA, LocRegE, 1);
-            SetOp(0x7C, InstrLD, LocRegA, LocRegH, 1);
-            SetOp(0x7D, InstrLD, LocRegA, LocRegL, 1);
-            SetOp(0x47, InstrLD, LocRegB, LocRegA, 1);
-            SetOp(0x40, InstrLD, LocRegB, LocRegB, 1);
-            SetOp(0x41, InstrLD, LocRegB, LocRegC, 1);
-            SetOp(0x42, InstrLD, LocRegB, LocRegD, 1);
-            SetOp(0x43, InstrLD, LocRegB, LocRegE, 1);
-            SetOp(0x44, InstrLD, LocRegB, LocRegH, 1);
-            SetOp(0x45, InstrLD, LocRegB, LocRegL, 1);
-            SetOp(0x4F, InstrLD, LocRegC, LocRegA, 1);
-            SetOp(0x48, InstrLD, LocRegC, LocRegB, 1);
-            SetOp(0x49, InstrLD, LocRegC, LocRegC, 1);
-            SetOp(0x4A, InstrLD, LocRegC, LocRegD, 1);
-            SetOp(0x4B, InstrLD, LocRegC, LocRegE, 1);
-            SetOp(0x4C, InstrLD, LocRegC, LocRegH, 1);
-            SetOp(0x4D, InstrLD, LocRegC, LocRegL, 1);
-            SetOp(0x57, InstrLD, LocRegD, LocRegA, 1);
-            SetOp(0x50, InstrLD, LocRegD, LocRegB, 1);
-            SetOp(0x51, InstrLD, LocRegD, LocRegC, 1);
-            SetOp(0x52, InstrLD, LocRegD, LocRegD, 1);
-            SetOp(0x53, InstrLD, LocRegD, LocRegE, 1);
-            SetOp(0x54, InstrLD, LocRegD, LocRegH, 1);
-            SetOp(0x55, InstrLD, LocRegD, LocRegL, 1);
-            SetOp(0x5F, InstrLD, LocRegE, LocRegA, 1);
-            SetOp(0x58, InstrLD, LocRegE, LocRegB, 1);
-            SetOp(0x59, InstrLD, LocRegE, LocRegC, 1);
-            SetOp(0x5A, InstrLD, LocRegE, LocRegD, 1);
-            SetOp(0x5B, InstrLD, LocRegE, LocRegE, 1);
-            SetOp(0x5C, InstrLD, LocRegE, LocRegH, 1);
-            SetOp(0x5D, InstrLD, LocRegE, LocRegL, 1);
-            SetOp(0x67, InstrLD, LocRegH, LocRegA, 1);
-            SetOp(0x60, InstrLD, LocRegH, LocRegB, 1);
-            SetOp(0x61, InstrLD, LocRegH, LocRegC, 1);
-            SetOp(0x62, InstrLD, LocRegH, LocRegD, 1);
-            SetOp(0x63, InstrLD, LocRegH, LocRegE, 1);
-            SetOp(0x64, InstrLD, LocRegH, LocRegH, 1);
-            SetOp(0x65, InstrLD, LocRegH, LocRegL, 1);
-            SetOp(0x6F, InstrLD, LocRegL, LocRegA, 1);
-            SetOp(0x68, InstrLD, LocRegL, LocRegB, 1);
-            SetOp(0x69, InstrLD, LocRegL, LocRegC, 1);
-            SetOp(0x6A, InstrLD, LocRegL, LocRegD, 1);
-            SetOp(0x6B, InstrLD, LocRegL, LocRegE, 1);
-            SetOp(0x6C, InstrLD, LocRegL, LocRegH, 1);
-            SetOp(0x6D, InstrLD, LocRegL, LocRegL, 1);
+            SetOp(0x7F, InstrLD, LocRegA, LocRegA, 4);
+            SetOp(0x78, InstrLD, LocRegA, LocRegB, 4);
+            SetOp(0x79, InstrLD, LocRegA, LocRegC, 4);
+            SetOp(0x7A, InstrLD, LocRegA, LocRegD, 4);
+            SetOp(0x7B, InstrLD, LocRegA, LocRegE, 4);
+            SetOp(0x7C, InstrLD, LocRegA, LocRegH, 4);
+            SetOp(0x7D, InstrLD, LocRegA, LocRegL, 4);
+            SetOp(0x47, InstrLD, LocRegB, LocRegA, 4);
+            SetOp(0x40, InstrLD, LocRegB, LocRegB, 4);
+            SetOp(0x41, InstrLD, LocRegB, LocRegC, 4);
+            SetOp(0x42, InstrLD, LocRegB, LocRegD, 4);
+            SetOp(0x43, InstrLD, LocRegB, LocRegE, 4);
+            SetOp(0x44, InstrLD, LocRegB, LocRegH, 4);
+            SetOp(0x45, InstrLD, LocRegB, LocRegL, 4);
+            SetOp(0x4F, InstrLD, LocRegC, LocRegA, 4);
+            SetOp(0x48, InstrLD, LocRegC, LocRegB, 4);
+            SetOp(0x49, InstrLD, LocRegC, LocRegC, 4);
+            SetOp(0x4A, InstrLD, LocRegC, LocRegD, 4);
+            SetOp(0x4B, InstrLD, LocRegC, LocRegE, 4);
+            SetOp(0x4C, InstrLD, LocRegC, LocRegH, 4);
+            SetOp(0x4D, InstrLD, LocRegC, LocRegL, 4);
+            SetOp(0x57, InstrLD, LocRegD, LocRegA, 4);
+            SetOp(0x50, InstrLD, LocRegD, LocRegB, 4);
+            SetOp(0x51, InstrLD, LocRegD, LocRegC, 4);
+            SetOp(0x52, InstrLD, LocRegD, LocRegD, 4);
+            SetOp(0x53, InstrLD, LocRegD, LocRegE, 4);
+            SetOp(0x54, InstrLD, LocRegD, LocRegH, 4);
+            SetOp(0x55, InstrLD, LocRegD, LocRegL, 4);
+            SetOp(0x5F, InstrLD, LocRegE, LocRegA, 4);
+            SetOp(0x58, InstrLD, LocRegE, LocRegB, 4);
+            SetOp(0x59, InstrLD, LocRegE, LocRegC, 4);
+            SetOp(0x5A, InstrLD, LocRegE, LocRegD, 4);
+            SetOp(0x5B, InstrLD, LocRegE, LocRegE, 4);
+            SetOp(0x5C, InstrLD, LocRegE, LocRegH, 4);
+            SetOp(0x5D, InstrLD, LocRegE, LocRegL, 4);
+            SetOp(0x67, InstrLD, LocRegH, LocRegA, 4);
+            SetOp(0x60, InstrLD, LocRegH, LocRegB, 4);
+            SetOp(0x61, InstrLD, LocRegH, LocRegC, 4);
+            SetOp(0x62, InstrLD, LocRegH, LocRegD, 4);
+            SetOp(0x63, InstrLD, LocRegH, LocRegE, 4);
+            SetOp(0x64, InstrLD, LocRegH, LocRegH, 4);
+            SetOp(0x65, InstrLD, LocRegH, LocRegL, 4);
+            SetOp(0x6F, InstrLD, LocRegL, LocRegA, 4);
+            SetOp(0x68, InstrLD, LocRegL, LocRegB, 4);
+            SetOp(0x69, InstrLD, LocRegL, LocRegC, 4);
+            SetOp(0x6A, InstrLD, LocRegL, LocRegD, 4);
+            SetOp(0x6B, InstrLD, LocRegL, LocRegE, 4);
+            SetOp(0x6C, InstrLD, LocRegL, LocRegH, 4);
+            SetOp(0x6D, InstrLD, LocRegL, LocRegL, 4);
 
-            SetOp(0x3E, InstrLD, LocRegA, Loc8Immediate, 2);
-            SetOp(0x06, InstrLD, LocRegB, Loc8Immediate, 2);
-            SetOp(0x0E, InstrLD, LocRegC, Loc8Immediate, 2);
-            SetOp(0x16, InstrLD, LocRegD, Loc8Immediate, 2);
-            SetOp(0x1E, InstrLD, LocRegE, Loc8Immediate, 2);
-            SetOp(0x26, InstrLD, LocRegH, Loc8Immediate, 2);
-            SetOp(0x2E, InstrLD, LocRegL, Loc8Immediate, 2);
+            SetOp(0x3E, InstrLD, LocRegA, Loc8Immediate, 7);
+            SetOp(0x06, InstrLD, LocRegB, Loc8Immediate, 7);
+            SetOp(0x0E, InstrLD, LocRegC, Loc8Immediate, 7);
+            SetOp(0x16, InstrLD, LocRegD, Loc8Immediate, 7);
+            SetOp(0x1E, InstrLD, LocRegE, Loc8Immediate, 7);
+            SetOp(0x26, InstrLD, LocRegH, Loc8Immediate, 7);
+            SetOp(0x2E, InstrLD, LocRegL, Loc8Immediate, 7);
 
-            SetOp(0x7E, InstrLD, LocRegA, LocAddrHL, 2);
-            SetOp(0x46, InstrLD, LocRegB, LocAddrHL, 2);
-            SetOp(0x4E, InstrLD, LocRegC, LocAddrHL, 2);
-            SetOp(0x56, InstrLD, LocRegD, LocAddrHL, 2);
-            SetOp(0x5E, InstrLD, LocRegE, LocAddrHL, 2);
-            SetOp(0x66, InstrLD, LocRegH, LocAddrHL, 2);
-            SetOp(0x6E, InstrLD, LocRegL, LocAddrHL, 2);
+            SetOp(0x7E, InstrLD, LocRegA, LocAddrHL, 7);
+            SetOp(0x46, InstrLD, LocRegB, LocAddrHL, 7);
+            SetOp(0x4E, InstrLD, LocRegC, LocAddrHL, 7);
+            SetOp(0x56, InstrLD, LocRegD, LocAddrHL, 7);
+            SetOp(0x5E, InstrLD, LocRegE, LocAddrHL, 7);
+            SetOp(0x66, InstrLD, LocRegH, LocAddrHL, 7);
+            SetOp(0x6E, InstrLD, LocRegL, LocAddrHL, 7);
 
-            SetOp(0x77, InstrLD, LocAddrHL, LocRegA, 2);
-            SetOp(0x70, InstrLD, LocAddrHL, LocRegB, 2);
-            SetOp(0x71, InstrLD, LocAddrHL, LocRegC, 2);
-            SetOp(0x72, InstrLD, LocAddrHL, LocRegD, 2);
-            SetOp(0x73, InstrLD, LocAddrHL, LocRegE, 2);
-            SetOp(0x74, InstrLD, LocAddrHL, LocRegH, 2);
-            SetOp(0x75, InstrLD, LocAddrHL, LocRegL, 2);
+            SetOp(0x77, InstrLD, LocAddrHL, LocRegA, 7);
+            SetOp(0x70, InstrLD, LocAddrHL, LocRegB, 7);
+            SetOp(0x71, InstrLD, LocAddrHL, LocRegC, 7);
+            SetOp(0x72, InstrLD, LocAddrHL, LocRegD, 7);
+            SetOp(0x73, InstrLD, LocAddrHL, LocRegE, 7);
+            SetOp(0x74, InstrLD, LocAddrHL, LocRegH, 7);
+            SetOp(0x75, InstrLD, LocAddrHL, LocRegL, 7);
 
-            SetOp(0x36, InstrLD, LocAddrHL, Loc8Immediate, 3);
+            SetOp(0x36, InstrLD, LocAddrHL, Loc8Immediate, 10);
 
-            SetOp(0x0A, InstrLD, LocRegA, LocAddrBC, 2);
-            SetOp(0x1A, InstrLD, LocRegA, LocAddrDE, 2);
+            SetOp(0x0A, InstrLD, LocRegA, LocAddrBC, 7);
+            SetOp(0x1A, InstrLD, LocRegA, LocAddrDE, 7);
 
-            SetOp(0x3A, InstrLD, LocRegA, LocAddrAbsoulute, 4);
+            SetOp(0x3A, InstrLD, LocRegA, LocAddrAbsoulute, 13);
 
-            SetOp(0x02, InstrLD, LocAddrBC, LocRegA, 2);
-            SetOp(0x12, InstrLD, LocAddrDE, LocRegA, 2);
+            SetOp(0x02, InstrLD, LocAddrBC, LocRegA, 7);
+            SetOp(0x12, InstrLD, LocAddrDE, LocRegA, 7);
 
-            SetOp(0x32, InstrLD, LocAddrAbsoulute, LocRegA, 4);
+            SetOp(0x32, InstrLD, LocAddrAbsoulute, LocRegA, 13);
 
-            SetOp(0x01, InstrLD, LocRegBC, Loc16Immediate, 2);
-            SetOp(0x11, InstrLD, LocRegDE, Loc16Immediate, 2);
-            SetOp(0x21, InstrLD, LocRegHL, Loc16Immediate, 2);
-            SetOp(0x31, InstrLD, LocRegSP, Loc16Immediate, 2);
+            SetOp(0x01, InstrLD, LocRegBC, Loc16Immediate, 10);
+            SetOp(0x11, InstrLD, LocRegDE, Loc16Immediate, 10);
+            SetOp(0x21, InstrLD, LocRegHL, Loc16Immediate, 10);
+            SetOp(0x31, InstrLD, LocRegSP, Loc16Immediate, 10);
 
-            SetOp(0x2A, InstrLD, LocRegHL, Loc16AddrAbsoulute, 5);
+            SetOp(0x2A, InstrLD, LocRegHL, Loc16AddrAbsoulute, 16);
 
-            SetOp(0x22, InstrLD, Loc16AddrAbsoulute, LocRegHL, 5);
+            SetOp(0x22, InstrLD, Loc16AddrAbsoulute, LocRegHL, 16);
 
-            SetOp(0xF9, InstrLD, LocRegSP, LocRegHL, 1);
+            SetOp(0xF9, InstrLD, LocRegSP, LocRegHL, 6);
 
-            SetOp(0xC5, InstrLD, Loc16Stack, LocRegBC, 3);
-            SetOp(0xD5, InstrLD, Loc16Stack, LocRegDE, 3);
-            SetOp(0xE5, InstrLD, Loc16Stack, LocRegHL, 3);
-            SetOp(0xF5, InstrLD, Loc16Stack, LocRegAF, 3);
+            SetOp(0xC5, InstrLD, Loc16Stack, LocRegBC, 11);
+            SetOp(0xD5, InstrLD, Loc16Stack, LocRegDE, 11);
+            SetOp(0xE5, InstrLD, Loc16Stack, LocRegHL, 11);
+            SetOp(0xF5, InstrLD, Loc16Stack, LocRegAF, 11);
 
-            SetOp(0xC1, InstrLD, LocRegBC, Loc16Stack, 3);
-            SetOp(0xD1, InstrLD, LocRegDE, Loc16Stack, 3);
-            SetOp(0xE1, InstrLD, LocRegHL, Loc16Stack, 3);
-            SetOp(0xF1, InstrLD, LocRegAF, Loc16Stack, 3);
+            SetOp(0xC1, InstrLD, LocRegBC, Loc16Stack, 11);
+            SetOp(0xD1, InstrLD, LocRegDE, Loc16Stack, 11);
+            SetOp(0xE1, InstrLD, LocRegHL, Loc16Stack, 11);
+            SetOp(0xF1, InstrLD, LocRegAF, Loc16Stack, 11);
 
 
-            SetOp(0xEB, InstrEXDEHL, LocNone, LocNone, 1);
-            SetOp(0x08, InstrEXAFAF, LocNone, LocNone, 1);
-            SetOp(0xD9, InstrEXX, LocNone, LocNone, 1);
+            SetOp(0xEB, InstrEXDEHL, LocNone, LocNone, 4);
+            SetOp(0x08, InstrEXAFAF, LocNone, LocNone, 4);
+            SetOp(0xD9, InstrEXX, LocNone, LocNone, 4);
 
-            SetOp(0xE3, InstrEXSP, LocRegHL, LocRegHL, 5);
+            SetOp(0xE3, InstrEXSP, LocRegHL, LocRegHL, 19);
 
-            SetOp(0x87, Instr8ADD, LocRegA, LocRegA, 1);
-            SetOp(0x80, Instr8ADD, LocRegA, LocRegB, 1);
-            SetOp(0x81, Instr8ADD, LocRegA, LocRegC, 1);
-            SetOp(0x82, Instr8ADD, LocRegA, LocRegD, 1);
-            SetOp(0x83, Instr8ADD, LocRegA, LocRegE, 1);
-            SetOp(0x84, Instr8ADD, LocRegA, LocRegH, 1);
-            SetOp(0x85, Instr8ADD, LocRegA, LocRegL, 1);
+            SetOp(0x87, Instr8ADD, LocRegA, LocRegA, 4);
+            SetOp(0x80, Instr8ADD, LocRegA, LocRegB, 4);
+            SetOp(0x81, Instr8ADD, LocRegA, LocRegC, 4);
+            SetOp(0x82, Instr8ADD, LocRegA, LocRegD, 4);
+            SetOp(0x83, Instr8ADD, LocRegA, LocRegE, 4);
+            SetOp(0x84, Instr8ADD, LocRegA, LocRegH, 4);
+            SetOp(0x85, Instr8ADD, LocRegA, LocRegL, 4);
 
-            SetOp(0xC6, Instr8ADD, LocRegA, Loc8Immediate, 2);
+            SetOp(0xC6, Instr8ADD, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0x86, Instr8ADD, LocRegA, LocAddrHL, 2);
+            SetOp(0x86, Instr8ADD, LocRegA, LocAddrHL, 7);
 
-            SetOp(0x8F, Instr8ADC, LocRegA, LocRegA, 1);
-            SetOp(0x88, Instr8ADC, LocRegA, LocRegB, 1);
-            SetOp(0x89, Instr8ADC, LocRegA, LocRegC, 1);
-            SetOp(0x8A, Instr8ADC, LocRegA, LocRegD, 1);
-            SetOp(0x8B, Instr8ADC, LocRegA, LocRegE, 1);
-            SetOp(0x8C, Instr8ADC, LocRegA, LocRegH, 1);
-            SetOp(0x8D, Instr8ADC, LocRegA, LocRegL, 1);
+            SetOp(0x8F, Instr8ADC, LocRegA, LocRegA, 4);
+            SetOp(0x88, Instr8ADC, LocRegA, LocRegB, 4);
+            SetOp(0x89, Instr8ADC, LocRegA, LocRegC, 4);
+            SetOp(0x8A, Instr8ADC, LocRegA, LocRegD, 4);
+            SetOp(0x8B, Instr8ADC, LocRegA, LocRegE, 4);
+            SetOp(0x8C, Instr8ADC, LocRegA, LocRegH, 4);
+            SetOp(0x8D, Instr8ADC, LocRegA, LocRegL, 4);
 
-            SetOp(0xCE, Instr8ADC, LocRegA, Loc8Immediate, 2);
+            SetOp(0xCE, Instr8ADC, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0x8E, Instr8ADC, LocRegA, LocAddrHL, 2);
+            SetOp(0x8E, Instr8ADC, LocRegA, LocAddrHL, 7);
 
-            SetOp(0x97, Instr8SUB, LocRegA, LocRegA, 1);
-            SetOp(0x90, Instr8SUB, LocRegA, LocRegB, 1);
-            SetOp(0x91, Instr8SUB, LocRegA, LocRegC, 1);
-            SetOp(0x92, Instr8SUB, LocRegA, LocRegD, 1);
-            SetOp(0x93, Instr8SUB, LocRegA, LocRegE, 1);
-            SetOp(0x94, Instr8SUB, LocRegA, LocRegH, 1);
-            SetOp(0x95, Instr8SUB, LocRegA, LocRegL, 1);
+            SetOp(0x97, Instr8SUB, LocRegA, LocRegA, 4);
+            SetOp(0x90, Instr8SUB, LocRegA, LocRegB, 4);
+            SetOp(0x91, Instr8SUB, LocRegA, LocRegC, 4);
+            SetOp(0x92, Instr8SUB, LocRegA, LocRegD, 4);
+            SetOp(0x93, Instr8SUB, LocRegA, LocRegE, 4);
+            SetOp(0x94, Instr8SUB, LocRegA, LocRegH, 4);
+            SetOp(0x95, Instr8SUB, LocRegA, LocRegL, 4);
 
-            SetOp(0xD6, Instr8SUB, LocRegA, Loc8Immediate, 2);
+            SetOp(0xD6, Instr8SUB, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0x96, Instr8SUB, LocRegA, LocAddrHL, 2);
+            SetOp(0x96, Instr8SUB, LocRegA, LocAddrHL, 7);
 
-            SetOp(0x9F, Instr8SBC, LocRegA, LocRegA, 1);
-            SetOp(0x98, Instr8SBC, LocRegA, LocRegB, 1);
-            SetOp(0x99, Instr8SBC, LocRegA, LocRegC, 1);
-            SetOp(0x9A, Instr8SBC, LocRegA, LocRegD, 1);
-            SetOp(0x9B, Instr8SBC, LocRegA, LocRegE, 1);
-            SetOp(0x9C, Instr8SBC, LocRegA, LocRegH, 1);
-            SetOp(0x9D, Instr8SBC, LocRegA, LocRegL, 1);
+            SetOp(0x9F, Instr8SBC, LocRegA, LocRegA, 4);
+            SetOp(0x98, Instr8SBC, LocRegA, LocRegB, 4);
+            SetOp(0x99, Instr8SBC, LocRegA, LocRegC, 4);
+            SetOp(0x9A, Instr8SBC, LocRegA, LocRegD, 4);
+            SetOp(0x9B, Instr8SBC, LocRegA, LocRegE, 4);
+            SetOp(0x9C, Instr8SBC, LocRegA, LocRegH, 4);
+            SetOp(0x9D, Instr8SBC, LocRegA, LocRegL, 4);
 
-            SetOp(0xDE, Instr8SBC, LocRegA, Loc8Immediate, 2);
+            SetOp(0xDE, Instr8SBC, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0x9E, Instr8SBC, LocRegA, LocAddrHL, 2);
+            SetOp(0x9E, Instr8SBC, LocRegA, LocAddrHL, 7);
 
-            SetOp(0xA7, InstrAND, LocRegA, LocRegA, 1);
-            SetOp(0xA0, InstrAND, LocRegA, LocRegB, 1);
-            SetOp(0xA1, InstrAND, LocRegA, LocRegC, 1);
-            SetOp(0xA2, InstrAND, LocRegA, LocRegD, 1);
-            SetOp(0xA3, InstrAND, LocRegA, LocRegE, 1);
-            SetOp(0xA4, InstrAND, LocRegA, LocRegH, 1);
-            SetOp(0xA5, InstrAND, LocRegA, LocRegL, 1);
+            SetOp(0xA7, InstrAND, LocRegA, LocRegA, 4);
+            SetOp(0xA0, InstrAND, LocRegA, LocRegB, 4);
+            SetOp(0xA1, InstrAND, LocRegA, LocRegC, 4);
+            SetOp(0xA2, InstrAND, LocRegA, LocRegD, 4);
+            SetOp(0xA3, InstrAND, LocRegA, LocRegE, 4);
+            SetOp(0xA4, InstrAND, LocRegA, LocRegH, 4);
+            SetOp(0xA5, InstrAND, LocRegA, LocRegL, 4);
 
-            SetOp(0xE6, InstrAND, LocRegA, Loc8Immediate, 2);
+            SetOp(0xE6, InstrAND, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0xA6, InstrAND, LocRegA, LocAddrHL, 2);
+            SetOp(0xA6, InstrAND, LocRegA, LocAddrHL, 7);
 
-            SetOp(0xB7, InstrOR, LocRegA, LocRegA, 1);
-            SetOp(0xB0, InstrOR, LocRegA, LocRegB, 1);
-            SetOp(0xB1, InstrOR, LocRegA, LocRegC, 1);
-            SetOp(0xB2, InstrOR, LocRegA, LocRegD, 1);
-            SetOp(0xB3, InstrOR, LocRegA, LocRegE, 1);
-            SetOp(0xB4, InstrOR, LocRegA, LocRegH, 1);
-            SetOp(0xB5, InstrOR, LocRegA, LocRegL, 1);
+            SetOp(0xB7, InstrOR, LocRegA, LocRegA, 4);
+            SetOp(0xB0, InstrOR, LocRegA, LocRegB, 4);
+            SetOp(0xB1, InstrOR, LocRegA, LocRegC, 4);
+            SetOp(0xB2, InstrOR, LocRegA, LocRegD, 4);
+            SetOp(0xB3, InstrOR, LocRegA, LocRegE, 4);
+            SetOp(0xB4, InstrOR, LocRegA, LocRegH, 4);
+            SetOp(0xB5, InstrOR, LocRegA, LocRegL, 4);
 
-            SetOp(0xF6, InstrOR, LocRegA, Loc8Immediate, 2);
+            SetOp(0xF6, InstrOR, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0xB6, InstrOR, LocRegA, LocAddrHL, 2);
+            SetOp(0xB6, InstrOR, LocRegA, LocAddrHL, 7);
 
-            SetOp(0xAF, InstrXOR, LocRegA, LocRegA, 1);
-            SetOp(0xA8, InstrXOR, LocRegA, LocRegB, 1);
-            SetOp(0xA9, InstrXOR, LocRegA, LocRegC, 1);
-            SetOp(0xAA, InstrXOR, LocRegA, LocRegD, 1);
-            SetOp(0xAB, InstrXOR, LocRegA, LocRegE, 1);
-            SetOp(0xAC, InstrXOR, LocRegA, LocRegH, 1);
-            SetOp(0xAD, InstrXOR, LocRegA, LocRegL, 1);
+            SetOp(0xAF, InstrXOR, LocRegA, LocRegA, 4);
+            SetOp(0xA8, InstrXOR, LocRegA, LocRegB, 4);
+            SetOp(0xA9, InstrXOR, LocRegA, LocRegC, 4);
+            SetOp(0xAA, InstrXOR, LocRegA, LocRegD, 4);
+            SetOp(0xAB, InstrXOR, LocRegA, LocRegE, 4);
+            SetOp(0xAC, InstrXOR, LocRegA, LocRegH, 4);
+            SetOp(0xAD, InstrXOR, LocRegA, LocRegL, 4);
 
-            SetOp(0xEE, InstrXOR, LocRegA, Loc8Immediate, 2);
+            SetOp(0xEE, InstrXOR, LocRegA, Loc8Immediate, 7);
 
-            SetOp(0xAE, InstrXOR, LocRegA, LocAddrHL, 2);
+            SetOp(0xAE, InstrXOR, LocRegA, LocAddrHL, 7);
 
-            SetOp(0xBF, InstrCP, LocRegA, LocRegA, 1);
-            SetOp(0xB8, InstrCP, LocRegA, LocRegB, 1);
-            SetOp(0xB9, InstrCP, LocRegA, LocRegC, 1);
-            SetOp(0xBA, InstrCP, LocRegA, LocRegD, 1);
-            SetOp(0xBB, InstrCP, LocRegA, LocRegE, 1);
-            SetOp(0xBC, InstrCP, LocRegA, LocRegH, 1);
-            SetOp(0xBD, InstrCP, LocRegA, LocRegL, 1);
+            SetOp(0xBF, InstrCP, LocNone, LocRegA, 4);
+            SetOp(0xB8, InstrCP, LocNone, LocRegB, 4);
+            SetOp(0xB9, InstrCP, LocNone, LocRegC, 4);
+            SetOp(0xBA, InstrCP, LocNone, LocRegD, 4);
+            SetOp(0xBB, InstrCP, LocNone, LocRegE, 4);
+            SetOp(0xBC, InstrCP, LocNone, LocRegH, 4);
+            SetOp(0xBD, InstrCP, LocNone, LocRegL, 4);
 
-            SetOp(0xFE, InstrCP, LocRegA, Loc8Immediate, 2);
+            SetOp(0xFE, InstrCP, LocNone, Loc8Immediate, 7);
 
-            SetOp(0xBE, InstrCP, LocRegA, LocAddrHL, 2);
+            SetOp(0xBE, InstrCP, LocNone, LocAddrHL, 7);
 
-            SetOp(0x3C, Instr8INC, LocRegA, LocRegA, 1);
-            SetOp(0x04, Instr8INC, LocRegB, LocRegB, 1);
-            SetOp(0x0C, Instr8INC, LocRegC, LocRegC, 1);
-            SetOp(0x14, Instr8INC, LocRegD, LocRegD, 1);
-            SetOp(0x1C, Instr8INC, LocRegE, LocRegE, 1);
-            SetOp(0x24, Instr8INC, LocRegH, LocRegH, 1);
-            SetOp(0x2C, Instr8INC, LocRegL, LocRegL, 1);
+            SetOp(0x3C, Instr8INC, LocRegA, LocRegA, 4);
+            SetOp(0x04, Instr8INC, LocRegB, LocRegB, 4);
+            SetOp(0x0C, Instr8INC, LocRegC, LocRegC, 4);
+            SetOp(0x14, Instr8INC, LocRegD, LocRegD, 4);
+            SetOp(0x1C, Instr8INC, LocRegE, LocRegE, 4);
+            SetOp(0x24, Instr8INC, LocRegH, LocRegH, 4);
+            SetOp(0x2C, Instr8INC, LocRegL, LocRegL, 4);
 
-            SetOp(0x34, Instr8INC, LocAddrHL, LocAddrHL, 3);
+            SetOp(0x34, Instr8INC, LocAddrHL, LocAddrHL, 11);
 
-            SetOp(0x3D, Instr8DEC, LocRegA, LocRegA, 1);
-            SetOp(0x05, Instr8DEC, LocRegB, LocRegB, 1);
-            SetOp(0x0D, Instr8DEC, LocRegC, LocRegC, 1);
-            SetOp(0x15, Instr8DEC, LocRegD, LocRegD, 1);
-            SetOp(0x1D, Instr8DEC, LocRegE, LocRegE, 1);
-            SetOp(0x25, Instr8DEC, LocRegH, LocRegH, 1);
-            SetOp(0x2D, Instr8DEC, LocRegL, LocRegL, 1);
+            SetOp(0x3D, Instr8DEC, LocRegA, LocRegA, 4);
+            SetOp(0x05, Instr8DEC, LocRegB, LocRegB, 4);
+            SetOp(0x0D, Instr8DEC, LocRegC, LocRegC, 4);
+            SetOp(0x15, Instr8DEC, LocRegD, LocRegD, 4);
+            SetOp(0x1D, Instr8DEC, LocRegE, LocRegE, 4);
+            SetOp(0x25, Instr8DEC, LocRegH, LocRegH, 4);
+            SetOp(0x2D, Instr8DEC, LocRegL, LocRegL, 4);
 
-            SetOp(0x35, Instr8DEC, LocAddrHL, LocAddrHL, 3);
+            SetOp(0x35, Instr8DEC, LocAddrHL, LocAddrHL, 11);
 
-            SetOp(0x27, InstrDAA, LocRegA, LocNone, 1);
+            SetOp(0x27, InstrDAA, LocRegA, LocNone, 4);
 
-            SetOp(0x2F, InstrCPL, LocRegA, LocNone, 1);
+            SetOp(0x2F, InstrCPL, LocRegA, LocNone, 4);
 
-            SetOp(0x3F, InstrCCF, LocNone, LocNone, 1);
+            SetOp(0x3F, InstrCCF, LocNone, LocNone, 4);
 
-            SetOp(0x37, InstrSCF, LocNone, LocNone, 1);
+            SetOp(0x37, InstrSCF, LocNone, LocNone, 4);
 
-            SetOp(0x00, InstrNOP, LocNone, LocNone, 1);
+            SetOp(0x00, InstrNOP, LocNone, LocNone, 4);
 
-            SetOp(0x76, InstrHALT, LocNone, LocNone, 1);
+            SetOp(0x76, InstrHALT, LocNone, LocNone, 4);
 
-            SetOp(0xF3, InstrDI, LocNone, LocNone, 1);
+            SetOp(0xF3, InstrDI, LocNone, LocNone, 4);
 
-            SetOp(0xFB, InstrEI, LocNone, LocNone, 1);
+            SetOp(0xFB, InstrEI, LocNone, LocNone, 4);
 
-            SetOp(0x09, InstrADD, LocRegHL, LocRegBC, 3);
-            SetOp(0x19, InstrADD, LocRegHL, LocRegDE, 3);
-            SetOp(0x29, InstrADD, LocRegHL, LocRegHL, 3);
-            SetOp(0x39, InstrADD, LocRegHL, LocRegSP, 3);
+            SetOp(0x09, InstrADD, LocRegHL, LocRegBC, 11);
+            SetOp(0x19, InstrADD, LocRegHL, LocRegDE, 11);
+            SetOp(0x29, InstrADD, LocRegHL, LocRegHL, 11);
+            SetOp(0x39, InstrADD, LocRegHL, LocRegSP, 11);
 
-            SetOp(0x03, InstrINC, LocRegBC, LocRegBC, 1);
-            SetOp(0x13, InstrINC, LocRegDE, LocRegDE, 1);
-            SetOp(0x23, InstrINC, LocRegHL, LocRegHL, 1);
-            SetOp(0x33, InstrINC, LocRegSP, LocRegSP, 1);
+            SetOp(0x03, InstrINC, LocRegBC, LocRegBC, 6);
+            SetOp(0x13, InstrINC, LocRegDE, LocRegDE, 6);
+            SetOp(0x23, InstrINC, LocRegHL, LocRegHL, 6);
+            SetOp(0x33, InstrINC, LocRegSP, LocRegSP, 6);
 
-            SetOp(0x0B, InstrDEC, LocRegBC, LocRegBC, 1);
-            SetOp(0x1B, InstrDEC, LocRegDE, LocRegDE, 1);
-            SetOp(0x2B, InstrDEC, LocRegHL, LocRegHL, 1);
-            SetOp(0x3B, InstrDEC, LocRegSP, LocRegSP, 1);
+            SetOp(0x0B, InstrDEC, LocRegBC, LocRegBC, 6);
+            SetOp(0x1B, InstrDEC, LocRegDE, LocRegDE, 6);
+            SetOp(0x2B, InstrDEC, LocRegHL, LocRegHL, 6);
+            SetOp(0x3B, InstrDEC, LocRegSP, LocRegSP, 6);
 
-            SetOp(0x07, InstrRLCA, LocRegA, LocNone, 1);
+            SetOp(0x07, InstrRLCA, LocRegA, LocNone, 4);
 
-            SetOp(0x17, InstrRLA, LocRegA, LocNone, 1);
+            SetOp(0x17, InstrRLA, LocRegA, LocNone, 4);
 
-            SetOp(0x0F, InstrRRCA, LocRegA, LocNone, 1);
+            SetOp(0x0F, InstrRRCA, LocRegA, LocNone, 4);
 
-            SetOp(0x1F, InstrRRA, LocRegA, LocNone, 1);
+            SetOp(0x1F, InstrRRA, LocRegA, LocNone, 4);
 
-            SetOp(0xC3, InstrJP, LocNone, Loc16Immediate, 3);
+            SetOp(0xC3, InstrJP, LocNone, Loc16Immediate, 10);
 
-            SetOp(0xC2, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xD2, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xE2, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xF2, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xCA, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xDA, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xEA, InstrJPc, LocNone, Loc16Immediate, 3);
-            SetOp(0xFA, InstrJPc, LocNone, Loc16Immediate, 3);
+            SetOp(0xC2, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xD2, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xE2, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xF2, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xCA, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xDA, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xEA, InstrJPc, LocNone, Loc16Immediate, 10);
+            SetOp(0xFA, InstrJPc, LocNone, Loc16Immediate, 10);
 
-            SetOp(0x18, InstrJR, LocNone, Loc8Immediate, 3);
+            SetOp(0x18, InstrJR, LocNone, Loc8Immediate, 12);
 
-            SetOp(0x38, InstrJRC, LocNone, Loc8Immediate, 2);
+            SetOp(0x38, InstrJRC, LocNone, Loc8Immediate, 7);
 
-            SetOp(0x30, InstrJRNC, LocNone, Loc8Immediate, 2);
+            SetOp(0x30, InstrJRNC, LocNone, Loc8Immediate, 7);
 
-            SetOp(0x28, InstrJRZ, LocNone, Loc8Immediate, 2);
+            SetOp(0x28, InstrJRZ, LocNone, Loc8Immediate, 7);
 
-            SetOp(0x20, InstrJRNZ, LocNone, Loc8Immediate, 2);
+            SetOp(0x20, InstrJRNZ, LocNone, Loc8Immediate, 7);
 
-            SetOp(0xE9, InstrJP, LocNone, LocAddrHL, 1);
+            SetOp(0xE9, InstrJP, LocNone, LocRegHL, 4);
 
-            SetOp(0x10, InstrDJNZ, LocNone, Loc8Immediate, 2);
+            SetOp(0x10, InstrDJNZ, LocNone, Loc8Immediate, 8);
 
-            SetOp(0xCD, InstrCALL, LocNone, Loc16Immediate, 5);
+            SetOp(0xCD, InstrCALL, LocNone, Loc16Immediate, 17);
 
-            SetOp(0xC4, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xD4, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xE4, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xF4, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xCC, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xDC, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xEC, InstrCALLc, LocNone, Loc16Immediate, 3);
-            SetOp(0xFC, InstrCALLc, LocNone, Loc16Immediate, 3);
+            SetOp(0xC4, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xD4, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xE4, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xF4, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xCC, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xDC, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xEC, InstrCALLc, LocNone, Loc16Immediate, 10);
+            SetOp(0xFC, InstrCALLc, LocNone, Loc16Immediate, 10);
 
-            SetOp(0xC9, InstrRET, LocNone, LocNone, 3);
+            SetOp(0xC9, InstrRET, LocNone, LocNone, 10);
 
-            SetOp(0xC0, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xD0, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xE0, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xF0, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xC8, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xD8, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xE8, InstrRET, LocNone, LocNone, 1);
-            SetOp(0xF8, InstrRET, LocNone, LocNone, 1);
+            SetOp(0xC0, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xD0, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xE0, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xF0, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xC8, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xD8, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xE8, InstrRETc, LocNone, LocNone, 5);
+            SetOp(0xF8, InstrRETc, LocNone, LocNone, 5);
 
-            SetOp(0xC7, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xD7, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xE7, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xF7, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xCF, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xDF, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xEF, InstrRST, LocNone, LocNone, 3);
-            SetOp(0xFF, InstrRST, LocNone, LocNone, 3);
+            SetOp(0xC7, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xD7, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xE7, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xF7, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xCF, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xDF, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xEF, InstrRST, LocNone, LocNone, 11);
+            SetOp(0xFF, InstrRST, LocNone, LocNone, 11);
 
-            SetOp(0xDB, InstrINA, LocNone, Loc8Immediate, 3);
+            SetOp(0xDB, InstrINA, LocNone, Loc8Immediate, 11);
 
-            SetOp(0xD3, InstrOUTA, LocNone , Loc8Immediate, 3);
+            SetOp(0xD3, InstrOUTA, LocNone , Loc8Immediate, 11);
 
         }
 

coleco-o-tron/PPU.cs

 
         byte[] memory = new byte[0x4000];
         byte[] registers = new byte[8];
-        uint[] screen = new uint[(256 + 15 + 13) * (192 + 24 + 27)];
+        public uint[] screen = new uint[(256 + 15 + 13) * (192 + 24 + 27)];
 
 
         uint[] colorChart = new uint[16];
         private byte writeData;
         private ushort writeAddress;
         private ushort readAddress;
+        public bool frameComplete;
+        private bool fifthSpriteFlag;
+        private byte fifthSpriteNumber;
+        private bool coincidenceFlag;
 
         public PPU()
         {
-            colorChart[0] = (uint)Color.Black.ToArgb();
-            colorChart[1] = (uint)Color.Black.ToArgb();
-            colorChart[2] = (uint)Color.Green.ToArgb();
-            colorChart[3] = (uint)Color.LightGreen.ToArgb();
-            colorChart[4] = (uint)Color.DarkBlue.ToArgb();
-            colorChart[5] = (uint)Color.LightBlue.ToArgb();
-            colorChart[6] = (uint)Color.DarkRed.ToArgb();
-            colorChart[7] = (uint)Color.Cyan.ToArgb();
-            colorChart[8] = (uint)Color.Red.ToArgb();
-            colorChart[9] = (uint)Color.LightCoral.ToArgb();
-            colorChart[10] = (uint)Color.DarkGoldenrod.ToArgb();
-            colorChart[11] = (uint)Color.LightYellow.ToArgb();
-            colorChart[12] = (uint)Color.DarkGreen.ToArgb();
-            colorChart[13] = (uint)Color.Magenta.ToArgb();
-            colorChart[14] = (uint)Color.Gray.ToArgb();
-            colorChart[15] = (uint)Color.White.ToArgb();
+            colorChart[0] = 0xFF000000;
+            colorChart[1] = 0xFF000000;
+            colorChart[2] = 0xFF3FB849;
+            colorChart[3] = 0xFF75D07D;
+            colorChart[4] = 0xFF5A55E0;
+            colorChart[5] = 0xFF8076F1;
+            colorChart[6] = 0xFFB95E52;
+            colorChart[7] = 0xFF65DBEF;
+            colorChart[8] = 0xFFDB6559;
+            colorChart[9] = 0xFFFF897D;
+            colorChart[10] = 0xFFCCC35E;
+            colorChart[11] = 0xFFDED087;
+            colorChart[12] = 0xFF3BA242;
+            colorChart[13] = 0xFFB666B5;
+            colorChart[14] = 0xFFCCCCCC;
+            colorChart[15] = 0xFFFFFFFF;
         }
 
         private bool ev
         {
             get
             {
-                return 0x1400;
                 return (registers[2] & 0xF) * 0x400; }
         }
 
         {
             get
             {
-                return 0x1800;
                 return registers[3] * 0x40; }
         }
 
         {
             get
             {
-                return 0x1800;
                 return (registers[4] & 0x7) * 0x800; }
         }
 
         {
             get
             {
-                return 13; return registers[7] & 0xF; }
+                return registers[7] & 0xF; }
         }
 
         private int text1Color
         {
-            get { return registers[7] >> 4; }
+            get
+            {
+                return registers[7] >> 4; }
         }
 
         public byte Read(int address)
             byte data = 0;
             if (inVblank)
                 data |= 0x80;
+            if (coincidenceFlag)
+                data |= 0x40;
+            if (fifthSpriteFlag)
+            {
+                data |= 0x20;
+                data |= fifthSpriteNumber;
+            }
+            else
+            {
+                data |= 0x1f;
+            }
             nmi = false;
             inVblank = false;
             writeLatch = false;
-            return (byte)(data | 0x1f);
+            coincidenceFlag = false;
+            fifthSpriteFlag = false;
+            return data;
         }
 
         public void Write(byte value, int address)
         {
             if((address & 1) == 0)
             {
-                memory[writeAddress++] = value;
+                memory[writeAddress++ & 0x3FFF] = value;
                 return;
             }
             if(!writeLatch)
             writeLatch = !writeLatch;
         }
 
-        private int frame = 0;
-        public unsafe void Clock(int cycles)
+
+        private unsafe void DumpScreen(string fileName)
+        {
+            File.WriteAllBytes(fileName + ".bin", memory);
+            Bitmap imscreen = new Bitmap(284, 243, PixelFormat.Format32bppRgb);
+            var bmd = imscreen.LockBits(new Rectangle(0, 0, 284, 243), ImageLockMode.WriteOnly,
+                            PixelFormat.Format32bppRgb);
+            var ptr = (uint*)bmd.Scan0;
+            for (int i = 0; i < 284 * 243; i++)
+                ptr[i] = screen[i];
+            imscreen.UnlockBits(bmd);
+
+            imscreen.Save(fileName + ".png");
+            
+        }
+
+        public int frame = 0;
+        public void Clock(int cycles)
         {
             counter += cycles;
             if(counter > 342)
                 }
                 else if(scanline < 219)//MainScreen
                 {
+                    int borderLeft = 13;
+                    int borderRight = 15;
                     int screenScanline = scanline - 27;
                     switch(mode)
                     {
+                        case Mode.Text:
+                            {
+                                borderLeft = 19;
+                                borderRight = 25;
+
+                                int row = screenScanline >> 3;
+                                for (int tile = 0; tile < 40; tile++)
+                                {
+                                    int tileNumber = memory[baseNameTable | ((40*row) + tile)];
+                                    int tileRowAddress = basePatternGen | (tileNumber << 3) | (screenScanline & 7);
+                                    int tileRow = memory[tileRowAddress];
+
+                                    uint color;
+                                    for (int pixel = 0; pixel < 6; pixel++)
+                                    {
+                                        if ((tileRow & 0x80) != 0)
+                                            color = colorChart[text1Color];
+                                        else
+                                            color = colorChart[text0Color];
+                                        screen[(scanline * 284) + (tile * 6) + pixel + borderLeft] = color;
+                                        tileRow <<= 1;
+                                    }
+
+                                }
+                            }
+                            break;
                         case Mode.Graphics1:
-                            for (int pixel = 0; pixel < 13; pixel++)
-                                screen[(scanline * 284) + pixel] = colorChart[text0Color];
+                            {
+                                borderLeft = 13;
+                                borderRight = 15;
 
-                            int row = screenScanline / 8;
-                            int nameTable = baseNameTable | (row << 5);
-                            for (int tile = 0; tile < 32; tile++)
+                                int row = screenScanline >> 3;
+                                int nameTable = baseNameTable | (row << 5);
+                                for (int tile = 0; tile < 32; tile++)
+                                {
+                                    int tileAddress = nameTable | tile;
+                                    int tileNumber = memory[tileAddress];
+                                    int tileRowAddress = basePatternGen | (tileNumber << 3) | (screenScanline & 7);
+                                    int tileRow = memory[tileRowAddress];
+                                    int colorAddress = baseColorTable | tileNumber >> 3;
+                                    int tileColors = memory[colorAddress];
+
+                                    uint color;
+                                    for (int pixel = 0; pixel < 8; pixel++)
+                                    {
+                                        if ((tileRow & 0x80) != 0)
+                                            color = colorChart[tileColors >> 4];
+                                        else
+                                            color = colorChart[tileColors & 0xF];
+                                        screen[(scanline*284) + (tile*8) + pixel + borderLeft] = color;
+                                        tileRow <<= 1;
+                                    }
+
+                                }
+                            }
+                            break;
+                            case Mode.Graphics2:
                             {
-                                int tileAddress = nameTable | tile;
-                                int tileNumber = memory[tileAddress];
-                                int tileRowAddress = basePatternGen | (tileNumber << 3) | (screenScanline % 8);
-                                int tileRow = memory[tileRowAddress];
-                                int colorAddress = baseColorTable | tileNumber >> 3;
-                                int tileColors = memory[colorAddress];
+                                borderLeft = 13;
+                                borderRight = 15;
 
-                                //tileRow = 0x55;
+                                int row = screenScanline >> 3;
+                                int segment = (screenScanline << 5) & 0x1800;
+                                int nameTable = baseNameTable | (row << 5);
+                                for (int tile = 0; tile < 32; tile++)
+                                {
+                                    int tileAddress = nameTable | tile;
+                                    int tileNumber = memory[tileAddress];
+                                    int tileRowAddress = (basePatternGen & 0x2000) | segment | (tileNumber << 3) | (screenScanline & 7);
+                                    int tileRow = memory[tileRowAddress];
+                                    int colorAddress = (baseColorTable & 0x2000) | segment | (tileNumber << 3) | (screenScanline & 7);
+                                    int tileColors = memory[colorAddress];
 
-                                uint color;
-                                for(int pixel = 0; pixel < 8; pixel++)
-                                {
-                                    if ((tileRow & 0x80) != 0)
-                                        color = colorChart[tileColors >> 4];
-                                    else
-                                        color = colorChart[tileColors & 0xF];
-                                    screen[(scanline * 284) + (tile * 8) + pixel + 13] = color;
-                                    tileRow <<= 1;
+                                    uint color;
+                                    for (int pixel = 0; pixel < 8; pixel++)
+                                    {
+                                        if ((tileRow & 0x80) != 0)
+                                            color = colorChart[tileColors >> 4];
+                                        else
+                                            color = colorChart[tileColors & 0xF];
+                                        screen[(scanline * 284) + (tile * 8) + pixel + borderLeft] = color;
+                                        tileRow <<= 1;
+                                    }
+
                                 }
+                                
+                            }
+                            break;
+                            case Mode.MultiColor:
+                            {
+                                borderLeft = 13;
+                                borderRight = 15;
+                            }
+                            break;
+                    }
+                    for (int pixel = 0; pixel < borderLeft; pixel++)
+                        screen[(scanline * 284) + pixel] = colorChart[text0Color];
 
-                            }
-                            for (int pixel = 0; pixel < 15; pixel++)
-                                screen[(scanline * 284) + pixel + 256 + 13] = colorChart[text0Color];
+                    for (int pixel = 284 - borderRight; pixel < 284; pixel++)
+                        screen[(scanline * 284) + pixel] = colorChart[text0Color];
 
-                                break;
-                    }
                 }
                 else if(scanline < 243)//BottomBorder
                 {
                 if (scanline == 219)