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();
        }
        private void GenerateExecutionTimings(StringWriter writer, InstructionParamVariantLine instrVariant)
        {
            if (instrVariant.execCondition.Length > 0)
            {
                writer.WriteLine(String.Format("                        Condition = \"{0}\",", instrVariant.execCondition));
            }

            int nbMCycles = Int32.Parse(instrVariant.MCycles);

            writer.WriteLine(String.Format("                        MachineCyclesCount = {0},", instrVariant.MCycles));

            string TStatesCount     = null;
            int    startParentIndex = instrVariant.TStates.IndexOf('(');

            if (startParentIndex >= 0)
            {
                TStatesCount = instrVariant.TStates.Substring(0, startParentIndex - 1).Trim();
            }
            else
            {
                TStatesCount         = instrVariant.TStates;
                instrVariant.TStates = "1 (" + instrVariant.TStates + ")";
            }
            writer.WriteLine(String.Format("                        TStatesCount = {0},", TStatesCount));

            writer.WriteLine("                        MachineCycles = new MachineCycle[] {");
            for (int McycleIndex = 1; McycleIndex <= nbMCycles; McycleIndex++)
            {
                string currentMcycle = null;
                switch (McycleIndex)
                {
                case 1:
                    currentMcycle = instrVariant.M1;
                    break;

                case 2:
                    currentMcycle = instrVariant.M2;
                    break;

                case 3:
                    currentMcycle = instrVariant.M3;
                    break;

                case 4:
                    currentMcycle = instrVariant.M4;
                    break;

                case 5:
                    currentMcycle = instrVariant.M5;
                    break;

                case 6:
                    currentMcycle = instrVariant.M6;
                    break;
                }
                startParentIndex = currentMcycle.IndexOf('(');
                string mcycleType    = currentMcycle.Substring(0, startParentIndex).Trim();
                string mcycleTStates = currentMcycle.Substring(startParentIndex + 1, 1);

                writer.Write(String.Format("                            new MachineCycle() {{ Type = MachineCycleType.{0}, TStates = {1} }}", mcycleType, mcycleTStates));
                if (McycleIndex < nbMCycles)
                {
                    writer.WriteLine(",");
                }
                else
                {
                    writer.WriteLine(" },");
                }
            }
            writer.Write(String.Format("                        TStatesByMachineCycle = \"{0}\"", instrVariant.TStates));
            if (instrVariant.stackComment.Length > 0)
            {
                writer.WriteLine(",");
                writer.Write(String.Format("                        StackOperations = \"{0}\"", instrVariant.stackComment));
            }
            if (instrVariant.M1comment.Length > 0)
            {
                writer.WriteLine(",");
                writer.Write(String.Format("                        M1Comment = \"{0}\"", instrVariant.M1comment));
            }
            writer.WriteLine("");
        }
        private void GenerateExecutionTimings(StringWriter writer, InstructionParamVariantLine instrVariant)
        {
            if (instrVariant.execCondition.Length > 0)
            {
                writer.WriteLine(String.Format("                        Condition = \"{0}\",", instrVariant.execCondition));
            }

            int nbMCycles = Int32.Parse(instrVariant.MCycles);
            writer.WriteLine(String.Format("                        MachineCyclesCount = {0},", instrVariant.MCycles));

            string TStatesCount = null;
            int startParentIndex = instrVariant.TStates.IndexOf('(');
            if (startParentIndex >= 0)
            {
                TStatesCount = instrVariant.TStates.Substring(0, startParentIndex - 1).Trim();
            }
            else
            {
                TStatesCount = instrVariant.TStates;
                instrVariant.TStates = "1 (" + instrVariant.TStates + ")";
            }
            writer.WriteLine(String.Format("                        TStatesCount = {0},", TStatesCount));

            writer.WriteLine("                        MachineCycles = new MachineCycle[] {");
            for (int McycleIndex = 1; McycleIndex <= nbMCycles; McycleIndex++)
            {
                string currentMcycle = null;
                switch (McycleIndex)
                {
                    case 1:
                        currentMcycle = instrVariant.M1;
                        break;
                    case 2:
                        currentMcycle = instrVariant.M2;
                        break;
                    case 3:
                        currentMcycle = instrVariant.M3;
                        break;
                    case 4:
                        currentMcycle = instrVariant.M4;
                        break;
                    case 5:
                        currentMcycle = instrVariant.M5;
                        break;
                    case 6:
                        currentMcycle = instrVariant.M6;
                        break;
                }
                startParentIndex = currentMcycle.IndexOf('(');
                string mcycleType = currentMcycle.Substring(0, startParentIndex).Trim();
                string mcycleTStates = currentMcycle.Substring(startParentIndex + 1, 1);

                writer.Write(String.Format("                            new MachineCycle() {{ Type = MachineCycleType.{0}, TStates = {1} }}", mcycleType, mcycleTStates));
                if (McycleIndex < nbMCycles)
                {
                    writer.WriteLine(",");
                }
                else
                {
                    writer.WriteLine(" },");
                }
            }
            writer.Write(String.Format("                        TStatesByMachineCycle = \"{0}\"", instrVariant.TStates));
            if (instrVariant.stackComment.Length > 0)
            {
                writer.WriteLine(",");
                writer.Write(String.Format("                        StackOperations = \"{0}\"", instrVariant.stackComment));
            }
            if (instrVariant.M1comment.Length > 0)
            {
                writer.WriteLine(",");
                writer.Write(String.Format("                        M1Comment = \"{0}\"", instrVariant.M1comment));
            }
            writer.WriteLine("");
        }
        private void GenerateInstructionType(StringWriter writer, IList <InstructionParamVariantLine> paramVariants)
        {
            InstructionParamVariantLine instrLine = paramVariants[0];

            writer.WriteLine(String.Format("            Table[{0}] = new InstructionType()", instrLine.instructionIndex));
            writer.WriteLine("            {");
            writer.WriteLine(String.Format("                Index = {0},", instrLine.instructionIndex));
            writer.WriteLine(String.Format("                IsUndocumented = {0},", instrLine.undocumented));
            writer.WriteLine(String.Format("                IsInternalZ80Operation = {0},", instrLine.isInternal));
            writer.WriteLine("");
            writer.WriteLine(String.Format("                InstructionGroup = \"{0}\",", instrLine.instructionGroup));
            writer.WriteLine(String.Format("                OpCodeName = \"{0}\",", instrLine.mnemonic));
            if (instrLine.param1AddressingMode.Length > 0)
            {
                writer.WriteLine(String.Format("                Param1Type = AddressingMode.{0},", ReadAddressingMode(instrLine.param1AddressingMode)));
            }
            if (instrLine.param2AddressingMode.Length > 0)
            {
                writer.WriteLine(String.Format("                Param2Type = AddressingMode.{0},", ReadAddressingMode(instrLine.param2AddressingMode)));
            }
            if (instrLine.param3AddressingMode.Length > 0)
            {
                writer.WriteLine(String.Format("                Param3Type = AddressingMode.{0},", ReadAddressingMode(instrLine.param3AddressingMode)));
            }
            if (instrLine.operationSchema.Length > 0)
            {
                writer.WriteLine(String.Format("                Equation = \"{0}\",", instrLine.operationSchema.Replace("\"", "")));
            }
            writer.WriteLine("");
            writer.WriteLine("                ParametersVariants = new InstructionParametersVariant[] {");

            for (int instrVariantIndex = 0; instrVariantIndex < paramVariants.Count; instrVariantIndex++)
            {
                InstructionParamVariantLine instrVariant = paramVariants[instrVariantIndex];

                writer.WriteLine("                new InstructionParametersVariant() {");
                writer.WriteLine(String.Format("                    Index = {0},", instrVariant.paramVariant));
                writer.WriteLine(String.Format("                    IsUndocumented = {0},", instrVariant.undocumented));
                writer.WriteLine(String.Format("                    InstructionCodeCount = {0},", instrVariant.numberOfInstructionCodes));
                if (instrVariant.param1List.Length > 0)
                {
                    writer.Write("                    Param1List = new string[] { ");
                    bool isFirstParam = true;
                    foreach (string param in instrVariant.param1List.Split(','))
                    {
                        if (!isFirstParam)
                        {
                            writer.Write(",");
                        }
                        writer.Write(String.Format("\"{0}\"", param));
                        isFirstParam = false;
                    }
                    writer.WriteLine(" },");
                }
                if (instrVariant.param2List.Length > 0)
                {
                    writer.Write("                    Param2List = new string[] { ");
                    bool isFirstParam = true;
                    foreach (string param in instrVariant.param2List.Split(','))
                    {
                        if (!isFirstParam)
                        {
                            writer.Write(",");
                        }
                        writer.Write(String.Format("\"{0}\"", param));
                        isFirstParam = false;
                    }
                    writer.WriteLine(" },");
                }
                if (instrVariant.param3List.Length > 0)
                {
                    writer.Write("                    Param3List = new string[] { ");
                    bool isFirstParam = true;
                    foreach (string param in instrVariant.param3List.Split(','))
                    {
                        if (!isFirstParam)
                        {
                            writer.Write(",");
                        }
                        writer.Write(String.Format("\"{0}\"", param));
                        isFirstParam = false;
                    }
                    writer.WriteLine(" },");
                }
                writer.WriteLine(String.Format("                    InstructionCodeSizeInBytes = {0},", instrVariant.instructionCodeSizeInBytes));

                writer.WriteLine("                    ExecutionTimings = new InstructionExecutionVariant() {");
                GenerateExecutionTimings(writer, instrVariant);

                if (instrVariant.ExecutionVariant != null)
                {
                    writer.WriteLine("                    },");
                    writer.WriteLine("                    AlternateExecutionTimings = new InstructionExecutionVariant() {");
                    GenerateExecutionTimings(writer, instrVariant.ExecutionVariant);
                }
                writer.WriteLine("                    }");

                writer.Write("                }");
                if (instrVariantIndex < paramVariants.Count - 1)
                {
                    writer.WriteLine(",");
                }
                else
                {
                    writer.WriteLine("");
                }
            }

            writer.WriteLine("                },");
            writer.WriteLine("");
            if (instrLine.userManualPage.Length > 0)
            {
                writer.WriteLine(String.Format("                UserManualPage = \"{0}\",", instrLine.userManualPage.Replace("\"", "")));
            }
            writer.Write(String.Format("                Description = \"{0}\"", instrLine.description.Replace("\"", "")));
            if (instrLine.conditionBitsAffected.Length > 0)
            {
                writer.WriteLine(",");
                writer.Write(String.Format("                ConditionBitsAffected = \"{0}\"", instrLine.conditionBitsAffected.Replace("\"", "")));
            }
            if (instrLine.example.Length > 0)
            {
                writer.WriteLine(",");
                writer.Write(String.Format("                Example = \"{0}\"", instrLine.example.Replace("\"", "")));
            }
            writer.WriteLine("");
            writer.WriteLine("            };");
            writer.WriteLine("");
        }
        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();
        }