public void GenerateInstructionTypesTable()
        {
            string tableName = "InstructionTables/z80_instructions.csv";

            StringWriter writer = new StringWriter();

            writer.WriteLine("using System;");
            writer.WriteLine("");
            writer.WriteLine("namespace Z80Simulator.Instructions");
            writer.WriteLine("{");
            writer.WriteLine("    public static class Z80InstructionTypes");
            writer.WriteLine("    {");
            writer.WriteLine("        /// <summary>");
            writer.WriteLine("        /// Z80 Instruction Types tables.");
            writer.WriteLine("        /// To be user friendly in the documentation, the first instruction type is found at index 1.");
            writer.WriteLine("        /// </summary>");
            writer.WriteLine("        public static InstructionType[] Table = new InstructionType[163];");
            writer.WriteLine("");
            writer.WriteLine("        static Z80InstructionTypes()");
            writer.WriteLine("        {");

            IList <InstructionParamVariantLine> paramVariants   = new List <InstructionParamVariantLine>();
            InstructionParamVariantLine         previousVariant = null;

            Stream stream = PlatformSpecific.GetStreamForProjectFile(tableName);

            using (StreamReader reader = new StreamReader(stream))
            {
                reader.ReadLine();
                string line      = null;
                string nextLine  = null;
                int    lineCount = 0;
                while (true)
                {
                    if (lineCount == 0)
                    {
                        line = reader.ReadLine();
                        lineCount++;
                    }
                    else
                    {
                        line = nextLine;
                    }
                    if (line == null)
                    {
                        break;
                    }
                    while (true)
                    {
                        nextLine = reader.ReadLine();
                        lineCount++;
                        if (nextLine == null)
                        {
                            break;
                        }
                        else if (nextLine.StartsWith("instr;") || nextLine.StartsWith("execvar;"))
                        {
                            break;
                        }
                        else
                        {
                            line += "\\n" + nextLine;
                        }
                    }

                    InstructionParamVariantLine instrLine = new InstructionParamVariantLine();

                    string[] columns = line.Split(';');
                    instrLine.lineType                   = columns[0];
                    instrLine.instructionIndex           = columns[1];
                    instrLine.paramVariant               = columns[2];
                    instrLine.numberOfInstructionCodes   = columns[3];
                    instrLine.isInternal                 = columns[4] == "1" ? "true" : "false";
                    instrLine.mnemonic                   = columns[5];
                    instrLine.param1List                 = columns[6];
                    instrLine.param2List                 = columns[7];
                    instrLine.param3List                 = columns[8];
                    instrLine.param1AddressingMode       = columns[10];
                    instrLine.param2AddressingMode       = columns[11];
                    instrLine.param3AddressingMode       = columns[12];
                    instrLine.instructionCodeSizeInBytes = columns[15];
                    instrLine.execVariant                = columns[16];
                    instrLine.MCycles               = columns[17];
                    instrLine.TStates               = columns[18];
                    instrLine.execCondition         = columns[19];
                    instrLine.M1                    = columns[20].Trim();
                    instrLine.M2                    = columns[21].Trim();
                    instrLine.M3                    = columns[22].Trim();
                    instrLine.M4                    = columns[23].Trim();
                    instrLine.M5                    = columns[24].Trim();
                    instrLine.M6                    = columns[25].Trim();
                    instrLine.stackComment          = columns[26];
                    instrLine.M1comment             = columns[27];
                    instrLine.instructionGroup      = columns[29];
                    instrLine.undocumented          = columns[30] == "1" ? "true" : "false";
                    instrLine.userManualPage        = columns[31];
                    instrLine.operationSchema       = columns[32];
                    instrLine.description           = columns[33];
                    instrLine.conditionBitsAffected = columns[34];
                    instrLine.example               = columns[35];

                    // Instruction / param variant
                    if (instrLine.lineType == "instr")
                    {
                        if (previousVariant != null && instrLine.instructionIndex != previousVariant.instructionIndex)
                        {
                            GenerateInstructionType(writer, paramVariants);
                            paramVariants = new List <InstructionParamVariantLine>();
                        }
                        paramVariants.Add(instrLine);
                    }
                    // Exec variant
                    else if (instrLine.lineType == "execvar")
                    {
                        previousVariant.ExecutionVariant = instrLine;
                    }

                    previousVariant = instrLine;
                }
            }
            GenerateInstructionType(writer, paramVariants);

            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("}");

            string Z80InstructionTypes_cs = writer.ToString();
        }
        public void GenerateOpCodesTable()
        {
            string[] tableNames = new string[] {
                "InstructionTables/z80_opcodes_table_1byte.csv",
                "InstructionTables/z80_opcodes_table_2bytes_CB.csv",
                "InstructionTables/z80_opcodes_table_2bytes_DD.csv",
                "InstructionTables/z80_opcodes_table_2bytes_ED.csv",
                "InstructionTables/z80_opcodes_table_2bytes_FD.csv",
                "InstructionTables/z80_opcodes_table_4bytes_DDCB.csv",
                "InstructionTables/z80_opcodes_table_4bytes_FDCB.csv"
            };

            StringWriter writer = new StringWriter();

            writer.WriteLine("using System;");
            writer.WriteLine("using System.Collections.Generic;");
            writer.WriteLine("");
            writer.WriteLine("namespace Z80Simulator.Instructions");
            writer.WriteLine("{");
            writer.WriteLine("    public static class Z80OpCodes");
            writer.WriteLine("    {");
            writer.WriteLine("        /// <summary>");
            writer.WriteLine("        /// Z80 OpCodes tables.");
            writer.WriteLine("        /// ");
            writer.WriteLine("        /// [0,] : 1 byte opcodes table.");
            writer.WriteLine("        /// [1,] : 2 bytes CB prefix opcodes table.");
            writer.WriteLine("        /// [2,] : 2 bytes DD prefix opcodes table.");
            writer.WriteLine("        /// [3,] : 2 bytes ED prefix opcodes table.");
            writer.WriteLine("        /// [4,] : 2 bytes FB prefix opcodes table.");
            writer.WriteLine("        /// [5,] : 4 bytes DDCB prefix opcodes table.");
            writer.WriteLine("        /// [6,] : 4 bytes FDCB prefix opcodes table.");
            writer.WriteLine("        /// </summary>");
            writer.WriteLine("        public static InstructionCode[,] Tables = new InstructionCode[7, 256];");
            writer.WriteLine("");
            writer.WriteLine("        /// <summary>");
            writer.WriteLine("        /// Lookup table used to find an InstructionCode by its InstructionText");
            writer.WriteLine("        /// </summary>");
            writer.WriteLine("        public static IDictionary<string, InstructionCode> Dictionary = new Dictionary<string, InstructionCode>(1792);");
            writer.WriteLine("");
            writer.WriteLine("        static Z80OpCodes()");
            writer.WriteLine("        {");

            for (int tableIndex = 0; tableIndex < 7; tableIndex++)
            {
                Stream stream = PlatformSpecific.GetStreamForProjectFile(tableNames[tableIndex]);
                using (StreamReader reader = new StreamReader(stream))
                {
                    string line        = reader.ReadLine();
                    int    opcodeIndex = 0;
                    while ((line = reader.ReadLine()) != null)
                    {
                        string[] columns = line.Split(';');
                        //param 1;param 2;param 3;duplicate

                        string prefix            = columns[0];
                        string opcode            = columns[1];
                        string opCodeBytes       = columns[2].Length == 0 ? "0" : columns[2];
                        string operandBytes      = columns[3].Length == 0 ? "0" : columns[3];
                        string undocumented      = columns[4] == "1" ? "true" : "false";
                        string fetchMoreBytes    = columns[5];
                        string switchToTable     = columns[6].Length == 0 ? "null" : columns[6];
                        string text              = columns[7];
                        string instrTypeIndex    = columns[8].Length == 0 ? "0" : columns[8];
                        string instrParamVariant = columns[9].Length == 0 ? "0" : columns[9];

                        int instructionIndex = Int32.Parse(instrTypeIndex);
                        Z80Simulator.Instructions.InstructionType instruction = Z80Simulator.Instructions.Z80InstructionTypes.Table[instructionIndex];

                        string param1 = columns[10].Length == 0 ? null : GetEnumFromParam(columns[10], instruction.Param1Type, instruction.Index);
                        string param2 = columns[11].Length == 0 ? null : GetEnumFromParam(columns[11], instruction.Param2Type, instruction.Index);
                        string param3 = columns[12].Length == 0 ? null : GetEnumFromParam(columns[12], instruction.Param3Type, instruction.Index);

                        string duplicate = columns[13] == "1" ? "true" : "false";

                        writer.WriteLine(String.Format("            Tables[{0}, {1}] = new InstructionCode()", tableIndex, opcodeIndex));
                        writer.WriteLine("            {");
                        byte[] prefixBytes = null;
                        if (prefix.Length == 4)
                        {
                            prefixBytes = new byte[] { Convert.ToByte(prefix.Substring(2, 2), 16) };
                            writer.WriteLine(String.Format("                Prefix = new byte[] {{ {0} }},", prefix));
                        }
                        else if (prefix.Length == 6)
                        {
                            prefixBytes = new byte[] { Convert.ToByte(prefix.Substring(2, 2), 16), Convert.ToByte(prefix.Substring(4, 2), 16) };
                            writer.WriteLine(String.Format("                Prefix = new byte[] {{ {0}, 0x{1} }},", prefix.Substring(0, 4), prefix.Substring(4)));
                        }
                        writer.WriteLine(String.Format("                OpCode = {0},", opcode));

                        if (duplicate == "true")
                        {
                            string instrCodeBytes = "[";
                            foreach (byte b in prefixBytes)
                            {
                                instrCodeBytes += b.ToString("X2") + "H ";
                            }
                            instrCodeBytes += opcode.Substring(2, 2) + "H]";

                            int insertIndex = text.IndexOf(' ');
                            if (insertIndex < 0)
                            {
                                text += instrCodeBytes;
                            }
                            else
                            {
                                text = text.Insert(insertIndex, instrCodeBytes);
                            }
                        }
                        writer.WriteLine(String.Format("                InstructionText = \"{0}\",", text));

                        if (param1 != null)
                        {
                            writer.WriteLine(String.Format("                Param1 = {0},", param1));
                        }
                        if (param2 != null)
                        {
                            writer.WriteLine(String.Format("                Param2 = {0},", param2));
                        }
                        if (param3 != null)
                        {
                            writer.WriteLine(String.Format("                Param3 = {0},", param3));
                        }
                        writer.WriteLine(String.Format("                InstructionTypeIndex = {0},", instrTypeIndex));
                        writer.WriteLine(String.Format("                InstructionTypeParamVariant = {0},", instrParamVariant));
                        writer.WriteLine(String.Format("                IsUndocumented = {0},", undocumented));
                        writer.WriteLine(String.Format("                IsDuplicate = {0},", duplicate));
                        writer.WriteLine(String.Format("                OpCodeByteCount = {0},", opCodeBytes));
                        writer.WriteLine(String.Format("                OperandsByteCount = {0},", operandBytes));
                        writer.WriteLine(String.Format("                FetchMoreBytes = {0},", fetchMoreBytes));
                        writer.WriteLine(String.Format("                SwitchToTableNumber = {0}", switchToTable));
                        writer.WriteLine("            };");
                        writer.WriteLine("            ");

                        opcodeIndex++;
                        if (opcodeIndex == 256)
                        {
                            break;
                        }
                    }
                }
            }

            writer.WriteLine("            for (int i = 0; i < 7; i++)");
            writer.WriteLine("            {");
            writer.WriteLine("                for (int j = 0; j < 256; j++)");
            writer.WriteLine("                {");
            writer.WriteLine("                    InstructionCode opcode = Tables[i, j];");
            writer.WriteLine("                    if (opcode.FetchMoreBytes == 0 && opcode.SwitchToTableNumber == null && !opcode.IsDuplicate)");
            writer.WriteLine("                    {");
            writer.WriteLine("                        string text = opcode.InstructionText.Replace(\"nn\", \"n\").Replace(\"e\", \"n\");");
            writer.WriteLine("                        if (!Dictionary.ContainsKey(text))");
            writer.WriteLine("                        {");
            writer.WriteLine("                            Dictionary.Add(text, opcode);");
            writer.WriteLine("                        }");
            writer.WriteLine("                    }");
            writer.WriteLine("                }");
            writer.WriteLine("            }");
            writer.WriteLine("        }");
            writer.WriteLine("    }");
            writer.WriteLine("}");

            string Z80OpCodes_cs = writer.ToString();
        }