private void LoadFontSheet(string stdDir)
        {
            Console.WriteLine("Loading font sheet...");

            string fontSheetPath = Path.Join(stdDir, "PSP_GAME", "USRDIR", "font", "SYS_RunTime.uvr");

            using (Stream stream = File.OpenRead(fontSheetPath)) {
                GBIX gbix = new GBIX(stream);
                KONTextRepacker.SetFontImage(((UVRT)gbix.Content).ToBitmap());
            }
        }
        private byte[] RewriteFile(string translationDir, string path, byte[] data)
        {
            if (_rewriteCache.ContainsKey(path))
            {
                return(_rewriteCache[path]);
            }

            using (Stream stream = new MemoryStream(data)) {
                byte[] rewritten = null;
                if (IsFmdx(path))
                {
                    FMDX fmdx     = new FMDX(stream);
                    bool modified = false;
                    foreach (FMDX.File file in fmdx.Files)
                    {
                        if (ShouldRewriteFile(translationDir, file.Path))
                        {
                            file.Data = RewriteFile(translationDir, file.Path, file.Data);
                            modified  = true;
                        }
                    }

                    if (modified)
                    {
                        using (MemoryStream outStream = new MemoryStream()) {
                            fmdx.Write(outStream);
                            rewritten = outStream.ToArray();
                        }
                    }
                }
                else
                {
                    string replacementPath = GetReplacementPath(translationDir, path);
                    if (File.Exists(replacementPath))
                    {
                        if (path.EndsWith(".uvr"))
                        {
                            Bitmap bitmap = new Bitmap(Image.FromFile(replacementPath));

                            GBIX gbix = new GBIX(stream);
                            UVRT uvrt = (UVRT)gbix.Content;
                            gbix.Content = new UVRT(bitmap, uvrt.Format, uvrt.Type, uvrt.MipLevels);

                            using (MemoryStream outStream = new MemoryStream()) {
                                gbix.Write(outStream);
                                rewritten = outStream.ToArray();
                            }
                        }
                        else if (path.EndsWith(".tts"))
                        {
                            string[] lines = File.ReadAllLines(replacementPath);
                            rewritten = KONTextRepacker.RewriteTTS(data, lines);
                        }
                        else
                        {
                            string[] lines = File.ReadAllLines(replacementPath);
                            rewritten = KONTextRepacker.RewriteSystemText(data, lines);
                        }
                    }
                }

                if (rewritten != null)
                {
                    _rewriteCache[path] = rewritten;
                }

                return(rewritten);
            }
        }
        public static byte[] RewriteTTS(byte[] fileData, string[] lines)
        {
            ISet <char> chars = new HashSet <char>();

            foreach (string s in lines)
            {
                foreach (char c in s)
                {
                    chars.Add(c);
                }
            }

            using (Stream stream = new MemoryStream(fileData)) {
                TTS tts = new TTS(stream);

                GBIX   fontGBIX = (GBIX)tts.DataDefinitions[0].Value;
                UVRT   fontUVRT = (UVRT)fontGBIX.Content;
                Bitmap fontImg  = fontUVRT.ToBitmap();
                Dictionary <char, int> charMap = RewriteFont(fontImg, chars);
                fontGBIX.Content = new UVRT(fontImg, fontUVRT.Format, fontUVRT.Type, fontUVRT.MipLevels);

                DataDefinition textIndexData = tts.DataDefinitions[1];
                byte[][][]     newLines      = RewriteScriptTextIndex((byte[])textIndexData.Value, lines, charMap);

                using (MemoryStream bOut = new MemoryStream()) {
                    int dialogueIndex = 0;
                    for (int i = 0; i < newLines.Length; i++)
                    {
                        byte[][] newLinesAt = newLines[i];

                        bOut.Write(newLinesAt[0]);
                        dialogueIndex++;

                        if (newLinesAt.Length > 1)
                        {
                            for (int j = 1; j < newLinesAt.Length; j++)
                            {
                                for (int k = 0; k < tts.Instructions.Count; k++)
                                {
                                    Instruction instr = tts.Instructions[k];
                                    if (instr is CharacterSpeakInstruction ins)
                                    {
                                        if (ins.Dialogue == dialogueIndex - 1)
                                        {
                                            tts.Instructions.Insert(k + 1,
                                                                    new CharacterSpeakInstruction((byte)dialogueIndex, ins.BubbleType));

                                            // Skip the newly added instruction.
                                            k++;
                                        }
                                        else if (ins.Dialogue >= dialogueIndex)
                                        {
                                            tts.Instructions[k] =
                                                new CharacterSpeakInstruction((byte)(ins.Dialogue + 1),
                                                                              ins.BubbleType);
                                        }
                                    }
                                }

                                tts.DataDefinitions.Insert(2 + dialogueIndex,
                                                           new DataDefinition(DataType.VOICE_CLIP, SILENT_AUDIO));

                                bOut.Write(newLinesAt[j]);
                                dialogueIndex++;
                            }
                        }
                    }

                    textIndexData.Value = bOut.ToArray();
                }

                using (MemoryStream outStream = new MemoryStream()) {
                    tts.Write(outStream);
                    return(outStream.ToArray());
                }
            }
        }