Esempio n. 1
0
        public static SEQ Load(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            // All SEP/SEQ stuff is big-endian, like MIDI
            if (data.Length < 15)
            {
                ErrorManager.SignalError("SEQ: Data is too short");
            }
            int magic   = BEBitConv.FromInt32(data, 0);
            int version = BEBitConv.FromInt32(data, 4);

            if (magic != Magic)
            {
                ErrorManager.SignalIgnorableError("SEQ: Magic number is wrong");
            }
            if (version != Version)
            {
                ErrorManager.SignalIgnorableError("SEQ: Version number is wrong");
            }
            short resolution = BEBitConv.FromInt16(data, 8);
            int   tempo      = MIDIConv.From3BE(data, 10);
            short rhythm     = BEBitConv.FromInt16(data, 13);

            byte[] scoredata = new byte [data.Length - 15];
            Array.Copy(data, 15, scoredata, 0, scoredata.Length);
            return(new SEQ(resolution, tempo, rhythm, scoredata));
        }
Esempio n. 2
0
        public static VAB Join(VH vh, SampleLine[] vb)
        {
            if (vh == null)
            {
                throw new ArgumentNullException("vh");
            }
            if (vb == null)
            {
                throw new ArgumentNullException("vb");
            }
            if (vh.VBSize != vb.Length)
            {
                ErrorManager.SignalIgnorableError("VAB: VB size field mismatch");
            }
            SampleSet[] waves  = new SampleSet [vh.Waves.Count];
            int         offset = 0;

            for (int i = 0; i < vh.Waves.Count; i++)
            {
                int wavelength = vh.Waves[i];
                if (offset + wavelength > vb.Length)
                {
                    ErrorManager.SignalError("VAB: Wave ends out of bounds");
                }
                SampleLine[] wavelines = new SampleLine[wavelength];
                for (int j = 0; j < wavelength; j++)
                {
                    wavelines[j] = vb[offset + j];
                }
                offset  += wavelength;
                waves[i] = new SampleSet(wavelines);
            }
            return(new VAB(vh.IsOldVersion, vh.Volume, vh.Panning, vh.Attribute1, vh.Attribute2, vh.Programs, waves));
        }
Esempio n. 3
0
        public override Entry Load(byte[][] items, int eid)
        {
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }
            if (items.Length != 2)
            {
                ErrorManager.SignalError("WavebankEntry: Wrong number of items");
            }
            if (items[0].Length != 8)
            {
                ErrorManager.SignalError("WavebankEntry: First item length is wrong");
            }
            int id     = BitConv.FromInt32(items[0], 0);
            int length = BitConv.FromInt32(items[0], 4);

            if (id < 0 || id > 6)
            {
                ErrorManager.SignalIgnorableError("WavebankEntry: ID is invalid");
            }
            if (length != items[1].Length)
            {
                ErrorManager.SignalIgnorableError("WavebankEntry: Length field mismatch");
            }
            return(new WavebankEntry(id, SampleSet.Load(items[1]), eid));
        }
Esempio n. 4
0
        public static VHTone Load(byte[] data)
        {
            if (data.Length != 32)
            {
                throw new ArgumentException("Value must be 32 bytes long.", "data");
            }
            byte  priority         = data[0];
            byte  mode             = data[1];
            byte  volume           = data[2];
            byte  panning          = data[3];
            byte  centernote       = data[4];
            byte  pitchshift       = data[5];
            byte  minimumnote      = data[6];
            byte  maximumnote      = data[7];
            byte  vibratowidth     = data[8];
            byte  vibratotime      = data[9];
            byte  portamentowidth  = data[10];
            byte  portamentotime   = data[11];
            byte  pitchbendminimum = data[12];
            byte  pitchbendmaximum = data[13];
            byte  reserved1        = data[14];
            byte  reserved2        = data[15];
            short adsr1            = BitConv.FromInt16(data, 16);
            short adsr2            = BitConv.FromInt16(data, 18);
            // Unused 2 bytes here
            short wave      = BitConv.FromInt16(data, 22);
            short reserved3 = BitConv.FromInt16(data, 24);
            short reserved4 = BitConv.FromInt16(data, 26);
            short reserved5 = BitConv.FromInt16(data, 28);
            short reserved6 = BitConv.FromInt16(data, 30);

            if (reserved1 != 0xB1)
            {
                ErrorManager.SignalIgnorableError("VHTone: Reserved value 1 is wrong");
            }
            if (reserved2 != 0xB2)
            {
                ErrorManager.SignalIgnorableError("VHTone: Reserved value 2 is wrong");
            }
            if (reserved3 != 0xC0)
            {
                ErrorManager.SignalIgnorableError("VHTone: Reserved value 3 is wrong");
            }
            if (reserved4 != 0xC1)
            {
                ErrorManager.SignalIgnorableError("VHTone: Reserved value 4 is wrong");
            }
            if (reserved5 != 0xC2)
            {
                ErrorManager.SignalIgnorableError("VHTone: Reserved value 5 is wrong");
            }
            if (reserved6 != 0xC3)
            {
                ErrorManager.SignalIgnorableError("VHTone: Reserved value 6 is wrong");
            }
            return(new VHTone(priority, mode, volume, panning, centernote, pitchshift, minimumnote, maximumnote, vibratowidth, vibratotime, portamentowidth, portamentotime, pitchbendminimum, pitchbendmaximum, adsr1, adsr2, wave));
        }
