public int ImageToMCBitmapData(Dictionary <int, List <ColorMappingTarget> > ForceBitPattern, List <Formats.CharData> Chars, bool[,] ErrornousBlocks, out GR.Memory.ByteBuffer bitmapData, out GR.Memory.ByteBuffer screenChar, out GR.Memory.ByteBuffer screenColor)
        {
            int numErrors = 0;

            Dictionary <int, GR.Collections.Set <ColorMappingTarget> > usedPatterns = new Dictionary <int, GR.Collections.Set <ColorMappingTarget> >();

            screenChar  = new GR.Memory.ByteBuffer((uint)(BlockWidth * BlockHeight));
            screenColor = new GR.Memory.ByteBuffer((uint)(BlockWidth * BlockHeight));
            bitmapData  = new GR.Memory.ByteBuffer((uint)(8 * BlockWidth * BlockHeight));

            GR.Collections.Map <byte, ColorMappingTarget> usedColors = new GR.Collections.Map <byte, ColorMappingTarget>();

            /*
             * ForceBitPattern = new Dictionary<int, byte>();
             * ForceBitPattern.Add( 4, 1 );
             * ForceBitPattern.Add( 1, 2 );
             * ForceBitPattern.Add( 3, 3 );*/

            for (int y = 0; y < BlockHeight; ++y)
            {
                for (int x = 0; x < BlockWidth; ++x)
                {
                    // ein zeichen-block
                    usedColors.Clear();
                    if (ErrornousBlocks != null)
                    {
                        ErrornousBlocks[x, y] = false;
                    }
                    for (int charY = 0; charY < 8; ++charY)
                    {
                        for (int charX = 0; charX < 4; ++charX)
                        {
                            byte colorIndex = (byte)Image.GetPixel(x * 8 + charX * 2, y * 8 + charY);
                            if (colorIndex >= 16)
                            {
                                if (Chars != null)
                                {
                                    Chars[x + y * BlockWidth].Error = "Color index >= 16 (" + colorIndex + ") at " + (x * 8 + charX * 2).ToString() + ", " + (y * 8 + charY).ToString() + " (" + charX + "," + charY + ")";
                                }
                                if (ErrornousBlocks != null)
                                {
                                    ErrornousBlocks[x, y] = true;
                                }
                                ++numErrors;
                            }
                            if (colorIndex != BackgroundColor)
                            {
                                // remember used color
                                usedColors.Add(colorIndex, 0);
                            }
                        }
                    }
                    // more than 3 colors?
                    if (usedColors.Count > 3)
                    {
                        if (Chars != null)
                        {
                            Chars[x + y * BlockWidth].Error = "Too many colors used";
                        }
                        if (ErrornousBlocks != null)
                        {
                            ErrornousBlocks[x, y] = true;
                        }
                        ++numErrors;
                    }
                    else
                    {
                        if (usedColors.Count > 0)
                        {
                            int         colorTarget = 0;
                            List <byte> keys        = new List <byte>(usedColors.Keys);

                            // check for overlaps - two colors are used that would map to the same target pattern?
                            Dictionary <int, ColorMappingTarget> recommendedPattern = new Dictionary <int, ColorMappingTarget>();

                            numErrors += DetermineBestMapping(keys, x, y, ForceBitPattern, recommendedPattern, ErrornousBlocks);

                            foreach (byte colorIndex in keys)
                            {
                                if (recommendedPattern.ContainsKey(colorIndex))
                                {
                                    usedColors[colorIndex] = recommendedPattern[colorIndex];

                                    if (!usedPatterns.ContainsKey(colorIndex))
                                    {
                                        usedPatterns.Add(colorIndex, new GR.Collections.Set <ColorMappingTarget>());
                                    }
                                    usedPatterns[colorIndex].Add(recommendedPattern[colorIndex]);

                                    switch (recommendedPattern[colorIndex])
                                    {
                                    case ColorMappingTarget.BITS_01:
                                    {
                                        // upper screen char nibble
                                        byte value = screenChar.ByteAt(x + y * BlockWidth);
                                        value &= 0x0f;
                                        value |= (byte)(colorIndex << 4);

                                        screenChar.SetU8At(x + y * BlockWidth, value);
                                    }
                                    break;

                                    case ColorMappingTarget.BITS_10:
                                    {
                                        // lower nibble in screen char
                                        byte value = screenChar.ByteAt(x + y * BlockWidth);
                                        value &= 0xf0;
                                        value |= (byte)(colorIndex);

                                        screenChar.SetU8At(x + y * BlockWidth, value);
                                    }
                                    break;

                                    case ColorMappingTarget.BITS_11:
                                        // color ram
                                        screenColor.SetU8At(x + y * BlockWidth, colorIndex);
                                        break;
                                    }
                                    continue;
                                }

                                if (!usedPatterns.ContainsKey(colorIndex))
                                {
                                    usedPatterns.Add(colorIndex, new GR.Collections.Set <ColorMappingTarget>());
                                }
                                switch (colorTarget)
                                {
                                case 0:
                                    usedPatterns[colorIndex].Add(ColorMappingTarget.BITS_01);
                                    break;

                                case 1:
                                    usedPatterns[colorIndex].Add(ColorMappingTarget.BITS_10);
                                    break;

                                case 2:
                                    usedPatterns[colorIndex].Add(ColorMappingTarget.BITS_11);
                                    break;
                                }

                                if (colorTarget == 0)
                                {
                                    // upper screen char nibble
                                    byte value = screenChar.ByteAt(x + y * BlockWidth);
                                    value &= 0x0f;
                                    value |= (byte)(colorIndex << 4);

                                    screenChar.SetU8At(x + y * BlockWidth, value);
                                    usedColors[colorIndex] = ColorMappingTarget.BITS_01;
                                }
                                else if (colorTarget == 1)
                                {
                                    // lower nibble in screen char
                                    byte value = screenChar.ByteAt(x + y * BlockWidth);
                                    value &= 0xf0;
                                    value |= (byte)(colorIndex);

                                    screenChar.SetU8At(x + y * BlockWidth, value);
                                    usedColors[colorIndex] = ColorMappingTarget.BITS_10;
                                }
                                else if (colorTarget == 2)
                                {
                                    // color ram
                                    screenColor.SetU8At(x + y * BlockWidth, colorIndex);
                                    usedColors[colorIndex] = ColorMappingTarget.BITS_11;
                                }
                                ++colorTarget;
                            }
                        }
                        // write out bits
                        for (int charY = 0; charY < 8; ++charY)
                        {
                            for (int charX = 0; charX < 4; ++charX)
                            {
                                byte colorIndex = (byte)Image.GetPixel(x * 8 + charX * 2, y * 8 + charY);
                                if (colorIndex != BackgroundColor)
                                {
                                    // other color
                                    byte colorValue = 0;

                                    switch (usedColors[colorIndex])
                                    {
                                    case ColorMappingTarget.BITS_01:
                                        colorValue = 0x01;
                                        break;

                                    case ColorMappingTarget.BITS_10:
                                        colorValue = 0x02;
                                        break;

                                    case ColorMappingTarget.BITS_11:
                                        colorValue = 0x03;
                                        break;
                                    }
                                    int bitmapIndex = x * 8 + y * 8 * BlockWidth + charY;

                                    byte value = bitmapData.ByteAt(bitmapIndex);
                                    if (charX == 0)
                                    {
                                        value &= 0x3f;
                                        value |= (byte)(colorValue << 6);
                                    }
                                    else if (charX == 1)
                                    {
                                        value &= 0xcf;
                                        value |= (byte)(colorValue << 4);
                                    }
                                    else if (charX == 2)
                                    {
                                        value &= 0xf3;
                                        value |= (byte)(colorValue << 2);
                                    }
                                    else
                                    {
                                        value &= 0xfc;
                                        value |= colorValue;
                                    }
                                    bitmapData.SetU8At(bitmapIndex, value);
                                }
                            }
                        }
                    }
                }
            }

            /*
             * Debug.Log( "Used patterns:" );
             * foreach ( var entry in usedPatterns )
             * {
             * Debug.Log( "Index " + entry.Key );
             * foreach ( var pattern in entry.Value )
             * {
             *  Debug.Log( " used " + pattern );
             * }
             * }*/
            return(numErrors);
        }
