private void SearchForPointers() { byte[] overlayTableData = StreamHelper.ReadFile(OverlayTableFileName); this.overlayOffset = BitConverter.ToInt32(overlayTableData, this.overlayOffsetPointers[this.overlayNumber]); byte[] fileData = StreamHelper.ReadFile(this.GameFileName); List <int> offsets = new List <int>(); List <int> pointers = new List <int>(); for (int i = 0; i + Constants.PointerLength - 1 < fileData.Length; i += Constants.PointerLength) { int pointer = BitConverter.ToInt32(fileData, i); if (pointer >= this.overlayOffset && pointer <= this.overlayOffset + fileData.Length) { offsets.Add(i); pointers.Add(pointer - this.overlayOffset); } } this.pointerOffsets = offsets.ToArray(); this.pointerTable = pointers.ToArray(); this.strings = new string[pointers.Count]; for (int i = 0; i < pointers.Count; i++) { this.strings[i] = this.game.GetText(fileData, pointers[i]); } }
/// <summary> /// Repacks all files into the pack. /// </summary> public void Pack() { byte[] fileData = StreamHelper.ReadFile(this.DecompressedFileName); fileData = CompressionManager.CompressOverlay(fileData); StreamHelper.WriteFile(this.CompressedFileName, fileData); this.CompressedFileSize = fileData.Length; }
/// <summary> /// Extracts the text strings from the game file. /// </summary> /// <returns>A value indicating whether the file was successfully loaded.</returns> protected override bool LoadText() { byte[] fileData = StreamHelper.ReadFile(this.GameFileName); FileStream pointerFile = new FileStream(this.PointerFileName, FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(pointerFile); int numPointers = reader.ReadInt32(); this.pointers = new int[numPointers]; for (int i = 0; i < this.pointers.Length; i++) { this.pointers[i] = reader.ReadInt32(); } int numRanges = reader.ReadInt32(); this.validTextRanges = new KeyValuePair <int, int> [numRanges]; for (int i = 0; i < this.validTextRanges.Length; i++) { this.validTextRanges[i] = new KeyValuePair <int, int>(reader.ReadInt32(), reader.ReadInt32()); } this.strings = new string[this.pointers.Length]; for (int i = 0; i < this.pointers.Length; i++) { int textOffset = BitConverter.ToInt32(fileData, this.pointers[i]) - Arm9Offset; this.strings[i] = this.Game.GetText(fileData, textOffset); } reader.Close(); return(true); }
/// <summary> /// Unpacks and initializes all files from the pack. /// </summary> public void Unpack() { byte[] fileData = StreamHelper.ReadFile(this.CompressedFileName); fileData = CompressionManager.DecompressOverlay(fileData); StreamHelper.WriteFile(this.DecompressedFileName, fileData); this.InitializeChildren(); }
/// <summary> /// Repacks all files into the pack. /// </summary> public void Pack() { int headerLength = this.game.Cache.Settings["arm9"]["headerLength"].Int32Value; byte[] footer = DecodeFooter(this.game.Cache.Settings["arm9"]["footer"].Value); byte[] fileData = StreamHelper.ReadFile(this.DecompressedFileName); fileData = CompressionManager.CompressArm9(fileData, headerLength, footer); StreamHelper.WriteFile(this.CompressedFileName, fileData); }
private void GenerateOffsetPointers() { byte[] overlayTableData = StreamHelper.ReadFile(OverlayTableFileName); int overlayCount = overlayTableData.Length / OverlayTableEntryLength; this.overlayOffsetPointers = new int[overlayCount]; for (int i = 0; i < overlayCount; i++) { int overlayNumberPointer = (OverlayTableEntryLength * i) + 0x18; int overlayOffsetPointer = (OverlayTableEntryLength * i) + 0x04; int overlayNumber = BitConverter.ToInt32(overlayTableData, overlayNumberPointer); this.overlayOffsetPointers[overlayNumber] = overlayOffsetPointer; } }
/// <summary> /// Unpacks and initializes all files from the pack. /// </summary> public void Unpack() { int headerLength; byte[] footer; this.textFiles.Clear(); byte[] fileData = StreamHelper.ReadFile(this.CompressedFileName); fileData = CompressionManager.DecompressArm9(fileData, out headerLength, out footer); StreamHelper.WriteFile(this.DecompressedFileName, fileData); this.game.Cache.Settings["arm9"]["headerLength"].Int32Value = headerLength; this.game.Cache.Settings["arm9"]["footer"].Value = EncodeFooter(footer); this.InitializeChildren(); }
/* * private void SearchForPointers() * { * byte[] fileData = StreamHelper.ReadFile(this.GameFileName); * * List<int> offsets = new List<int>(); * List<int> pointers = new List<int>(); * for (int i = 0; i + Constants.PointerLength - 1 < fileData.Length; i += Constants.PointerLength) * { * int pointer = BitConverter.ToInt32(fileData, i); * if (pointer >= Arm9Offset && pointer <= fileData.Length + Arm9Offset) * { * offsets.Add(i); * pointers.Add(pointer - Arm9Offset); * } * } * * this.pointerOffsets = offsets.ToArray(); * this.pointerTable = pointers.ToArray(); * this.strings = new string[pointers.Count]; * for (int i = 0; i < pointers.Count; i++) * { * this.strings[i] = this.game.GetText(fileData, pointers[i]); * } * } */ private void SearchForPointers() { List <string> validList = new List <string>(); if (this.useValid) { FileStream validFile = new FileStream(TextDirectoryPrefix + @"\valid.sjs", FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(validFile, this.game.Encoding); string line = string.Empty; while ((line = reader.ReadLine()) != null) { validList.Add(line); } } byte[] fileData = StreamHelper.ReadFile(this.GameFileName); List <int> offsets = new List <int>(); List <int> pointers = new List <int>(); for (int i = 0; i + Constants.PointerLength - 1 < fileData.Length; i += Constants.PointerLength) { int pointer = BitConverter.ToInt32(fileData, i); if (pointer >= Arm9Offset && pointer <= fileData.Length + Arm9Offset) { string line = this.game.GetText(fileData, pointer - Arm9Offset); if (!this.useValid || validList.Contains(line)) { offsets.Add(i); pointers.Add(pointer - Arm9Offset); } } } this.pointerOffsets = offsets.ToArray(); this.pointerTable = pointers.ToArray(); this.strings = new string[pointers.Count]; for (int i = 0; i < pointers.Count; i++) { this.strings[i] = this.game.GetText(fileData, pointers[i]); } }
/// <summary> /// Extracts the text strings from the game file. /// </summary> /// <returns>A value indicating whether the file was successfully loaded.</returns> protected override bool LoadText() { byte[] overlayTableData = StreamHelper.ReadFile(OverlayTableFileName); this.overlayOffset = BitConverter.ToInt32(overlayTableData, this.overlayOffsetPointers[this.overlayNumber]); byte[] fileData = StreamHelper.ReadFile(this.GameFileName); FileStream pointerFile = new FileStream(this.PointerFileName, FileMode.Open, FileAccess.Read); BinaryReader reader = new BinaryReader(pointerFile); int numPointers = reader.ReadInt32(); this.pointers = new int[numPointers]; for (int i = 0; i < this.pointers.Length; i++) { this.pointers[i] = reader.ReadInt32(); } int numRanges = reader.ReadInt32(); this.validTextRanges = new List <TextRange>(numRanges); for (int i = 0; i < numRanges; i++) { TextRange textRange = new TextRange(reader.ReadInt32(), reader.ReadInt32()); this.validTextRanges.Add(textRange); } this.strings = new string[this.pointers.Length]; for (int i = 0; i < this.pointers.Length; i++) { int textOffset = BitConverter.ToInt32(fileData, this.pointers[i]) - this.overlayOffset; this.strings[i] = this.Game.GetText(fileData, textOffset); } reader.Close(); return(true); }
/// <summary> /// Inserts the text strings back into the game file. /// </summary> /// <returns>A value indicating whether the file was successfully saved.</returns> protected override bool SaveText() { byte[] fileData = StreamHelper.ReadFile(this.GameFileName); int linesAdded = 0; Dictionary <string, int> dupes = new Dictionary <string, int>(); List <ScriptPointer> scriptPointers = new List <ScriptPointer>(this.strings.Length); int i; for (i = 0; i < this.strings.Length; i++) { ScriptPointer scriptPointer = new ScriptPointer(this.Game, this.pointers[i], this.strings[i]); scriptPointers.Add(scriptPointer); } List <TextRange> textRanges = new List <TextRange>(this.validTextRanges); scriptPointers.Sort(); textRanges.Sort(); /* * System.Diagnostics.Debug.WriteLine("Phase 1"); * for (int a = 0; a < scriptPointers.Count; a++) * { * if (scriptPointers[a] == null) continue; * System.Diagnostics.Debug.WriteLine(a + ". " + scriptPointers[a].Length + " - " + scriptPointers[a].Text); * } * for (int b = 0; b < textRanges.Count; b++) * { * if (textRanges[b] == null) continue; * System.Diagnostics.Debug.WriteLine(b + ". " + textRanges[b].Length); * } */ i = 0; int k = 0; byte[] pointerBytes; while (i < scriptPointers.Count) { if (dupes.ContainsKey(scriptPointers[i].Text)) { ////System.Diagnostics.Debug.WriteLine("Skipping duplicate line " + i + "."); pointerBytes = BitConverter.GetBytes(dupes[scriptPointers[i].Text]); Array.Copy(pointerBytes, 0, fileData, scriptPointers[i].Pointer, Constants.PointerLength); scriptPointers[i] = null; linesAdded++; i++; } else if (k < textRanges.Count) { if (scriptPointers[i].Length > textRanges[k].Length) { ////System.Diagnostics.Debug.WriteLine("Line " + i + " is larger than current range, skipping."); i++; } else if (scriptPointers[i].Length < textRanges[k].Length) { ////System.Diagnostics.Debug.WriteLine("Range " + k + " is larger than current line, skipping."); k++; } else { ////System.Diagnostics.Debug.WriteLine("Writing line " + i + " to range " + k + ". New length = 0"); int textOffset = textRanges[k].Start; textRanges[k] = null; k++; byte[] encodedText = scriptPointers[i].GetEncodedText(); Array.Copy(encodedText, 0, fileData, textOffset, encodedText.Length); for (int pad = encodedText.Length; pad < scriptPointers[i].Length; pad++) { fileData[textOffset + pad] = 0x00; } pointerBytes = BitConverter.GetBytes(textOffset + this.overlayOffset); Array.Copy(pointerBytes, 0, fileData, scriptPointers[i].Pointer, Constants.PointerLength); dupes.Add(scriptPointers[i].Text, textOffset + this.overlayOffset); scriptPointers[i] = null; linesAdded++; i++; } } else { ////System.Diagnostics.Debug.WriteLine("Line " + i + " is larger than current range, skipping."); i++; } } /* * System.Diagnostics.Debug.WriteLine("Phase 2"); * for (int a = 0; a < scriptPointers.Count; a++) * { * if (scriptPointers[a] == null) continue; * System.Diagnostics.Debug.WriteLine(a + ". " + scriptPointers[a].Length + " - " + scriptPointers[a].Text); * } * for (int b = 0; b < textRanges.Count; b++) * { * if (textRanges[b] == null) continue; * System.Diagnostics.Debug.WriteLine(b + ". " + textRanges[b].Length); * } */ for (i = 0; i < scriptPointers.Count; i++) { if (scriptPointers[i] == null) { continue; } if (dupes.ContainsKey(scriptPointers[i].Text)) { ////System.Diagnostics.Debug.WriteLine("Skipping duplicate line " + i + "."); pointerBytes = BitConverter.GetBytes(dupes[scriptPointers[i].Text]); } else { int textOffset = -1; for (k = 0; k < textRanges.Count; k++) { if (textRanges[k] == null) { ////System.Diagnostics.Debug.WriteLine("No room for line " + i + "."); continue; } if (scriptPointers[i].Length <= textRanges[k].Length) { textOffset = textRanges[k].Start; textRanges[k].Start = textOffset + scriptPointers[i].Length; ////System.Diagnostics.Debug.WriteLine("Writing line " + i + " to range " + k + ". New start = " + textRanges[k].Start + ", new length = " + textRanges[k].Length); if (textRanges[k].Length == 0) { textRanges[k] = null; } break; } } if (textOffset == -1) { continue; } byte[] encodedText = scriptPointers[i].GetEncodedText(); Array.Copy(encodedText, 0, fileData, textOffset, encodedText.Length); for (int pad = encodedText.Length; pad < scriptPointers[i].Length; pad++) { fileData[textOffset + pad] = 0x00; } pointerBytes = BitConverter.GetBytes(textOffset + this.overlayOffset); dupes.Add(scriptPointers[i].Text, textOffset + this.overlayOffset); } Array.Copy(pointerBytes, 0, fileData, scriptPointers[i].Pointer, Constants.PointerLength); linesAdded++; } if (linesAdded < scriptPointers.Count) { string message = string.Format(CultureInfo.CurrentCulture, "Ran out of room for translated text! (lines fit {0}/{1})", linesAdded, scriptPointers.Count); throw new FormatException(message); } StreamHelper.WriteFile(this.GameFileName, fileData); return(true); }
private void ImportListOfValidPointers() { FileStream file = new FileStream(this.TextFileName, FileMode.Open, FileAccess.Read); StreamReader reader = new StreamReader(file, this.game.Encoding); List <int> offsets = new List <int>(); string line = StreamHelper.ReadNextLine(reader); int i = 0; while (line != null && line.Length > 0) { i++; int offset = Convert.ToInt32(line.Substring(0, 8), 16); offsets.Add(offset); line = StreamHelper.ReadNextLine(reader); } reader.Close(); ////======================== byte[] fileData = StreamHelper.ReadFile(this.GameFileName); this.pointerOffsets = offsets.ToArray(); SortedDictionary <int, int> textRanges = new SortedDictionary <int, int>(); for (i = 0; i < this.pointerOffsets.Length; i++) { int key = BitConverter.ToInt32(fileData, this.pointerOffsets[i]) - Arm9Offset; int val = key; for (val = key; fileData[val] != 0x00 || (val % 4) != 3; val++) { } if (!textRanges.ContainsKey(key)) { textRanges.Add(key, val); } } this.validTextRanges = new SortedDictionary <int, int>(); int startOffset = -1; int endOffset = -1; foreach (KeyValuePair <int, int> kvp in textRanges) { if (kvp.Key == endOffset + 1) { endOffset = kvp.Value; } else { if (startOffset != -1) { this.validTextRanges.Add(startOffset, endOffset); } startOffset = kvp.Key; endOffset = kvp.Value; } } this.validTextRanges.Add(startOffset, endOffset); }
/// <summary> /// Inserts the text strings back into the game file. /// </summary> /// <returns>A value indicating whether the file was successfully saved.</returns> protected override bool SaveText() { if (!this.IsModified) { return(false); } byte[] fileData = StreamHelper.ReadFile(this.GameFileName); Dictionary <string, int> dupes = new Dictionary <string, int>(); KeyValuePair <int, int>[] textRanges = new KeyValuePair <int, int> [this.validTextRanges.Length]; for (int i = 0; i < textRanges.Length; i++) { textRanges[i] = this.validTextRanges[i]; } byte[] pointerBytes; for (int i = 0; i < this.pointers.Length; i++) { if (dupes.ContainsKey(this.strings[i])) { pointerBytes = BitConverter.GetBytes(dupes[this.strings[i]]); } else { byte[] encodedString = this.Game.GetBytes(this.strings[i]); int textLength = encodedString.Length + 1; while (textLength % 4 != 0) { textLength++; } int textOffset = -1; for (int k = 0; k < textRanges.Length; k++) { int rangeLength = textRanges[k].Value - textRanges[k].Key + 1; if (textLength <= rangeLength) { textOffset = textRanges[k].Key; textRanges[k] = new KeyValuePair <int, int>(textOffset + textLength, textRanges[k].Value); break; } } if (textOffset == -1) { string message = string.Format(CultureInfo.CurrentCulture, "Ran out of room for translated text! (line {0}/{1})", i + 1, this.pointers.Length); throw new FormatException(message); } Array.Copy(encodedString, 0, fileData, textOffset, encodedString.Length); for (int pad = encodedString.Length; pad < textLength; pad++) { fileData[textOffset + pad] = 0x00; } pointerBytes = BitConverter.GetBytes(textOffset + Arm9Offset); dupes.Add(this.strings[i], textOffset + Arm9Offset); } Array.Copy(pointerBytes, 0, fileData, this.pointers[i], Constants.PointerLength); } StreamHelper.WriteFile(this.GameFileName, fileData); return(true); }