public bool ReadFromBuffer(GR.Memory.ByteBuffer DataIn)
        {
            if (DataIn == null)
            {
                return(false);
            }
            GR.IO.MemoryReader memIn = DataIn.MemoryReader();

            uint version = memIn.ReadUInt32();

            if (version == 1)
            {
                TotalNumberOfCharacters = 256;

                string name            = memIn.ReadString();
                string charsetFilename = memIn.ReadString();
                for (int i = 0; i < TotalNumberOfCharacters; ++i)
                {
                    Characters[i].Tile.CustomColor = memIn.ReadInt32();
                }

                bool hasAnyMC = false;
                for (int i = 0; i < TotalNumberOfCharacters; ++i)
                {
                    var mode = (TextCharMode)memIn.ReadUInt8();

                    if ((mode == TextCharMode.COMMODORE_MULTICOLOR) &&
                        (Characters[i].Tile.CustomColor < 8))
                    {
                        mode = TextCharMode.COMMODORE_HIRES;
                    }
                    if (mode == TextCharMode.COMMODORE_MULTICOLOR)
                    {
                        hasAnyMC = true;
                    }
                }
                Colors.BackgroundColor = memIn.ReadInt32();
                Colors.MultiColor1     = memIn.ReadInt32();
                Colors.MultiColor2     = memIn.ReadInt32();


                for (int i = 0; i < TotalNumberOfCharacters; ++i)
                {
                    int tileColor1 = memIn.ReadInt32();
                    int tileColor2 = memIn.ReadInt32();
                    int tileColor3 = memIn.ReadInt32();
                    int tileColor4 = memIn.ReadInt32();
                    int tileChar1  = memIn.ReadInt32();
                    int tileChar2  = memIn.ReadInt32();
                    int tileChar3  = memIn.ReadInt32();
                    int tileChar4  = memIn.ReadInt32();
                }

                bool genericMulticolor       = (memIn.ReadInt32() != 0);
                GR.Memory.ByteBuffer testbed = new GR.Memory.ByteBuffer();
                memIn.ReadBlock(testbed, 64);

                GR.Memory.ByteBuffer charsetData = new GR.Memory.ByteBuffer();
                memIn.ReadBlock(charsetData, (uint)(TotalNumberOfCharacters * 8));

                for (int i = 0; i < TotalNumberOfCharacters; ++i)
                {
                    Characters[i].Tile.Data = charsetData.SubBuffer(i * 8, 8);
                }

                UsedTiles = memIn.ReadUInt32();

                ExportFilename = memIn.ReadString();
                string exportPathBlockTable  = memIn.ReadString();
                string exportPathCharset     = memIn.ReadString();
                string exportPathEditorTiles = memIn.ReadString();

                // categories
                Categories.Clear();
                int categoryCount = memIn.ReadInt32();
                for (int i = 0; i < categoryCount; ++i)
                {
                    int    catKey  = memIn.ReadInt32();
                    string catName = memIn.ReadString();

                    Categories.Add(catName);
                }
                if (Categories.Count == 0)
                {
                    // add default category
                    Categories.Add("Uncategorized");
                }
                for (int i = 0; i < TotalNumberOfCharacters; ++i)
                {
                    Characters[i].Category = memIn.ReadInt32();
                    if ((Characters[i].Category < 0) ||
                        (Characters[i].Category >= Categories.Count))
                    {
                        Characters[i].Category = 0;
                    }
                }
                ExportNumCharacters = memIn.ReadInt32();
                if (ExportNumCharacters < TotalNumberOfCharacters)
                {
                    ExportNumCharacters = TotalNumberOfCharacters;
                }
                ShowGrid             = (memIn.ReadInt32() != 0);
                ExportStartCharacter = memIn.ReadInt32();
                Colors.BGColor4      = memIn.ReadInt32();

                // playground
                int w = memIn.ReadInt32();
                int h = memIn.ReadInt32();
                if (w * h < 256)
                {
                    w = 16;
                    h = 16;
                }
                PlaygroundChars = new List <uint>(w * h);
                for (int i = 0; i < w * h; ++i)
                {
                    ushort charInfo = memIn.ReadUInt16();
                    PlaygroundChars.Add((uint)((charInfo & 0xff) | ((charInfo & 0xff00) << 8)));
                }

                Mode = (TextCharMode)memIn.ReadInt32();
                if (hasAnyMC)
                {
                    Mode = TextCharMode.COMMODORE_MULTICOLOR;
                }
            }
            else if (version == 2)
            {
                Characters.Clear();
                Categories.Clear();
                Colors.Palettes.Clear();
                TotalNumberOfCharacters = 256;
                Mode = TextCharMode.COMMODORE_HIRES;

                var chunk = new GR.IO.FileChunk();

                while (chunk.ReadFromStream(memIn))
                {
                    if (chunk.Type == FileChunkConstants.CHARSET_PROJECT)
                    {
                        var chunkIn = chunk.MemoryReader();

                        var subChunk = new GR.IO.FileChunk();

                        while (subChunk.ReadFromStream(chunkIn))
                        {
                            var subMemIn = subChunk.MemoryReader();
                            switch (subChunk.Type)
                            {
                            case FileChunkConstants.CHARSET_INFO:
                                Mode = (TextCharMode)subMemIn.ReadInt32();
                                TotalNumberOfCharacters = subMemIn.ReadInt32();
                                ShowGrid = ((subMemIn.ReadInt32() & 1) == 1);
                                break;

                            case FileChunkConstants.CHARSET_COLOR_SETTINGS:
                                Colors.BackgroundColor = subMemIn.ReadInt32();
                                Colors.MultiColor1     = subMemIn.ReadInt32();
                                Colors.MultiColor2     = subMemIn.ReadInt32();
                                Colors.BGColor4        = subMemIn.ReadInt32();
                                Colors.ActivePalette   = subMemIn.ReadInt32();
                                break;

                            case FileChunkConstants.PALETTE:
                                Colors.Palettes.Add(Palette.Read(subMemIn));
                                break;

                            case FileChunkConstants.CHARSET_EXPORT:
                                ExportStartCharacter = subMemIn.ReadInt32();
                                ExportNumCharacters  = subMemIn.ReadInt32();
                                ExportFilename       = subMemIn.ReadString();
                                break;

                            case FileChunkConstants.CHARSET_CHAR:
                            {
                                var charData = new CharData();

                                subMemIn.ReadInt32(); // was TextCharMode
                                charData.Tile.CustomColor = subMemIn.ReadInt32();
                                charData.Tile.Mode        = Lookup.GraphicTileModeFromTextCharMode(Mode, charData.Tile.CustomColor);

                                charData.Category = subMemIn.ReadInt32();

                                int dataLength = subMemIn.ReadInt32();
                                charData.Tile.Data = new GR.Memory.ByteBuffer();
                                subMemIn.ReadBlock(charData.Tile.Data, (uint)dataLength);

                                Characters.Add(charData);
                            }
                            break;

                            case FileChunkConstants.CHARSET_CATEGORY:
                                Categories.Add(subMemIn.ReadString());
                                break;

                            case FileChunkConstants.CHARSET_PLAYGROUND:
                                PlaygroundWidth  = subMemIn.ReadInt32();
                                PlaygroundHeight = subMemIn.ReadInt32();

                                PlaygroundChars = new List <uint>(PlaygroundWidth * PlaygroundHeight);

                                for (int i = 0; i < PlaygroundWidth * PlaygroundHeight; ++i)
                                {
                                    // 16 bit index, 16 bit color
                                    PlaygroundChars.Add(subMemIn.ReadUInt32());
                                }
                                break;
                            }
                        }
                    }
                }
                if (Colors.Palettes.Count == 0)
                {
                    Colors.Palettes.Add(PaletteManager.PaletteFromNumColors(Lookup.NumberOfColorsInCharacter(Mode)));
                }
            }
            else
            {
                return(false);
            }
            return(true);
        }