Exemple #2
0
        private bool LoadVersion4(GR.Memory.ByteBuffer Data)
        {
            BackgroundColor = Data.ByteAt(4);
            MultiColor1     = Data.ByteAt(5);
            MultiColor2     = Data.ByteAt(6);
            CustomColor     = Data.ByteAt(7);
            TileColorMode   = (ColorMode)Data.ByteAt(8);
            MultiColor      = (Data.ByteAt(9) != 0);

            NumChars   = Data.UInt16At(10) + 1;
            NumTiles   = Data.ByteAt(12) + 1;
            TileWidth  = Data.ByteAt(13);
            TileHeight = Data.ByteAt(14);

            MapWidth  = Data.UInt16At(15);
            MapHeight = Data.UInt16At(17);

            bool isExpanded = (Data.ByteAt(19) != 0);

            int offsetToCharAttribs = 24 + NumChars * 8;

            for (int charIndex = 0; charIndex < NumChars; ++charIndex)
            {
                SingleChar newChar = new SingleChar();
                newChar.Data  = Data.SubBuffer(24 + charIndex * 8, 8);
                newChar.Color = Data.ByteAt(offsetToCharAttribs + charIndex) & 0x0f;

                Characters.Add(newChar);
            }

            for (int i = 0; i < NumTiles; ++i)
            {
                Tile tile = new Tile();

                tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                tile.ColorData.Resize((uint)(TileWidth * TileHeight));

                Tiles.Add(tile);
            }

            if (isExpanded)
            {
                byte curCharIndex = 0;
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int j = 0; j < TileWidth * TileHeight; ++j)
                    {
                        Tiles[i].CharData.SetU16At(j * 2, curCharIndex);
                        ++curCharIndex;
                    }
                }
            }
            else
            {
                // CELL_DATA.      Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded")
                int offsetCellData = 24 + NumChars * 8 + NumChars;
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int j = 0; j < TileWidth * TileHeight; ++j)
                    {
                        Tiles[i].CharData.SetU16At(j * 2, Data.UInt16At(offsetCellData + i * TileWidth * TileHeight * 2 + j * 2));
                    }
                }
            }
            // CELL_ATTRIBS.   Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes (exists for ALL modes)

            int offsetCellAttribs = 24 + NumChars * 8 + NumChars;

            if (!isExpanded)
            {
                offsetCellAttribs += NumTiles * TileWidth * TileHeight * 2;
            }
            for (int i = 0; i < NumTiles; ++i)
            {
                for (int y = 0; y < TileHeight; ++y)
                {
                    for (int x = 0; x < TileWidth; ++x)
                    {
                        if (TileColorMode == ColorMode.PER_TILE_CELL)
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight) & 0x0f));
                        }
                        else
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)CustomColor);
                        }
                    }
                }
            }

            // TILE_ATTRIBS.   Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile)
            int offsetTileAttribs = offsetCellAttribs + NumTiles * TileWidth * TileHeight;

            if (TileColorMode == ColorMode.PER_TILE)
            {
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int y = 0; y < TileHeight; ++y)
                    {
                        for (int x = 0; x < TileWidth; ++x)
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetTileAttribs + i) & 0x0f));
                        }
                    }
                }
            }

            /*
             * if ( TileColorMode == ColorMode.PER_TILE_CELL )
             * {
             * for ( int i = 0; i < NumTiles; ++i )
             * {
             *  for ( int y = 0; y < TileHeight; ++y )
             *  {
             *    for ( int x = 0; x < TileWidth; ++x )
             *    {
             *      Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) );
             *    }
             *  }
             * }
             * }*/

            // MAP_DATA.        Size =  MAP_WID x MAP_HEI bytes.
            int offsetMapData = offsetTileAttribs;

            if (TileColorMode == ColorMode.PER_TILE)
            {
                offsetMapData += NumTiles;
            }

            MapData = Data.SubBuffer(offsetMapData, MapWidth * MapHeight);
            return(true);
        }
        public bool ReadFromBuffer(GR.Memory.ByteBuffer DataIn)
        {
            if (DataIn == null)
            {
                return(false);
            }
            SpriteLayers.Clear();

            GR.IO.MemoryReader memIn = DataIn.MemoryReader();

            GR.Memory.ByteBuffer header = new GR.Memory.ByteBuffer();

            if (memIn.ReadBlock(header, 9) != 9)
            {
                return(false);
            }
            if ((header.ByteAt(0) != 0x53) ||
                (header.ByteAt(1) != 0x50) ||
                (header.ByteAt(2) != 0x44))
            {
                // no SPD
                return(false);
            }

            NumSprites = header.ByteAt(4) + 1;
            int numAnims = header.ByteAt(5) + 1;

            BackgroundColor = header.ByteAt(6);
            MultiColor1     = header.ByteAt(7);
            MultiColor2     = header.ByteAt(8);

            Sprites = new List <SpriteData>();

            GR.Memory.ByteBuffer tempData = new GR.Memory.ByteBuffer();
            for (int i = 0; i < NumSprites; ++i)
            {
                Sprites.Add(new SpriteData());
                PaletteManager.ApplyPalette(Sprites[i].Image);

                tempData.Clear();
                memIn.ReadBlock(tempData, 63);
                tempData.CopyTo(Sprites[i].Data, 0, 63);

                Sprites[i].Color      = memIn.ReadUInt8();
                Sprites[i].Multicolor = (((Sprites[i].Color) & 0x80) != 0);
                Sprites[i].Color     &= 0x0f;
            }

            if (numAnims > 0)
            {
                GR.Memory.ByteBuffer animFrom       = new GR.Memory.ByteBuffer();
                GR.Memory.ByteBuffer animTo         = new GR.Memory.ByteBuffer();
                GR.Memory.ByteBuffer animNumFrames  = new GR.Memory.ByteBuffer();
                GR.Memory.ByteBuffer animAttributes = new GR.Memory.ByteBuffer();

                memIn.ReadBlock(animFrom, (uint)numAnims);
                memIn.ReadBlock(animTo, (uint)numAnims);
                memIn.ReadBlock(animNumFrames, (uint)numAnims);
                memIn.ReadBlock(animAttributes, (uint)numAnims);
            }
            UsedSprites = (uint)NumSprites;
            return(true);
        }
        public int ImageToHiresBitmapData(List <Formats.CharData> Chars, bool[,] ErrornousBlocks, out GR.Memory.ByteBuffer bitmapData, out GR.Memory.ByteBuffer screenChar, out GR.Memory.ByteBuffer screenColor)
        {
            int numErrors = 0;

            screenChar  = new GR.Memory.ByteBuffer((uint)(BlockWidth * BlockHeight));
            screenColor = new GR.Memory.ByteBuffer((uint)(BlockWidth * BlockHeight));
            bitmapData  = new GR.Memory.ByteBuffer((uint)(8 * BlockWidth * BlockHeight));

            GR.Collections.Map <byte, byte> usedColors = new GR.Collections.Map <byte, byte>();

            for (int y = 0; y < BlockHeight; ++y)
            {
                for (int x = 0; x < BlockWidth; ++x)
                {
                    // ein zeichen-block
                    usedColors.Clear();
                    if (ErrornousBlocks != null)
                    {
                        ErrornousBlocks[x, y] = false;
                    }
                    for (int charY = 0; charY < 8; ++charY)
                    {
                        for (int charX = 0; charX < 8; ++charX)
                        {
                            byte colorIndex = (byte)Image.GetPixel(x * 8 + charX, y * 8 + charY);
                            if (colorIndex >= 16)
                            {
                                if (Chars != null)
                                {
                                    Chars[x + y * BlockWidth].Error = "Color index >= 16 (" + colorIndex + ") at " + (x * 8 + charX).ToString() + ", " + (y * 8 + charY).ToString() + " (" + charX + "," + charY + ")";
                                }
                                if (ErrornousBlocks != null)
                                {
                                    ErrornousBlocks[x, y] = true;
                                }
                                ++numErrors;
                            }
                            if (colorIndex != BackgroundColor)
                            {
                                // remember used color
                                usedColors.Add(colorIndex, 0);
                            }
                        }
                    }
                    // more than 2 colors?
                    if (usedColors.Count > 2)
                    {
                        if (Chars != null)
                        {
                            Chars[x + y * BlockWidth].Error = "Too many colors used";
                        }
                        if (ErrornousBlocks != null)
                        {
                            ErrornousBlocks[x, y] = true;
                        }
                        ++numErrors;
                    }
                    else
                    {
                        int firstColorIndex = -1;
                        if (usedColors.Count > 0)
                        {
                            int         colorTarget = 0;
                            List <byte> keys        = new List <byte>(usedColors.Keys);
                            foreach (byte colorIndex in keys)
                            {
                                if (colorTarget == 0)
                                {
                                    // upper screen char nibble
                                    byte value = screenChar.ByteAt(x + y * BlockWidth);
                                    value &= 0x0f;
                                    value |= (byte)(colorIndex << 4);

                                    screenChar.SetU8At(x + y * BlockWidth, value);
                                    usedColors[colorIndex] = 1;
                                    firstColorIndex        = colorIndex;
                                }
                                else if (colorTarget == 1)
                                {
                                    // lower nibble in screen char
                                    byte value = screenChar.ByteAt(x + y * BlockWidth);
                                    value &= 0xf0;
                                    value |= (byte)(colorIndex);

                                    screenChar.SetU8At(x + y * BlockWidth, value);
                                    usedColors[colorIndex] = 2;
                                }
                                ++colorTarget;
                            }
                        }
                        // write out bits
                        for (int charY = 0; charY < 8; ++charY)
                        {
                            for (int charX = 0; charX < 8; ++charX)
                            {
                                byte colorIndex = (byte)Image.GetPixel(x * 8 + charX, y * 8 + charY);
                                if (colorIndex == firstColorIndex)
                                {
                                    // other color
                                    byte colorValue  = usedColors[colorIndex];
                                    int  bitmapIndex = x * 8 + y * BlockWidth * 8 + charY;

                                    byte value = bitmapData.ByteAt(bitmapIndex);
                                    int  mask  = (1 << (7 - charX));

                                    value &= (byte)(0xff ^ mask);
                                    value |= (byte)mask;
                                    bitmapData.SetU8At(bitmapIndex, value);
                                }
                            }
                        }
                    }
                }
            }
            return(numErrors);
        }
        private bool LoadVersion7(GR.Memory.ByteBuffer Data)
        {
            BackgroundColor  = Data.ByteAt(4);
            MultiColor1      = Data.ByteAt(5);
            MultiColor2      = Data.ByteAt(6);
            BackgroundColor4 = Data.ByteAt(7);
            CustomColor      = Data.ByteAt(8);
            TileColorMode    = (ColorMode)Data.ByteAt(9);

            // only uses values 0 to 2, which maps fine
            DisplayModeFile = (DisplayMode)Data.ByteAt(10);

            byte flags          = Data.ByteAt(11);
            bool tileSysEnabled = ((flags & 0x01) != 0);


            ushort charDataBlockID      = 0xdab0;
            ushort charAttributeBlockID = 0xdab1;
            ushort mapDataBlockID       = 0xdab2;


            if (!tileSysEnabled)
            {
                // fake tiles (one per char)
                TileWidth  = 1;
                TileHeight = 1;
                NumTiles   = 256;

                for (int i = 0; i < NumTiles; ++i)
                {
                    Tile tile = new Tile();

                    tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                    tile.CharData.SetU16At(0, (ushort)i);

                    tile.ColorData.Resize((uint)(TileWidth * TileHeight));
                    tile.ColorData.SetU8At(0, (byte)CustomColor);

                    Tiles.Add(tile);
                }
            }

            var reader = Data.MemoryReader();

            reader.Skip(12);

            while (reader.DataAvailable)
            {
                ushort blockID = reader.ReadUInt16NetworkOrder();

                if (blockID == mapDataBlockID)
                {
                    if (tileSysEnabled)
                    {
                        // Tile data block

                        // TILECNT: Tile count minus one(16 - bit, LSBF).
                        NumTiles = reader.ReadUInt16() + 1;

                        // TILEWID: Tile width( byte).
                        TileWidth = reader.ReadUInt8();
                        // TILEHEI: Tile height( byte).
                        TileHeight = reader.ReadUInt8();

                        // TILEDAT: Tile data, 16 bits per tile cell( LSBF) for TILEWID* TILEHEI cells * TILECNT items, cells are in LRTB order.
                        for (int i = 0; i < NumTiles; ++i)
                        {
                            Tile tile = new Tile();

                            tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                            tile.ColorData.Resize((uint)(TileWidth * TileHeight));

                            Tiles.Add(tile);
                        }
                        if (NumChars < 256)
                        {
                            // add all chars for safety reasons
                            for (int i = NumChars; i < 256; ++i)
                            {
                                SingleChar newChar = new SingleChar();
                                newChar.Data = new GR.Memory.ByteBuffer(8);
                                Characters.Add(newChar);
                            }
                        }
                        for (int i = 0; i < NumTiles; ++i)
                        {
                            for (int j = 0; j < TileWidth * TileHeight; ++j)
                            {
                                Tiles[i].CharData.SetU16At(j * 2, reader.ReadUInt16());
                            }
                        }
                    }
                    else
                    {
                        // BLKMARK : Block marker (0xDA, 0xBn).
                        // MAPWID: Map Width(16 - bit, LSBF).
                        // MAPHEI: Map height(16 - bit, LSBF).
                        // MAPDAT: Map data, 16 bits per cell( LSBF ) for MAPWID* MAPHEI cells, cells are in LRTB order.
                        MapWidth  = reader.ReadUInt16();
                        MapHeight = reader.ReadUInt16();

                        MapData = new GR.Memory.ByteBuffer((uint)(MapWidth * MapHeight));

                        for (int i = 0; i < MapHeight; ++i)
                        {
                            for (int j = 0; j < MapWidth; ++j)
                            {
                                MapData.SetU8At(i * MapWidth + j, (byte)reader.ReadUInt16());
                            }
                        }
                    }
                }

                if (blockID == charDataBlockID)
                {
                    // Character data block

                    // CHARCNT: Character image count minus one( 16 - bit, LSBF ).
                    NumChars = reader.ReadUInt16() + 1;

                    // CHARDAT : Character image data( eight bytes / rows per image for CHARCNT images, rows are in TB order ).
                    for (int charIndex = 0; charIndex < NumChars; ++charIndex)
                    {
                        SingleChar newChar = new SingleChar();
                        newChar.Data  = new GR.Memory.ByteBuffer();
                        newChar.Color = CustomColor;
                        reader.ReadBlock(newChar.Data, 8);
                        Characters.Add(newChar);
                    }

                    if (!tileSysEnabled)
                    {
                        if (NumChars < 256)
                        {
                            // add all chars for safety reasons
                            for (int i = NumChars; i < 256; ++i)
                            {
                                SingleChar newChar = new SingleChar();
                                newChar.Data  = new GR.Memory.ByteBuffer(8);
                                newChar.Color = CustomColor;

                                Characters.Add(newChar);
                            }
                        }
                    }
                }
                else if (blockID == charAttributeBlockID)
                {
                    // char attributes
                    // BLKMARK: Block marker(0xDA, 0xB1).
                    // CHARATTS: Char attribute data, one byte per char image for CHARCNT images, low nybble = colour, high nybble = material.
                    //           nb.colours are only stored when the colouring mode is "per character".
                    for (int charIndex = 0; charIndex < NumChars; ++charIndex)
                    {
                        if (TileColorMode == ColorMode.PER_CHAR)
                        {
                            Characters[charIndex].Color = reader.ReadUInt8() & 0x0f;
                            if (!tileSysEnabled)
                            {
                                Tiles[charIndex].ColorData.SetU8At(0, (byte)Characters[charIndex].Color);
                            }
                        }
                    }
                }
            }
            return(true);
        }
