예제 #1
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(4);

            if (data.Length < 4)
            {
                return(null);
            }

            if (data[0x00] != 0x57)
            {
                return(null);
            }

            if (data[0x01] != 0x42)
            {
                return(null);
            }

            if (data[0x02] != 0x4E)
            {
                return(null);
            }

            if (data[0x03] != 0x44)
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }
예제 #2
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(0x4);

            if (data[0x0000] == 0x00 && data[0x0001] == 0x00)
            {
                return(null);
            }

            if ((data[0x0000] & 0x1F) != 0)
            {
                return(null);
            }

            if (data[0x0001] >= 0x20)
            {
                return(null);
            }

            if (data[0x0002] != 0x00)
            {
                return(null);
            }

            if (data[0x0003] != 0x38)
            {
                return(null);
            }

            reader.Skip(0x1FFC);

            var data2 = reader.Read(0x4);

            if (data2[0x0000] == 0x00 && data2[0x0001] == 0x00)
            {
                return(null);
            }

            if ((data2[0x0000] & 0x1F) != 0)
            {
                return(null);
            }

            if (data2[0x0001] >= 0x20)
            {
                return(null);
            }

            if (data2[0x0002] != 0x00)
            {
                return(null);
            }

            if (data2[0x0003] != 0x38)
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }
예제 #3
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(8);

            if (data.Length < 8)
            {
                return(null);
            }

            if (data[0] != 0x10)
            {
                return(null);
            }
            if (data[1] != 0x00)
            {
                return(null);
            }
            if (data[2] != 0x00)
            {
                return(null);
            }
            if (data[3] != 0x00)
            {
                return(null);
            }

            switch (data[4])
            {
            case 0x00: break;

            case 0x01: break;

            case 0x02: break;

            case 0x08: break;

            case 0x09: break;

            default: return(null);
            }

            if (data[5] != 0x00)
            {
                return(null);
            }
            if (data[6] != 0x00)
            {
                return(null);
            }
            if (data[7] != 0x00)
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(0x10);

            if (data.Length < 0x10)
            {
                return(null);
            }

            var length = Bitter.ToInt32S(data);

            if (length == 0)
            {
                return(null);
            }

            if ((length & 0x7FF) != 0)
            {
                return(null);
            }

            if (data[0x05] == 0)
            {
                return(null);
            }

            var sampleRate = Bitter.ToInt16S(data, 6);

            if (sampleRate == 0)
            {
                return(null);
            }

            if (data[0x08] == 0)
            {
                return(null);
            }

            if (data[0x08] > 2)
            {
                return(null);
            }

            return(new VagHeuristicResult(this)
            {
                Start = 0x800,
                Interleave = 0x800,
                Channels = data[0x08],
                SampleRate = sampleRate,
                Length = length
            });
        }
예제 #5
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(8);

            if (data.Length < 8)
            {
                return(null);
            }

            if (Encodings.CP437.GetString(data.Slice(0, 8)) != "PS-X EXE")
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }
        public HeuristicResult Match(IHeuristicReader reader)
        {
            if (reader.Length < 0x804)
            {
                return(null);
            }

            var data = reader.Read(0x2C);

            if (Bitter.ToInt32(data.Slice(0x00)) != 0x08640001)
            {
                return(null);
            }

            if (Bitter.ToInt32(data.Slice(0x04)) != 0)
            {
                return(null);
            }

            var startOffset = Bitter.ToInt32(data.Slice(0x08));

            if (startOffset < 0x00000030)
            {
                return(null);
            }

            var result = new VagHeuristicResult(this)
            {
                Start      = startOffset,
                Length     = Bitter.ToInt32(data.Slice(0x0C)),
                LoopStart  = Bitter.ToInt32(data.Slice(0x10)),
                LoopEnd    = Bitter.ToInt32(data.Slice(0x14)),
                SampleRate = Bitter.ToInt32(data.Slice(0x18)),
                Channels   = Bitter.ToInt32(data.Slice(0x1C)),
                Interleave = Bitter.ToInt32(data.Slice(0x24)),
                Volume     = new BigRational(Bitter.ToInt32(data.Slice(0x28)), 100),
            };

            if (data[0x20] != 0x00 || data[0x21] != 0x00 || data[0x22] != 0x00 || data[0x23] != 0x00)
            {
                result.Key = data.Slice(0x20, 4).ToArray();
            }

            return(result);
        }
예제 #7
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(0x10);

            if (data.Length < 0x10)
            {
                return(null);
            }

            var a = Bitter.ToInt32(data);
            var b = Bitter.ToInt32(data, 4);
            var c = Bitter.ToInt32(data, 8);
            var d = Bitter.ToInt32(data, 12);

            if (a <= 0)
            {
                return(null);
            }

            if (b <= 0)
            {
                return(null);
            }

            if (c < 0)
            {
                return(null);
            }

            if (d != 0)
            {
                return(null);
            }

            if (a - b - c != 16384)
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var maxTable = int.MaxValue;
            var offsets  = new List <int>();

            for (var i = 0; i < maxTable; i++)
            {
                var offset = reader.ReadInt();
                if (offset >= 4 && offset < 0x1000000 && !offsets.Contains(offset))
                {
                    offsets.Add(offset);
                    if (maxTable > offset / 4)
                    {
                        maxTable = offset / 4;
                    }
                }
                else if (offset != 0 && offset < i * 4)
                {
                    return(null);
                }
            }

            return(new HeuristicResult(this));
        }
