Example #1
0
        public void LoadRom(string FileName)
        {
            // Initialize save data
            ROMData data = this.GetROMData(FileName);

            this.Backup.ROMBackupType = data.backup;
            this.Backup.Init();

            if (File.Exists(Path.ChangeExtension(FileName, BackupSection.SaveExtension)))
            {
                this.Backup.LoadBackup(Path.ChangeExtension(FileName, BackupSection.SaveExtension));
            }

            // Load actual ROM
            byte[] GamePak = File.ReadAllBytes(FileName);
            this.Log(string.Format("{0:x8} Bytes loaded (hex)", GamePak.Length));

            this.Backup.ROMPath = FileName;
            this.ROMName        = Path.GetFileName(FileName);

            this.GamePak_L.ROMSize = (uint)GamePak.Length;
            this.GamePak_L.Load(GamePak, 0);
            this.GamePak_L.gpio = new GPIO.GPIO(data.chip);

            this.GamePak_H.ROMSize = (uint)GamePak.Length;
            this.GamePak_H.Load(GamePak, 0x0100_0000);
            // GPIO is in the lower region of the GamePak, we don't need to set it for GamePak_H
        }
Example #2
0
        public void TestRenderScreenWithSpriteFlipped()
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = VideoHardwareTestData.PALETTE_ROM;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = VideoHardwareTestData.TILE_ROM;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = VideoHardwareTestData.SPRITE_ROM;

            var video = new VideoHardware(romData);

            video.InitializeColors();
            video.InitializePalettes();
            video.InitializeTiles();
            video.InitializeSprites();

            // Arrange: Load a VRAM dump which contains tiles positions and palettes for each tile.

            var rawMemory = new byte[0xFFFF];

            var vram = File.ReadAllBytes($"../../../TestData/maze-1.vram");

            Array.Copy(vram, 0, rawMemory, 0x4000, 0x0800);

            var memory = new SimpleMemory(rawMemory);

            // Arrange: Setup the sprites to show.

            // Pac-Man facing left sprite (46), flip X/Y (0x02).
            var flags = (byte)((46 << 2) | (0x02));

            memory.Write(0x4FF0, flags);
            memory.Write(0x4FF1, 9); // Palette.

            // Act: Render the image based on the tiles and palettes in memory.

            var spriteCoordinates = new byte[16]
            {
                220, // x
                252, // y
                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
            };

            var image = video.Render(memory, spriteCoordinates, true);

            // Assert: the rendered image should be the same as the reference image.

            byte[] actualBytes = null;

            using (var steam = new MemoryStream())
            {
                image.Save(steam, new BmpEncoder());
                actualBytes = steam.ToArray();
            }

            var expectedBytes = File.ReadAllBytes($"../../../ReferenceData/render-maze-1-with-sprites-flipped.bmp");

            Assert.Equal(expectedBytes, actualBytes);
        }
Example #3
0
        public void TestRenderScreen(string vramFile, string expectedBitmapFile, bool flipScreen)
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = VideoHardwareTestData.PALETTE_ROM;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = VideoHardwareTestData.TILE_ROM;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = VideoHardwareTestData.SPRITE_ROM;

            var video = new VideoHardware(romData);

            video.InitializeColors();
            video.InitializePalettes();
            video.InitializeTiles();
            video.InitializeSprites();

            // Arrange: Load a VRAM dump which contains tiles positions and palettes for each tile.

            var rawMemory = new byte[0xFFFF];

            var vram = File.ReadAllBytes($"../../../TestData/{vramFile}");

            Array.Copy(vram, 0, rawMemory, 0x4000, 0x0800);

            var memory = new SimpleMemory(rawMemory);

            // Act: Render the image based on the tiles and palettes in memory.

            var spriteCoordinates = new byte[16];
            var image             = video.Render(memory, spriteCoordinates, flipScreen);

            // Assert: the rendered image should be the same as the reference image.

            byte[] actualBytes = null;

            using (var steam = new MemoryStream())
            {
                image.Save(steam, new BmpEncoder());
                actualBytes = steam.ToArray();
            }

            var expectedBytes = File.ReadAllBytes($"../../../ReferenceData/{expectedBitmapFile}");

            Assert.Equal(expectedBytes, actualBytes);
        }