Exemple #6
0
        public override bool Load(string Filename)
        {
            _LastError = "";
            GR.Memory.ByteBuffer diskData = GR.IO.File.ReadAllBytes(Filename);
            if (diskData == null)
            {
                _LastError = "Could not open/read file";
                return(false);
            }

            /*
             * 35 track, no errors        174848
             * 35 track, 683 error bytes  175531
             * 40 track, no errors        196608
             * 40 track, 768 error bytes  197376
             */

            if ((diskData.Length != 174848) &&
                (diskData.Length != 175531) &&
                (diskData.Length != 196608) &&
                (diskData.Length != 197376))
            {
                _LastError = "disk image size is not supported";
                return(false);
            }
            switch (diskData.Length)
            {
            case 174848:
            case 175531:
                CreateEmptyMedia();
                break;

            case 196608:
            case 197376:
                CreateEmptyMedia40Tracks();
                break;
            }

            int dataPos = 0;

            for (int i = 0; i < Tracks.Count; ++i)
            {
                for (int j = 0; j < Tracks[i].Sectors.Count; ++j)
                {
                    diskData.CopyTo(Tracks[i].Sectors[j].Data, dataPos, 256);
                    dataPos += 256;
                }
            }
            for (int i = 0; i < Tracks.Count; ++i)
            {
                for (int j = 0; j < Tracks[i].Sectors.Count; ++j)
                {
                    Tracks[i].Sectors[j].Free = !IsSectorMarkedAsUsedInBAM(i + 1, j);
                }
            }

            if ((diskData.Length == 175531) ||
                (diskData.Length == 197376))
            {
                // error info appended
                for (int i = 0; i < Tracks.Count; ++i)
                {
                    for (int j = 0; j < Tracks[i].Sectors.Count; ++j)
                    {
                        Tracks[i].Sectors[j].SectorErrorCode = diskData.ByteAt(dataPos);
                        ++dataPos;
                    }
                }
            }
            return(true);
        }
        public void SetPixel(int X, int Y, uint Value)
        {
            if ((X < 0) ||
                (X >= m_Width) ||
                (Y < 0) ||
                (Y >= m_Height))
            {
                return;
            }
            if (m_ImageData.Empty())
            {
                return;
            }
            switch (BitsPerPixel)
            {
            case 1:
                unsafe
                {
                    int  pitch     = (Width + 7) / 8;
                    byte origValue = m_ImageData.ByteAt(Y * pitch + X / 8);
                    byte newValue  = origValue;

                    if (Value != 0)
                    {
                        newValue = (byte)(origValue | (128 >> (X % 8)));
                    }
                    else
                    {
                        newValue = (byte)(origValue & (~(128 >> (X % 8))));
                    }
                    m_ImageData.SetU8At(Y * pitch + X / 8, newValue);
                }
                break;

            case 4:
                unsafe
                {
                    int pitch = Width / 2;

                    byte origValue = m_ImageData.ByteAt(Y * pitch + X / 2);
                    byte newValue  = 0;

                    if ((X % 2) == 0)
                    {
                        newValue = (byte)((origValue & 0x0f) | ((byte)Value << 4));
                    }
                    else
                    {
                        newValue = (byte)((origValue & 0xf0) | (byte)Value);
                    }

                    m_ImageData.SetU8At(Y * pitch + X / 2, newValue);
                };
                break;

            case 8:
                m_ImageData.SetU8At(Y * m_Width + X, (byte)Value);
                break;

            case 16:
                m_ImageData.SetU16At(2 * (Y * m_Width + X),
                                     (ushort)((((Value & 0xff0000) >> 19) << 10)
                                              + (((Value & 0x00ff00) >> 11) << 5)
                                              + (((Value & 0x0000ff) >> 3))));
                break;

            case 24:
                m_ImageData.SetU8At(3 * (Y * m_Width + X) + 0, (byte)(Value & 0xff));
                m_ImageData.SetU8At(3 * (Y * m_Width + X) + 1, (byte)((Value & 0xff00) >> 8));
                m_ImageData.SetU8At(3 * (Y * m_Width + X) + 2, (byte)((Value & 0xff0000) >> 16));
                break;

            case 32:
                m_ImageData.SetU32At(4 * (Y * m_Width + X), Value);
                break;

            default:
                throw new NotSupportedException("Bitdepth " + BitsPerPixel + " not supported yet");
            }
        }
Exemple #8
0
        public static GR.Image.MemoryImage BitmapFromKoala(GR.Memory.ByteBuffer koala)
        {
            byte fullValue;
            byte value;
            byte currentColor;

            int xCooBase = 0;
            int yCooBase = 0;

            GR.Image.MemoryImage Image = new GR.Image.MemoryImage(320, 200, System.Drawing.Imaging.PixelFormat.Format8bppIndexed);

            // Set the palette to the C64 one
            PaletteManager.ApplyPalette(Image);

            if (koala.Length >= 10002)
            {
                // Last Byte is Background Color and global
                Byte backgroundColor = koala.ByteAt(10002);

                for (int y = 0; y < 1000; y++)
                {
                    // koala has 3 colors which can be selected for ech "cell" (8x8 pixel)
                    byte lowerNibbleColor = (byte)(((((koala.ByteAt(y + 8002)) << 4) & 0xFF) >> 4));
                    byte upperNibbleColor = (byte)(koala.ByteAt(y + 8002) >> 4);
                    byte colorRamColor    = koala.ByteAt(y + 9002);

                    for (int x = 0; x < 8; x++)
                    {
                        fullValue = koala.ByteAt((8 * y) + x + 2);

                        for (int z = 0; z < 4; z++)
                        {
                            value = (byte)(((fullValue << (z * 2)) & 0xFF) >> 6);

                            switch (value)
                            {
                            case 0:
                                currentColor = backgroundColor;
                                break;

                            case 1:
                                currentColor = upperNibbleColor;
                                break;

                            case 2:
                                currentColor = lowerNibbleColor;
                                break;

                            default:
                                currentColor = colorRamColor;
                                break;
                            }
                            Image.SetPixel(((xCooBase * 4) * 2 + (z * 2)), yCooBase * 8 + x, currentColor);
                            // koala is doublepixel, so we repeat it for the right neighbour
                            Image.SetPixel(((xCooBase * 4) * 2 + (z * 2) + 1), yCooBase * 8 + x, currentColor);
                        }
                    }

                    xCooBase++;
                    if (xCooBase == 40)
                    {
                        xCooBase = 0;
                        yCooBase++;
                    }
                }
            }
            return(Image);
        }
