/// <summary>Gets the next packet or null if the end of the stream was reached.</summary> /// <param name="packet">The packet.</param> /// <param name="time">The time.</param> /// <returns></returns> /// <exception cref="ObjectDisposedException"></exception> public bool GetNextPacket(out CdgPacket packet, out TimeSpan time) { if (m_Reader == null) { throw new ObjectDisposedException(nameof(CdgReader)); } // can we check the position in the stream ? yes -> can we read another packet ? no -> exit if (m_Reader.BaseStream.CanSeek && m_Reader.Available < 24) { packet = default(CdgPacket); time = default(TimeSpan); return(false); } try { packet = m_Reader.ReadStruct <CdgPacket>(); time = new TimeSpan(m_PacketNumber++ *TimeSpan.TicksPerSecond / PacketPerSecond); return(true); } catch (EndOfStreamException) { packet = default(CdgPacket); time = default(TimeSpan); return(false); } }
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; } }
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)); }
void ParseDefineTransparentColor(SynchronizedLyricsItemBuilder sl, CdgPacket packet) { sl.Commands.Add(new SlcWithColorIndex(SynchronizedLyricsCommandType.SetTransparentColor, (byte)(packet.Data[0] & 0x0F))); }