示例#1
0
        private void StoreButton_Click(object sender, EventArgs e)
        {
            StoreButton.Enabled = false;
            string extension = Path.GetExtension(FileNameTextBox.Text).ToLower();
            bool   binFile   = !extension.Equals("bmp");

            if (!binFile)
            {
                // TODO: determine what to do with the control register
                controlByte = (byte)((LUTCombo.SelectedIndex << 1) + 1);
                Memory.WriteByte(controlRegisterAddress, controlByte); // enable
            }
            // Store the address in the pointer address - little endian - 24 bits
            string strAddress   = LoadAddressTextBox.Text.Replace(":", "");
            int    videoAddress = 0;

            if (strAddress != String.Empty)
            {
                int.TryParse(strAddress, System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.CurrentInfo, out videoAddress);
            }
            int writeVideoAddress = videoAddress;

            ResourceChecker.Resource res = new ResourceChecker.Resource
            {
                StartAddress = videoAddress,
                SourceFile   = FileNameTextBox.Text,
                Name         = Path.GetFileNameWithoutExtension(FileNameTextBox.Text)
            };

            if (!binFile)
            {
                // Store the bitmap at the user's determined address
                // The method below simply takes the file and writes it in memory.
                // What we want is the actual pixels.
                ImageConverter converter   = new ImageConverter();
                byte[]         data        = (byte[])converter.ConvertTo(bitmap, typeof(byte[]));
                int            startOffset = BitConverter.ToInt32(data, 10);
                int            fileLength  = BitConverter.ToInt32(data, 2);
                res.Length = bitmap.Height * bitmap.Width;
                if (ResChecker.Add(res))
                {
                    // The addresses in Vicky a offset by $B0:0000
                    videoAddress = videoAddress - 0xB0_0000;
                    Memory.WriteByte(pointerAddress, LowByte(videoAddress));
                    Memory.WriteByte(pointerAddress + 1, MidByte(videoAddress));
                    Memory.WriteByte(pointerAddress + 2, HighByte(videoAddress));

                    // Store the strides in the strideX and strideY
                    Memory.WriteByte(strideXAddress, LowByte(strideX));
                    Memory.WriteByte(strideXAddress + 1, MidByte(strideX));
                    Memory.WriteByte(strideYAddress, LowByte(strideY));
                    Memory.WriteByte(strideYAddress + 1, MidByte(strideY));



                    int numberOfColors = BitConverter.ToInt32(data, 46);
                    int lutOffset      = 0xAF_2000 + LUTCombo.SelectedIndex * 1024;
                    if (numberOfColors == 0)
                    {
                        // we need to create a LUT - each LUT only accepts 256 entries - 0 is black
                        TransformBitmap(data, startOffset, Int32.Parse(PixelDepthValueLabel.Text), lutOffset, writeVideoAddress, bitmap.Width, bitmap.Height);
                    }
                    else
                    {
                        for (int offset = 54; offset < 1024 + 54; offset = offset + 4)
                        {
                            int color = BitConverter.ToInt32(data, offset);
                            Memory.WriteByte(lutOffset, LowByte(color));
                            Memory.WriteByte(lutOffset + 1, MidByte(color));
                            Memory.WriteByte(lutOffset + 2, HighByte(color));
                            Memory.WriteByte(lutOffset + 3, 0xFF); // Alpha
                            lutOffset = lutOffset + 4;
                        }
                        for (int line = 0; line < bitmap.Height; line++)
                        {
                            for (int i = 0; i < bitmap.Width; i++)
                            {
                                Memory.WriteByte(writeVideoAddress + (bitmap.Height - line + 1) * bitmap.Width + i, data[startOffset + line * bitmap.Width + i]);
                            }
                        }
                    }
                    if (BitmapTypesCombo.SelectedIndex > 0 && BitmapTypesCombo.SelectedIndex < 5)
                    {
                        int layer = BitmapTypesCombo.SelectedIndex - 1;
                        OnTileLoaded?.Invoke(layer);
                    }
                    MessageBox.Show("Transfer successful!", "Bitmap Storage", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    this.Close();
                }
                else
                {
                    StoreButton.Enabled = true;
                }
            }
            else
            {
                byte[] data = File.ReadAllBytes(FileNameTextBox.Text);
                for (int i = 0; i < data.Length; i++)
                {
                    Memory.WriteByte(videoAddress + i, data[i]);
                }
                StoreButton.Enabled = true;
            }
        }
示例#2
0
        private unsafe void ConvertBitmapToRaw(Bitmap bitmap, ResourceChecker.Resource resource, byte lutIndex, int stride, int maxHeight)
        {
            if (ResChecker.Add(resource))
            {
                // Load LUT from memory - ignore indexes 0 and 1
                int lutBaseAddress = MemoryLocations.MemoryMap.GRP_LUT_BASE_ADDR + lutIndex * 0x400 - MemoryLocations.MemoryMap.VICKY_BASE_ADDR;

                // Limit how much data is imported based on the type of image
                int importedLines = maxHeight < bitmap.Height ? maxHeight : bitmap.Height;
                int importedCols  = stride < bitmap.Width ? stride : bitmap.Width;

                byte[] data = new byte[stride * importedLines]; // the bitmap is based on resolution of the machine
                resource.Length = stride * bitmap.Height;       // one byte per pixel - palette is separate

                Rectangle  rect           = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                BitmapData bitmapData     = bitmap.LockBits(rect, ImageLockMode.ReadOnly, bitmap.PixelFormat);
                int        bytesPerPixel  = bitmapData.Stride / bitmap.Width;
                byte *     bitmapPointer  = (byte *)bitmapData.Scan0.ToPointer();
                bool       tooManyColours = false;
                bool       done           = false;
                byte       mask           = 0xFF;
                List <int> lut            = null;
                while (!done && mask != 0xc0)
                {
                    int transparentColor = 0;
                    try
                    {
                        transparentColor = Convert.ToInt32(textTransparentColor.Text, 16) & ((mask << 16) + (mask << 8) + mask);
                    }
                    finally
                    { }

                    done = true;
                    // Reset the Lookup Table
                    lut = new List <int>(256)
                    {
                        // Always add black (transparent) and white
                        0,
                        0xFFFFFF
                    };

                    // The user may decide to overwrite the palette from this bitmap
                    if (!checkOverwriteLUT.Checked)
                    {
                        for (int i = 2; i < 256; i++)
                        {
                            int value = MemMgrRef.VICKY.ReadLong(lutBaseAddress + 4 * i);
                            if (value != 0)
                            {
                                lut.Add(value);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    for (int line = 0; line < importedLines; line++)
                    {
                        for (int col = 0; col < importedCols; col++)
                        {
                            byte b = 0;
                            byte r = 0;
                            byte g = 0;

                            switch (bytesPerPixel)
                            {
                            case 1:
                                byte palIndex = bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel];
                                System.Drawing.Color palValue = bitmap.Palette.Entries[palIndex];
                                b = (byte)(palValue.B & mask);
                                g = (byte)(palValue.G & mask);
                                r = (byte)(palValue.R & mask);
                                break;

                            case 2:
                                ushort wordValue = (ushort)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel] + bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel + 1] * 256);
                                b = (byte)(wordValue & 0x1F);        //  5bits
                                g = (byte)((wordValue >> 5) & 0x3F); // 6 bits
                                r = (byte)(wordValue >> 11);         // 5 bits
                                break;

                            case 3:
                                b = (byte)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel] & mask);
                                g = (byte)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel + 1] & mask);
                                r = (byte)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel + 2] & mask);
                                break;

                            case 4:
                                b = (byte)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel] & mask);
                                g = (byte)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel + 1] & mask);
                                r = (byte)(bitmapPointer[line * bitmapData.Stride + col * bytesPerPixel + 2] & mask);
                                //alpha is ignored

                                break;
                            }
                            int rgb = b + g * 256 + r * 256 * 256;
                            // Check if the RBG matches the transparent color
                            int index = 0;
                            if (rgb != transparentColor)
                            {
                                // if not, look in the LUT
                                index = lut.IndexOf(rgb);
                            }
                            // If the index is undefined, add a new entry
                            if (index == -1)
                            {
                                if (lut.Count < 256)
                                {
                                    lut.Add(rgb);
                                    index = (byte)lut.IndexOf(rgb);
                                }
                                else
                                {
                                    tooManyColours = true;
                                    break;
                                }
                            }
                            if (index != -1)
                            {
                                data[line * stride + col] = (byte)index;
                            }
                        }
                        if (tooManyColours)
                        {
                            // TODO should use a colour histogram to count how many times a colour is used and then decimate here, based on low usage.
                            done           = false;
                            tooManyColours = false;
                            mask         <<= 1;
                            break;
                        }
                    }
                }

                if (mask != 0xc0)
                {
                    int videoAddress = resource.StartAddress - 0xB0_0000;

                    MemMgrRef.VIDEO.CopyBuffer(data, 0, videoAddress, data.Length);

                    if (lut != null)
                    {
                        for (int i = 0; i < lut.Count; i++)
                        {
                            int rbg = lut[i];
                            MemMgrRef.VICKY.WriteByte(lutBaseAddress + 4 * i, LowByte(rbg));
                            MemMgrRef.VICKY.WriteByte(lutBaseAddress + 4 * i + 1, MidByte(rbg));
                            MemMgrRef.VICKY.WriteByte(lutBaseAddress + 4 * i + 2, HighByte(rbg));
                        }
                    }

                    // Check if a LUT matching our index is present in the Resources, if so don't do anything.
                    Resource resLut = ResChecker.Find(ResourceType.lut, lutBaseAddress + MemoryLocations.MemoryMap.VICKY_BASE_ADDR);
                    if (resLut == null)
                    {
                        Resource lutPlaceholder = new Resource
                        {
                            Length       = 0x400,
                            FileType     = ResourceType.lut,
                            Name         = "Generated LUT",
                            StartAddress = lutBaseAddress + MemoryLocations.MemoryMap.VICKY_BASE_ADDR
                        };
                        ResChecker.Add(lutPlaceholder);
                    }
                }
                else
                {
                    MessageBox.Show("An error occured converting the image colors to LUT.\n" +
                                    "You can try loading the image with a different LUT or\n" +
                                    "Zero one of the LUTs or\n" +
                                    "Check the Overwrite Existing LUT checkbox");

                    ResChecker.Items.Remove(resource);
                    resource.Length = -1;
                }
            }
            else
            {
                resource.Length = -1;
            }
        }