Exemple #9
0
        public static string ToASMData(GR.Memory.ByteBuffer Data, bool WrapData, int WrapByteCount, string DataByteDirective, bool AsHex)
        {
            StringBuilder sb = new StringBuilder();

            if (WrapData)
            {
                sb.Append(DataByteDirective);
                sb.Append(' ');

                int byteCount = 0;
                for (int i = 0; i < Data.Length; ++i)
                {
                    if (AsHex)
                    {
                        sb.Append('$');
                        sb.Append(Data.ByteAt(i).ToString("x2"));
                    }
                    else
                    {
                        sb.Append(Data.ByteAt(i).ToString());
                    }

                    ++byteCount;
                    if ((byteCount < WrapByteCount) &&
                        (i < Data.Length - 1))
                    {
                        sb.Append(',');
                    }
                    if (byteCount == WrapByteCount)
                    {
                        byteCount = 0;

                        sb.AppendLine();
                        if (i < Data.Length - 1)
                        {
                            sb.Append(DataByteDirective);
                            sb.Append(' ');
                        }
                    }
                }
            }
            else
            {
                sb.Append(DataByteDirective);
                sb.Append(' ');
                for (int i = 0; i < Data.Length; ++i)
                {
                    if (AsHex)
                    {
                        sb.Append('$');
                        sb.Append(Data.ByteAt(i).ToString("x2"));
                    }
                    else
                    {
                        sb.Append(Data.ByteAt(i).ToString());
                    }
                    if (i < Data.Length - 1)
                    {
                        sb.Append(',');
                    }
                }
            }
            return(sb.ToString());
        }
Exemple #10
0
        public void UpdateValue(string WatchVar, bool IndexedX, bool IndexedY, GR.Memory.ByteBuffer Data)
        {
            foreach (ListViewItem item in listWatch.Items)
            {
                WatchEntry watchEntry = (WatchEntry)item.Tag;

                if ((watchEntry.Name == WatchVar) &&
                    (watchEntry.IndexedX == IndexedX) &&
                    (watchEntry.IndexedY == IndexedY))
                {
                    watchEntry.CurrentValue = Data;

                    if (watchEntry.SizeInBytes != watchEntry.CurrentValue.Length)
                    {
                        Debug.Log("Watch entry received different size than expected!");
                    }

                    if (watchEntry.CurrentValue.Length == 0)
                    {
                        item.SubItems[2].Text = "(unread)";
                        continue;
                    }

                    switch (watchEntry.Type)
                    {
                    case WatchEntry.DisplayType.HEX:
                        if (watchEntry.DisplayMemory)
                        {
                            StringBuilder sb = new StringBuilder();

                            sb.Append("$");
                            if (watchEntry.BigEndian)
                            {
                                for (int i = 0; i < Data.Length; ++i)
                                {
                                    sb.Append(Data.ByteAt(i).ToString("x2"));
                                    if (i + 1 < Data.Length)
                                    {
                                        sb.Append(" ");
                                    }
                                }
                            }
                            else
                            {
                                for (int i = 0; i < Data.Length; ++i)
                                {
                                    sb.Append(Data.ByteAt((int)Data.Length - 1 - i).ToString("x2"));
                                    if (i + 1 < Data.Length)
                                    {
                                        sb.Append(" ");
                                    }
                                }
                            }
                            item.SubItems[2].Text = sb.ToString();
                        }
                        else
                        {
                            item.SubItems[2].Text = "$" + watchEntry.Address.ToString("x4");
                        }
                        break;

                    case WatchEntry.DisplayType.DEZ:
                        if (!watchEntry.DisplayMemory)
                        {
                            item.SubItems[2].Text = watchEntry.Address.ToString();
                        }
                        else if (watchEntry.SizeInBytes == 1)
                        {
                            item.SubItems[2].Text = Data.ByteAt(0).ToString();
                        }
                        else if (watchEntry.BigEndian)
                        {
                            string totalText = "";
                            for (uint i = 0; i < Data.Length; ++i)
                            {
                                totalText += Data.ByteAt((int)i).ToString("d") + " ";
                            }
                            item.SubItems[2].Text = totalText;
                        }
                        else
                        {
                            string totalText = "";
                            for (uint i = 0; i < Data.Length; ++i)
                            {
                                totalText += Data.ByteAt((int)Data.Length - 1 - (int)i).ToString("d") + " ";
                            }
                            item.SubItems[2].Text = totalText;
                        }
                        break;

                    case WatchEntry.DisplayType.BINARY:
                        if (!watchEntry.DisplayMemory)
                        {
                            item.SubItems[2].Text = "%" + Convert.ToString(watchEntry.Address, 2);
                        }
                        else if (watchEntry.SizeInBytes == 1)
                        {
                            item.SubItems[2].Text = "%" + Convert.ToString(Data.ByteAt(0), 2);
                        }
                        else if (watchEntry.SizeInBytes == 2)
                        {
                            item.SubItems[2].Text = "%" + Convert.ToString(Data.UInt16At(0), 2);
                        }
                        else
                        {
                            item.SubItems[2].Text = Data.ToString();
                        }
                        break;

                    default:
                        if (watchEntry.DisplayMemory)
                        {
                            item.SubItems[2].Text = Data.ByteAt(0).ToString();
                        }
                        else
                        {
                            item.SubItems[2].Text = watchEntry.Address.ToString("x4");
                        }
                        break;
                    }
                }
            }
        }
Exemple #11
0
        private string MnemonicToString(Tiny64.Opcode opcode, GR.Memory.ByteBuffer Data, int DataStartAddress, int CodePos, GR.Collections.Set <ushort> AccessedAddresses, GR.Collections.Map <int, string> NamedLabels)
        {
            string output = opcode.Mnemonic.ToLower();

            ushort targetAddress = 0;
            bool   twoBytes      = true;

            switch (opcode.Addressing)
            {
            case Tiny64.Opcode.AddressingType.IMPLICIT:
                break;

            case Tiny64.Opcode.AddressingType.ABSOLUTE:
                targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress);
                break;

            case Tiny64.Opcode.AddressingType.ABSOLUTE_X:
                targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress);
                break;

            case Tiny64.Opcode.AddressingType.ABSOLUTE_Y:
                targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress);
                break;

            case Tiny64.Opcode.AddressingType.IMMEDIATE:
                targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress);
                twoBytes      = false;
                break;

            case Tiny64.Opcode.AddressingType.INDIRECT:
                targetAddress = Data.UInt16At(CodePos + 1 - DataStartAddress);
                break;

            case Tiny64.Opcode.AddressingType.INDIRECT_X:
                targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress);
                twoBytes      = false;
                break;

            case Tiny64.Opcode.AddressingType.INDIRECT_Y:
                targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress);
                twoBytes      = false;
                break;

            case Tiny64.Opcode.AddressingType.RELATIVE:
            {
                // int delta = value - lineInfo.AddressStart - 2;
                sbyte relValue = (sbyte)Data.ByteAt(CodePos + 1 - DataStartAddress);

                targetAddress = (ushort)(relValue + 2 + CodePos);
            }
            break;

            case Tiny64.Opcode.AddressingType.ZEROPAGE:
                targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress);
                twoBytes      = false;
                break;

            case Tiny64.Opcode.AddressingType.ZEROPAGE_X:
                targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress);
                twoBytes      = false;
                break;

            case Tiny64.Opcode.AddressingType.ZEROPAGE_Y:
                targetAddress = Data.ByteAt(CodePos + 1 - DataStartAddress);
                twoBytes      = false;
                break;
            }
            string addressPlacement;

            if (twoBytes)
            {
                addressPlacement = "$" + targetAddress.ToString("x4");
            }
            else
            {
                addressPlacement = "$" + targetAddress.ToString("x2");
            }

            if (AccessedAddresses.ContainsValue(targetAddress))
            {
                addressPlacement = "label_" + targetAddress.ToString("x4");
            }

            if (NamedLabels.ContainsKey(targetAddress))
            {
                addressPlacement = NamedLabels[targetAddress];
            }

            switch (opcode.Addressing)
            {
            case Tiny64.Opcode.AddressingType.IMPLICIT:
                break;

            case Tiny64.Opcode.AddressingType.ABSOLUTE:
                output += " " + addressPlacement;
                break;

            case Tiny64.Opcode.AddressingType.ABSOLUTE_X:
                output += " " + addressPlacement + ", x";
                break;

            case Tiny64.Opcode.AddressingType.ABSOLUTE_Y:
                output += " " + addressPlacement + ", y";
                break;

            case Tiny64.Opcode.AddressingType.IMMEDIATE:
                output += " #" + addressPlacement;
                break;

            case Tiny64.Opcode.AddressingType.INDIRECT:
                output += " ( " + addressPlacement + " )";
                break;

            case Tiny64.Opcode.AddressingType.INDIRECT_X:
                output += " ( " + addressPlacement + ", x)";
                break;

            case Tiny64.Opcode.AddressingType.INDIRECT_Y:
                output += " ( " + addressPlacement + " ), y";
                break;

            case Tiny64.Opcode.AddressingType.RELATIVE:
            {
                // int delta = value - lineInfo.AddressStart - 2;

                output += " " + addressPlacement;
                //output += " (" + delta.ToString( "X2" ) + ")";
            }
            break;

            case Tiny64.Opcode.AddressingType.ZEROPAGE:
                output += " " + addressPlacement;
                break;

            case Tiny64.Opcode.AddressingType.ZEROPAGE_X:
                output += " " + addressPlacement + ", x";
                break;

            case Tiny64.Opcode.AddressingType.ZEROPAGE_Y:
                output += " " + addressPlacement + ", y";
                break;
            }
            return(output);
        }
