From cfbcbcab12241643430f71a0603d13cc68bbdcb9 Mon Sep 17 00:00:00 2001 From: Brett Sanderson Date: Sun, 6 Mar 2016 00:32:50 -0500 Subject: [PATCH] Refactoring Progress --- CdgLib/CdgFileIoStream.cs | 94 --------- CdgLib/CdgLib.csproj | 5 +- CdgLib/Extension/Extensions.cs | 13 -- CdgLib/Graphic.cs | 338 ++++++++++++++++++++++++++++++++- CdgLib/GraphicFileStream.cs | 46 +++++ CdgLib/GraphicUtil.cs | 109 ----------- CdgLib/GraphicsFile.cs | 99 ++-------- CdgLib/SubCode/Packet.cs | 335 +------------------------------- CdgLib/Surface.cs | 14 -- 9 files changed, 405 insertions(+), 648 deletions(-) delete mode 100644 CdgLib/CdgFileIoStream.cs delete mode 100644 CdgLib/Extension/Extensions.cs create mode 100644 CdgLib/GraphicFileStream.cs delete mode 100644 CdgLib/GraphicUtil.cs delete mode 100644 CdgLib/Surface.cs diff --git a/CdgLib/CdgFileIoStream.cs b/CdgLib/CdgFileIoStream.cs deleted file mode 100644 index 624a033..0000000 --- a/CdgLib/CdgFileIoStream.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.IO; - -namespace CdgLib -{ - /// - /// - public class CdgFileIoStream - { - private Stream _cdgFile; - - /// - /// - public CdgFileIoStream() - { - _cdgFile = null; - } - - /// - /// Reads the specified buf. - /// - /// The buf. - /// The buf_size. - /// - public int Read(ref byte[] buf, int bufSize) - { - return _cdgFile.Read(buf, 0, bufSize); - } - - /// - /// Writes the specified buf. - /// - /// The buf. - /// The buf_size. - /// - public int Write(ref byte[] buf, int bufSize) - { - _cdgFile.Write(buf, 0, bufSize); - return 1; - } - - /// - /// Seeks the specified offset. - /// - /// The offset. - /// The whence. - /// - public int Seek(int offset, SeekOrigin whence) - { - return (int) _cdgFile.Seek(offset, whence); - } - - /// - /// EOFs this instance. - /// - /// - public bool Eof() - { - return _cdgFile.Position >= _cdgFile.Length; - } - - /// - /// Getsizes this instance. - /// - /// - public int Getsize() - { - return (int) _cdgFile.Length; - } - - /// - /// Opens the specified filename. - /// - /// The filename. - /// - public bool Open(string filename) - { - Close(); - _cdgFile = new FileStream(filename, FileMode.Open, FileAccess.Read); - return _cdgFile != null; - } - - /// - /// Closes this instance. - /// - public void Close() - { - if (_cdgFile != null) - { - _cdgFile.Close(); - _cdgFile = null; - } - } - } -} \ No newline at end of file diff --git a/CdgLib/CdgLib.csproj b/CdgLib/CdgLib.csproj index b2b5136..82e7198 100644 --- a/CdgLib/CdgLib.csproj +++ b/CdgLib/CdgLib.csproj @@ -42,15 +42,12 @@ - + - - - diff --git a/CdgLib/Extension/Extensions.cs b/CdgLib/Extension/Extensions.cs deleted file mode 100644 index c1ea5f7..0000000 --- a/CdgLib/Extension/Extensions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace CdgLib.Extension -{ - internal class Extensions - { - void tr - } -} diff --git a/CdgLib/Graphic.cs b/CdgLib/Graphic.cs index 484fca4..c057ea8 100644 --- a/CdgLib/Graphic.cs +++ b/CdgLib/Graphic.cs @@ -1,24 +1,30 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Drawing.Imaging; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.InteropServices; using CdgLib.SubCode; namespace CdgLib { public class Graphic { + private const int ColourTableSize = 16; + private const int TileHeight = 12; + private const int TileWidth = 6; + public const int FullWidth = 300; + public const int FullHeight = 216; + private readonly int[] _colourTable = new int[ColourTableSize]; + private readonly byte[,] _pixelColours = new byte[FullHeight, FullWidth]; private int[,] _graphicData; public Graphic(IEnumerable packets) { foreach (var packet in packets) { - packet.ApplyTransform(ref _graphicData); + Process(packet); } } @@ -27,21 +33,339 @@ namespace CdgLib Bitmap myBitmap; using (var bitmapStream = new MemoryStream()) { - foreach (var colourValue in _mPSurface.RgbData) + foreach (var colourValue in _graphicData) { var colour = BitConverter.GetBytes(colourValue); bitmapStream.Write(colour, 0, 4); } - myBitmap = GraphicUtil.StreamToBitmap(bitmapStream, FullWidth, FullHeight); + myBitmap = StreamToBitmap(bitmapStream, FullWidth, FullHeight); } myBitmap.MakeTransparent(myBitmap.GetPixel(1, 1)); return myBitmap; } + private Bitmap StreamToBitmap(Stream stream, int width, int height) + { + //create a new bitmap + var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); + var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat); + stream.Seek(0, SeekOrigin.Begin); + //copy the stream of pixel + for (var n = 0; n <= stream.Length - 1; n++) + { + var myByte = new byte[1]; + stream.Read(myByte, 0, 1); + Marshal.WriteByte(bmpData.Scan0, n, myByte[0]); + } + bmp.UnlockBits(bmpData); + return bmp; + } - + private void Process(Packet packet) + { + if (packet.Command != Command.Graphic) return; + switch (packet.Instruction) + { + case Instruction.MemoryPreset: + MemoryPreset(packet); + break; + case Instruction.BorderPreset: + BorderPreset(packet); + break; + case Instruction.TileBlockNormal: + TileBlock(packet, false); + break; + case Instruction.ScrollPreset: + Scroll(packet, false); + break; + case Instruction.ScrollCopy: + Scroll(packet, true); + break; + case Instruction.DefineTransparentColor: + DefineTransparentColour(packet); + break; + case Instruction.LoadColorTableLower: + LoadColorTable(packet, 0); + break; + case Instruction.LoadColorTableUpper: + LoadColorTable(packet, 1); + break; + case Instruction.TileBlockXor: + TileBlock(packet, true); + break; + } + } + private void MemoryPreset(Packet packet) + { + var colour = packet.Data[0] & 0xf; + var repeat = packet.Data[1] & 0xf; + + //we have a reliable packet stream, so the repeat command + //is executed only the first time + if (repeat == 0) + { + //Note that this may be done before any load colour table + //commands by some CDGs. So the load colour table itself + //actual recalculates the RGB values for all pixels when + //the colour table changes. + + //Set the preset colour for every pixel. Must be stored in + //the pixel colour table indeces array + for (int rowIndex = 0; rowIndex < _pixelColours.GetLength(0); rowIndex++) + { + for (int columnIndex = 0; columnIndex < _pixelColours.GetLength(1); columnIndex++) + { + _pixelColours[rowIndex, columnIndex] = (byte)colour; + } + } + } + } + + private void BorderPreset(Packet packet) + { + int rowIndex; + int columnIndex; + + var colour = packet.Data[0] & 0xf; + + //The border area is the area contained with a rectangle + //defined by (0,0,300,216) minus the interior pixels which are contained + //within a rectangle defined by (6,12,294,204). + + for (rowIndex = 0; rowIndex < _pixelColours.GetLength(0); rowIndex++) + { + for (columnIndex = 0; columnIndex < 6; columnIndex++) + { + _pixelColours[rowIndex, columnIndex] = (byte)colour; + } + + for (columnIndex = _pixelColours.GetLength(1) - 6; columnIndex < _pixelColours.GetLength(1); columnIndex++) + { + _pixelColours[rowIndex, columnIndex] = (byte)colour; + } + } + + for (columnIndex = 6; columnIndex < _pixelColours.GetLength(1) - 6; columnIndex++) + { + for (rowIndex = 0; rowIndex < 12; rowIndex++) + { + _pixelColours[rowIndex, columnIndex] = (byte)colour; + } + + for (rowIndex = _pixelColours.GetLength(1) - 12; rowIndex < _pixelColours.GetLength(1); rowIndex++) + { + _pixelColours[rowIndex, columnIndex] = (byte)colour; + } + } + } + + + private void LoadColorTable(Packet packet, int table) + { + for (var i = 0; i < 8; i++) + { + //[---high byte---] [---low byte----] + //7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 + //X X r r r r g g X X g g b b b b + var highByte = packet.Data[2 * i]; + var lowByte = packet.Data[2 * i + 1]; + + var red = (highByte & 0x3f) >> 2; + var green = ((highByte & 0x3) << 2) | ((lowByte & 0x3f) >> 4); + var blue = lowByte & 0xf; + + //4 bit colour to 8 bit colour + red *= 17; + green *= 17; + blue *= 17; + + _colourTable[i + table*8] = Color.FromArgb(red, green, blue).ToArgb(); + } + } + + + private void TileBlock(Packet packet, bool bXor) + { + var colour0 = packet.Data[0] & 0xf; + var colour1 = packet.Data[1] & 0xf; + var rowIndex = (packet.Data[2] & 0x1f) * 12; + var columnIndex = (packet.Data[3] & 0x3f) * 6; + + if (rowIndex > FullHeight - TileHeight) + return; + if (columnIndex > FullWidth - TileWidth) + return; + + //Set the pixel array for each of the pixels in the 12x6 tile. + //Normal = Set the colour to either colour0 or colour1 depending + //on whether the pixel value is 0 or 1. + //XOR = XOR the colour with the colour index currently there. + + + for (var i = 0; i <= 11; i++) + { + var myByte = packet.Data[4 + i] & 0x3f; + for (var j = 0; j <= 5; j++) + { + var pixel = (myByte >> (5 - j)) & 0x1; + var newCol = 0; + if (bXor) + { + //Tile Block XOR + var xorCol = pixel == 0 ? colour0 : colour1; + + //Get the colour index currently at this location, and xor with it + int currentColourIndex = _pixelColours[rowIndex + i, columnIndex + j]; + newCol = currentColourIndex ^ xorCol; + } + else + { + newCol = pixel == 0 ? colour0 : colour1; + } + + //Set the pixel with the new colour. We set both the surfarray + //containing actual RGB values, as well as our array containing + //the colour indexes into our colour table. + _pixelColours[rowIndex + i, columnIndex + j] = (byte)newCol; + } + } + } + + private void DefineTransparentColour(Packet packet) + { + //_mTransparentColour = packet.Data[0] & 0xf; + } + + + private void Scroll(Packet packet, bool copy) + { + //Decode the scroll command parameters + var colour = packet.Data[0] & 0xf; + var horizontalScroll = packet.Data[1] & 0x3f; + var verticalScroll = packet.Data[2] & 0x3f; + + var horizontalScrollCommand = (horizontalScroll & 0x30) >> 4; + var horizontalOffset = horizontalScroll & 0x7; + var verticalScrollCommand = (verticalScroll & 0x30) >> 4; + var verticalOffset = verticalScroll & 0xf; + + + _mHOffset = horizontalOffset < 5 ? horizontalOffset : 5; + _mVOffset = verticalOffset < 11 ? verticalOffset : 11; + + //Scroll Vertical - Calculate number of pixels + + var verticalScrollPixels = 0; + switch (verticalScrollCommand) + { + case 2: + verticalScrollPixels = -12; + break; + case 1: + verticalScrollPixels = 12; + break; + } + + //Scroll Horizontal- Calculate number of pixels + + var horizontalScrollPixels = 0; + switch (horizontalScrollCommand) + { + case 2: + horizontalScrollPixels = -6; + break; + case 1: + horizontalScrollPixels = 6; + break; + } + + if (horizontalScrollPixels == 0 && verticalScrollPixels == 0) + { + return; + } + + //Perform the actual scroll. + + var temp = new byte[FullHeight + 1, FullWidth + 1]; + var vInc = verticalScrollPixels + FullHeight; + var hInc = horizontalScrollPixels + FullWidth; + var rowIndex = 0; + //row index + var columnIndex = 0; + //column index + + for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) + { + for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) + { + temp[(rowIndex + vInc) % FullHeight, (columnIndex + hInc) % FullWidth] = _pixelColours[rowIndex, columnIndex]; + } + } + + + //if copy is false, we were supposed to fill in the new pixels + //with a new colour. Go back and do that now. + + + if (copy == false) + { + if (verticalScrollPixels > 0) + { + for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) + { + for (rowIndex = 0; rowIndex <= verticalScrollPixels - 1; rowIndex++) + { + temp[rowIndex, columnIndex] = (byte)colour; + } + } + } + else if (verticalScrollPixels < 0) + { + for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) + { + for (rowIndex = FullHeight + verticalScrollPixels; rowIndex <= FullHeight - 1; rowIndex++) + { + temp[rowIndex, columnIndex] = (byte)colour; + } + } + } + + + if (horizontalScrollPixels > 0) + { + for (columnIndex = 0; columnIndex <= horizontalScrollPixels - 1; columnIndex++) + { + for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) + { + temp[rowIndex, columnIndex] = (byte)colour; + } + } + } + else if (horizontalScrollPixels < 0) + { + for (columnIndex = FullWidth + horizontalScrollPixels; columnIndex <= FullWidth - 1; columnIndex++) + { + for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) + { + temp[rowIndex, columnIndex] = (byte)colour; + } + } + } + } + + //Now copy the temporary buffer back to our array + + for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) + { + for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) + { + _pixelColours[rowIndex, columnIndex] = temp[rowIndex, columnIndex]; + } + } + } + } } diff --git a/CdgLib/GraphicFileStream.cs b/CdgLib/GraphicFileStream.cs new file mode 100644 index 0000000..c7e3e6d --- /dev/null +++ b/CdgLib/GraphicFileStream.cs @@ -0,0 +1,46 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using CdgLib.SubCode; + +namespace CdgLib +{ + public class GraphicFileStream : FileStream + { + private const int PacketSize = 24; + + public GraphicFileStream(string path) : base(path, FileMode.Open, FileAccess.Read, FileShare.Read) + { + } + + public async Task> ReadFile() + { + Position = 0; + var subCodePackets = new List(); + var buffer = new byte[Length]; + var bytesRead = await ReadAsync(buffer, 0, buffer.Length); + + for (var i = 0; i < bytesRead/PacketSize; i++) + { + var subCodePacket = new Packet(buffer.Skip(i*PacketSize).Take(PacketSize).ToArray()); + subCodePackets.Add(subCodePacket); + } + return subCodePackets; + } + + private async Task> ReadSubCodeAsync(long numberOfPackets) + { + var subCodePackets = new List(); + var buffer = new byte[PacketSize*numberOfPackets]; + var bytesRead = await ReadAsync(buffer, 0, buffer.Length); + + for (var i = 0; i < bytesRead/PacketSize; i++) + { + var subCodePacket = new Packet(buffer.Skip(i*PacketSize).Take(PacketSize).ToArray()); + subCodePackets.Add(subCodePacket); + } + return subCodePackets; + } + } +} \ No newline at end of file diff --git a/CdgLib/GraphicUtil.cs b/CdgLib/GraphicUtil.cs deleted file mode 100644 index a1ba19b..0000000 --- a/CdgLib/GraphicUtil.cs +++ /dev/null @@ -1,109 +0,0 @@ -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Runtime.InteropServices; - -namespace CdgLib -{ - /// - /// - public class GraphicUtil - { - /// - /// Bitmaps to stream. - /// - /// The filename. - /// - public static Stream BitmapToStream(string filename) - { - var oldBmp = (Bitmap) Image.FromFile(filename); - var oldData = oldBmp.LockBits(new Rectangle(0, 0, oldBmp.Width, oldBmp.Height), ImageLockMode.WriteOnly, - PixelFormat.Format24bppRgb); - var length = oldData.Stride*oldBmp.Height; - var stream = new byte[length]; - Marshal.Copy(oldData.Scan0, stream, 0, length); - oldBmp.UnlockBits(oldData); - oldBmp.Dispose(); - return new MemoryStream(stream); - } - - - /// - /// Streams to bitmap. - /// - /// The stream. - /// The width. - /// The height. - /// - public static Bitmap StreamToBitmap(Stream stream, int width, int height) - { - //create a new bitmap - var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb); - var bmpData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat); - stream.Seek(0, SeekOrigin.Begin); - //copy the stream of pixel - for (var n = 0; n <= stream.Length - 1; n++) - { - var myByte = new byte[1]; - stream.Read(myByte, 0, 1); - Marshal.WriteByte(bmpData.Scan0, n, myByte[0]); - } - bmp.UnlockBits(bmpData); - return bmp; - } - - /// - /// Gets the CDG size bitmap. - /// - /// The filename. - /// - public static Bitmap GetCdgSizeBitmap(string filename) - { - var bm = new Bitmap(filename); - return ResizeBitmap(ref bm, GraphicsFile.FullWidth, GraphicsFile.FullHeight); - } - - /// - /// Resizes the bitmap. - /// - /// The bm. - /// The width. - /// The height. - /// - public static Bitmap ResizeBitmap(ref Bitmap bm, int width, int height) - { - var thumb = new Bitmap(width, height); - using (bm) - { - using (var g = Graphics.FromImage(thumb)) - { - g.InterpolationMode = InterpolationMode.HighQualityBicubic; - g.DrawImage(bm, new Rectangle(0, 0, width, height), new Rectangle(0, 0, bm.Width, bm.Height), - GraphicsUnit.Pixel); - } - } - return thumb; - } - - /// - /// Merges the images with transparency. - /// - /// The pic1. - /// The pic2. - /// - public static Bitmap MergeImagesWithTransparency(Bitmap picture1, Bitmap picture2) - { - Bitmap mergedImage; - var bm = new Bitmap(picture1.Width, picture1.Height); - using (var gr = Graphics.FromImage(bm)) - { - gr.DrawImage(picture1, 0, 0); - picture2.MakeTransparent(picture2.GetPixel(1, 1)); - gr.DrawImage(picture2, 0, 0); - mergedImage = bm; - } - return mergedImage; - } - } -} \ No newline at end of file diff --git a/CdgLib/GraphicsFile.cs b/CdgLib/GraphicsFile.cs index d019a2d..d38e7a5 100644 --- a/CdgLib/GraphicsFile.cs +++ b/CdgLib/GraphicsFile.cs @@ -1,105 +1,46 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Drawing; -using System.Drawing.Imaging; -using System.IO; using System.Linq; using System.Threading.Tasks; using CdgLib.SubCode; namespace CdgLib { - public class GraphicsFile : FileStream + public class GraphicsFile { - private const int ColourTableSize = 16; - private const int PacketSize = 24; - private const int TileHeight = 12; - private const int TileWidth = 6; - public const int FullWidth = 300; - public const int FullHeight = 216; + private IEnumerable _packets; - private readonly int[] _colourTable = new int[ColourTableSize]; - private readonly byte[,] _pixelColours = new byte[FullHeight, FullWidth]; - - - private long _previousPosition; - - public GraphicsFile(string path) : base(path, FileMode.Open, FileAccess.Read, FileShare.Read) + private GraphicsFile() { } public bool Transparent => true; - public long Duration => Length/PacketSize*1000/300; + public long Duration => _packets.Count()/PacketSize*1000/300; - public async Task RenderAtTime(long position = -1) + public static async Task LoadAsync(string fileName) { - if (position < 0) - { - position = _previousPosition + PacketSize; - } + var graphicsFile = new GraphicsFile {_packets = await LoadFileAsync(fileName)}; + return graphicsFile; + } - if (position < _previousPosition) + private static async Task> LoadFileAsync(string fileName) + { + using (var fileStream = new GraphicFileStream(fileName)) { - // Reset(); + return await fileStream.ReadFile(); } + } + public Bitmap RenderAtTime(long time) + { //duration of one packet is 1/300 seconds (4 packets per sector, 75 sectors per second) //p=t*3/10 t=p*10/3 t=milliseconds, p=packets - var timeToRender = position - _previousPosition; - _previousPosition += timeToRender; - var numberOfSubCodePackets = timeToRender*3/10; - - var subCodePackets = await ReadSubCodeAsync(numberOfSubCodePackets); - foreach (var subCodePacket in subCodePackets) - { - // ProcessPacket(subCodePacket); - } - - RenderSurface(); - - - - } - - - - private async Task> ReadSubCodeAsync(long numberOfPackets) - { - var subCodePackets = new List(); - var buffer = new byte[PacketSize*numberOfPackets]; - var bytesRead = await ReadAsync(buffer, 0, buffer.Length); - - for (var i = 0; i < bytesRead/PacketSize; i++) - { - var subCodePacket = new Packet(buffer.Skip(i* PacketSize).Take(PacketSize).ToArray()); - subCodePackets.Add(subCodePacket); - } - return subCodePackets; - } - - - - private void RenderSurface() - { - if (_mPSurface == null) - return; - for (var ri = 0; ri <= FullHeight - 1; ri++) - { - for (var ci = 0; ci <= FullWidth - 1; ci++) - { - if (ri < TileHeight || ri >= FullHeight - TileHeight || ci < TileWidth || - ci >= FullWidth - TileWidth) - { - // _mPSurface.RgbData[ri, ci] = _colourTable[_mBorderColourIndex]; - } - else - { - _mPSurface.RgbData[ri, ci] = _colourTable[_pixelColours[ri + _mVOffset, ci + _mHOffset]]; - } - } - } + var numberOfSubCodePackets = (int) (time*3/10); + var graphic = new Graphic(_packets.Take(numberOfSubCodePackets)); + var image = graphic.ToBitmap(); + return image; } } } \ No newline at end of file diff --git a/CdgLib/SubCode/Packet.cs b/CdgLib/SubCode/Packet.cs index 4c89639..2b2bb09 100644 --- a/CdgLib/SubCode/Packet.cs +++ b/CdgLib/SubCode/Packet.cs @@ -4,340 +4,19 @@ namespace CdgLib.SubCode { public class Packet { - public Command Command { get; } - - public Instruction Instruction { get; } - - public byte[] ParityQ { get; } = new byte[2]; - - public byte[] Data { get; } = new byte[16]; - - public byte[] ParityP { get; } = new byte[4]; - - public Packet(byte[] data) { - Command = (Command)(data[0] & 0x3F); - Instruction = (Instruction)(data[1] & 0x3F); + Command = (Command) (data[0] & 0x3F); + Instruction = (Instruction) (data[1] & 0x3F); Array.Copy(data, 2, ParityQ, 0, 2); Array.Copy(data, 4, Data, 0, 16); Array.Copy(data, 20, ParityP, 0, 4); } - public void ApplyTransform(int[,] data) - { - if (Command != Command.Graphic) return; - switch (Instruction) - { - case Instruction.MemoryPreset: - MemoryPreset(data); - break; - case Instruction.BorderPreset: - BorderPreset(data); - break; - case Instruction.TileBlockNormal: - TileBlock(data,false); - break; - case Instruction.ScrollPreset: - Scroll(data,false); - break; - case Instruction.ScrollCopy: - Scroll(data,true); - break; - case Instruction.DefineTransparentColor: - DefineTransparentColour(data); - break; - case Instruction.LoadColorTableLower: - LoadColorTable(data,0); - break; - case Instruction.LoadColorTableUpper: - LoadColorTable(data,1); - break; - case Instruction.TileBlockXor: - TileBlock(data,true); - break; - } - } - - - private void MemoryPreset(int[,] data) - { - var colour = Data[0] & 0xf; - var repeat = Data[1] & 0xf; - - //we have a reliable data stream, so the repeat command - //is executed only the first time - if (repeat == 0) - { - //Note that this may be done before any load colour table - //commands by some CDGs. So the load colour table itself - //actual recalculates the RGB values for all pixels when - //the colour table changes. - - //Set the preset colour for every pixel. Must be stored in - //the pixel colour table indeces array - for (int rowIndex = 0; rowIndex < data.GetLength(0); rowIndex++) - { - for (int columnIndex = 0; columnIndex < data.GetLength(1); columnIndex++) - { - data[rowIndex, columnIndex] = (byte) colour; - } - } - } - } - - private void BorderPreset(int[,] data) - { - int rowIndex; - int columnIndex; - - var colour = Data[0] & 0xf; - - //The border area is the area contained with a rectangle - //defined by (0,0,300,216) minus the interior pixels which are contained - //within a rectangle defined by (6,12,294,204). - - for (rowIndex = 0; rowIndex < data.GetLength(0); rowIndex++) - { - for (columnIndex = 0; columnIndex < 6; columnIndex++) - { - data[rowIndex, columnIndex] = (byte) colour; - } - - for (columnIndex = data.GetLength(1) - 6; columnIndex < data.GetLength(1); columnIndex++) - { - data[rowIndex, columnIndex] = (byte) colour; - } - } - - for (columnIndex = 6; columnIndex < data.GetLength(1) - 6; columnIndex++) - { - for (rowIndex = 0; rowIndex < 12; rowIndex++) - { - data[rowIndex, columnIndex] = (byte) colour; - } - - for (rowIndex = data.GetLength(1) - 12; rowIndex < data.GetLength(1); rowIndex++) - { - data[rowIndex, columnIndex] = (byte) colour; - } - } - } - - - private void LoadColorTable(int[,] data,int table) - { - for (var i = 0; i < 8; i++) - { - //[---high byte---] [---low byte----] - //7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 - //X X r r r r g g X X g g b b b b - - var byte0 = Data[2*i]; - var byte1 = Data[2*i + 1]; - var red = (byte0 & 0x3f) >> 2; - var green = ((byte0 & 0x3) << 2) | ((byte1 & 0x3f) >> 4); - var blue = byte1 & 0xf; - - red *= 17; - green *= 17; - blue *= 17; - - if (_mPSurface != null) - { - _mColourTable[i + table*8] = _mPSurface.MapRgbColour(red, green, blue); - } - } - } - - - private void TileBlock(int[,] data,bool bXor) - { - var colour0 = 0; - var colour1 = 0; - var columnIndex = 0; - var rowIndex = 0; - var myByte = 0; - var pixel = 0; - var xorCol = 0; - var currentColourIndex = 0; - var newCol = 0; - - colour0 = pack.Data[0] & 0xf; - colour1 = pack.Data[1] & 0xf; - rowIndex = (pack.Data[2] & 0x1f)*12; - columnIndex = (pack.Data[3] & 0x3f)*6; - - if (rowIndex > FullHeight - TileHeight) - return; - if (columnIndex > FullWidth - TileWidth) - return; - - //Set the pixel array for each of the pixels in the 12x6 tile. - //Normal = Set the colour to either colour0 or colour1 depending - //on whether the pixel value is 0 or 1. - //XOR = XOR the colour with the colour index currently there. - - - for (var i = 0; i <= 11; i++) - { - myByte = pack.Data[4 + i] & 0x3f; - for (var j = 0; j <= 5; j++) - { - pixel = (myByte >> (5 - j)) & 0x1; - if (bXor) - { - //Tile Block XOR - xorCol = pixel == 0 ? colour0 : colour1; - - //Get the colour index currently at this location, and xor with it - currentColourIndex = _mPixelColours[rowIndex + i, columnIndex + j]; - newCol = currentColourIndex ^ xorCol; - } - else - { - newCol = pixel == 0 ? colour0 : colour1; - } - - //Set the pixel with the new colour. We set both the surfarray - //containing actual RGB values, as well as our array containing - //the colour indexes into our colour table. - _mPixelColours[rowIndex + i, columnIndex + j] = (byte) newCol; - } - } - } - - private void DefineTransparentColour(int[,] data) - { - _mTransparentColour = Data[0] & 0xf; - } - - - private void Scroll(int[,] data,bool copy) - { - //Decode the scroll command parameters - var colour = Data[0] & 0xf; - var horizontalScroll = Data[1] & 0x3f; - var verticalScroll = Data[2] & 0x3f; - - var horizontalScrollCommand = (horizontalScroll & 0x30) >> 4; - var horizontalOffset = horizontalScroll & 0x7; - var verticalScrollCommand = (verticalScroll & 0x30) >> 4; - var verticalOffset = verticalScroll & 0xf; - - - _mHOffset = horizontalOffset < 5 ? horizontalOffset : 5; - _mVOffset = verticalOffset < 11 ? verticalOffset : 11; - - //Scroll Vertical - Calculate number of pixels - - var verticalScrollPixels = 0; - switch (verticalScrollCommand) - { - case 2: - verticalScrollPixels = -12; - break; - case 1: - verticalScrollPixels = 12; - break; - } - - //Scroll Horizontal- Calculate number of pixels - - var horizontalScrollPixels = 0; - switch (horizontalScrollCommand) - { - case 2: - horizontalScrollPixels = -6; - break; - case 1: - horizontalScrollPixels = 6; - break; - } - - if (horizontalScrollPixels == 0 && verticalScrollPixels == 0) - { - return; - } - - //Perform the actual scroll. - - var temp = new byte[FullHeight + 1, FullWidth + 1]; - var vInc = verticalScrollPixels + FullHeight; - var hInc = horizontalScrollPixels + FullWidth; - var rowIndex = 0; - //row index - var columnIndex = 0; - //column index - - for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) - { - for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) - { - temp[(rowIndex + vInc)%FullHeight, (columnIndex + hInc)%FullWidth] = _mPixelColours[rowIndex, columnIndex]; - } - } - - - //if copy is false, we were supposed to fill in the new pixels - //with a new colour. Go back and do that now. - - - if (copy == false) - { - if (verticalScrollPixels > 0) - { - for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) - { - for (rowIndex = 0; rowIndex <= verticalScrollPixels - 1; rowIndex++) - { - temp[rowIndex, columnIndex] = (byte) colour; - } - } - } - else if (verticalScrollPixels < 0) - { - for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) - { - for (rowIndex = FullHeight + verticalScrollPixels; rowIndex <= FullHeight - 1; rowIndex++) - { - temp[rowIndex, columnIndex] = (byte) colour; - } - } - } - - - if (horizontalScrollPixels > 0) - { - for (columnIndex = 0; columnIndex <= horizontalScrollPixels - 1; columnIndex++) - { - for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) - { - temp[rowIndex, columnIndex] = (byte) colour; - } - } - } - else if (horizontalScrollPixels < 0) - { - for (columnIndex = FullWidth + horizontalScrollPixels; columnIndex <= FullWidth - 1; columnIndex++) - { - for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) - { - temp[rowIndex, columnIndex] = (byte) colour; - } - } - } - } - - //Now copy the temporary buffer back to our array - - for (rowIndex = 0; rowIndex <= FullHeight - 1; rowIndex++) - { - for (columnIndex = 0; columnIndex <= FullWidth - 1; columnIndex++) - { - _mPixelColours[rowIndex, columnIndex] = temp[rowIndex, columnIndex]; - } - } - } + public Command Command { get; } + public Instruction Instruction { get; } + public byte[] ParityQ { get; } = new byte[2]; + public byte[] Data { get; } = new byte[16]; + public byte[] ParityP { get; } = new byte[4]; } } \ No newline at end of file diff --git a/CdgLib/Surface.cs b/CdgLib/Surface.cs deleted file mode 100644 index dfad705..0000000 --- a/CdgLib/Surface.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Drawing; - -namespace CdgLib -{ - public class Surface - { - public int[,] RgbData = new int[GraphicsFile.FullHeight, GraphicsFile.FullWidth]; - - public int MapRgbColour(int red, int green, int blue) - { - return Color.FromArgb(red, green, blue).ToArgb(); - } - } -} \ No newline at end of file