Esempio n. 5
0
        public sealed override Chunk Load(int chunkid, byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.Length != Chunk.Length)
            {
                throw new ArgumentException("Data must be 65536 bytes long.");
            }
            int id         = BitConv.FromInt32(data, 4);
            int entrycount = BitConv.FromInt32(data, 8);
            int checksum   = BitConv.FromInt32(data, 12);
            int headersize = 20 + entrycount * 4;

            if (id != chunkid)
            {
                ErrorManager.SignalIgnorableError("EntryChunk: Chunk id is incorrect");
            }
            if (entrycount < 0)
            {
                ErrorManager.SignalError("EntryChunk: Entry count is negative");
            }
            if (checksum != Chunk.CalculateChecksum(data))
            {
                ErrorManager.SignalIgnorableError("Chunk: Checksum is wrong");
            }
            if (headersize > data.Length)
            {
                ErrorManager.SignalError("EntryChunk: Data is too short");
            }
            Entry[] entries = new Entry [entrycount];
            byte[]  entrydata;
            for (int i = 0; i < entrycount; i++)
            {
                int entrystart = BitConv.FromInt32(data, 16 + i * 4);
                int entryend   = BitConv.FromInt32(data, 20 + i * 4);
                if (entrystart < 0)
                {
                    ErrorManager.SignalError("EntryChunk: Entry begins out of bounds");
                }
                if (entryend < entrystart)
                {
                    ErrorManager.SignalError("EntryChunk: Entry ends before it begins");
                }
                if (entryend > data.Length)
                {
                    ErrorManager.SignalError("EntryChunk: Entry ends out of bounds");
                }
                int entrysize = entryend - entrystart;
                entrydata = new byte [entrysize];
                Array.Copy(data, entrystart, entrydata, 0, entrysize);
                entries[i] = Entry.Load(entrydata);
            }
            return(Load(entries));
        }
Esempio n. 6
0
        public static UnprocessedEntry Load(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.Length < 16)
            {
                ErrorManager.SignalError("Entry: Data is too short");
            }
            int magic     = BitConv.FromInt32(data, 0);
            int eid       = BitConv.FromInt32(data, 4);
            int type      = BitConv.FromInt32(data, 8);
            int itemcount = BitConv.FromInt32(data, 12);

            if (magic != Magic)
            {
                ErrorManager.SignalIgnorableError("Entry: Magic number is wrong");
            }
            if (itemcount < 0)
            {
                ErrorManager.SignalError("Entry: Item count is negative");
            }
            if (data.Length < 20 + itemcount * 4)
            {
                ErrorManager.SignalError("Entry: Data is too short");
            }
            byte[][] items = new byte [itemcount][];
            byte[]   itemdata;
            for (int i = 0; i < itemcount; i++)
            {
                int itemstart = BitConv.FromInt32(data, 16 + i * 4);
                int itemend   = BitConv.FromInt32(data, 20 + i * 4);
                if (itemstart < 0)
                {
                    ErrorManager.SignalError("Entry: Item begins out of bounds");
                }
                if (itemend < itemstart)
                {
                    ErrorManager.SignalError("Entry: Item ends before it begins");
                }
                if (itemend > data.Length)
                {
                    ErrorManager.SignalError("Entry: Item ends out of bounds");
                }
                int itemsize = itemend - itemstart;
                itemdata = new byte [itemsize];
                Array.Copy(data, itemstart, itemdata, 0, itemsize);
                items[i] = itemdata;
            }
            return(new UnprocessedEntry(items, eid, type));
        }