Exemple #12
0
        bool AddDirectoryEntry(GR.Memory.ByteBuffer Filename, int StartTrack, int StartSector, int SectorsWritten, C64Studio.Types.FileType Type)
        {
            _LastError = "";
            Track dirTrack      = Tracks[TRACK_DIRECTORY - 1];
            byte  dirTrackIndex = (byte)TRACK_DIRECTORY;

            int directoryInterleave = 3;

            int sector = 1;

            do
            {
                Sector sect = dirTrack.Sectors[sector];
                for (int i = 0; i < 8; ++i)
                {
                    if (sect.Data.ByteAt(BYTES_PER_DIR_ENTRY * i + 2) == 0)
                    {
                        // scratched (empty) entry
                        // default set PRG
                        if (i > 0)
                        {
                            // set track/sector of next dir sector
                            sect.Data.SetU8At(0, 0);
                            sect.Data.SetU8At(1, 0);
                        }
                        sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 2, (byte)Type);
                        sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 3, (byte)StartTrack);
                        sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 4, (byte)StartSector);

                        for (int j = 0; j < 16; ++j)
                        {
                            sect.Data.SetU8At(BYTES_PER_DIR_ENTRY * i + 5 + j, Filename.ByteAt(j));
                        }
                        sect.Data.SetU16At(BYTES_PER_DIR_ENTRY * i + 30, (UInt16)SectorsWritten);
                        return(true);
                    }
                }
                // do we need to alloc next dir sector?
                do
                {
                    sector = (sector + directoryInterleave) % dirTrack.Sectors.Count;

                    // do NOT write into BAM
                }while (sector == SECTOR_BAM);

                if (sector == 1)
                {
                    // arrived at starting sector, disk full!
                    break;
                }
                if (sect.Data.ByteAt(0) == 0)
                {
                    // current sector was last dir sector
                    sect.Data.SetU8At(0, dirTrackIndex);
                    sect.Data.SetU8At(1, (byte)(sector));
                    AllocSector(dirTrackIndex, sector);

                    dirTrack.Sectors[sector].Data.SetU8At(0, 0);
                    dirTrack.Sectors[sector].Data.SetU8At(1, 0xff);
                }
            }while (true);
            _LastError = "disk is full";
            return(false);
        }
        private bool LoadVersion8(GR.Memory.ByteBuffer Data)
        {
            DisplayModeFile = (DisplayMode)Data.ByteAt(4);
            TileColorMode   = (ColorMode)Data.ByteAt(5);

            byte flags = Data.ByteAt(6);

            BackgroundColor  = Data.ByteAt(7);
            MultiColor1      = Data.ByteAt(8);
            MultiColor2      = Data.ByteAt(9);
            BackgroundColor4 = Data.ByteAt(10);

            BaseCellColorColorMatrix = Data.ByteAt(11);
            BaseCellColorScreenLo    = Data.ByteAt(12);
            BaseCellColorScreenHi    = Data.ByteAt(13);

            bool tileSysEnabled = ((flags & 0x01) != 0);


            ushort charDataBlockID      = 0xdab0;
            ushort charAttributeBlockID = 0xdab1;
            ushort charSetColorBlockID  = 0;
            ushort tileSetDataBlockID   = 0;
            ushort tileSetColorBlockID  = 0;
            ushort tileSetTagBlockID    = 0;
            ushort tileSetNameBlockID   = 0;
            ushort mapDataBlockID       = 0;

            int curBlockID = 0xdab2;

            if (TileColorMode == ColorMode.PER_CHAR)
            {
                charSetColorBlockID = (ushort)curBlockID++;
            }
            if (tileSysEnabled)
            {
                tileSetDataBlockID = (ushort)curBlockID++;
                if (TileColorMode == ColorMode.PER_TILE)
                {
                    tileSetColorBlockID = (ushort)curBlockID++;
                }
                tileSetTagBlockID  = (ushort)curBlockID++;
                tileSetNameBlockID = (ushort)curBlockID++;
            }
            mapDataBlockID = (ushort)curBlockID++;

            if (!tileSysEnabled)
            {
                // fake tiles (one per char)
                TileWidth  = 1;
                TileHeight = 1;
                NumTiles   = 256;

                for (int i = 0; i < NumTiles; ++i)
                {
                    Tile tile = new Tile();

                    tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                    tile.CharData.SetU16At(0, (ushort)i);

                    tile.ColorData.Resize((uint)(TileWidth * TileHeight));
                    tile.ColorData.SetU8At(0, (byte)CustomColor);

                    Tiles.Add(tile);
                }
            }

            var reader = Data.MemoryReader();

            reader.Skip(14);

            while (reader.DataAvailable)
            {
                ushort blockID = reader.ReadUInt16NetworkOrder();

                if (blockID == charDataBlockID)
                {
                    // Character data block

                    // CHARCNT: Character image count minus one( 16 - bit, LSBF ).
                    NumChars = reader.ReadUInt16() + 1;

                    // CHARDAT : Character image data( eight bytes / rows per image for CHARCNT images, rows are in TB order ).
                    for (int charIndex = 0; charIndex < NumChars; ++charIndex)
                    {
                        SingleChar newChar = new SingleChar();
                        newChar.Data  = new GR.Memory.ByteBuffer();
                        newChar.Color = CustomColor;
                        reader.ReadBlock(newChar.Data, 8);
                        Characters.Add(newChar);
                    }

                    if (!tileSysEnabled)
                    {
                        if (NumChars < 256)
                        {
                            // add all chars for safety reasons
                            for (int i = NumChars; i < 256; ++i)
                            {
                                SingleChar newChar = new SingleChar();
                                newChar.Data  = new GR.Memory.ByteBuffer(8);
                                newChar.Color = CustomColor;

                                Characters.Add(newChar);
                            }
                        }
                    }
                }
                else if (blockID == charAttributeBlockID)
                {
                    // char attributes
                    // BLKMARK: Block marker(0xDA, 0xB1).
                    // CHARATTS: Char attribute data, one byte per char image for CHARCNT images, low nybble = colour, high nybble = material.
                    //           nb.colours are only stored when the colouring mode is "per character".
                    for (int charIndex = 0; charIndex < NumChars; ++charIndex)
                    {
                        if (TileColorMode == ColorMode.PER_CHAR)
                        {
                            Characters[charIndex].Color = reader.ReadUInt8() & 0x0f;
                            if (!tileSysEnabled)
                            {
                                Tiles[charIndex].ColorData.SetU8At(0, (byte)Characters[charIndex].Color);
                            }
                        }
                    }
                }
                else if (blockID == charSetColorBlockID)
                {
                    // Character set colours block (only present if the project uses per-char colouring)...
                    //
                    // BLKMARK         : Block marker (0xDA, 0xBn).
                    // MTRXCOLRS_CHARS : Char colour data, 1-3 bytes per char image for CHARCNT images...
                    //
                    //    Colour_CmLo : Colour Matrix Low nybble (0-15) (not present if DISP_MODE is Bitmap_HR).
                    //    Colour_SmLo : Screen Matrix Low nybble (0-15) (only present if DISP_MODE is Bitmap_HR or Bitmap_MC).
                    //    Colour_SmHi : Screen Matrix High nybble (0-15) (only present if DISP_MODE is Bitmap_HR or Bitmap_MC).
                    //
                    //    Notes:-
                    //    - The colours in this block are intended for transfer to the C64 colour RAM cells and/or screen RAM cells.
                    //    - The usage / usefulness of a colour will depend on the display mode.
                    //    - Only the low nybbles of each byte are currently used, each provides a colour 0-15.

                    for (int i = 0; i < NumChars; ++i)
                    {
                        if (DisplayModeFile != DisplayMode.BITMAP_HIRES)
                        {
                            Characters[i].Color = reader.ReadUInt8();
                        }
                        if ((DisplayModeFile == DisplayMode.BITMAP_MC) ||
                            (DisplayModeFile == DisplayMode.BITMAP_HIRES))
                        {
                            // screen color lo
                            reader.ReadUInt8();
                            // screen color hi
                            reader.ReadUInt8();
                        }
                        if (!tileSysEnabled)
                        {
                            // use the charset color for our faked tiles
                            Tiles[i].ColorData.SetU8At(0, (byte)Characters[i].Color);
                        }
                    }
                }
                else if (blockID == tileSetDataBlockID)
                {
                    // Tile data block

                    // TILECNT: Tile count minus one(16 - bit, LSBF).
                    NumTiles = reader.ReadUInt16() + 1;

                    // TILEWID: Tile width( byte).
                    TileWidth = reader.ReadUInt8();
                    // TILEHEI: Tile height( byte).
                    TileHeight = reader.ReadUInt8();

                    // TILEDAT: Tile data, 16 bits per tile cell( LSBF) for TILEWID* TILEHEI cells * TILECNT items, cells are in LRTB order.
                    for (int i = 0; i < NumTiles; ++i)
                    {
                        Tile tile = new Tile();

                        tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                        tile.ColorData.Resize((uint)(TileWidth * TileHeight));

                        Tiles.Add(tile);
                    }
                    if (NumChars < 256)
                    {
                        // add all chars for safety reasons
                        for (int i = NumChars; i < 256; ++i)
                        {
                            SingleChar newChar = new SingleChar();
                            newChar.Data = new GR.Memory.ByteBuffer(8);
                            Characters.Add(newChar);
                        }
                    }
                    for (int i = 0; i < NumTiles; ++i)
                    {
                        for (int j = 0; j < TileWidth * TileHeight; ++j)
                        {
                            Tiles[i].CharData.SetU16At(j * 2, reader.ReadUInt16());
                        }
                    }
                }
                else if (blockID == tileSetColorBlockID)
                {
                    // Tile color block

                    // BLKMARK         : Block marker (0xDA, 0xBn).
                    // MTRXCOLRS_TILES : Tile colour data, 1-3 bytes per tile for TILECNT tiles...
                    //
                    //    Colour_CmLo : Colour Matrix Low nybble (0-15) (not present if DISP_MODE is Bitmap_HR).
                    //    Colour_SmLo : Screen Matrix Low nybble (0-15) (only present if DISP_MODE is Bitmap_HR or Bitmap_MC).
                    //    Colour_SmHi : Screen Matrix High nybble (0-15) (only present if DISP_MODE is Bitmap_HR or Bitmap_MC).
                    //
                    //    Notes:-
                    //    - The colours in this block are intended for transfer to the C64 colour RAM cells and/or screen RAM cells.
                    //    - The usage / usefulness of a colour will depend on the display mode.
                    //    - Only the low nybbles of each byte are currently used, each provides a colour 0-15.

                    for (int i = 0; i < NumTiles; ++i)
                    {
                        if (DisplayModeFile != DisplayMode.BITMAP_HIRES)
                        {
                            // tile generic color
                            reader.ReadUInt8();
                        }
                        if ((DisplayModeFile == DisplayMode.BITMAP_MC) ||
                            (DisplayModeFile == DisplayMode.BITMAP_HIRES))
                        {
                            // screen color lo
                            reader.ReadUInt8();
                            // screen color hi
                            reader.ReadUInt8();
                        }
                    }
                }
                else if (blockID == tileSetTagBlockID)
                {
                    // BLKMARK  : Block marker (0xDA, 0xBn).
                    // TILETAGS : Tile tag values, one byte per tile for TILECNT items.
                    for (int i = 0; i < NumTiles; ++i)
                    {
                        byte tileTag = reader.ReadUInt8();
                    }
                }
                else if (blockID == tileSetNameBlockID)
                {
                    // BLKMARK  : Block marker (0xDA, 0xBn).
                    // TILETAGS : Tile tag values, one byte per tile for TILECNT items.
                    for (int i = 0; i < NumTiles; ++i)
                    {
                        // zero terminated strings (urgh)
                        string name = "";
                        char   c    = (char)0;
                        do
                        {
                            c = (char)reader.ReadUInt8();
                            if (c != 0)
                            {
                                name += c;
                            }
                        }while (c != 0);
                        Tiles[i].Name = name;
                    }
                }
                else if (blockID == mapDataBlockID)
                {
                    // BLKMARK : Block marker (0xDA, 0xBn).
                    // MAPWID: Map Width(16 - bit, LSBF).
                    // MAPHEI: Map height(16 - bit, LSBF).
                    // MAPDAT: Map data, 16 bits per cell( LSBF ) for MAPWID* MAPHEI cells, cells are in LRTB order.
                    MapWidth  = reader.ReadUInt16();
                    MapHeight = reader.ReadUInt16();

                    MapData = new GR.Memory.ByteBuffer((uint)(MapWidth * MapHeight));
                    if (!tileSysEnabled)
                    {
                        // map has color data
                        MapColorData = new GR.Memory.ByteBuffer((uint)(MapWidth * MapHeight));
                    }

                    for (int i = 0; i < MapHeight; ++i)
                    {
                        for (int j = 0; j < MapWidth; ++j)
                        {
                            ushort mapData = reader.ReadUInt16();

                            // we only support 8 bytes per char
                            MapData.SetU8At(i * MapWidth + j, (byte)mapData); // do we?? Mega65!

                            if (TileColorMode == ColorMode.PER_CHAR)
                            {
                                MapColorData.SetU8At(i * MapWidth + j, (byte)Characters[(byte)mapData].Color);
                            }
                        }
                    }
                }
                else
                {
                    Debug.Log("Unexpected block ID: " + blockID.ToString("X"));
                    return(false);
                }
            }
            return(true);
        }
