/// <summary>
        /// Builds a file where all the references to voice IDs in the
        /// ISO file are mapped. To be used as a cache by ISOModifier
        /// </summary>
        static void Main()
        {
            string isoFile  = Properties.Settings.Default.ISOPath;
            string workDir  = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            long   startPos = Convert.ToInt64(Properties.Settings.Default.StartAddressOfScan, 16);
            // long endPos = Convert.ToInt64(Properties.Settings.Default.EndAddressOfScan, 16);
            var listeOfVoiceIDsToFind = SoundInfo.GetAllVoiceIDs();

            List <Tuple <string, int> > listeOfPositionsAndVoiceId = new List <Tuple <string, int> >();

            string        logFilePath = Path.Combine(workDir, "output.log");
            List <string> logLines    = new List <string>();

            if (File.Exists(logFilePath))
            {
                File.Delete(logFilePath);
            }

            string        errorsLogFilePath = Path.Combine(workDir, "errors.log");
            List <string> errorsLines       = new List <string>();

            if (File.Exists(errorsLogFilePath))
            {
                File.Delete(errorsLogFilePath);
            }

            string outputFilePath = Path.Combine(workDir, "VoiceIDsAddressesCache.csv");

            if (File.Exists(outputFilePath))
            {
                File.Delete(outputFilePath);
            }

            var binReader = new BinaryReader(File.OpenRead(isoFile));

            binReader.BaseStream.Position = startPos;

            Console.WriteLine("Searching...");
            File.AppendAllLines(logFilePath, new string[] { "Searching..." });

            using (binReader)
            {
                var areaOfInterest = binReader.ReadBytes((int)(binReader.BaseStream.Length - binReader.BaseStream.Position));

                Parallel.ForEach(listeOfVoiceIDsToFind, voiceIdToSeek =>
                {
                    byte[] voiceIdToSeekAsByteArray = ASCIIEncoding.ASCII.GetBytes(voiceIdToSeek.ToString());

                    List <byte> voiceIdSurroundedByZeroes = new List <byte>();
                    List <byte> voiceIdTailedWithZero     = new List <byte>();
                    List <byte> voiceIdPrefixedWithZero   = new List <byte>();

                    //To avoid false positives
                    voiceIdPrefixedWithZero.Add(BitConverter.GetBytes(0)[0]);
                    voiceIdSurroundedByZeroes.Add(BitConverter.GetBytes(0)[0]);
                    voiceIdSurroundedByZeroes.AddRange(voiceIdToSeekAsByteArray);
                    voiceIdPrefixedWithZero.AddRange(voiceIdToSeekAsByteArray);
                    voiceIdTailedWithZero.AddRange(voiceIdToSeekAsByteArray);
                    //To avoid false positives
                    voiceIdSurroundedByZeroes.Add(BitConverter.GetBytes(0)[0]);
                    voiceIdTailedWithZero.Add(BitConverter.GetBytes(0)[0]);

                    int indexOfVoiceId = GetIndexOfBytePattern(areaOfInterest, voiceIdSurroundedByZeroes.ToArray());

                    if (indexOfVoiceId != -1)
                    {
                        indexOfVoiceId += 1;
                    }

                    if (indexOfVoiceId == -1)
                    {
                        indexOfVoiceId = GetIndexOfBytePattern(areaOfInterest, voiceIdPrefixedWithZero.ToArray());
                        if (indexOfVoiceId != -1)
                        {
                            indexOfVoiceId += 1;
                        }
                    }

                    if (indexOfVoiceId == -1)
                    {
                        indexOfVoiceId = GetIndexOfBytePattern(areaOfInterest, voiceIdTailedWithZero.ToArray());
                    }

                    if (indexOfVoiceId == -1)
                    {
                        indexOfVoiceId = GetIndexOfBytePattern(areaOfInterest, voiceIdToSeekAsByteArray);
                    }

                    if (indexOfVoiceId != -1)
                    {
                        long finalIndex = indexOfVoiceId + startPos;

                        string logLineVoiceId = @"index found for voiceID : " + voiceIdToSeek + "->" + Convert.ToString(finalIndex, 16);
                        Console.WriteLine(logLineVoiceId);
                        logLines.Add(logLineVoiceId);

                        listeOfPositionsAndVoiceId.Add(new Tuple <string, int>(Convert.ToString(finalIndex, 16), voiceIdToSeek));
                    }
                    else
                    {
                        string logLineFailure = @"/!\ index NOT found for voiceID : " + voiceIdToSeek;
                        logLines.Add(logLineFailure);
                        errorsLines.Add(logLineFailure);
                        Console.WriteLine(logLineFailure);
                        listeOfPositionsAndVoiceId.Add(new Tuple <string, int>(indexOfVoiceId.ToString(), voiceIdToSeek));
                    }
                });
            }

            string logLine = "Writing results to " + outputFilePath;

            logLines.Add(logLine);
            Console.WriteLine(logLine);

            File.AppendAllLines(logFilePath, logLines.ToArray());
            File.AppendAllLines(errorsLogFilePath, errorsLines.ToArray());

            List <string> outputContent = new List <string>();

            Parallel.ForEach(listeOfPositionsAndVoiceId.AsParallel().OrderBy(x => x.Item2), IndexAndVoiceId =>
            {
                string line = string.Format("{0},{1}", IndexAndVoiceId.Item1, IndexAndVoiceId.Item2.ToString());
                outputContent.Add(line);
            });

            File.WriteAllLines(outputFilePath, outputContent);

            string finalLogLine = "Done ! :)";

            File.AppendAllLines(logFilePath, new string[] { finalLogLine });
            Console.WriteLine(finalLogLine);
        }