示例#3
0
        private void StoreButton_Click(object sender, EventArgs e)
        {
            StoreButton.Enabled = false;

            // Store the address in the pointer address - little endian - 24 bits
            int destAddress = Convert.ToInt32(LoadAddressTextBox.Text.Replace(":", ""), 16);

            byte[] data = File.ReadAllBytes(FileNameTextBox.Text);
            for (int i = 0; i < data.Length; i++)
            {
                Memory.WriteByte(destAddress + i, data[i]);
            }

            // Determine which addresses to store the bitmap into.
            if (FileTypesCombo.SelectedIndex == 0)
            {
                // Raw
            }
            else if (FileTypesCombo.SelectedIndex < 5)
            {
                // Tilemaps 4
                int  tilemapIndex = FileTypesCombo.SelectedIndex - 1;
                int  baseAddress  = MemoryLocations.MemoryMap.TILE_CONTROL_REGISTER_ADDR + tilemapIndex * 12;
                byte lutValue     = (byte)LUTCombo.SelectedIndex;
                // enable the tilemap
                Memory.WriteByte(baseAddress, (byte)(1 + (lutValue << 1)));
                // write address offset by bank $b0
                int offsetAddress = destAddress - 0xB0_0000;
                Memory.WriteByte(baseAddress + 1, (byte)(offsetAddress & 0xFF));
                Memory.WriteByte(baseAddress + 2, (byte)((offsetAddress & 0xFF00) >> 8));
                Memory.WriteByte(baseAddress + 3, (byte)((offsetAddress & 0xFF_0000) >> 16));
                // TODO: Need to write the size of the tilemap
            }
            else if (FileTypesCombo.SelectedIndex < 13)
            {
                // Tilesets 8
                int  tilesetIndex = FileTypesCombo.SelectedIndex - 5;
                int  baseAddress  = MemoryLocations.MemoryMap.TILESET_BASE_ADDR + tilesetIndex * 4;
                byte lutValue     = (byte)LUTCombo.SelectedIndex;

                // write address offset by bank $b0
                int offsetAddress = destAddress - 0xB0_0000;
                Memory.WriteByte(baseAddress, (byte)(offsetAddress & 0xFF));
                Memory.WriteByte(baseAddress + 1, (byte)((offsetAddress & 0xFF00) >> 8));
                Memory.WriteByte(baseAddress + 2, (byte)((offsetAddress & 0xFF_0000) >> 16));
                Memory.WriteByte(baseAddress + 3, lutValue);  // TODO: Add the stride 256 bit 3.
            }
            else
            {
                // Sprites 64
                int  spriteIndex = FileTypesCombo.SelectedIndex - 13;
                int  baseAddress = MemoryLocations.MemoryMap.SPRITE_CONTROL_REGISTER_ADDR + spriteIndex * 8;
                byte lutValue    = (byte)LUTCombo.SelectedIndex;

                // enable the tilemap
                Memory.WriteByte(baseAddress, (byte)(1 + (lutValue << 1)));  // TODO: Add sprite depth

                // write address offset by bank $b0
                int offsetAddress = destAddress - 0xB0_0000;
                Memory.WriteByte(baseAddress + 1, (byte)(offsetAddress & 0xFF));
                Memory.WriteByte(baseAddress + 2, (byte)((offsetAddress & 0xFF00) >> 8));
                Memory.WriteByte(baseAddress + 3, (byte)((offsetAddress & 0xFF_0000) >> 16));
                // TODO: set the position of the sprite
            }

            ResourceChecker.Resource res = new ResourceChecker.Resource
            {
                StartAddress = destAddress,
                SourceFile   = FileNameTextBox.Text,
                Name         = Path.GetFileNameWithoutExtension(FileNameTextBox.Text),
                FileType     = FileTypesCombo.SelectedIndex
            };

            StoreButton.Enabled = true;

            //// Store the bitmap at the user's determined address
            //// The method below simply takes the file and writes it in memory.
            //// What we want is the actual pixels.
            //ImageConverter converter = new ImageConverter();
            //byte[] data = (byte[])converter.ConvertTo(bitmap, typeof(byte[]));
            //int startOffset = BitConverter.ToInt32(data, 10);
            //int fileLength = BitConverter.ToInt32(data, 2);
            //res.Length = bitmap.Height * bitmap.Width;
            //if (ResChecker.Add(res))
            //{

            //    // The addresses in Vicky a offset by $B0:0000
            //    videoAddress = videoAddress - 0xB0_0000;
            //    Memory.WriteByte(pointerAddress, LowByte(videoAddress));
            //    Memory.WriteByte(pointerAddress + 1, MidByte(videoAddress));
            //    Memory.WriteByte(pointerAddress + 2, HighByte(videoAddress));

            //    // Store the strides in the strideX and strideY
            //    Memory.WriteByte(strideXAddress, LowByte(strideX));
            //    Memory.WriteByte(strideXAddress + 1, MidByte(strideX));
            //    Memory.WriteByte(strideYAddress, LowByte(strideY));
            //    Memory.WriteByte(strideYAddress + 1, MidByte(strideY));



            //    int numberOfColors = BitConverter.ToInt32(data, 46);
            //    int lutOffset = 0xAF_2000 + LUTCombo.SelectedIndex * 1024;
            //    if (numberOfColors == 0)
            //    {
            //        // we need to create a LUT - each LUT only accepts 256 entries - 0 is black
            //        TransformBitmap(data, startOffset, Int32.Parse(PixelDepthValueLabel.Text), lutOffset, writeVideoAddress, bitmap.Width, bitmap.Height);
            //    }
            //    else
            //    {
            //        for (int offset = 54; offset < 1024 + 54; offset = offset + 4)
            //        {
            //            int color = BitConverter.ToInt32(data, offset);
            //            Memory.WriteByte(lutOffset, LowByte(color));
            //            Memory.WriteByte(lutOffset + 1, MidByte(color));
            //            Memory.WriteByte(lutOffset + 2, HighByte(color));
            //            Memory.WriteByte(lutOffset + 3, 0xFF); // Alpha
            //            lutOffset = lutOffset + 4;
            //        }
            //        for (int line = 0; line < bitmap.Height; line++)
            //        {
            //            for (int i = 0; i < bitmap.Width; i++)
            //            {
            //                Memory.WriteByte(writeVideoAddress + (bitmap.Height - line + 1) * bitmap.Width + i, data[startOffset + line * bitmap.Width + i]);
            //            }
            //        }
            //    }
            //    if (FileTypesCombo.SelectedIndex > 0 && FileTypesCombo.SelectedIndex < 5)
            //    {
            //        int layer = FileTypesCombo.SelectedIndex - 1;
            //        OnTileLoaded?.Invoke(layer);
            //    }
            //    MessageBox.Show("Transfer successful!", "Bitmap Storage", MessageBoxButtons.OK, MessageBoxIcon.Information);
            //    this.Close();
            //}
            //else
            //{
            //    StoreButton.Enabled = true;
            //}
        }