Exemple #14
0
        private bool LoadVersion5(GR.Memory.ByteBuffer Data)
        {
            BackgroundColor = Data.ByteAt(4);
            MultiColor1     = Data.ByteAt(5);
            MultiColor2     = Data.ByteAt(6);
            CustomColor     = Data.ByteAt(7);
            TileColorMode   = (ColorMode)Data.ByteAt(8);

            byte flags   = Data.ByteAt(9);
            bool noTiles = ((flags & 0x01) == 0);

            MultiColor = ((flags & 0x04) != 0);
            bool isExpanded = ((flags & 0x02) != 0);

            NumChars   = Data.UInt16At(10) + 1;
            NumTiles   = Data.UInt16At(12) + 1;
            TileWidth  = Data.ByteAt(14);
            TileHeight = Data.ByteAt(15);

            MapWidth  = Data.UInt16At(16);
            MapHeight = Data.UInt16At(18);

            if (noTiles)
            {
                // fake tiles
                TileWidth  = 1;
                TileHeight = 1;
                NumTiles   = 256;
            }


            int headerSize          = 20;
            int offsetToCharData    = headerSize;
            int offsetToCharAttribs = offsetToCharData + NumChars * 8;
            int offsetToTileData    = offsetToCharAttribs + NumChars;
            int offsetToTileColors  = offsetToTileData + NumTiles * TileWidth * TileHeight * 2;

            if ((isExpanded) ||
                (noTiles))
            {
                offsetToTileColors = offsetToTileData;
            }
            int offsetToMapData = offsetToTileColors + NumTiles;

            if ((TileColorMode != ColorMode.PER_TILE) ||
                (noTiles))
            {
                offsetToMapData = offsetToTileColors;
            }

            // char_data/char_attribs
            for (int charIndex = 0; charIndex < NumChars; ++charIndex)
            {
                SingleChar newChar = new SingleChar();
                newChar.Data = Data.SubBuffer(offsetToCharData + charIndex * 8, 8);
                if (TileColorMode == ColorMode.PER_TILE_CELL)
                {
                    newChar.Color = Data.ByteAt(offsetToCharAttribs + charIndex) & 0x0f;
                }
                else
                {
                    newChar.Color = CustomColor;
                }

                Characters.Add(newChar);
            }

            // tile_data
            if (noTiles)
            {
                for (int i = 0; i < NumTiles; ++i)
                {
                    Tile tile = new Tile();

                    tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                    tile.CharData.SetU16At(0, (ushort)i);

                    tile.ColorData.Resize((uint)(TileWidth * TileHeight));
                    tile.ColorData.SetU8At(0, (byte)CustomColor);

                    Tiles.Add(tile);
                }
                if (NumChars < 256)
                {
                    // add all chars for safety reasons
                    for (int i = NumChars; i < 256; ++i)
                    {
                        SingleChar newChar = new SingleChar();
                        newChar.Data = new GR.Memory.ByteBuffer(8);
                        if (TileColorMode == ColorMode.PER_TILE_CELL)
                        {
                            newChar.Color = Data.ByteAt(offsetToCharAttribs + i) & 0x0f;
                        }
                        else
                        {
                            newChar.Color = CustomColor;
                        }

                        Characters.Add(newChar);
                    }
                }
            }
            else
            {
                for (int i = 0; i < NumTiles; ++i)
                {
                    Tile tile = new Tile();

                    tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                    tile.ColorData.Resize((uint)(TileWidth * TileHeight));

                    Tiles.Add(tile);
                }

                if (isExpanded)
                {
                    byte curCharIndex = 0;
                    for (int i = 0; i < NumTiles; ++i)
                    {
                        for (int j = 0; j < TileWidth * TileHeight; ++j)
                        {
                            Tiles[i].CharData.SetU16At(j * 2, curCharIndex);
                            ++curCharIndex;
                        }
                    }
                }
                else
                {
                    // tile_data.      Size = NUM_TILES * TILE_WIDTH * TILE_HEIGHT bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded")
                    for (int i = 0; i < NumTiles; ++i)
                    {
                        for (int j = 0; j < TileWidth * TileHeight; ++j)
                        {
                            Tiles[i].CharData.SetU16At(j * 2, Data.UInt16At(offsetToTileData + i * TileWidth * TileHeight * 2 + j * 2));
                        }
                    }
                }
            }

            // TILE_COLOURS.   Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile)
            if (TileColorMode == ColorMode.PER_TILE)
            {
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int y = 0; y < TileHeight; ++y)
                    {
                        for (int x = 0; x < TileWidth; ++x)
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetToTileColors + i) & 0x0f));
                        }
                    }
                }
            }
            else if (TileColorMode == ColorMode.PER_TILE_CELL)
            {
                // with V5 this actually means per character
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int y = 0; y < TileHeight; ++y)
                    {
                        for (int x = 0; x < TileWidth; ++x)
                        {
                            byte charColor = (byte)Characters[Tiles[i].CharData.ByteAt(2 * (x + y * TileWidth))].Color;
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, charColor);
                        }
                    }
                }
            }
            else if (TileColorMode == ColorMode.GLOBAL)
            {
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int y = 0; y < TileHeight; ++y)
                    {
                        for (int x = 0; x < TileWidth; ++x)
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)CustomColor);
                        }
                    }
                }
            }

            /*
             * else if ( TileColorMode == ColorMode.PER_TILE_CELL )
             * {
             * for ( int i = 0; i < NumTiles; ++i )
             * {
             *  for ( int y = 0; y < TileHeight; ++y )
             *  {
             *    for ( int x = 0; x < TileWidth; ++x )
             *    {
             *      Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) );
             *    }
             *  }
             * }
             * }*/

            // MAP_DATA.        Size =  MAP_WID x MAP_HEI bytes.
            // tile indices are now 16 bit! for now force 8bit

            //MapData = Data.SubBuffer( offsetMapData, MapWidth * MapHeight * 2 );

            MapData = new GR.Memory.ByteBuffer((uint)(MapWidth * MapHeight));

            for (int i = 0; i < MapHeight; ++i)
            {
                for (int j = 0; j < MapWidth; ++j)
                {
                    MapData.SetU8At(i * MapWidth + j, Data.ByteAt(offsetToMapData + 2 * (i * MapWidth + j)));
                }
            }
            return(true);
        }
        public bool LoadFromFile(GR.Memory.ByteBuffer Data)
        {
            Characters.Clear();
            MapData.Clear();

            if ((Data == null) ||
                (Data.Length < 24) ||
                (Data.ByteAt(0) != 'C') ||
                (Data.ByteAt(1) != 'T') ||
                (Data.ByteAt(2) != 'M'))
            {
                // not a valid CTM file
                return(false);
            }
            int version = Data.ByteAt(3);

            if (version != 4)
            {
                System.Windows.Forms.MessageBox.Show("Currently only version 4 of Charpad project files is supported. Sorry!", "Unsupported version " + version);
                return(false);
            }

            BackgroundColor = Data.ByteAt(4);
            MultiColor1     = Data.ByteAt(5);
            MultiColor2     = Data.ByteAt(6);
            CustomColor     = Data.ByteAt(7);
            TileColorMode   = (ColorMode)Data.ByteAt(8);
            MultiColor      = (Data.ByteAt(9) != 0);

            NumChars   = Data.UInt16At(10) + 1;
            NumTiles   = Data.ByteAt(12) + 1;
            TileWidth  = Data.ByteAt(13);
            TileHeight = Data.ByteAt(14);

            MapWidth  = Data.UInt16At(15);
            MapHeight = Data.UInt16At(17);

            bool isExpanded = (Data.ByteAt(19) != 0);

            int offsetToCharAttribs = 24 + NumChars * 8;

            for (int charIndex = 0; charIndex < NumChars; ++charIndex)
            {
                SingleChar newChar = new SingleChar();
                newChar.Data  = Data.SubBuffer(24 + charIndex * 8, 8);
                newChar.Color = Data.ByteAt(offsetToCharAttribs + charIndex) & 0x0f;

                Characters.Add(newChar);
            }

            for (int i = 0; i < NumTiles; ++i)
            {
                Tile tile = new Tile();

                tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                tile.ColorData.Resize((uint)(TileWidth * TileHeight));

                Tiles.Add(tile);
            }

            if (isExpanded)
            {
                byte curCharIndex = 0;
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int j = 0; j < TileWidth * TileHeight; ++j)
                    {
                        Tiles[i].CharData.SetU16At(j * 2, curCharIndex);
                        ++curCharIndex;
                    }
                }
            }
            else
            {
                // CELL_DATA.      Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded")
                int offsetCellData = 24 + NumChars * 8 + NumChars;
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int j = 0; j < TileWidth * TileHeight; ++j)
                    {
                        Tiles[i].CharData.SetU16At(j * 2, Data.UInt16At(offsetCellData + i * TileWidth * TileHeight * 2 + j * 2));
                    }
                }
            }
            // CELL_ATTRIBS.   Size = NUM_TILES * TILE_SIZE * TILE_SIZE bytes (exists for ALL modes)

            int offsetCellAttribs = 24 + NumChars * 8 + NumChars;

            if (!isExpanded)
            {
                offsetCellAttribs += NumTiles * TileWidth * TileHeight * 2;
            }
            for (int i = 0; i < NumTiles; ++i)
            {
                for (int y = 0; y < TileHeight; ++y)
                {
                    for (int x = 0; x < TileWidth; ++x)
                    {
                        if (TileColorMode == ColorMode.PER_TILE_CELL)
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight) & 0x0f));
                        }
                        else
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)CustomColor);
                        }
                    }
                }
            }

            // TILE_ATTRIBS.   Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile)
            int offsetTileAttribs = offsetCellAttribs + NumTiles * TileWidth * TileHeight;

            if (TileColorMode == ColorMode.PER_TILE)
            {
                for (int i = 0; i < NumTiles; ++i)
                {
                    for (int y = 0; y < TileHeight; ++y)
                    {
                        for (int x = 0; x < TileWidth; ++x)
                        {
                            Tiles[i].ColorData.SetU8At(x + y * TileWidth, (byte)(Data.ByteAt(offsetTileAttribs + i) & 0x0f));
                        }
                    }
                }
            }

            /*
             * if ( TileColorMode == ColorMode.PER_TILE_CELL )
             * {
             * for ( int i = 0; i < NumTiles; ++i )
             * {
             *  for ( int y = 0; y < TileHeight; ++y )
             *  {
             *    for ( int x = 0; x < TileWidth; ++x )
             *    {
             *      Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) );
             *    }
             *  }
             * }
             * }*/

            // MAP_DATA.        Size =  MAP_WID x MAP_HEI bytes.
            int offsetMapData = offsetTileAttribs;

            if (TileColorMode == ColorMode.PER_TILE)
            {
                offsetMapData += NumTiles;
            }

            MapData = Data.SubBuffer(offsetMapData, MapWidth * MapHeight);
            return(true);
        }