Esempio n. 7
0
 public override Entry Load(byte[][] items, int eid)
 {
     if (items == null)
     {
         throw new ArgumentNullException("items");
     }
     T4Item[] t4items = new T4Item [items.Length];
     for (int i = 0; i < items.Length; i++)
     {
         t4items[i] = T4Item.Load(items[i]);
         if (t4items[i].Unknown1 != ((i == 0 || i == items.Length - 1) ? 0 : 1))
         {
             ErrorManager.SignalIgnorableError("T4Entry: Item unknown field is wrong");
         }
     }
     return(new T4Entry(t4items, eid));
 }
Esempio n. 8
0
        public static VHProgram Load(byte[] data, byte[] tonedata, bool isoldversion)
        {
            if (data.Length != 16)
            {
                throw new ArgumentException("Value must be 16 bytes long.", "data");
            }
            if (tonedata.Length != 32 * 16)
            {
                throw new ArgumentException("Value must be 512 bytes long.", "tonedata");
            }
            byte  tonecount = data[0];
            byte  volume    = data[1];
            byte  priority  = data[2];
            byte  mode      = data[3];
            byte  panning   = data[4];
            byte  reserved1 = data[5];
            short attribute = BitConv.FromInt16(data, 6);
            int   reserved2 = BitConv.FromInt32(data, 8);
            int   reserved3 = BitConv.FromInt32(data, 12);

            if (tonecount < 0 || tonecount > 16)
            {
                ErrorManager.SignalError("VHProgram: Tone count is wrong");
            }
            if (reserved1 != (isoldversion ? 0x00 : 0xFF))
            {
                ErrorManager.SignalIgnorableError("VHProgram: Reserved value 1 is wrong");
            }
            if (reserved2 != -1)
            {
                ErrorManager.SignalIgnorableError("VHProgram: Reserved value 2 is wrong");
            }
            if (reserved3 != -1)
            {
                ErrorManager.SignalIgnorableError("VHProgram: Reserved value 3 is wrong");
            }
            VHTone[] tones = new VHTone [tonecount];
            for (int i = 0; i < tonecount; i++)
            {
                byte[] thistonedata = new byte [32];
                Array.Copy(tonedata, i * 32, thistonedata, 0, 32);
                tones[i] = VHTone.Load(thistonedata);
            }
            return(new VHProgram(isoldversion, volume, priority, mode, panning, attribute, tones));
        }
Esempio n. 9
0
        public static UnprocessedChunk Load(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (data.Length != Length)
            {
                throw new ArgumentException("Value must be 65536 bytes long.", "data");
            }
            short magic = BitConv.FromInt16(data, 0);

            if (magic != Magic)
            {
                ErrorManager.SignalIgnorableError("Chunk: Magic number is wrong");
            }
            return(new UnprocessedChunk(data));
        }
Esempio n. 10
0
        public static EntityProperty Load(byte type, byte elementsize, short unknown, bool last, byte[] data)
        {
            if (((type & 128) != 0) != last)
            {
                ErrorManager.SignalIgnorableError("EntityProperty: Flag 128 has an unexpected value");
            }
            bool issparse      = (type & 64) != 0;
            bool hasmetavalues = (type & 32) != 0;

            type &= 31;
            if (loaders.ContainsKey(type))
            {
                return(loaders[type].Load(elementsize, unknown, issparse, hasmetavalues, data));
            }
            else
            {
                return(new EntityUnknownProperty(type, elementsize, unknown, issparse, hasmetavalues, data));
            }
        }
