public DLCObjectData(DLCObjectData origdata) { Act = origdata.Act; Flags = origdata.Flags; Level = origdata.Level; Message = origdata.Message; InternalID = origdata.InternalID; ObjectType = origdata.ObjectType; TriggerDistance = origdata.TriggerDistance; RotSpeedX = origdata.RotSpeedX; RotSpeedY = origdata.RotSpeedY; RotSpeedZ = origdata.RotSpeedZ; RotationX = origdata.RotationX; RotationY = origdata.RotationY; RotationZ = origdata.RotationZ; ScaleX = origdata.ScaleX; ScaleY = origdata.ScaleY; ScaleZ = origdata.ScaleZ; WarpActOrSoundID = origdata.WarpActOrSoundID; Texture = origdata.Texture; Unknown3 = origdata.Unknown3; WarpLevelOrSoundbank = origdata.WarpLevelOrSoundbank; X = origdata.X; Y = origdata.Y; Z = origdata.Z; }
private void comboBoxType_SelectedIndexChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; DLCObjectTypes result; switch (comboBoxType.SelectedIndex) { case 1: result = DLCObjectTypes.TYPE_SPRITE; break; case 2: result = DLCObjectTypes.TYPE_INVISIBLE; break; case 0: default: result = DLCObjectTypes.TYPE_MODEL; break; } data.ObjectType = result; editorMeta.Items[index] = data; RefreshObjectList(); listBoxObjects.SelectedIndex = index; }
private void ToggleFlag(object sender, DLCObjectFlags flag) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; CheckBox check = (CheckBox)sender; if (check.Checked) { data.Flags |= flag; } else { data.Flags &= ~flag; } groupBoxWarp.Enabled = data.Flags.HasFlag(DLCObjectFlags.FLAG_WARP); groupBoxPlaySound.Enabled = data.Flags.HasFlag(DLCObjectFlags.FLAG_SOUND); comboBoxMessage.Enabled = labelMessage.Enabled = data.Flags.HasFlag(DLCObjectFlags.FLAG_MESSAGE); editorMeta.Items[index] = data; RefreshObjectList(); listBoxObjects.SelectedIndex = index; }
private void numericUpDownSoundBank_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.WarpLevelOrSoundbank = (byte)numericUpDownSoundBank.Value; editorMeta.Items[index] = data; }
private void comboBoxWarpLevel_SelectedIndexChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.WarpLevelOrSoundbank = (byte)comboBoxWarpLevel.SelectedIndex; editorMeta.Items[index] = data; }
private void comboBoxMessage_SelectedIndexChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.Message = (byte)comboBoxMessage.SelectedIndex; editorMeta.Items[index] = data; }
private void numericUpDownRotSpeedZ_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.RotSpeedZ = (sbyte)numericUpDownRotSpeedZ.Value; editorMeta.Items[index] = data; }
private void numericUpDownCollectibleID_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.InternalID = (byte)numericUpDownCollectibleID.Value; editorMeta.Items[index] = data; }
private void numericUpDownTriggerDistance_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.TriggerDistance = (byte)numericUpDownTriggerDistance.Value; editorMeta.Items[index] = data; }
private void numericUpDownRotY_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.RotationY = (ushort)numericUpDownRotY.Value; editorMeta.Items[index] = data; }
private void buttonAddNew_Click(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index == -1) { index = 0; } DLCObjectData newdata = new DLCObjectData(); editorMeta.Items.Insert(index, newdata); RefreshObjectList(); listBoxObjects.SelectedIndex = index; }
private void comboBoxLevel_SelectedIndexChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.Level = (byte)comboBoxLevel.SelectedIndex; editorMeta.Items[index] = data; RefreshObjectList(); listBoxObjects.SelectedIndex = index; }
private void numericUpDownAct_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData data = editorMeta.Items[index]; data.Act = (byte)numericUpDownAct.Value; editorMeta.Items[index] = data; RefreshObjectList(); listBoxObjects.SelectedIndex = index; }
private void buttonDuplicate_Click(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } DLCObjectData origdata = editorMeta.Items[listBoxObjects.SelectedIndex]; DLCObjectData newdata = new DLCObjectData(origdata); editorMeta.Items.Insert(index + 1, newdata); RefreshObjectList(); listBoxObjects.SelectedIndex = index + 1; }
private void numericUpDownTextureID_ValueChanged(object sender, EventArgs e) { int index = listBoxObjects.SelectedIndex; if (index < 0) { return; } if (numericUpDownTextureID.Value < puyo.Entries.Count) { DLCObjectData data = editorMeta.Items[index]; data.Texture = (byte)numericUpDownTextureID.Value; pictureBoxTexture.Image = puyo.Entries[data.Texture].GetBitmap(); editorMeta.Items[index] = data; } }
private void listBoxObjects_SelectedIndexChanged(object sender, EventArgs e) { if (listBoxObjects.SelectedIndex == -1) { return; } DLCObjectData item = editorMeta.Items[listBoxObjects.SelectedIndex]; numericUpDownTriggerDistance.Value = item.TriggerDistance; numericUpDownSoundBank.Value = comboBoxWarpLevel.SelectedIndex = item.WarpLevelOrSoundbank; numericUpDownSoundID.Value = numericUpDownWarpAct.Value = item.WarpActOrSoundID; // Warp if (item.Flags.HasFlag(DLCObjectFlags.FLAG_WARP)) { groupBoxPlaySound.Enabled = false; groupBoxWarp.Enabled = true; } // Sound else if (item.Flags.HasFlag(DLCObjectFlags.FLAG_SOUND)) { groupBoxWarp.Enabled = false; groupBoxPlaySound.Enabled = true; } // Neither of the above else { groupBoxWarp.Enabled = false; groupBoxPlaySound.Enabled = false; } // Message comboBoxMessage.SelectedIndex = item.Message; comboBoxMessage.Enabled = labelMessage.Enabled = item.Flags.HasFlag(DLCObjectFlags.FLAG_MESSAGE); // Texture numericUpDownTextureID.Maximum = puyo.Entries.Count - 1; numericUpDownTextureID.Value = item.Texture; // Unknown numericUpDownUnknown.Value = item.Unknown3; // Location comboBoxLevel.SelectedIndex = item.Level; numericUpDownAct.Value = item.Act; numericUpDownCollectibleID.Value = item.InternalID; numericUpDownPosX.Value = item.X; numericUpDownPosY.Value = item.Y; numericUpDownPosZ.Value = item.Z; numericUpDownRotX.Value = item.RotationX; numericUpDownRotY.Value = item.RotationY; numericUpDownRotZ.Value = item.RotationZ; numericUpDownRotSpeedX.Value = item.RotSpeedX; numericUpDownRotSpeedY.Value = item.RotSpeedY; numericUpDownRotSpeedZ.Value = item.RotSpeedZ; numericUpDownScaleX.Value = item.ScaleX; numericUpDownScaleY.Value = item.ScaleY; numericUpDownScaleZ.Value = item.ScaleZ; // Add flags checkBoxFlagMessage.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_MESSAGE); checkBoxFlagCollectible.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_COLLECTIBLE); checkBoxFlagCollisionOnly.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_COLLISION_ONLY); checkBoxFlagSolid.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_SOLID); checkBoxFlagSound.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_SOUND); checkBoxFlagStart.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_CHALLENGE); checkBoxFlagTimer.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_TIMER); checkBoxFlagWarp.Checked = item.Flags.HasFlag(DLCObjectFlags.FLAG_WARP); checkBoxFlagUnknown0.Checked = item.Flags.HasFlag(DLCObjectFlags.UNKNOWN_0); checkBoxFlagUnknown1.Checked = item.Flags.HasFlag(DLCObjectFlags.UNUSED_1); checkBoxFlagUnknown2.Checked = item.Flags.HasFlag(DLCObjectFlags.UNUSED_2); checkBoxFlagUnknown3.Checked = item.Flags.HasFlag(DLCObjectFlags.UNUSED_3); checkBoxFlagUnknown4.Checked = item.Flags.HasFlag(DLCObjectFlags.UNKNOWN_4); checkBoxFlagUnknown5.Checked = item.Flags.HasFlag(DLCObjectFlags.UNUSED_5); checkBoxFlagUnknown6.Checked = item.Flags.HasFlag(DLCObjectFlags.UNUSED_6); checkBoxFlagUnknown7.Checked = item.Flags.HasFlag(DLCObjectFlags.UNUSED_7); switch (item.ObjectType) { case DLCObjectTypes.TYPE_MODEL: comboBoxType.SelectedIndex = 0; break; case DLCObjectTypes.TYPE_SPRITE: comboBoxType.SelectedIndex = 1; break; case DLCObjectTypes.TYPE_INVISIBLE: comboBoxType.SelectedIndex = 2; break; } }
static void MetatadaToINI(byte[] file, string filename) { DLCMetadata header = new DLCMetadata(); //Get title byte[] title_b = GetTextItem(ref file, 0, 16); byte[] description_b = GetTextItem(ref file, 0x10, 32); byte[] appname_b = GetTextItem(ref file, 0x30, 16); header.description = System.Text.Encoding.GetEncoding(932).GetString(description_b); header.title = System.Text.Encoding.GetEncoding(932).GetString(title_b); header.appname = System.Text.Encoding.GetEncoding(932).GetString(appname_b); //Get items int item_pointer = BitConverter.ToInt32(file, 0x280); header.dlc_id = BitConverter.ToUInt32(file, item_pointer); Console.WriteLine("Identifier: {0}", header.dlc_id); if ((file[item_pointer + 4] & 0xF) > 0) { header.chars_sonic = true; } if ((file[item_pointer + 4] >> 4) > 0) { header.chars_tails = true; } if ((file[item_pointer + 5] & 0xF) > 0) { header.chars_knuckles = true; } if ((file[item_pointer + 5] >> 4) > 0) { header.chars_e102 = true; } if ((file[item_pointer + 6] & 0xF) > 0) { header.chars_amy = true; } if ((file[item_pointer + 6] >> 4) > 0) { header.chars_big = true; } Console.Write("Characters: "); if (header.chars_sonic) { Console.Write("Sonic "); } if (header.chars_tails) { Console.Write("Tails "); } if (header.chars_knuckles) { Console.Write("Knuckles "); } if (header.chars_amy) { Console.Write("Amy "); } if (header.chars_big) { Console.Write("Big "); } if (header.chars_e102) { Console.Write("Gamma"); } Console.Write(System.Environment.NewLine); header.whatever = file[item_pointer + 7]; header.region = (DLCRegionLocks)BitConverter.ToInt32(file, item_pointer + 8); int item_count = BitConverter.ToInt32(file, 0x284); Console.WriteLine("Item table at {0}, count {1} (size {2} + 12)", item_pointer.ToString("X"), item_count, item_count * 30); header.items = new List <DLCObjectData>(item_count); item_pointer += 12; //Skip 12-byte item section header for (int u = 0; u < item_count; u++) { DLCObjectData dlcitem = new DLCObjectData(); dlcitem.level = file[item_pointer + u * 30]; dlcitem.act = file[item_pointer + u * 30 + 1]; dlcitem.scale_x = file[item_pointer + u * 30 + 2]; dlcitem.scale_y = file[item_pointer + u * 30 + 3]; dlcitem.scale_z = file[item_pointer + u * 30 + 4]; dlcitem.rotspeed_x = (sbyte)file[item_pointer + u * 30 + 5]; dlcitem.rotspeed_y = (sbyte)file[item_pointer + u * 30 + 6]; dlcitem.rotspeed_z = (sbyte)file[item_pointer + u * 30 + 7]; dlcitem.objecttype = (DLCObjectTypes)file[item_pointer + u * 30 + 8]; dlcitem.textureid = file[item_pointer + u * 30 + 9]; dlcitem.flags = (DLCObjectFlags)(BitConverter.ToUInt16(file, item_pointer + u * 30 + 10)); dlcitem.objectid = file[item_pointer + u * 30 + 12]; dlcitem.unknown3 = file[item_pointer + u * 30 + 13]; dlcitem.message = file[item_pointer + u * 30 + 14]; dlcitem.radius = file[item_pointer + u * 30 + 15]; dlcitem.warplevel = file[item_pointer + u * 30 + 16]; dlcitem.sound = file[item_pointer + u * 30 + 17]; dlcitem.rot_x = BitConverter.ToUInt16(file, item_pointer + u * 30 + 18); dlcitem.rot_y = BitConverter.ToUInt16(file, item_pointer + u * 30 + 20); dlcitem.rot_z = BitConverter.ToUInt16(file, item_pointer + u * 30 + 22); dlcitem.x = BitConverter.ToInt16(file, item_pointer + u * 30 + 24); dlcitem.y = BitConverter.ToInt16(file, item_pointer + u * 30 + 26); dlcitem.z = BitConverter.ToInt16(file, item_pointer + u * 30 + 28); header.items.Add(dlcitem); } //Get strings header.JapaneseStrings = new string[16]; header.EnglishStrings = new string[16]; header.FrenchStrings = new string[16]; header.SpanishStrings = new string[16]; header.GermanStrings = new string[16]; int text_pointer = BitConverter.ToInt32(file, 0x288); int text_count = BitConverter.ToInt32(file, 0x28C); Console.WriteLine("String table at {0}, count {1} (size {2})", text_pointer.ToString("X"), text_count, text_count * 64); List <string> strings = new List <string>(); for (int u = 0; u < text_count; u++) { byte[] arr = new byte[64]; Array.Copy(file, text_pointer + 64 * u, arr, 0, 64); int charcount = 0; for (int a = 0; a < arr.Length; a++) { if (arr[a] == 0) { break; } charcount++; } System.Text.Encoding enc = System.Text.Encoding.GetEncoding(932); if (u >= 32) { enc = System.Text.Encoding.GetEncoding(1252); } string str = enc.GetString(arr, 0, charcount); strings.Add(str); } //Process special characters List <string> strings_new = new List <string>(); foreach (string str in strings) { string newstr = System.String.Empty; for (int s = 0; s < str.Length; s++) { if (s == 0 && (str[s] == '~' || str[s] == 't')) { newstr += ("\t"); } else if (str[s] == 't' && str[0] == 't') { newstr += ("\t"); } else if (str[s] == '~' && str[0] == '~') { newstr += ("\t"); } else if ((str[s] == 'n' && str[0] == 't') || (str[s] == '@' && str[0] == '~')) { newstr += ("\n"); } else { newstr += str[s]; } } strings_new.Add(newstr); } string[] stringarr = strings_new.ToArray(); for (int u = 0; u < 16; u++) { if (u >= text_count) { break; } header.JapaneseStrings[u] = stringarr[u]; if (text_count <= 16) { continue; } header.EnglishStrings[u] = stringarr[u + 16]; if (text_count <= 32) { continue; } header.FrenchStrings[u] = stringarr[u + 32]; if (text_count <= 48) { continue; } header.SpanishStrings[u] = stringarr[u + 48]; if (text_count <= 64) { continue; } header.GermanStrings[u] = stringarr[u + 64]; } //Check if an MLT is present int mlt_value = BitConverter.ToInt32(file, 0x2A0); if (mlt_value != 0) { header.has_mlt = true; } IniSerializer.Serialize(header, filename); }
/// <summary> /// Load from a byte array (VMS file) /// </summary> public VMS_DLC(byte[] file) { // Decrypt if encrypted if (BitConverter.ToUInt32(file, 0x280) != 0x2C0) { int aniFrames = file[0x40] + (file[0x41] << 8); int dataStart = 0x80 + (aniFrames * 0x200); byte[] encrypted = new byte[file.Length - dataStart]; Array.Copy(file, dataStart, encrypted, 0, encrypted.Length); VMSFile.DecryptData(ref encrypted); Array.Copy(encrypted, 0, file, dataStart, encrypted.Length); } // Get title and other stuff byte[] title_b = GetTextItem(ref file, 0, 16); byte[] description_b = GetTextItem(ref file, 0x10, 32); byte[] appname_b = GetTextItem(ref file, 0x30, 16); Description = System.Text.Encoding.GetEncoding(932).GetString(description_b); Title = System.Text.Encoding.GetEncoding(932).GetString(title_b); AppName = System.Text.Encoding.GetEncoding(932).GetString(appname_b); Icon = GetIconFromFile(file); // Get items int item_pointer = BitConverter.ToInt32(file, 0x280); if (item_pointer != 0x2C0) { System.Windows.Forms.MessageBox.Show("Unable to find SA1 DLC data.", "DLC Tool Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error); Items = new List <DLCObjectData>(); JapaneseStrings = new string[16]; EnglishStrings = new string[16]; FrenchStrings = new string[16]; GermanStrings = new string[16]; SpanishStrings = new string[16]; TextureData = new byte[0]; SoundData = new byte[0]; ModelData = new byte[0]; return; } Identifier = BitConverter.ToUInt32(file, item_pointer); if ((file[item_pointer + 4] & 0xF) > 0) { EnableSonic = true; } if ((file[item_pointer + 4] >> 4) > 0) { EnableTails = true; } if ((file[item_pointer + 5] & 0xF) > 0) { EnableKnuckles = true; } if ((file[item_pointer + 5] >> 4) > 0) { EnableGamma = true; } if ((file[item_pointer + 6] & 0xF) > 0) { EnableAmy = true; } if ((file[item_pointer + 6] >> 4) > 0) { EnableBig = true; } if ((file[item_pointer + 7] & 0xF) > 0) { EnableWhatever1 = true; } if ((file[item_pointer + 7] >> 4) > 0) { EnableWhatever2 = true; } Region = (DLCRegionLocks)BitConverter.ToInt32(file, item_pointer + 8); // Item table int item_count = BitConverter.ToInt32(file, 0x284); Items = new List <DLCObjectData>(item_count); item_pointer += 12; // Skip 12-byte item section header for (int u = 0; u < item_count; u++) { DLCObjectData dlcitem = new DLCObjectData(); dlcitem.Level = file[item_pointer + u * 30]; dlcitem.Act = file[item_pointer + u * 30 + 1]; dlcitem.ScaleX = file[item_pointer + u * 30 + 2]; dlcitem.ScaleY = file[item_pointer + u * 30 + 3]; dlcitem.ScaleZ = file[item_pointer + u * 30 + 4]; dlcitem.RotSpeedX = (sbyte)file[item_pointer + u * 30 + 5]; dlcitem.RotSpeedY = (sbyte)file[item_pointer + u * 30 + 6]; dlcitem.RotSpeedX = (sbyte)file[item_pointer + u * 30 + 7]; dlcitem.ObjectType = (DLCObjectTypes)file[item_pointer + u * 30 + 8]; dlcitem.Texture = file[item_pointer + u * 30 + 9]; dlcitem.Flags = (DLCObjectFlags)(BitConverter.ToUInt16(file, item_pointer + u * 30 + 10)); dlcitem.InternalID = file[item_pointer + u * 30 + 12]; dlcitem.Unknown3 = file[item_pointer + u * 30 + 13]; dlcitem.Message = file[item_pointer + u * 30 + 14]; dlcitem.TriggerDistance = file[item_pointer + u * 30 + 15]; dlcitem.WarpLevelOrSoundbank = file[item_pointer + u * 30 + 16]; dlcitem.WarpActOrSoundID = file[item_pointer + u * 30 + 17]; dlcitem.RotationX = BitConverter.ToUInt16(file, item_pointer + u * 30 + 18); dlcitem.RotationY = BitConverter.ToUInt16(file, item_pointer + u * 30 + 20); dlcitem.RotationZ = BitConverter.ToUInt16(file, item_pointer + u * 30 + 22); dlcitem.X = BitConverter.ToInt16(file, item_pointer + u * 30 + 24); dlcitem.Y = BitConverter.ToInt16(file, item_pointer + u * 30 + 26); dlcitem.Z = BitConverter.ToInt16(file, item_pointer + u * 30 + 28); Items.Add(dlcitem); } // Get strings JapaneseStrings = new string[16]; EnglishStrings = new string[16]; FrenchStrings = new string[16]; SpanishStrings = new string[16]; GermanStrings = new string[16]; int text_pointer = BitConverter.ToInt32(file, 0x288); int text_count = BitConverter.ToInt32(file, 0x28C); List <string> strings = new List <string>(); for (int u = 0; u < text_count; u++) { byte[] arr = new byte[64]; Array.Copy(file, text_pointer + 64 * u, arr, 0, 64); int charcount = 0; for (int a = 0; a < arr.Length; a++) { if (arr[a] == 0) { break; } charcount++; } System.Text.Encoding enc = System.Text.Encoding.GetEncoding(932); if (u >= 32) { enc = System.Text.Encoding.GetEncoding(1252); } string str = enc.GetString(arr, 0, charcount); strings.Add(str); } // Process special characters List <string> strings_new = new List <string>(); foreach (string str in strings) { string newstr = System.String.Empty; for (int s = 0; s < str.Length; s++) { if (s == 0 && (str[s] == '~' || str[s] == 't')) { newstr += ("\t"); } else if (str[s] == 't' && str[0] == 't') { newstr += ("\t"); } else if (str[s] == '~' && str[0] == '~') { newstr += ("\t"); } else if ((str[s] == 'n' && str[0] == 't') || (str[s] == '@' && str[0] == '~')) { newstr += ("\n"); } else { newstr += str[s]; } } strings_new.Add(newstr); } string[] stringarr = strings_new.ToArray(); for (int u = 0; u < 16; u++) { if (u >= text_count) { break; } JapaneseStrings[u] = stringarr[u]; if (text_count <= 16) { continue; } EnglishStrings[u] = stringarr[u + 16]; if (text_count <= 32) { continue; } FrenchStrings[u] = stringarr[u + 32]; if (text_count <= 48) { continue; } SpanishStrings[u] = stringarr[u + 48]; if (text_count <= 64) { continue; } GermanStrings[u] = stringarr[u + 64]; } TextureData = new byte[0]; SoundData = new byte[0]; ModelData = new byte[0]; // Get PVM pointer uint pvm_pointer = BitConverter.ToUInt32(file, 0x290); // Number of PVMs at 0x294, number of textures at 0x298 // Get MLT pointer uint mlt_pointer = BitConverter.ToUInt32(file, 0x29C); int nummlt = BitConverter.ToInt32(file, 0x2A0); if (nummlt != 0) { ContainsSound = true; } // Get PRS pointer uint prs_pointer = BitConverter.ToUInt32(file, 0x2A4); // Number of PRSes at 0x2A8 // Get PVM data int pvm_size = (int)mlt_pointer - (int)pvm_pointer; if (pvm_size > 0) { TextureData = new byte[pvm_size]; Array.Copy(file, pvm_pointer, TextureData, 0, pvm_size); } // Get MLT data int mlt_size = (int)prs_pointer - (int)mlt_pointer; if (mlt_size > 0) { SoundData = new byte[mlt_size]; Array.Copy(file, mlt_pointer, SoundData, 0, mlt_size); } int item_size = (item_count * 30 + 12); // 12-byte header, headerless section size at 0x48 do { item_size++; }while (item_size % 16 != 0); // The size of the PRS cannot be determined reliably because the file might be padded to have a size divisible by 512 // To get the correct size, the PRS chunk is read until the end of file or a sequence of 16 empty bytes int prs_size = 0; for (int indx = (int)prs_pointer; indx < file.Length; indx += 16) { bool valid = false; for (int u = 0; u < 16; u++) { if (file[indx + u] != 0) { valid = true; break; } } if (valid) { prs_size += 16; } else { break; } } // Get PRS data if (prs_size > 0) { ModelData = new byte[prs_size]; Array.Copy(file, prs_pointer, ModelData, 0, prs_size); } }