Exemple #16
0
        private bool LoadVersion7(GR.Memory.ByteBuffer Data)
        {
            BackgroundColor  = Data.ByteAt(4);
            MultiColor1      = Data.ByteAt(5);
            MultiColor2      = Data.ByteAt(6);
            BackgroundColor4 = Data.ByteAt(7);
            CustomColor      = Data.ByteAt(8);
            TileColorMode    = (ColorMode)Data.ByteAt(9);

            CharsetMode = (Types.CharsetMode)Data.ByteAt(10);

            byte flags          = Data.ByteAt(11);
            bool tileSysEnabled = ((flags & 0x01) != 0);


            ushort charDataBlockID      = 0xdab0;
            ushort charAttributeBlockID = 0xdab1;
            ushort mapDataBlockID       = 0xdab2;


            if (!tileSysEnabled)
            {
                // fake tiles (one per char)
                TileWidth  = 1;
                TileHeight = 1;
                NumTiles   = 256;

                for (int i = 0; i < NumTiles; ++i)
                {
                    Tile tile = new Tile();

                    tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                    tile.CharData.SetU16At(0, (ushort)i);

                    tile.ColorData.Resize((uint)(TileWidth * TileHeight));
                    tile.ColorData.SetU8At(0, (byte)CustomColor);

                    Tiles.Add(tile);
                }
            }

            var reader = Data.MemoryReader();

            reader.Skip(12);

            while (reader.DataAvailable)
            {
                ushort blockID = reader.ReadUInt16NetworkOrder();

                if (blockID == mapDataBlockID)
                {
                    if (tileSysEnabled)
                    {
                        // Tile data block

                        // TILECNT: Tile count minus one(16 - bit, LSBF).
                        NumTiles = reader.ReadUInt16() + 1;

                        // TILEWID: Tile width( byte).
                        TileWidth = reader.ReadUInt8();
                        // TILEHEI: Tile height( byte).
                        TileHeight = reader.ReadUInt8();

                        // TILEDAT: Tile data, 16 bits per tile cell( LSBF) for TILEWID* TILEHEI cells * TILECNT items, cells are in LRTB order.
                        for (int i = 0; i < NumTiles; ++i)
                        {
                            Tile tile = new Tile();

                            tile.CharData.Resize((uint)(TileWidth * TileHeight * 2));
                            tile.ColorData.Resize((uint)(TileWidth * TileHeight));

                            Tiles.Add(tile);
                        }
                        if (NumChars < 256)
                        {
                            // add all chars for safety reasons
                            for (int i = NumChars; i < 256; ++i)
                            {
                                SingleChar newChar = new SingleChar();
                                newChar.Data = new GR.Memory.ByteBuffer(8);
                                Characters.Add(newChar);
                            }
                        }
                        for (int i = 0; i < NumTiles; ++i)
                        {
                            for (int j = 0; j < TileWidth * TileHeight; ++j)
                            {
                                Tiles[i].CharData.SetU16At(j * 2, reader.ReadUInt16());
                            }
                        }
                    }
                    else
                    {
                        // BLKMARK : Block marker (0xDA, 0xBn).
                        // MAPWID: Map Width(16 - bit, LSBF).
                        // MAPHEI: Map height(16 - bit, LSBF).
                        // MAPDAT: Map data, 16 bits per cell( LSBF ) for MAPWID* MAPHEI cells, cells are in LRTB order.
                        MapWidth  = reader.ReadUInt16();
                        MapHeight = reader.ReadUInt16();

                        MapData = new GR.Memory.ByteBuffer((uint)(MapWidth * MapHeight));

                        for (int i = 0; i < MapHeight; ++i)
                        {
                            for (int j = 0; j < MapWidth; ++j)
                            {
                                MapData.SetU8At(i * MapWidth + j, (byte)reader.ReadUInt16());
                            }
                        }
                    }
                }

                if (blockID == charDataBlockID)
                {
                    // Character data block

                    // CHARCNT: Character image count minus one( 16 - bit, LSBF ).
                    NumChars = reader.ReadUInt16() + 1;

                    // CHARDAT : Character image data( eight bytes / rows per image for CHARCNT images, rows are in TB order ).
                    for (int charIndex = 0; charIndex < NumChars; ++charIndex)
                    {
                        SingleChar newChar = new SingleChar();
                        newChar.Data  = new GR.Memory.ByteBuffer();
                        newChar.Color = CustomColor;
                        reader.ReadBlock(newChar.Data, 8);
                        Characters.Add(newChar);
                    }

                    if (!tileSysEnabled)
                    {
                        if (NumChars < 256)
                        {
                            // add all chars for safety reasons
                            for (int i = NumChars; i < 256; ++i)
                            {
                                SingleChar newChar = new SingleChar();
                                newChar.Data  = new GR.Memory.ByteBuffer(8);
                                newChar.Color = CustomColor;

                                Characters.Add(newChar);
                            }
                        }
                    }
                }
                else if (blockID == charAttributeBlockID)
                {
                    // char attributes
                    // BLKMARK: Block marker(0xDA, 0xB1).
                    // CHARATTS: Char attribute data, one byte per char image for CHARCNT images, low nybble = colour, high nybble = material.
                    //           nb.colours are only stored when the colouring mode is "per character".
                    for (int charIndex = 0; charIndex < NumChars; ++charIndex)
                    {
                        if (TileColorMode == ColorMode.PER_TILE_CELL)
                        {
                            Characters[charIndex].Color = reader.ReadUInt8() & 0x0f;
                            if (!tileSysEnabled)
                            {
                                Tiles[charIndex].ColorData.SetU8At(0, (byte)Characters[charIndex].Color);
                            }
                        }
                    }
                }
            }


            /*
             *
             *
             * int headerSize = 20;
             * int offsetToCharData = headerSize;
             * int offsetToCharAttribs = offsetToCharData + NumChars * 8;
             * int offsetToTileData = offsetToCharAttribs + NumChars;
             * int offsetToTileColors = offsetToTileData + NumTiles * TileWidth * TileHeight * 2;
             * if ( ( tileSysEnabled )
             || ( noTiles ) )
             ||{
             ||offsetToTileColors = offsetToTileData;
             ||}
             ||int offsetToMapData = offsetToTileColors + NumTiles;
             ||if ( ( TileColorMode != ColorMode.PER_TILE )
             || ( noTiles ) )
             ||{
             ||offsetToMapData = offsetToTileColors;
             ||}
             ||
             ||// tile_data
             ||if ( noTiles )
             ||{
             ||for ( int i = 0; i < NumTiles; ++i )
             ||{
             || Tile tile = new Tile();
             ||
             || tile.CharData.Resize( (uint)( TileWidth * TileHeight * 2 ) );
             || tile.CharData.SetU16At( 0, (ushort)i );
             ||
             || tile.ColorData.Resize( (uint)( TileWidth * TileHeight ) );
             || tile.ColorData.SetU8At( 0, (byte)CustomColor );
             ||
             || Tiles.Add( tile );
             ||}
             ||if ( NumChars < 256 )
             ||{
             || // add all chars for safety reasons
             || for ( int i = NumChars; i < 256; ++i )
             || {
             ||   SingleChar    newChar = new SingleChar();
             ||   newChar.Data = new GR.Memory.ByteBuffer( 8 );
             ||   if ( TileColorMode == ColorMode.PER_TILE_CELL )
             ||   {
             ||     newChar.Color = Data.ByteAt( offsetToCharAttribs + i ) & 0x0f;
             ||   }
             ||   else
             ||   {
             ||     newChar.Color = CustomColor;
             ||   }
             ||
             ||   Characters.Add( newChar );
             || }
             ||}
             ||}
             ||else
             ||{
             ||for ( int i = 0; i < NumTiles; ++i )
             ||{
             || Tile tile = new Tile();
             ||
             || tile.CharData.Resize( (uint)( TileWidth * TileHeight * 2 ) );
             || tile.ColorData.Resize( (uint)( TileWidth * TileHeight ) );
             ||
             || Tiles.Add( tile );
             ||}
             ||
             ||if ( tileSysEnabled )
             ||{
             || byte curCharIndex = 0;
             || for ( int i = 0; i < NumTiles; ++i )
             || {
             ||   for ( int j = 0; j < TileWidth * TileHeight; ++j )
             ||   {
             ||     Tiles[i].CharData.SetU16At( j * 2, curCharIndex );
             ++curCharIndex;
             ||   }
             || }
             ||}
             ||else
             ||{
             || // tile_data.      Size = NUM_TILES * TILE_WIDTH * TILE_HEIGHT bytes * 2 bytes. (only exists if CHAR_DATA is not "Expanded")
             || for ( int i = 0; i < NumTiles; ++i )
             || {
             ||   for ( int j = 0; j < TileWidth * TileHeight; ++j )
             ||   {
             ||     Tiles[i].CharData.SetU16At( j * 2, Data.UInt16At( offsetToTileData + i * TileWidth * TileHeight * 2 + j * 2 ) );
             ||   }
             || }
             ||}
             ||}
             ||
             ||// TILE_COLOURS.   Size = NUM_TILES bytes (1 byte per tile = "RAM colour". only exists if COLOR_MODE = 1 (Per Tile)
             ||if ( TileColorMode == ColorMode.PER_TILE )
             ||{
             ||for ( int i = 0; i < NumTiles; ++i )
             ||{
             || for ( int y = 0; y < TileHeight; ++y )
             || {
             ||   for ( int x = 0; x < TileWidth; ++x )
             ||   {
             ||     Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetToTileColors + i ) & 0x0f ) );
             ||   }
             || }
             ||}
             ||}
             ||else if ( TileColorMode == ColorMode.PER_TILE_CELL )
             ||{
             ||// with V5 this actually means per character
             ||for ( int i = 0; i < NumTiles; ++i )
             ||{
             || for ( int y = 0; y < TileHeight; ++y )
             || {
             ||   for ( int x = 0; x < TileWidth; ++x )
             ||   {
             ||     byte    charColor = (byte)Characters[Tiles[i].CharData.ByteAt( 2 * ( x + y * TileWidth ) )].Color;
             ||     Tiles[i].ColorData.SetU8At( x + y * TileWidth, charColor );
             ||   }
             || }
             ||}
             ||}
             ||else if ( TileColorMode == ColorMode.GLOBAL )
             ||{
             ||for ( int i = 0; i < NumTiles; ++i )
             ||{
             || for ( int y = 0; y < TileHeight; ++y )
             || {
             ||   for ( int x = 0; x < TileWidth; ++x )
             ||   {
             ||     Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)CustomColor );
             ||   }
             || }
             ||}
             ||}
             ||else if ( TileColorMode == ColorMode.PER_TILE_CELL )
             ||{
             ||for ( int i = 0; i < NumTiles; ++i )
             ||{
             || for ( int y = 0; y < TileHeight; ++y )
             || {
             ||   for ( int x = 0; x < TileWidth; ++x )
             ||   {
             ||     Tiles[i].ColorData.SetU8At( x + y * TileWidth, (byte)( Data.ByteAt( offsetCellAttribs + i * TileWidth * TileHeight + x + y * TileHeight ) & 0x0f ) );
             ||   }
             || }
             ||}
             ||}
             ||
             */
            return(true);
        }