Example #4
0
        private ROMData GetROMData(string FileName)
        {
            ROMData data = new ROMData()
            {
                backup = BackupType.SRAM,
                chip   = GPIO.GPIO.Chip.Empty
            };

            // search for the type of backup used in ROM file
            using (StreamReader file = new StreamReader(FileName))
            {
                string line;
                while ((line = file.ReadLine()) != null)
                {
                    if (data.backup == BackupType.SRAM)
                    {
                        foreach (BackupType BackupType in Enum.GetValues(typeof(BackupType)))
                        {
                            if (Regex.Match(line, $"{BackupType}_V\\d\\d\\d").Success)
                            {
                                data.backup = BackupType;
                            }
                        }
                    }

                    if (data.chip == GPIO.GPIO.Chip.Empty)
                    {
                        foreach (GPIO.GPIO.Chip chip in Enum.GetValues(typeof(GPIO.GPIO.Chip)))
                        {
                            if (Regex.Match(line, $"{chip}_V\\d\\d\\d").Success)
                            {
                                data.chip = chip;
                            }
                        }
                    }
                }
                file.Close();
            }
            Console.WriteLine($"Read data for ROM {FileName}:");
            Console.WriteLine($"    Using BackupType {data.backup} for ROM");
            Console.WriteLine($"    Using GPIO chip {data.chip} for ROM");

            return(data);
        }
        public void TestRenderSpriteRendersAllSpritesWithTransparency()
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = VideoHardwareTestData.PALETTE_ROM;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = null;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = null;

            var video = new VideoHardware(romData);

            video.InitializeColors();
            video.InitializePalettes();

            var spriteRenderer = new SpriteRenderer(VideoHardwareTestData.SPRITE_ROM, video._palettes);

            // There are 64 sprites, so we can render a grid of 8x8 sprites.
            // Each sprite is 16x16 pixels.
            var width  = 8 * 16;
            var height = 8 * 16;

            // Holds the (x, y) coordinates of the origin (top/left) of the location
            // to render the next sprite.
            var spriteOriginX = 0;
            var spriteOriginY = 0;

            // The image we'll be rendering all the sprites to.
            var image = new Image <Rgba32>(width, height, new Rgba32()
            {
                R = 255, G = 0, B = 255, A = 255
            });

            // Render each of the 64 sprites.
            for (var spriteIndex = 0; spriteIndex < 64; spriteIndex++)
            {
                // Render the sprite with the given color palette.
                var sprite = spriteRenderer.RenderSprite(spriteIndex, 5);

                // Copy the rendered sprite over into the full image.
                for (var y = 0; y < 16; y++)
                {
                    for (var x = 0; x < 16; x++)
                    {
                        var pixel         = sprite[x, y];
                        var isTransparent = pixel.A == 0;

                        if (!isTransparent)
                        {
                            image[spriteOriginX + x, spriteOriginY + y] = sprite[x, y];
                        }
                    }
                }

                if ((spriteIndex + 1) % 8 == 0)
                {
                    // Row is finished, wrap back around.
                    spriteOriginX  = 0;
                    spriteOriginY += 16;
                }
                else
                {
                    // Next column.
                    spriteOriginX += 16;
                }
            }

            // Assert: the rendered image should be the same as the reference image.

            byte[] actualBytes = null;

            using (var steam = new MemoryStream())
            {
                image.Save(steam, new BmpEncoder());
                actualBytes = steam.ToArray();
            }

            var expectedBytes = File.ReadAllBytes("../../../ReferenceData/render-all-sprites-with-transparency.bmp");

            Assert.Equal(expectedBytes, actualBytes);
        }
        public void TestRenderSpriteRendersAllSpritesWithRotations()
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = VideoHardwareTestData.PALETTE_ROM;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = null;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = null;

            var video = new VideoHardware(romData);

            video.InitializeColors();
            video.InitializePalettes();

            var spriteRenderer = new SpriteRenderer(VideoHardwareTestData.SPRITE_ROM, video._palettes);

            // There are 64 sprites, so we can render a grid of 8x8 sprites.
            // Each sprite is 16x16 pixels.
            var width  = 8 * 16;
            var height = 8 * 16;

            // Holds the (x, y) coordinates of the origin (top/left) of the location
            // to render the next sprite.
            var spriteOriginX = 0;
            var spriteOriginY = 0;

            // The image we'll be rendering all the sprites to.
            var image = new Image <Rgba32>(width, height, new Rgba32()
            {
                R = 0, G = 51, B = 102, A = 255
            });

            // Alternate between not flipping, flipping only X and only Y, and both.

            var flipIndex = 0;

            var flipValues = new List <Tuple <bool, bool> >()
            {
                new Tuple <bool, bool>(false, false),
                new Tuple <bool, bool>(true, false),
                new Tuple <bool, bool>(false, true),
                new Tuple <bool, bool>(true, true),
            };

            // Render each of the 64 sprites.
            for (var spriteIndex = 0; spriteIndex < 64; spriteIndex++)
            {
                // Determine how we'll flip this sprite.
                var flip  = flipValues[flipIndex];
                var flipX = flip.Item1;
                var flipY = flip.Item2;

                // Render the sprite with the given color palette.
                var sprite = spriteRenderer.RenderSprite(spriteIndex, 1, flipX, flipY);

                // Increment the value so we flip differently on the next sprite.

                flipIndex++;

                if (flipIndex == 4)
                {
                    flipIndex = 0;
                }

                // Copy the rendered sprite over into the full image.
                for (var y = 0; y < 16; y++)
                {
                    for (var x = 0; x < 16; x++)
                    {
                        var pixel         = sprite[x, y];
                        var isTransparent = pixel.A == 0;

                        if (!isTransparent)
                        {
                            image[spriteOriginX + x, spriteOriginY + y] = sprite[x, y];
                        }
                    }
                }

                if ((spriteIndex + 1) % 8 == 0)
                {
                    // Row is finished, wrap back around.
                    spriteOriginX  = 0;
                    spriteOriginY += 16;
                }
                else
                {
                    // Next column.
                    spriteOriginX += 16;
                }
            }

            // Assert: the rendered image should be the same as the reference image.

            byte[] actualBytes = null;

            using (var steam = new MemoryStream())
            {
                image.Save(steam, new BmpEncoder());
                actualBytes = steam.ToArray();
            }

            var expectedBytes = File.ReadAllBytes("../../../ReferenceData/render-all-sprites-with-rotations.bmp");

            Assert.Equal(expectedBytes, actualBytes);
        }
        public void TestRenderTileRendersAllTiles(int paletteIndex, string fileToCompare)
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = VideoHardwareTestData.PALETTE_ROM;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = null;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = null;

            var video = new VideoHardware(romData);

            video.InitializeColors();
            video.InitializePalettes();

            var tileRenderer = new TileRenderer(VideoHardwareTestData.TILE_ROM, video._palettes);

            // There are 256 tiles, so we can render a grid of 16x16 tiles.
            // Each tile is 8x8 pixels.
            var width  = 16 * 8;
            var height = 16 * 8;

            // Holds the (x, y) coordinates of the origin (top/left) of the location
            // to render the next tile.
            var tileOriginX = 0;
            var tileOriginY = 0;

            // The image we'll be rendering all the tiles to.
            var image = new Image <Rgba32>(width, height);

            // Render each of the 256 tiles.
            for (var tileIndex = 0; tileIndex < 256; tileIndex++)
            {
                // Render the tile with the given color palette.
                var tile = tileRenderer.RenderTile(tileIndex, paletteIndex);

                // Copy the rendered tile over into the full image.
                for (var y = 0; y < 8; y++)
                {
                    for (var x = 0; x < 8; x++)
                    {
                        image[tileOriginX + x, tileOriginY + y] = tile[x, y];
                    }
                }

                if ((tileIndex + 1) % 16 == 0)
                {
                    // Row is finished, wrap back around.
                    tileOriginX  = 0;
                    tileOriginY += 8;
                }
                else
                {
                    // Next column.
                    tileOriginX += 8;
                }
            }

            // Assert: the rendered image should be the same as the reference image.

            byte[] actualBytes = null;

            using (var steam = new MemoryStream())
            {
                image.Save(steam, new BmpEncoder());
                actualBytes = steam.ToArray();
            }

            var expectedBytes = File.ReadAllBytes($"../../../ReferenceData/{fileToCompare}");

            Assert.Equal(expectedBytes, actualBytes);
        }