Esempio n. 11
0
 internal override void LoadToField(object obj, FieldInfo field)
 {
     if (field.FieldType == typeof(string))
     {
         if (Rows.Count == 1)
         {
             if (Rows[0].MetaValue == null)
             {
                 byte[] bytestr = new byte [Rows[0].Values.Count];
                 for (int i = 0; i < bytestr.Length; i++)
                 {
                     bytestr[i] = Rows[0].Values[i];
                 }
                 string str = System.Text.Encoding.UTF8.GetString(bytestr);
                 if (str.EndsWith("\0"))
                 {
                     str = str.Remove(str.Length - 1);
                 }
                 else
                 {
                     ErrorManager.SignalIgnorableError("EntityProperty: String is not null-terminated");
                 }
                 field.SetValue(obj, str);
             }
             else
             {
                 ErrorManager.SignalError("EntityProperty: Property has an unexpected metavalue");
             }
         }
         else
         {
             ErrorManager.SignalError("EntityProperty: Property has more rows than expected");
         }
     }
     else
     {
         base.LoadToField(obj, field);
     }
 }
Esempio n. 12
0
        public static SEP Load(byte[] data, int seqcount)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (seqcount < 0)
            {
                throw new ArgumentOutOfRangeException("seqcount");
            }
            // All SEP/SEQ stuff is big-endian, like MIDI
            if (data.Length < 6)
            {
                ErrorManager.SignalError("SEP: Data is too short");
            }
            int   magic   = BEBitConv.FromInt32(data, 0);
            short version = BEBitConv.FromInt16(data, 4);

            if (magic != Magic)
            {
                ErrorManager.SignalIgnorableError("SEP: Magic number is wrong");
            }
            if (version != Version)
            {
                ErrorManager.SignalIgnorableError("SEP: Version number is wrong");
            }
            int offset = 6;

            SEQ[] seqs = new SEQ [seqcount];
            for (int i = 0; i < seqcount; i++)
            {
                if (data.Length < offset + 13)
                {
                    ErrorManager.SignalError("SEP: Data is too short");
                }
                short seqid      = BEBitConv.FromInt16(data, offset);
                short resolution = BEBitConv.FromInt16(data, offset + 2);
                // tempo is 3 (yes, three) bytes
                int   tempo  = MIDIConv.From3BE(data, offset + 4);
                short rhythm = BEBitConv.FromInt16(data, offset + 7);
                int   length = BEBitConv.FromInt32(data, offset + 9);
                if (seqid != i)
                {
                    ErrorManager.SignalIgnorableError("SEP: Track number is wrong");
                }
                if (length < 0)
                {
                    ErrorManager.SignalError("SEP: Track length is negative");
                }
                offset += 13;
                if (data.Length < offset + length)
                {
                    ErrorManager.SignalError("SEP: Data is too short");
                }
                byte[] seqdata = new byte [length];
                Array.Copy(data, offset, seqdata, 0, length);
                seqs[i] = new SEQ(resolution, tempo, rhythm, seqdata);
                offset += length;
            }
            return(new SEP(seqs));
        }
Esempio n. 13
0
        public sealed override EntityProperty Load(byte elementsize, short unknown, bool issparse, bool hasmetavalues, byte[] data)
        {
            if (elementsize != ElementSize)
            {
                ErrorManager.SignalError("EntityProperty: Element size is wrong");
            }
            if (unknown < 0)
            {
                ErrorManager.SignalError("EntityProperty: Unknown value is invalid");
            }
            List <EntityPropertyRow <T> > rows = new List <EntityPropertyRow <T> >();

            for (int i = 0; i < unknown; i++)
            {
                rows.Add(new EntityPropertyRow <T>());
            }
            int offset = 0;

            if (issparse)
            {
                if (offset + 2 * unknown > data.Length)
                {
                    ErrorManager.SignalError("EntityProperty: Not enough data");
                }
                foreach (EntityPropertyRow <T> row in rows)
                {
                    int valuecount = (ushort)BitConv.FromInt16(data, offset);
                    offset += 2;
                    for (int i = 0; i < valuecount; i++)
                    {
                        row.Values.Add(new T());
                    }
                }
            }
            else
            {
                if (offset + 2 > data.Length)
                {
                    ErrorManager.SignalError("EntityProperty: Not enough data");
                }
                int valuecount = (ushort)BitConv.FromInt16(data, offset);
                offset += 2;
                foreach (EntityPropertyRow <T> row in rows)
                {
                    for (int i = 0; i < valuecount; i++)
                    {
                        row.Values.Add(new T());
                    }
                }
            }
            if (hasmetavalues)
            {
                if (offset + 2 * unknown > data.Length)
                {
                    ErrorManager.SignalError("EntityProperty: Not enough data");
                }
                foreach (EntityPropertyRow <T> row in rows)
                {
                    short metavalue = BitConv.FromInt16(data, offset);
                    offset       += 2;
                    row.MetaValue = metavalue;
                }
            }
            Aligner.Align(ref offset, 4);
            byte[] elementdata = new byte [elementsize];
            foreach (EntityPropertyRow <T> row in rows)
            {
                if (offset + row.Values.Count * elementsize > data.Length)
                {
                    ErrorManager.SignalError("EntityProperty: Not enough data");
                }
                for (int i = 0; i < row.Values.Count; i++)
                {
                    Array.Copy(data, offset, elementdata, 0, elementsize);
                    offset       += elementsize;
                    row.Values[i] = LoadElement(elementdata);
                }
            }
            Aligner.Align(ref offset, 4);
            if (offset != data.Length)
            {
                ErrorManager.SignalIgnorableError("EntityProperty: More data than expected");
            }
            return(Load(rows));
        }