Exemple #17
0
        public override bool Load(string Filename)
        {
            _LastError = "";
            Clear();
            GR.Memory.ByteBuffer data = GR.IO.File.ReadAllBytes(Filename);
            if (data == null)
            {
                _LastError = "could not open/read file";
                return(false);
            }
            if (data.Length < 64)
            {
                _LastError = "file size is too small";
                return(false);
            }

            // Tape Header
            // 0 32 DOS tape description + EOF (for type)
            // 32 2 tape version ($0200)
            // 34 2 number of directory entries
            // 36 2 number of used entries (can be 0 in my loader)
            // 38 2 free
            // 40 24 user description as displayed in tape menu

            for (int i = 0; i < 32; ++i)
            {
                if (data.ByteAt(i) == (char)0x1a)
                {
                    break;
                }
                TapeInfo.Description += (char)data.ByteAt(i);
            }
            ushort version = data.UInt16At(32);

            /*
             * if ( version != 0x0200 )
             * {
             * return false;
             * }*/
            TapeInfo.NumberEntries     = data.UInt16At(34);
            TapeInfo.NumberUsedEntries = data.UInt16At(36);

            for (int i = 0; i < 24; ++i)
            {
                if (data.ByteAt(40 + i) == (char)0x20)
                {
                    break;
                }
                TapeInfo.UserDescription += (char)data.ByteAt(i);
            }
            int entryPos = 64;

            for (int i = 0; i < TapeInfo.NumberEntries; ++i)
            {
                // File Header
                // Offset Size Description
                // 0 1 entry type (see below)
                // 1 1 C64 file type
                // 2 2 start address
                // 4 2 end address
                // 6 2 free
                // 8 4 offset of file contents start within T64 file
                // 12 4 free
                // 16 16 C64 file name

                // Code Explanation
                // 0 free entry
                // 1 normal tape file
                // 2 tape file with header: header is saved just before file data
                // 3 memory snapshot v0.9, uncompressed
                // 4 tape block
                // 5 digitized stream
                // 6 ... 255 reserved
                FileRecord file = new FileRecord();

                file.EntryType = data.ByteAt(entryPos + 0);
                if ((file.EntryType != 1) &&
                    (file.EntryType != 0))
                {
                    // unsupported type!
                    _LastError = "unsupported entry type";
                    return(false);
                }
                if (file.EntryType == 0)
                {
                    FileRecords.Add(file);
                    FileDatas.Add(new GR.Memory.ByteBuffer());

                    entryPos += 32;
                    continue;
                }
                file.C64FileType  = (C64Studio.Types.FileType)data.ByteAt(entryPos + 1);
                file.StartAddress = data.UInt16At(entryPos + 2);
                file.EndAddress   = data.UInt16At(entryPos + 4);
                file.FileOffset   = data.UInt32At(entryPos + 8);
                for (int j = 0; j < 16; ++j)
                {
                    file.Filename.AppendU8(data.ByteAt(entryPos + 16 + j));
                }
                FileRecords.Add(file);
                FileDatas.Add(data.SubBuffer((int)file.FileOffset, (int)(file.EndAddress - file.StartAddress)));
                entryPos += 32;
            }
            return(true);
        }
Exemple #18
0
            public override float ReadF32()
            {
                if (m_Buffer == null)
                {
                    return(0.0f);
                }
                if (m_Position + 4 > m_Buffer.Length)
                {
                    return(0.0f);
                }
                System.UInt32 ui32 = (uint)m_Buffer.ByteAt(m_Position);

                ui32 |= ((uint)m_Buffer.ByteAt(m_Position + 1) << 8);
                ui32 |= ((uint)m_Buffer.ByteAt(m_Position + 2) << 16);
                ui32 |= ((uint)m_Buffer.ByteAt(m_Position + 3) << 24);

                m_Position += 4;

                return(System.BitConverter.ToSingle(System.BitConverter.GetBytes(ui32), 0));
            }
Exemple #19
0
            public override float ReadF32()
            {
                if (m_Buffer == null)
                {
                    return(0.0f);
                }
                if (m_Position + 4 > m_Buffer.Length)
                {
                    return(0.0f);
                }
                System.UInt32 ui32 = (uint)m_Buffer.ByteAt(m_Position);

                ui32 |= ((uint)m_Buffer.ByteAt(m_Position + 1) << 8);
                ui32 |= ((uint)m_Buffer.ByteAt(m_Position + 2) << 16);
                ui32 |= ((uint)m_Buffer.ByteAt(m_Position + 3) << 24);

                m_Position += 4;

                float Value = System.BitConverter.ToSingle(System.BitConverter.GetBytes(ui32), 0);

                /*
                 * unsafe
                 * {
                 * Value = *(float*)( &ui32 );
                 * }*/

                return(Value);
            }