Example #8
0
        public void TestInitializePalettesParsesPaletteRomAndBuildsTableCorrectly()
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = VideoHardwareTestData.PALETTE_ROM;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = null;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = null;

            var video = new VideoHardware(romData);

            video.InitializeColors();
            video.InitializePalettes();

            // Expected palette colors values as listed in Chris Lomont's Pac-Man Emulation
            // Guide v0.1, page 6, figure 3.
            var expectedPalettes = new Color[][]
            {
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(33, 33, 255), Color.Red, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(33, 33, 255), Color.FromArgb(255, 184, 255), },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(33, 33, 255), Color.Aqua, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(33, 33, 255), Color.FromArgb(255, 184, 81), },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(33, 33, 255), Color.Red, Color.Yellow, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.Black, Color.FromArgb(255, 184, 174), },
                new Color[] { Color.Black, Color.Red, Color.Lime, Color.FromArgb(222, 222, 255), },
                new Color[] { Color.Black, Color.FromArgb(255, 184, 174), Color.Black, Color.FromArgb(33, 33, 255), },
                new Color[] { Color.Black, Color.Lime, Color.FromArgb(33, 33, 255), Color.FromArgb(255, 184, 174), },
                new Color[] { Color.Black, Color.Lime, Color.FromArgb(222, 222, 255), Color.Red, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Red, Color.FromArgb(222, 151, 81), Color.FromArgb(222, 222, 255), },
                new Color[] { Color.Black, Color.FromArgb(255, 184, 81), Color.Lime, Color.FromArgb(222, 151, 81), },
                new Color[] { Color.Black, Color.Yellow, Color.FromArgb(71, 184, 255), Color.FromArgb(222, 222, 255), },
                new Color[] { Color.Black, Color.FromArgb(71, 184, 174), Color.Lime, Color.FromArgb(222, 222, 255), },
                new Color[] { Color.Black, Color.Aqua, Color.FromArgb(255, 184, 255), Color.Yellow, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(33, 33, 255), Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(255, 184, 174), Color.Black, Color.FromArgb(33, 33, 255), },
                new Color[] { Color.Black, Color.FromArgb(255, 184, 174), Color.Black, Color.FromArgb(33, 33, 255), },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(255, 184, 174), Color.Red },
                new Color[] { Color.Black, Color.FromArgb(222, 222, 255), Color.FromArgb(33, 33, 255), Color.FromArgb(255, 184, 174) },
                new Color[] { Color.Black, Color.FromArgb(255, 184, 174), Color.Black, Color.FromArgb(222, 222, 255) },


                // The last 32 palettes aren't used; they're all just black.
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
                new Color[] { Color.Black, Color.Black, Color.Black, Color.Black, },
            };

            Assert.Equal(64, video._palettes.Length);
            Assert.Equal(64, expectedPalettes.Length);

            for (var i = 0; i < expectedPalettes.Length; i++)
            {
                var actualPalette   = video._palettes[i];
                var expectedPalette = expectedPalettes[i];

                Assert.True(actualPalette.Length == 4, $"The palette at index {i} should have exactly 4 color entries, but found {actualPalette.Length}");

                for (var j = 0; j < 4; j++)
                {
                    var actualColor   = actualPalette[j];
                    var expectedColor = expectedPalette[j];

                    Assert.True(expectedColor.R == actualColor.R, $"The Red value for color at index {j} for the palette at index {i} was expected to be {expectedColor.R} but was actually {actualColor.R}");
                    Assert.True(expectedColor.G == actualColor.G, $"The Green value for color at index {j} for the palette at index {i} was expected to be {expectedColor.G} but was actually {actualColor.G}");
                    Assert.True(expectedColor.B == actualColor.B, $"The Blue value for color at index {j} for the palette at index {i} was expected to be {expectedColor.B} but was actually {actualColor.B}");
                }
            }
        }
