예제 #1
0
        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)));
            }
        }
예제 #2
0
        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));
        }
예제 #3
0
        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;
            }
        }
예제 #4
0
        /// <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));
        }
예제 #5
0
        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));
        }
예제 #6
0
        /// <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));
        }
예제 #7
0
 void ParseDefineTransparentColor(SynchronizedLyricsItemBuilder sl, CdgPacket packet)
 {
     sl.Commands.Add(new SlcWithColorIndex(SynchronizedLyricsCommandType.SetTransparentColor, (byte)(packet.Data[0] & 0x0F)));
 }