示例#4
0
        private void StoreButton_Click(object sender, EventArgs e)
        {
            StoreButton.Enabled = false;

            // Store the address in the pointer address - little endian - 24 bits
            int      destAddress = Convert.ToInt32(LoadAddressTextBox.Text.Replace(":", ""), 16);
            FileInfo info        = new FileInfo(FileNameTextBox.Text);
            byte     MCRHigh     = (byte)(MemMgrRef.VICKY.ReadByte(1) & 3);
            int      screenResX  = 640;
            int      screenResY  = 480;

            switch (MCRHigh)
            {
            case 1:
                screenResX = 800;
                screenResY = 600;
                break;

            case 2:
                screenResX = 320;
                screenResY = 240;
                break;

            case 3:
                screenResX = 400;
                screenResY = 300;
                break;
            }

            ResourceType operationType    = ResourceType.raw;
            int          conversionStride = 0;
            int          maxHeight        = screenResY;

            if (FileTypesCombo.SelectedIndex < 2)
            {
                operationType    = ResourceType.bitmap;
                conversionStride = screenResX;
            }
            else if (FileTypesCombo.SelectedIndex < 6)
            {
                operationType = ResourceType.tilemap;
                ExtLabel.Text = ".data";
            }
            else if (FileTypesCombo.SelectedIndex < 14)
            {
                operationType    = ResourceType.tileset;
                conversionStride = 256;
                maxHeight        = 256;
            }
            else if (FileTypesCombo.SelectedIndex < 78)
            {
                operationType    = ResourceType.sprite;
                conversionStride = 32;
                maxHeight        = 32;
            }
            else
            {
                operationType = ResourceType.lut;
                ExtLabel.Text = ".data";
            }

            ResourceChecker.Resource res = new ResourceChecker.Resource
            {
                StartAddress = destAddress,
                SourceFile   = FileNameTextBox.Text,
                Name         = Path.GetFileNameWithoutExtension(FileNameTextBox.Text),
                FileType     = operationType,
            };


            switch (ExtLabel.Text.ToLower())
            {
            case ".png":
                Bitmap png = new Bitmap(FileNameTextBox.Text, false);
                ConvertBitmapToRaw(png, res, (byte)LUTCombo.SelectedIndex, conversionStride, maxHeight);
                break;

            case ".bmp":
                Bitmap bmp = new Bitmap(FileNameTextBox.Text, false);
                ConvertBitmapToRaw(bmp, res, (byte)LUTCombo.SelectedIndex, conversionStride, maxHeight);
                break;

            default:
                // Read the file as raw
                byte[] data = File.ReadAllBytes(FileNameTextBox.Text);
                // Check if there's a resource conflict
                res.Length = data.Length;
                if (ResChecker.Add(res))
                {
                    MemMgrRef.CopyBuffer(data, 0, destAddress, data.Length);
                }
                else
                {
                    res.Length = -1;
                }
                break;
            }

            if (res.Length > 0)
            {
                // write address offset by bank $b0
                int  imageAddress = destAddress - 0xB0_0000;
                int  regAddress   = -1;
                byte lutValue     = (byte)LUTCombo.SelectedIndex;

                // Determine which addresses to store the bitmap into.
                if (FileTypesCombo.SelectedIndex < 2)
                {
                    // Bitmaps
                    regAddress = MemoryLocations.MemoryMap.BITMAP_CONTROL_REGISTER_ADDR + FileTypesCombo.SelectedIndex * 8;
                    // enable the bitmap - TODO add the LUT
                    MemMgrRef.WriteByte(regAddress, (byte)(1 + lutValue * 2));
                }
                else if (FileTypesCombo.SelectedIndex < 6)
                {
                    // Tilemaps 4
                    int tilemapIndex = FileTypesCombo.SelectedIndex - 1;
                    regAddress = MemoryLocations.MemoryMap.TILE_CONTROL_REGISTER_ADDR + tilemapIndex * 12;

                    // enable the tilemap
                    MemMgrRef.WriteByte(regAddress, (byte)(1 + (lutValue << 1)));

                    // TODO: Need to write the size of the tilemap
                }
                else if (FileTypesCombo.SelectedIndex < 14)
                {
                    // Tilesets 8
                    int tilesetIndex = FileTypesCombo.SelectedIndex - 5;
                    regAddress = MemoryLocations.MemoryMap.TILESET_BASE_ADDR + tilesetIndex * 4;

                    MemMgrRef.WriteByte(regAddress + 3, lutValue);  // TODO: Add the stride 256 bit 3.
                }
                else
                {
                    // Sprites 64
                    int spriteIndex = FileTypesCombo.SelectedIndex - 14;
                    regAddress = MemoryLocations.MemoryMap.SPRITE_CONTROL_REGISTER_ADDR + spriteIndex * 8;

                    // enable the tilemap
                    MemMgrRef.WriteByte(regAddress, (byte)(1 + (lutValue << 1)));  // TODO: Add sprite depth
                                                                                   // write address offset by bank $b0
                    // Set the sprite at (32,32)
                    MemMgrRef.WriteWord(regAddress + 4, 32);
                    MemMgrRef.WriteWord(regAddress + 6, 32);
                }
                // write address offset by bank $b0
                MemMgrRef.WriteByte(regAddress + 1, LowByte(imageAddress));
                MemMgrRef.WriteByte(regAddress + 2, MidByte(imageAddress));
                MemMgrRef.WriteByte(regAddress + 3, HighByte(imageAddress));

                StoreButton.Enabled = true;
            }
            if (res.Length != -1)
            {
                this.DialogResult = DialogResult.OK;
                if (FileTypesCombo.SelectedIndex > 1 && FileTypesCombo.SelectedIndex < 6)
                {
                    int layer = FileTypesCombo.SelectedIndex - 2;
                    //OnTileLoaded?.Invoke(layer);
                }
                Close();
            }
            else
            {
                // Keep the Asset Loader open
                StoreButton.Enabled = true;
            }
        }