Example #9
0
        public void TestInitializeColorsParsesRomColorsCorrectly()
        {
            var romData = new ROMData();

            romData.Data[ROMs.PAC_MAN_COLOR.FileName]   = VideoHardwareTestData.COLOR_ROM;
            romData.Data[ROMs.PAC_MAN_PALETTE.FileName] = null;
            romData.Data[ROMs.PAC_MAN_TILE.FileName]    = null;
            romData.Data[ROMs.PAC_MAN_SPRITE.FileName]  = null;

            var video = new VideoHardware(romData);

            video.InitializeColors();

            // Expected RGB color values as listed in Chris Lomont's Pac-Man Emulation
            // Guide v0.1, page 5, table 3.
            var expectedColors = new Color[]
            {
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(255, 0, 0),
                Color.FromArgb(222, 151, 81),
                Color.FromArgb(255, 184, 255),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 255, 255),
                Color.FromArgb(71, 184, 255),
                Color.FromArgb(255, 184, 81),

                Color.FromArgb(0, 0, 0),
                Color.FromArgb(255, 255, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(33, 33, 255),
                Color.FromArgb(0, 255, 0),
                Color.FromArgb(71, 184, 174),
                Color.FromArgb(255, 184, 174),
                Color.FromArgb(222, 222, 255),

                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),

                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
                Color.FromArgb(0, 0, 0),
            };

            Assert.Equal(32, video._colors.Length);

            for (var i = 0; i < 32; i++)
            {
                Assert.True(expectedColors[i].R == video._colors[i].R, $"The Red value for color #{i} was expected to be {expectedColors[i].R} but was actually {video._colors[i].R}");
                Assert.True(expectedColors[i].G == video._colors[i].G, $"The Green value for color #{i} was expected to be {expectedColors[i].G} but was actually {video._colors[i].G}");
                Assert.True(expectedColors[i].B == video._colors[i].B, $"The Blue value for color #{i} was expected to be {expectedColors[i].B} but was actually {video._colors[i].B}");
            }
        }