Esempio n. 14
0
        public static VH Load(byte[] data)
        {
            if (data.Length < 2592)
            {
                ErrorManager.SignalError("VH: Data is too short");
            }
            int magic   = BitConv.FromInt32(data, 0);
            int version = BitConv.FromInt32(data, 4);

            if (magic != Magic)
            {
                ErrorManager.SignalIgnorableError("VH: Magic number is wrong");
            }
            bool isoldversion;

            if (version == Version)
            {
                isoldversion = false;
            }
            else if (version == OldVersion)
            {
                ErrorManager.SignalIgnorableError("VH: VABv6 (crash 1) is not fully supported");
                isoldversion = true;
            }
            else
            {
                ErrorManager.SignalIgnorableError("VH: Version number is wrong");
                isoldversion = true;
            }
            int   id           = BitConv.FromInt32(data, 8);
            int   size         = BitConv.FromInt32(data, 12);
            short reserved1    = BitConv.FromInt16(data, 16);
            short programcount = BitConv.FromInt16(data, 18);
            short tonecount    = BitConv.FromInt16(data, 20);
            short wavecount    = BitConv.FromInt16(data, 22);
            byte  volume       = data[24];
            byte  panning      = data[25];
            byte  attribute1   = data[26];
            byte  attribute2   = data[27];
            int   reserved2    = BitConv.FromInt32(data, 28);

            if (id != 0)
            {
                ErrorManager.SignalIgnorableError("VH: ID is wrong");
            }
            if (size < data.Length)
            {
                ErrorManager.SignalError("VH: Size field mismatch");
            }
            if ((size - data.Length) % 16 != 0)
            {
                ErrorManager.SignalError("VH: Size field is invalid");
            }
            int vbsize = (size - data.Length) / 16;

            if (reserved1 != -0x1112)
            {
                ErrorManager.SignalIgnorableError("VH: Reserved value 1 is wrong");
            }
            if (programcount < 0 || programcount > 128)
            {
                ErrorManager.SignalError("VH: Program count is invalid");
            }
            if (tonecount < 0 || tonecount > 2048)
            {
                ErrorManager.SignalError("VH: Tone count is invalid");
            }
            if (wavecount < 0 || wavecount > 254)
            {
                ErrorManager.SignalError("VH: Wave count is invalid");
            }
            if (reserved2 != -1)
            {
                ErrorManager.SignalIgnorableError("VH: Reserved value 2 is wrong");
            }
            if (data.Length < 2592 + 32 * 16 * programcount)
            {
                ErrorManager.SignalError("VH: Data is too short");
            }
            Dictionary <int, VHProgram> programs = new Dictionary <int, VHProgram>();

            for (int i = 0; i < 128; i++)
            {
                byte[] programdata = new byte [16];
                Array.Copy(data, 32 + 16 * i, programdata, 0, 16);
                if (programdata[0] == 0)
                {
                    continue;
                }
                if (programs.Count == programcount)
                {
                    ErrorManager.SignalError("VH: Program count field mismatch");
                }
                byte[] tonedata = new byte [32 * 16];
                Array.Copy(data, 32 + 16 * 128 + 32 * 16 * programs.Count, tonedata, 0, 32 * 16);
                programs.Add(i, VHProgram.Load(programdata, tonedata, isoldversion));
            }
            if (programs.Count != programcount)
            {
                ErrorManager.SignalError("VH: Program count field mismatch");
            }
            int[] waves = new int [wavecount];
            for (int i = 0; i < wavecount; i++)
            {
                int wave = BitConv.FromInt16(data, 32 + 16 * 128 + 32 * 16 * programcount + 2 + i * 2);
                if (wave % 2 != 0)
                {
                    ErrorManager.SignalError("VH: Wave size is invalid");
                }
                waves[i] = wave / 2;
            }
            return(new VH(isoldversion, vbsize, volume, panning, attribute1, attribute2, programs, waves));
        }
