From 628ad531af5372ad004274bb469230c5ec4fa2e3 Mon Sep 17 00:00:00 2001 From: Brett Sanderson Date: Fri, 4 Mar 2016 22:58:03 -0500 Subject: [PATCH] Refactor progress --- CdgLib/CdgLib.csproj | 1 + CdgLib/Extension/Extensions.cs | 13 ++ CdgLib/Graphic.cs | 394 +-------------------------------- CdgLib/GraphicsFile.cs | 11 +- CdgLib/SubCode/Packet.cs | 332 ++++++++++++++++++++++++++- 5 files changed, 354 insertions(+), 397 deletions(-) create mode 100644 CdgLib/Extension/Extensions.cs diff --git a/CdgLib/CdgLib.csproj b/CdgLib/CdgLib.csproj index 402b69e..b2b5136 100644 --- a/CdgLib/CdgLib.csproj +++ b/CdgLib/CdgLib.csproj @@ -42,6 +42,7 @@ + diff --git a/CdgLib/Extension/Extensions.cs b/CdgLib/Extension/Extensions.cs new file mode 100644 index 0000000..c1ea5f7 --- /dev/null +++ b/CdgLib/Extension/Extensions.cs @@ -0,0 +1,13 @@ +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 587111d..484fca4 100644 --- a/CdgLib/Graphic.cs +++ b/CdgLib/Graphic.cs @@ -11,26 +11,15 @@ namespace CdgLib { public class Graphic { - private int _mPresetColourIndex; - private int _mBorderColourIndex; - private long _mDuration; - private int _mHOffset; - private Bitmap _mImage; - - private CdgFileIoStream _mPStream; - private readonly Surface _mPSurface; - private int _mTransparentColour; - private int _mVOffset; - - private const byte Command = 0x9; - private const byte CdgMask = 0x3f; - private const int CdgDisplayWidth = 294; - private const int CdgDisplayHeight = 204; private int[,] _graphicData; + public Graphic(IEnumerable packets) { - + foreach (var packet in packets) + { + packet.ApplyTransform(ref _graphicData); + } } public Bitmap ToBitmap() @@ -51,379 +40,8 @@ namespace CdgLib } - private void ProcessPacket(Packet packetPacket) - { - if ((packetPacket.Command[0] & CdgMask) != Command) return; - var instructionCode = (Instruction)(packetPacket.Instruction[0] & CdgMask); - switch (instructionCode) - { - case Instruction.MemoryPreset: - MemoryPreset(packetPacket); - break; - case Instruction.BorderPreset: - BorderPreset(packetPacket); - break; - case Instruction.TileBlockNormal: - TileBlock(packetPacket, false); - break; - case Instruction.ScrollPreset: - Scroll(packetPacket, false); - break; - case Instruction.ScrollCopy: - Scroll(packetPacket, true); - break; - case Instruction.DefineTransparentColor: - DefineTransparentColour(packetPacket); - break; - case Instruction.LoadColorTableLower: - LoadColorTable(packetPacket, 0); - break; - case Instruction.LoadColorTableUpper: - LoadColorTable(packetPacket, 1); - break; - case Instruction.TileBlockXor: - TileBlock(packetPacket, true); - break; - } - } + - private void MemoryPreset(Packet pack) - { - var colour = 0; - var ri = 0; - var ci = 0; - var repeat = 0; - - colour = pack.Data[0] & 0xf; - repeat = pack.Data[1] & 0xf; - - //Our new interpretation of CD+G Revealed is that memory preset - //commands should also change the border - _mPresetColourIndex = colour; - _mBorderColourIndex = colour; - - //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 (ri = 0; ri <= FullHeight - 1; ri++) - { - for (ci = 0; ci <= FullWidth - 1; ci++) - { - _mPixelColours[ri, ci] = (byte)colour; - } - } - } - } - - private void Reset() - { - Position = 0; - Array.Clear(_mPixelColours, 0, _mPixelColours.Length); - Array.Clear(_mColourTable, 0, _mColourTable.Length); - - _mBorderColourIndex = 0; - _mTransparentColour = 0; - _mHOffset = 0; - _mVOffset = 0; - - _mDuration = 0; - _previousPosition = 0; - - //clear surface - if (_mPSurface.RgbData != null) - { - Array.Clear(_mPSurface.RgbData, 0, _mPSurface.RgbData.Length); - } - } - - private void BorderPreset(Packet pack) - { - var colour = 0; - var ri = 0; - var ci = 0; - - colour = pack.Data[0] & 0xf; - _mBorderColourIndex = colour; - - //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 (ri = 0; ri <= FullHeight - 1; ri++) - { - for (ci = 0; ci <= 5; ci++) - { - _mPixelColours[ri, ci] = (byte)colour; - } - - for (ci = FullWidth - 6; ci <= FullWidth - 1; ci++) - { - _mPixelColours[ri, ci] = (byte)colour; - } - } - - for (ci = 6; ci <= FullWidth - 7; ci++) - { - for (ri = 0; ri <= 11; ri++) - { - _mPixelColours[ri, ci] = (byte)colour; - } - - for (ri = FullHeight - 12; ri <= FullHeight - 1; ri++) - { - _mPixelColours[ri, ci] = (byte)colour; - } - } - } - - - private void LoadColorTable(Packet pack, int table) - { - for (var i = 0; i <= 7; 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 = pack.Data[2 * i]; - var byte1 = pack.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(Packet pack, 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 - if (pixel == 0) - { - xorCol = colour0; - } - else - { - xorCol = colour1; - } - - //Get the colour index currently at this location, and xor with it - currentColourIndex = _mPixelColours[rowIndex + i, columnIndex + j]; - newCol = currentColourIndex ^ xorCol; - } - else - { - if (pixel == 0) - { - newCol = colour0; - } - else - { - newCol = 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(Packet pack) - { - _mTransparentColour = pack.Data[0] & 0xf; - } - - - private void Scroll(Packet pack, bool copy) - { - var colour = 0; - var hScroll = 0; - var vScroll = 0; - var hSCmd = 0; - var hOffset = 0; - var vSCmd = 0; - var vOffset = 0; - var vScrollPixels = 0; - var hScrollPixels = 0; - - //Decode the scroll command parameters - colour = pack.Data[0] & 0xf; - hScroll = pack.Data[1] & 0x3f; - vScroll = pack.Data[2] & 0x3f; - - hSCmd = (hScroll & 0x30) >> 4; - hOffset = hScroll & 0x7; - vSCmd = (vScroll & 0x30) >> 4; - vOffset = vScroll & 0xf; - - - _mHOffset = hOffset < 5 ? hOffset : 5; - _mVOffset = vOffset < 11 ? vOffset : 11; - - //Scroll Vertical - Calculate number of pixels - - vScrollPixels = 0; - if (vSCmd == 2) - { - vScrollPixels = -12; - } - else if (vSCmd == 1) - { - vScrollPixels = 12; - } - - //Scroll Horizontal- Calculate number of pixels - - hScrollPixels = 0; - if (hSCmd == 2) - { - hScrollPixels = -6; - } - else if (hSCmd == 1) - { - hScrollPixels = 6; - } - - if (hScrollPixels == 0 && vScrollPixels == 0) - { - return; - } - - //Perform the actual scroll. - - var temp = new byte[FullHeight + 1, FullWidth + 1]; - var vInc = vScrollPixels + FullHeight; - var hInc = hScrollPixels + FullWidth; - var ri = 0; - //row index - var ci = 0; - //column index - - for (ri = 0; ri <= FullHeight - 1; ri++) - { - for (ci = 0; ci <= FullWidth - 1; ci++) - { - temp[(ri + vInc) % FullHeight, (ci + hInc) % FullWidth] = _mPixelColours[ri, ci]; - } - } - - - //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 (vScrollPixels > 0) - { - for (ci = 0; ci <= FullWidth - 1; ci++) - { - for (ri = 0; ri <= vScrollPixels - 1; ri++) - { - temp[ri, ci] = (byte)colour; - } - } - } - else if (vScrollPixels < 0) - { - for (ci = 0; ci <= FullWidth - 1; ci++) - { - for (ri = FullHeight + vScrollPixels; ri <= FullHeight - 1; ri++) - { - temp[ri, ci] = (byte)colour; - } - } - } - - - if (hScrollPixels > 0) - { - for (ci = 0; ci <= hScrollPixels - 1; ci++) - { - for (ri = 0; ri <= FullHeight - 1; ri++) - { - temp[ri, ci] = (byte)colour; - } - } - } - else if (hScrollPixels < 0) - { - for (ci = FullWidth + hScrollPixels; ci <= FullWidth - 1; ci++) - { - for (ri = 0; ri <= FullHeight - 1; ri++) - { - temp[ri, ci] = (byte)colour; - } - } - } - } - - //Now copy the temporary buffer back to our array - - for (ri = 0; ri <= FullHeight - 1; ri++) - { - for (ci = 0; ci <= FullWidth - 1; ci++) - { - _mPixelColours[ri, ci] = temp[ri, ci]; - } - } - } } } diff --git a/CdgLib/GraphicsFile.cs b/CdgLib/GraphicsFile.cs index 332c847..6f61132 100644 --- a/CdgLib/GraphicsFile.cs +++ b/CdgLib/GraphicsFile.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; +using System.Linq; using System.Threading.Tasks; using CdgLib.SubCode; @@ -24,9 +25,8 @@ namespace CdgLib private long _previousPosition; - public GraphicsFile(string path, FileMode mode, FileAccess fileAccess) : base(path, mode, fileAccess, FileShare.Read) + public GraphicsFile(string path) : base(path, FileMode.Open, FileAccess.Read, FileShare.Read) { - } public bool Transparent => true; @@ -73,12 +73,7 @@ namespace CdgLib for (var i = 0; i < bytesRead/CdgPacketSize; i++) { - var subCodePacket = new Packet(); - Array.Copy(buffer, i*CdgPacketSize + 0, subCodePacket.Command, 0, 1); - Array.Copy(buffer, i*CdgPacketSize + 1, subCodePacket.Instruction, 0, 1); - Array.Copy(buffer, i*CdgPacketSize + 2, subCodePacket.ParityQ, 0, 2); - Array.Copy(buffer, i*CdgPacketSize + 4, subCodePacket.Data, 0, 16); - Array.Copy(buffer, i*CdgPacketSize + 20, subCodePacket.ParityP, 0, 4); + var subCodePacket = new Packet(buffer.Skip(i* CdgPacketSize).Take(CdgPacketSize).ToArray()); subCodePackets.Add(subCodePacket); } return subCodePackets; diff --git a/CdgLib/SubCode/Packet.cs b/CdgLib/SubCode/Packet.cs index c0df716..c2e7f38 100644 --- a/CdgLib/SubCode/Packet.cs +++ b/CdgLib/SubCode/Packet.cs @@ -1,4 +1,6 @@ -namespace CdgLib.SubCode +using System; + +namespace CdgLib.SubCode { public class Packet { @@ -7,5 +9,333 @@ public byte[] Instruction = new byte[1]; public byte[] ParityP = new byte[4]; public byte[] ParityQ = new byte[2]; + + private const byte Mask = 0x3f; + + public Packet(byte[] data) + { + Array.Copy(data, 0, Command, 0, 1); + Array.Copy(data, 1, Instruction, 0, 1); + 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[0] & Mask) != (int) SubCode.Command.Graphic) return; + var instructionCode = (Instruction)(Instruction[0] & Mask); + switch (instructionCode) + { + case SubCode.Instruction.MemoryPreset: + MemoryPreset(data); + break; + case SubCode.Instruction.BorderPreset: + BorderPreset(data); + break; + case SubCode.Instruction.TileBlockNormal: + TileBlock(data,false); + break; + case SubCode.Instruction.ScrollPreset: + Scroll(data,false); + break; + case SubCode.Instruction.ScrollCopy: + Scroll(data,true); + break; + case SubCode.Instruction.DefineTransparentColor: + DefineTransparentColour(data); + break; + case SubCode.Instruction.LoadColorTableLower: + LoadColorTable(data,0); + break; + case SubCode.Instruction.LoadColorTableUpper: + LoadColorTable(data,1); + break; + case SubCode.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]; + } + } + } } } \ No newline at end of file