public void SaveLocale(int LocaleTableIndex, int StringIndex, string strName) { //Get our Locale Table LocaleHandler.LocaleTable selectedTable = LocaleTables[LocaleTableIndex]; //Compare our string lengths. if (selectedTable.LocaleStrings[StringIndex].Name.Length == strName.Length) { //Open our IO Map.OpenIO(); //Go to that locale's position Map.IO.Out.BaseStream.Position = selectedTable.LocaleTableOffset + selectedTable.LocaleStrings[StringIndex].Offset; //Write our new locale. Map.IO.Out.WriteAsciiString(strName, strName.Length); //Close our IO Map.CloseIO(); } else { //Get our variables int differenceStringLength = strName.Length - selectedTable.LocaleStrings[StringIndex].Name.Length; int oldTableSize = selectedTable.LocaleTableSize; int newTableSize = selectedTable.LocaleTableSize + differenceStringLength; int oldTableSizePadded = oldTableSize + ExtraFunctions.CalculatePadding(oldTableSize, 0x1000); int newTableSizePadded = newTableSize + ExtraFunctions.CalculatePadding(newTableSize, 0x1000); int differenceTableSize = newTableSizePadded - oldTableSizePadded; //Let's recalculate some variables. //Open our IO Map.OpenIO(); //Go to our following string index's position Map.IO.Out.BaseStream.Position = selectedTable.LocaleTableIndexOffset + ((StringIndex + 1) * 8); //Loop for every string after. for (int i = StringIndex + 1; i < selectedTable.LocaleCount; i++) { //Skip 4 bytes Map.IO.Out.BaseStream.Position += 4; //Write our new index Map.IO.Out.Write(selectedTable.LocaleStrings[i].Offset + differenceStringLength); } //Let's shift our other tables //Loop for each table after this one. for (int i = LocaleTableIndex + 1; i < LocaleTables.Count; i++) { //Go to that table's offset. Map.IO.Out.BaseStream.Position = LocaleTables[i].Offset + 8; //Shift our values LocaleTables[i].LocaleTableOffset += differenceTableSize; LocaleTables[i].LocaleTableIndexOffset += differenceTableSize; //Write our values. Map.IO.Out.Write((LocaleTables[i].LocaleTableIndexOffset - Map.MapHeader.localeTableAddressModifier)); Map.IO.Out.Write((LocaleTables[i].LocaleTableOffset - Map.MapHeader.localeTableAddressModifier)); } byte[] restOfTable = new byte[0]; try { //Read the rest of our table after we'll insert Map.IO.In.BaseStream.Position = selectedTable.LocaleTableOffset + selectedTable.LocaleStrings[StringIndex + 1].Offset; restOfTable = Map.IO.In.ReadBytes(oldTableSize - selectedTable.LocaleStrings[StringIndex].Offset); } catch { } //Close our IO Map.CloseIO(); //Check our difference. if (differenceTableSize > 0) { //Insert ExtraFunctions.InsertBytes(Map.FileName, selectedTable.LocaleTableOffset + oldTableSizePadded, differenceTableSize); } else if (differenceTableSize < 0) { //Delete ExtraFunctions.DeleteBytes(Map.FileName, selectedTable.LocaleTableOffset + newTableSizePadded, oldTableSizePadded - newTableSizePadded); } //Open our IO Map.OpenIO(); //Let's write our new strings name. Map.IO.Out.BaseStream.Position = selectedTable.LocaleTableOffset + selectedTable.LocaleStrings[StringIndex].Offset; Map.IO.Out.WriteAsciiString(strName, strName.Length + 1); //Write the ending of our table Map.IO.Out.Write(restOfTable); Map.IO.Out.Write(new byte[newTableSizePadded - newTableSize]); //Lets go write our new locale table size Map.IO.Out.BaseStream.Position = selectedTable.Offset + 4; //Write our new size. Map.IO.Out.Write(newTableSize); //Close our IO Map.CloseIO(); //Set our new table size selectedTable.LocaleTableSize = newTableSize; } //Open our IO Map.OpenIO(); //Go back to the beginning of the table Map.IO.SeekTo(selectedTable.LocaleTableOffset); byte[] hash = SHA1.Create().ComputeHash(Map.IO.In.ReadBytes( selectedTable.LocaleTableSize)); //Seek to where the hash is Map.IO.SeekTo(selectedTable.Offset + 0x24); //Write it Map.IO.Out.Write(hash); //Go back to the beginning of the index table Map.IO.SeekTo(selectedTable.LocaleTableIndexOffset); hash = SHA1.Create().ComputeHash(Map.IO.In.ReadBytes(0x08 * selectedTable.LocaleCount)); //Seek to where the hash is Map.IO.SeekTo(selectedTable.Offset + 0x10); //Write it Map.IO.Out.Write(hash); //Close our IO Map.CloseIO(); }
/// <summary> /// This function renames a tag. /// </summary> /// <param name="tagIndex">The index of the tag to rename.</param> /// <param name="newName">The new name of the tag to rename as.</param> public void RenameTag(int tagIndex, string newName) { //Get our tag instance HaloMap.TagItem tagItem = map.IndexItems[tagIndex]; //Compare our string lengths.. if (tagItem.Name.Length == newName.Length) { //They are the same length. Let's write our new string. //Open our IO map.OpenIO(); //Go to our tag_name_index_entry map.IO.In.BaseStream.Position = map.MapHeader.fileTableIndexOffset + (tagIndex * 4); //Read our tagnameoffset int tagNameOffset = map.IO.In.ReadInt32() + map.MapHeader.fileTableOffset; //Go to this position map.IO.In.BaseStream.Position = tagNameOffset; //Write our tagname map.IO.Out.WriteAsciiString(newName, tagItem.Name.Length); //Close our IO map.CloseIO(); //Set our tagname. map.IndexItems[tagIndex].Name = newName; } else { //Calculate our table difference. int differenceInStringLength = (tagItem.Name.Length - newName.Length); int newTableSizeUnpadded = map.MapHeader.fileTableSize - differenceInStringLength; int newTableSize = newTableSizeUnpadded + ExtraFunctions.CalculatePadding(newTableSizeUnpadded, 0x1000); int oldTableSize = map.MapHeader.fileTableSize + ExtraFunctions.CalculatePadding(map.MapHeader.fileTableSize, 0x1000); int differenceInSize = oldTableSize - newTableSize; //Open our IO map.OpenIO(); //Go to our tag_name_index_entry map.IO.In.BaseStream.Position = map.MapHeader.fileTableIndexOffset + (tagIndex * 4); //Read our tagnameoffset int tagNameOffset = map.IO.In.ReadInt32() + map.MapHeader.fileTableOffset; //Loop for each tag_name_index after it. for (int i = tagIndex + 1; i < map.IndexHeader.tagCount; i++) { //Go to our tag_name_index_entry map.IO.In.BaseStream.Position = map.MapHeader.fileTableIndexOffset + (i * 4); //Read our tagindex int tagOff = map.IO.In.ReadInt32(); //Recalculate it. tagOff -= differenceInStringLength; //Go to our tag_name_index_entry map.IO.Out.BaseStream.Position = map.MapHeader.fileTableIndexOffset + (i * 4); //Write it map.IO.Out.Write(tagOff); } //Close our IO map.CloseIO(); //If it's any different. if (differenceInSize > 0) { ExtraFunctions.DeleteBytes(map.FileName, map.MapHeader.fileTableOffset + newTableSize, oldTableSize - newTableSize); } else { ExtraFunctions.InsertBytes(map.FileName, map.MapHeader.fileTableOffset + oldTableSize, newTableSize - oldTableSize); } //Open our IO map.OpenIO(); //Go to this position map.IO.Out.BaseStream.Position = tagNameOffset; //Write our tagname map.IO.Out.WriteAsciiString(newName, newName.Length); map.IO.Out.Write((byte)0); for (int i = tagIndex + 1; i < map.IndexHeader.tagCount; i++) { //Write the tagname map.IO.Out.WriteAsciiString(map.IndexItems[i].Name, map.IndexItems[i].Name.Length); map.IO.Out.Write((byte)0); } //For the rest of our table, write the padding. byte[] padding = new byte[newTableSize - newTableSizeUnpadded]; //Write our padding map.IO.Out.Write(padding); //Recalculate some header values. map.IO.Out.BaseStream.Position = 20; map.IO.Out.Write(((map.MapHeader.virtSegmentStart - differenceInSize) + map.MapHeader.headerMagic)); map.IO.Out.BaseStream.Position = 700; map.IO.Out.Write(newTableSizeUnpadded); map.IO.Out.BaseStream.Position = 704; map.IO.Out.Write(((map.MapHeader.fileTableIndexOffset - differenceInSize) + map.MapHeader.headerMagic)); map.IO.Out.BaseStream.Position = 1136; map.IO.Out.Write((map.MapHeader.RawTableOffset - differenceInSize)); map.IO.Out.BaseStream.Position = 1144; map.IO.Out.Write((map.MapHeader.localeTableAddressModifier - differenceInSize)); //Close our IO map.CloseIO(); //Reload our map map.Reload(); } }