Esempio n. 15
0
        private static byte[] ReadChunk(byte[] data, ref int offset, out bool compressed)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            if (offset < 0 || offset > data.Length)
            {
                throw new ArgumentOutOfRangeException("offset");
            }
            if (data.Length < offset + 2)
            {
                ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
            }
            byte[] result = new byte [Chunk.Length];
            short  magic  = BitConv.FromInt16(data, offset);

            if (magic == Chunk.Magic)
            {
                compressed = false;
                if (data.Length < offset + Chunk.Length)
                {
                    ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                }
                Array.Copy(data, offset, result, 0, Chunk.Length);
                offset += Chunk.Length;
            }
            else if (magic == Chunk.CompressedMagic)
            {
                compressed = true;
                int pos = 0;
                if (data.Length < offset + 12)
                {
                    ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                }
                short zero   = BitConv.FromInt16(data, offset + 2);
                int   length = BitConv.FromInt32(data, offset + 4);
                int   skip   = BitConv.FromInt32(data, offset + 8);
                if (zero != 0)
                {
                    ErrorManager.SignalIgnorableError("NSF.ReadChunk: Zero value is wrong");
                }
                if (length < 0 || length > Chunk.Length)
                {
                    ErrorManager.SignalError("NSF.ReadChunk: Length field is invalid");
                }
                if (skip < 0)
                {
                    ErrorManager.SignalError("NSF.ReadChunk: Skip value is negative");
                }
                offset += 12;
                while (pos < length)
                {
                    if (data.Length < offset + 1)
                    {
                        ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                    }
                    byte prefix = data[offset];
                    offset++;
                    if ((prefix & 0x80) != 0)
                    {
                        prefix &= 0x7F;
                        if (data.Length < offset + 1)
                        {
                            ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                        }
                        int seek = data[offset];
                        offset++;
                        int span = seek & 7;
                        seek >>= 3;
                        seek  |= prefix << 5;
                        if (span == 7)
                        {
                            span = 64;
                        }
                        else
                        {
                            span += 3;
                        }
                        if (pos - seek < 0)
                        {
                            ErrorManager.SignalError("NSF.ReadChunk: Repeat begins out of bounds");
                        }
                        if (pos + span > Chunk.Length)
                        {
                            ErrorManager.SignalError("NSF.ReadChunk: Repeat ends out of bounds");
                        }
                        // Do NOT use Array.Copy as
                        // overlap is possible i.e. span
                        // may be greater than seek
                        for (int i = 0; i < span; i++)
                        {
                            result[pos + i] = result[pos - seek + i];
                        }
                        pos += span;
                    }
                    else
                    {
                        if (data.Length < offset + prefix)
                        {
                            ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                        }
                        Array.Copy(data, offset, result, pos, prefix);
                        offset += prefix;
                        pos    += prefix;
                    }
                }
                if (data.Length < offset + skip)
                {
                    ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                }
                offset += skip;
                if (data.Length < offset + (Chunk.Length - length))
                {
                    ErrorManager.SignalError("NSF.ReadChunk: Data is too short");
                }
                Array.Copy(data, offset, result, pos, Chunk.Length - length);
                offset += (Chunk.Length - length);
            }
            else
            {
                compressed = false; // Fixes a stupid compile error
                ErrorManager.SignalError("NSF.ReadChunk: Unknown magic number");
            }
            return(result);
        }
