示例#1
0
        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]);
            }
        }
示例#2
0
 /// <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;
 }
示例#3
0
        /// <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);
        }
示例#4
0
        /// <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();
        }
示例#5
0
        /// <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);
        }
示例#6
0
        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;
            }
        }
示例#7
0
        /// <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();
        }
示例#8
0
        /*
         * 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]);
            }
        }
示例#9
0
        /// <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);
        }
示例#10
0
        /// <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);
        }
示例#11
0
        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);
        }
示例#12
0
        /// <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);
        }