예제 #9
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data = reader.Read(12);

            if (data.Length < 12)
            {
                return(null);
            }

            if (data[0] % 4 != 0)
            {
                return(null);
            }

            if (data[0] == 0 && data[1] == 0)
            {
                return(null);
            }

            if (data[2] != 0)
            {
                return(null);
            }

            if (data[3] != 0)
            {
                return(null);
            }

            if (data[4] != 1)
            {
                return(null);
            }

            if (data[5] != 0)
            {
                return(null);
            }

            if (data[6] == 0 && data[7] == 0)
            {
                return(null);
            }

            if (data[8] == 0 && data[9] == 0)
            {
                return(null);
            }

            if (data[10] != 0)
            {
                return(null);
            }

            if (data[11] != 0)
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }
예제 #10
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            // Must have at least 4 bytes
            if (reader.Length == null || reader.Length < 4)
            {
                return(null);
            }

            // Put a hard cap of 64k as a sanity check
            if (reader.Length > 65536)
            {
                return(null);
            }

            // Must be divisible by 4
            if ((reader.Length & 0x3) != 0)
            {
                return(null);
            }

            var data = reader.Read((int)reader.Length);

            // Make sure each chunk length makes sense
            var thisOffset = 0;

            while (thisOffset < reader.Length)
            {
                var thisChunkLength = Bitter.ToInt32(data, thisOffset);
                if (thisChunkLength == 0)
                {
                    break;
                }
                if (thisChunkLength < 0)
                {
                    return(null);
                }
                if (thisOffset + thisChunkLength >= reader.Length)
                {
                    return(null);
                }
                if ((thisOffset & 0x3) != 0)
                {
                    return(null);
                }
                thisOffset += thisChunkLength;
            }

            // Try to make sense of the timing chunk length
            var timingChunkLength = Bitter.ToInt32(data);

            if (timingChunkLength < 20)
            {
                return(null);
            }
            if (timingChunkLength >= reader.Length)
            {
                return(null);
            }
            if ((timingChunkLength & 0x3) != 0)
            {
                return(null);
            }

            // Check both the measure and the second offset, make sure they are increasing
            var timingMeasure = int.MinValue;
            var timingSector  = int.MinValue;

            for (var i = 1; i < timingChunkLength >> 2; i += 2)
            {
                var thisTimingMeasure = Bitter.ToInt32(data, i << 2);
                var thisTimingSector  = Bitter.ToInt32(data, 0x4 + (i << 2));
                if (thisTimingMeasure < timingMeasure)
                {
                    return(null);
                }
                if (thisTimingSector < timingSector)
                {
                    return(null);
                }
                timingMeasure = thisTimingMeasure;
                timingSector  = thisTimingSector;
            }

            // No reason to believe this isn't a step1 at this point
            return(new HeuristicResult(this));
        }
예제 #11
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var data  = reader.Read(0x1C);
            var words = MemoryMarshal.Cast <byte, int>(data);

            // "Svag"
            if (words[0] != 0x67617653)
            {
                return(null);
            }

            // Make sure length is 16-byte aligned
            if ((words[1] & 0xF) != 0)
            {
                return(null);
            }

            // Make sure sample rate fits in 16bits
            if (words[2] > 0xFFFF || words[2] <= 0)
            {
                return(null);
            }

            // More than 4 channels is pretty unlikely
            if (words[3] < 1 || words[3] > 4)
            {
                return(null);
            }

            // Total length must be at least the header size
            if (words[1] < 0x800)
            {
                return(null);
            }

            // Interleave must be non negative
            if (words[4] < 0)
            {
                return(null);
            }

            // Interleave must be present if more than 1 channel
            if (words[3] > 1 && words[4] == 0)
            {
                return(null);
            }

            // Must have at least 1 full block present
            if (words[1] < words[3] * words[4])
            {
                return(null);
            }

            // The usable header length is 0x1C but the last two words are loop info, we don't care about it

            return(new VagHeuristicResult(this)
            {
                Start = 0x800,
                Length = words[1] - 0x800,
                SampleRate = words[2],
                Channels = words[3],
                Interleave = words[4],
                LoopStart = words[5],
                LoopEnd = words[6]
            });
        }
예제 #12
0
        public HeuristicResult Match(IHeuristicReader reader)
        {
            var noteCountMode = true;
            var hasBpm        = false;
            var hasEnd        = false;
            var hasTerminator = false;
            var evData        = new byte[4];

            while (true)
            {
                if (reader.Read(evData, 0, 4) < 4)
                {
                    break;
                }

                var eventOffset    = Bitter.ToInt16S(evData);
                var eventValue     = evData[2];
                var eventCommand   = evData[3];
                var eventParameter = eventCommand >> 4;
                var eventType      = eventCommand & 0xF;

                // empty event = invalid
                if (Bitter.ToInt32(evData) == 0)
                {
                    return(null);
                }

                // positive event offsets only
                if (eventOffset < 0)
                {
                    return(null);
                }

                // offsets can't be present during note count
                if (noteCountMode && eventOffset != 0)
                {
                    return(null);
                }

                // disable note count info if another event type shows up
                if (eventCommand != 0x00 && eventCommand != 0x01)
                {
                    noteCountMode = false;
                }

                // skip the rest of processing if in note count mode
                if (noteCountMode)
                {
                    continue;
                }

                // terminator bytes
                if (eventOffset == 0x7FFF)
                {
                    hasTerminator = true;
                    break;
                }

                // make sure we have the bare minimums
                if (eventType == 6)
                {
                    hasEnd = true;
                }
                else if (eventType == 4 && eventValue + (eventParameter << 8) != 0)
                {
                    hasBpm = true;
                }
            }

            if (!(hasBpm && hasEnd && hasTerminator))
            {
                return(null);
            }

            return(new HeuristicResult(this));
        }