void ParseMemoryPreset(SynchronizedLyricsItemBuilder sl, CdgPacket packet) { int repeat = packet.Data[1] & 0x0F; if (repeat == 0) { sl.Commands.Add(new SlcWithColorIndex(SynchronizedLyricsCommandType.ClearScreen, (byte)(packet.Data[0] & 0x0F))); } }
void ParseLoadColorTable(SynchronizedLyricsItemBuilder sl, CdgPacket packet, bool higherTable) { int offset = higherTable ? 8 : 0; ARGB[] palette = new ARGB[8]; for (int i = 0; i < 8; i++) { byte r = (byte)((packet.Data[i * 2] & 0x3C) << 2); byte g = (byte)(((packet.Data[i * 2] & 0x03) << 6) | (packet.Data[(i * 2) + 1] & 0x30)); byte b = (byte)((packet.Data[(i * 2) + 1] & 0x0F) << 4); palette[i] = ARGB.FromColor(r, g, b); } sl.Commands.Add(new SlcReplacePaletteColors((byte)offset, palette)); }
void ParseScroll(SynchronizedLyricsItemBuilder sl, CdgPacket packet, bool roll) { int colorIndex = packet.Data[0] & 0x0F; int cdgHScroll = packet.Data[1] & 0x3F; int cdgVScroll = packet.Data[2] & 0x3F; sbyte hScroll = 0; sbyte vScroll = 0; switch (cdgHScroll >> 4) { default: case 0: /*no scroll*/ break; case 1: /*right 6px*/ hScroll = 6; break; case 2: /*left 6px*/ hScroll = -6; break; } switch (cdgVScroll >> 4) { default: case 0: /*no scroll*/ break; case 1: /*down 12px*/ vScroll = 12; break; case 2: /*up 12px*/ vScroll = -12; break; } if (hScroll != 0 || vScroll != 0) { if (roll) { sl.Commands.Add(new SlcScreenRoll(hScroll, vScroll)); } else { sl.Commands.Add(new SlcScreenScroll((byte)colorIndex, hScroll, vScroll)); } } sbyte hOffset = (sbyte)((cdgHScroll & 0xF) % 6); sbyte vOffset = (sbyte)((cdgVScroll & 0xF) % 12); if (hOffset != currentOffsetHorizontal || vOffset != currentOffsetVertical) { sl.Commands.Add(new SlcScreenOffset(hOffset, vOffset)); currentOffsetHorizontal = hOffset; currentOffsetVertical = vOffset; } }
/// <summary>Reads all frames.</summary> /// <param name="stream">The stream.</param> /// <returns></returns> public static SynchronizedLyrics ReadAllFrames(Stream stream) { var items = new List <SynchronizedLyricsItem>(); var reader = new CdgReader(stream); CdgPacket packet; TimeSpan time; while (reader.GetNextPacket(out packet, out time)) { var builder = new SynchronizedLyricsItemBuilder(); builder.TimeCode = time; switch (packet.Instruction) { case CdgInstruction.MemoryPreset: reader.ParseMemoryPreset(builder, packet); break; case CdgInstruction.BorderPreset: break; case CdgInstruction.TileBlock: reader.ParseTileBlock(builder, packet, false); break; case CdgInstruction.TileBlockXor: reader.ParseTileBlock(builder, packet, true); break; case CdgInstruction.ScrollPreset: reader.ParseScroll(builder, packet, false); break; case CdgInstruction.ScrollCopy: reader.ParseScroll(builder, packet, true); break; case CdgInstruction.DefineTransparentColor: reader.ParseDefineTransparentColor(builder, packet); break; case CdgInstruction.LoadLowerColorTable: reader.ParseLoadColorTable(builder, packet, false); break; case CdgInstruction.LoadHigherColorTable: reader.ParseLoadColorTable(builder, packet, true); break; case CdgInstruction.Unknown: continue; default: Trace.TraceError("Unknown command <red>{0}", packet.Instruction); continue; } if (builder.Commands.Count > 0) { items.Add(builder.ToSynchronizedLyricsItem()); } } return(new SynchronizedLyrics(items)); }
void ParseTileBlock(SynchronizedLyricsItemBuilder sl, CdgPacket packet, bool xor) { byte color0 = (byte)(packet.Data[0] & 0x0F); byte color1 = (byte)(packet.Data[1] & 0x0F); int y = (packet.Data[2] & 0x1F) * 12; int x = (packet.Data[3] & 0x3F) * 6; int w = 6; int h = 12; if (x + w > BufferWidth || y + h > BufferHeight) { Trace.TraceError(string.Format("Subchannel decode error x={0} y={1}", x, y)); return; } byte[] data = new byte[12]; Array.Copy(packet.Data, 4, data, 0, 12); SynchronizedLyricsCommandType cmd = xor ? SynchronizedLyricsCommandType.SetSprite2ColorsXOR : SynchronizedLyricsCommandType.SetSprite2Colors; sl.Commands.Add(new SlcSetSprite2Colors(cmd, w, h, x, y, color0, color1, data)); }
/// <summary>Creates a new <see cref="SynchronizedLyrics"/> instance by parsing the specified stream.</summary> /// <param name="stream">The stream.</param> /// <returns></returns> public static SynchronizedLyrics FromStream(MemoryStream stream) { var items = new List <SynchronizedLyricsItem>(); long milliSecond = 0; var reader = new DataReader(stream); if (reader.ReadString(3) != "SLT") { throw new InvalidDataException("Invalid format!"); } if (reader.Read7BitEncodedUInt64() != 1) { throw new InvalidDataException("Invalid version!"); } while (reader.Available > 0) { long milliSecondDistance = reader.Read7BitEncodedInt64(); milliSecond += milliSecondDistance; var item = new SynchronizedLyricsItemBuilder(); item.TimeCode = new TimeSpan(milliSecond * TimeSpan.TicksPerMillisecond); while (true) { ISynchronizedLyricsCommand command = SynchronizedLyricsCommand.Parse(reader); if (command == null) { break; } item.Commands.Add(command); } items.Add(item.ToSynchronizedLyricsItem()); } return(new SynchronizedLyrics(items)); }
void ParseDefineTransparentColor(SynchronizedLyricsItemBuilder sl, CdgPacket packet) { sl.Commands.Add(new SlcWithColorIndex(SynchronizedLyricsCommandType.SetTransparentColor, (byte)(packet.Data[0] & 0x0F))); }