Esempio n. 16
0
        public static NSF Load(byte[] data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
            int offset  = 0;
            int?firstid = null;
            List <UnprocessedChunk> prelude            = null;
            List <Chunk>            chunks             = new List <Chunk>();
            List <bool>             preludecompression = null;
            List <bool>             chunkcompression   = new List <bool>();

            while (offset < data.Length)
            {
                bool             compressed;
                byte[]           chunkdata = ReadChunk(data, ref offset, out compressed);
                UnprocessedChunk chunk     = Chunk.Load(chunkdata);
                if (firstid == null)
                {
                    firstid = chunk.ID;
                }
                else if (firstid == chunk.ID)
                {
                    if (prelude != null)
                    {
                        ErrorManager.SignalError("NSF: Double prelude");
                    }
                    prelude = new List <UnprocessedChunk>();
                    foreach (UnprocessedChunk unprocessedchunk in chunks)
                    {
                        prelude.Add(unprocessedchunk);
                    }
                    chunks.Clear();
                    preludecompression = chunkcompression;
                    chunkcompression   = new List <bool>();
                }
                chunkcompression.Add(compressed);
                if (prelude != null && chunks.Count < prelude.Count)
                {
                    for (int i = 0; i < Chunk.Length; i++)
                    {
                        if (prelude[chunks.Count].Data[i] != chunk.Data[i])
                        {
                            ErrorManager.SignalIgnorableError("NSF: Prelude data mismatch");
                            break;
                        }
                    }
                }
                chunks.Add(chunk);
            }
            if (prelude != null && chunks.Count < prelude.Count)
            {
                ErrorManager.SignalIgnorableError("NSF: Prelude is longer than actual data");
            }
            if (prelude != null)
            {
                ErrorManager.SignalIgnorableError("NSF: Prelude saving is not yet implemented");
            }
            foreach (bool compressed in chunkcompression)
            {
                if (compressed)
                {
                    ErrorManager.SignalIgnorableError("NSF: Non-prelude chunk was compressed");
                }
            }
            return(new NSF(chunks));
        }
Esempio n. 17
0
        public static Entity Load(byte[] data)
        {
            if (data.Length < 16)
            {
                ErrorManager.SignalError("Entity: Data is too short");
            }
            int length        = BitConv.FromInt32(data, 0);
            int blank1        = BitConv.FromInt32(data, 4);
            int blank2        = BitConv.FromInt32(data, 8);
            int propertycount = BitConv.FromInt32(data, 12);

            if (length != data.Length)
            {
                ErrorManager.SignalIgnorableError("Entity: Length field mismatch");
            }
            if (blank1 != 0 || blank2 != 0)
            {
                ErrorManager.SignalIgnorableError("Entity: Blank value is wrong");
            }
            if (propertycount < 0 || propertycount > ushort.MaxValue)
            {
                ErrorManager.SignalError("Entity: Property count is invalid");
            }
            if (data.Length < 16 + propertycount * 8)
            {
                ErrorManager.SignalError("Entity: Data is too short");
            }
            Dictionary <short, EntityProperty> properties = new Dictionary <short, EntityProperty>();

            for (int i = 0; i < propertycount; i++)
            {
                short id          = BitConv.FromInt16(data, 16 + i * 8);
                int   offset      = (ushort)BitConv.FromInt16(data, 18 + i * 8) + 12;
                int   nextoffset  = (i == propertycount - 1) ? data.Length : ((ushort)BitConv.FromInt16(data, 26 + i * 8) + 12);
                byte  type        = data[20 + i * 8];
                byte  elementsize = data[21 + i * 8];
                short unknown     = BitConv.FromInt16(data, 22 + i * 8);
                if (offset > data.Length)
                {
                    ErrorManager.SignalError("Entity: Property begins out of bounds");
                }
                if (nextoffset < offset)
                {
                    ErrorManager.SignalError("Entity: Property ends before it begins");
                }
                if (nextoffset > data.Length)
                {
                    ErrorManager.SignalError("Entity: Property ends out of bounds");
                }
                if (properties.ContainsKey(id))
                {
                    ErrorManager.SignalIgnorableError("Entity: Duplicate property");
                }
                else
                {
                    byte[] propertydata = new byte [nextoffset - offset];
                    Array.Copy(data, offset, propertydata, 0, propertydata.Length);
                    EntityProperty property = EntityProperty.Load(type, elementsize, unknown, i == propertycount - 1, propertydata);
                    properties.Add(id, property);
                }
            }
            return(new Entity(properties));
        }