public static SceneryTriangle Load(byte[] adata, byte[] bdata) { if (adata == null) { throw new ArgumentNullException("adata"); } if (bdata == null) { throw new ArgumentNullException("bdata"); } if (adata.Length != 4) { throw new ArgumentException("Value must be 4 bytes long.", "adata"); } if (bdata.Length != 2) { throw new ArgumentException("Value must be 2 bytes long.", "adata"); } int avalue = BitConv.FromInt32(adata, 0); short bvalue = BitConv.FromInt16(bdata, 0); int vertexa = (avalue >> 8) & 0xFFF; int vertexb = (avalue >> 20) & 0xFFF; int vertexc = (bvalue >> 4) & 0xFFF; byte unknown1 = (byte)avalue; byte unknown2 = (byte)(bvalue & 0xF); return(new SceneryTriangle(vertexa, vertexb, vertexc, unknown1, unknown2)); }
public static SceneryVertex Load(byte[] xydata, byte[] zdata) { if (xydata == null) { throw new ArgumentNullException("xydata"); } if (zdata == null) { throw new ArgumentNullException("zdata"); } if (xydata.Length != 4) { throw new ArgumentException("Value must be 4 bytes long.", "xydata"); } if (zdata.Length != 2) { throw new ArgumentException("Value must be 2 bytes long.", "zdata"); } int xy = BitConv.FromInt32(xydata, 0); short z = BitConv.FromInt16(zdata, 0); short y = (short)(xy >> 16); short x = (short)xy; int unknownx = x & 0xF; int unknowny = y & 0xF; int unknownz = z & 0xF; x >>= 4; y >>= 4; z >>= 4; return(new SceneryVertex(x, y, z, unknownx, unknowny, unknownz)); }
public static T4Item Load(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < 4) { ErrorManager.SignalError("T4Item: Data is too short"); } short count = BitConv.FromInt16(data, 0); short unknown1 = BitConv.FromInt16(data, 2); if (count < 0) { ErrorManager.SignalError("T4Item: Value count is negative"); } if (data.Length < 4 + 2 * count) { ErrorManager.SignalError("T4Item: Data is too short"); } short[] values = new short [count]; for (int i = 0; i < count; i++) { values[i] = BitConv.FromInt16(data, 4 + i * 2); } return(new T4Item(unknown1, values)); }
protected override EntityPosition LoadElement(byte[] data) { short x = BitConv.FromInt16(data, 0); short y = BitConv.FromInt16(data, 2); short z = BitConv.FromInt16(data, 4); return(new EntityPosition(x, y, z)); }
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)); }
public static short FromInt16(Endianness endianness, byte[] str, int offset) { switch (endianness) { case Endianness.LittleEndian: return(BitConv.FromInt16(str, offset)); case Endianness.BigEndian: return(BEBitConv.FromInt16(str, offset)); default: throw new ArgumentException("Endianness is invalid."); } }
public static OldModelPolygon Load(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length != 8) { throw new ArgumentException("Value must be 8 bytes long.", "data"); } short vertexa = BitConv.FromInt16(data, 0); short vertexb = BitConv.FromInt16(data, 2); short vertexc = BitConv.FromInt16(data, 4); short unknown = BitConv.FromInt16(data, 6); return(new OldModelPolygon(vertexa, vertexb, vertexc, unknown)); }
public static OldFrame Load(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length < 56) { ErrorManager.SignalError("OldFrame: Data is too short"); } int vertexcount = BitConv.FromInt32(data, 0); if (vertexcount < 0 || vertexcount > Chunk.Length / 6) { ErrorManager.SignalError("OldFrame: Vertex count is invalid"); } if (data.Length < 56 + vertexcount * 6 + 2) { ErrorManager.SignalError("OldFrame: Data is too short"); } int modeleid = BitConv.FromInt32(data, 4); int xoffset = BitConv.FromInt32(data, 8); int yoffset = BitConv.FromInt32(data, 12); int zoffset = BitConv.FromInt32(data, 16); int x1 = BitConv.FromInt32(data, 20); int y1 = BitConv.FromInt32(data, 24); int z1 = BitConv.FromInt32(data, 28); int x2 = BitConv.FromInt32(data, 32); int y2 = BitConv.FromInt32(data, 36); int z2 = BitConv.FromInt32(data, 40); int xglobal = BitConv.FromInt32(data, 44); int yglobal = BitConv.FromInt32(data, 48); int zglobal = BitConv.FromInt32(data, 52); OldFrameVertex[] vertices = new OldFrameVertex [vertexcount]; for (int i = 0; i < vertexcount; i++) { byte[] vertexdata = new byte [6]; Array.Copy(data, 56 + i * 6, vertexdata, 0, vertexdata.Length); vertices[i] = OldFrameVertex.Load(vertexdata); } short unknown = BitConv.FromInt16(data, 56 + vertexcount * 6); return(new OldFrame(modeleid, xoffset, yoffset, zoffset, x1, y1, z1, x2, y2, z2, xglobal, yglobal, zglobal, vertices, unknown)); }
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)); }
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)); }
public static OldSceneryVertex Load(byte[] data) { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length != 8) { throw new ArgumentException("Value must be 8 bytes long.", "data"); } short x = (short)(BitConv.FromInt16(data, 4) & 0xFFF8); short y = (short)(BitConv.FromInt16(data, 6) & 0xFFF8); int zhigh = data[6] & 7; int zmid = (data[4] & 6) >> 1; int zlow = data[3]; short z = (short)(zhigh << 13 | zmid << 11 | zlow << 3); byte red = data[0]; byte green = data[1]; byte blue = data[2]; bool lightingflag = ((data[4] & 1) != 0); return(new OldSceneryVertex(x, y, z, red, green, blue, lightingflag)); }
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)); }
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); }
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)); }
protected override short LoadElement(byte[] data) { return(BitConv.FromInt16(data, 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)); }