private void ReadAnimalData(Stream stream, List <string> stringsList)
        {
            byte[] buffer = new byte[1024];
            stream.Seek(serializationSection_start, SeekOrigin.Begin);
            stream.Read(buffer, 0, 1);
            Debug.WriteLine("Expected number of entries: " + (int)buffer[0]);

            while (true)
            {
                long animalDataBlock_Start = stream.Position;
                stream.Read(buffer, 0, 1024);

                if (buffer[0] == 0x00)
                {
                    break;
                }

                ReadOnlySpan <byte> ro   = buffer;
                long animalDataBlock_End = animalDataBlock_Start + ro.IndexOf(animalSerialization_endBytes) + animalSerialization_endBytes.Length;

                AnimalData animal = new AnimalData();
                Animals.Add(animal);

                if (Gamemode == Gamemode.FRANCHISE)
                {
                    if (Helper.CheckFirstFourBits(buffer[0], 0xC0))
                    {
                        animal.AnimalId = Helper.ConvertLastThreeBytes(buffer[0], buffer[1]);

                        if (Helper.CheckFirstFourBits(buffer[2], 0xC0))
                        {
                            animal.SpeciesId = Helper.ConvertLastThreeBytes(buffer[2], buffer[3]);
                        }
                        else
                        {
                            animal.SpeciesId = buffer[2];
                        }
                    }
                    else
                    {
                        animal.AnimalId  = buffer[0];
                        animal.SpeciesId = buffer[1];
                    }
                }
                else
                {
                    if (BitConverter.IsLittleEndian)
                    {
                        animal.AnimalId = BitConverter.ToUInt32(buffer.Skip(1).Take(4).Reverse().ToArray(), 0);
                    }
                    else
                    {
                        animal.AnimalId = BitConverter.ToUInt32(buffer.Skip(1).Take(4).ToArray(), 0);
                    }
                    animal.SpeciesId = buffer[5];
                }

                if (stringsList.Count >= animal.SpeciesId)
                {
                    animal.Species = stringsList[(int)animal.SpeciesId];
                }

                int genePos = 0;
                IEnumerable <byte> geneSequence = FallbackGeneSearch(buffer, stream, ref genePos);

                // 8 bytes that we will use to find the animal's name and verify genes
                byte[] geneIdBytes = new byte[8];
                for (int i = genePos; i < buffer.Length; i++)
                {
                    if (Helper.CheckFirstFourBits(buffer[i], 0x80))
                    {
                        geneIdBytes = buffer.Skip(i).Take(8).ToArray();
                        break;
                    }
                }

                animal.GeneId = BitConverter.ToUInt64(geneIdBytes, 0);

                stream.Seek(datastoreSection_start, SeekOrigin.Begin);
                long geneIdPosition = Helper.Seek(stream, geneIdBytes, datastoreSection_end);

                byte[] buffer2 = new byte[60];
                stream.Seek(geneIdPosition + 8, SeekOrigin.Begin);
                stream.Read(buffer2, 0, 60);
                ro = buffer2;

                //Verify gene, both should be the same; only type of error should be gene being offset by some number of bytes
                // If they don't match, check if a subset of the 1st gene sequence is within the 2nd gene sequence
                // else, keep checking ahead for the ID and repeat
                if (ro.IndexOf(geneSequence.ToArray()) == -1)
                {
                    if (ro.IndexOf(geneSequence.Skip(8).ToArray()) != -1)
                    {
                        geneSequence = ro.ToArray();
                    }
                    else
                    {
                        long geneIdPosition2 = Helper.Seek(stream, geneIdBytes, datastoreSection_end);
                        while (geneIdPosition2 != -1)
                        {
                            stream.Seek(geneIdPosition2 + 8, SeekOrigin.Begin);
                            stream.Read(buffer2, 0, 60);
                            ro = buffer2;
                            if (ro.IndexOf(geneSequence.ToArray()) == -1 && ro.IndexOf(geneSequence.Skip(8).ToArray()) != -1)
                            {
                                geneIdPosition2 = Helper.Seek(stream, geneIdBytes, datastoreSection_end);
                            }
                            else
                            {
                                geneIdPosition = geneIdPosition2;
                                break;
                            }
                        }
                    }
                }

                if (Gene.IsValidGeneSequence(geneSequence))
                {
                    animal.SetGene(geneSequence);
                }

                animal.Name = ReadAnimalDataStore(animal, stream, geneIdPosition, AnimalData.GENE_LENGTH * 5 + geneIdBytes.Length);

                stream.Seek(animalDataBlock_End, SeekOrigin.Begin);
            }

            Debug.WriteLine("Found " + Animals.Count);
        }
        /* First 12 bytes seem to be some unknown gene
         * The next byte is the animal's sex
         *
         * Name is (most of the time) stored as a reference to a string in string list.
         * Only interested in the 12 bits, marked as '?' below.
         * Format: 0xC?, ??, 0x0, 0x0, 0x0, 0x0 (preceded by some series of 0x00 and 0xF3)
         * There may be multiple references but we just take the last one for now.
         */

        private string ReadAnimalDataStore(AnimalData animal, Stream stream, long geneIdPosition, int initialSkip)
        {
            string name = "";

            byte[] buffer = new byte[128];
            stream.Seek(geneIdPosition + initialSkip, SeekOrigin.Begin);
            stream.Read(buffer, 0, 128);
            ReadOnlySpan <byte> ro = buffer;

            animal.SetGene(buffer.Take(12).ToArray(), GeneType.UNKNOWN_2);
            animal.Sex = buffer.Skip(12).Take(1).First();

            int searchPos;

            if (Gamemode == Gamemode.FRANCHISE)
            {
                searchPos = ro.IndexOf(nameSearch_Franchise);
            }
            else
            {
                searchPos = ro.IndexOf(nameSearch_Sandbox);
            }

            if (searchPos != -1)
            {
                int  i = 0, tempNamePos = searchPos;
                int  zeroCount          = 0;
                bool foundSomeReference = false;
                for (i = searchPos; i < ro.Length; i++)
                {
                    if ((Helper.CheckFirstFourBits(ro[i], 0xC0)) && zeroCount > 0)
                    {
                        foundSomeReference = true;
                        tempNamePos        = i;
                        zeroCount          = 0;
                    }
                    else if (ro[i] == 0x00)
                    {
                        zeroCount++;
                        if (zeroCount >= 4)
                        {
                            break;
                        }
                    }
                    else
                    {
                        zeroCount = 0;
                    }
                }

                // Sometimes the name is stored here instead of in the string list.
                // Format in this case: 0xF3, [ character bytes ], 0x0, 0x0, 0x0, 0x0
                if (i - tempNamePos > 7 || !foundSomeReference)
                {
                    zeroCount = 0;

                    for (i = tempNamePos; i < ro.Length; i++)
                    {
                        if (ro[i] == 0xF3)
                        {
                            zeroCount = 0;
                            name      = "";
                        }
                        else if (ro[i] == 0x00)
                        {
                            zeroCount++;
                            if (zeroCount >= 4)
                            {
                                return(name);
                            }
                        }
                        else
                        {
                            zeroCount = 0;
                            name     += (char)ro[i];
                        }
                    }
                }
                else
                {
                    int nameIndex = ((ro[tempNamePos] & 0x0F) << 8) + ro[tempNamePos + 1];
                    if (nameIndex < StringsList.Count)
                    {
                        name = StringsList[nameIndex];
                    }
                    else
                    {
                        name = "";
#if DEBUG
                        string debugString = "";
                        foreach (byte b in buffer)
                        {
                            debugString += b.ToString("X2");
                        }
                        Debug.WriteLine(debugString);
#endif
                    }
                }
            }

            return(name);
        }