public int MeasureStringInFont(string s, PatcherLib.Datatypes.FFTFont font) { var widths = MeasureEachLineInFont(s, font); int width = int.MinValue; widths.ForEach(w => width = Math.Max(width, w)); return(width); }
private int MeasureSingleLineInFont(string s, PatcherLib.Datatypes.FFTFont font) { IList <UInt32> everyChar = GetEachEncodedCharacter(s); int sum = 0; foreach (UInt32 c in everyChar) { sum += GetWidthForEncodedCharacter(c, font); } return(sum); }
public IList <int> MeasureEachLineInFont(string s, PatcherLib.Datatypes.FFTFont font) { string[] strings = s.Split(new string[] { "{Newline}", "{Close}" }, StringSplitOptions.RemoveEmptyEntries); int[] result = new int[strings.Length]; for (int i = 0; i < strings.Length; i++) { result[i] = strings[i].Length == 0 ? 0 : MeasureSingleLineInFont(strings[i], font); } return(result.AsReadOnly()); }
private int GetWidthForEncodedCharacter(UInt32 c, PatcherLib.Datatypes.FFTFont font) { if (c == 0xFA) { return(4); } else if (c <= 0xCF) { return(font.Glyphs[(int)c].Width); } else if ((c & 0xFF00) >= 0xD100 && (c & 0xFF00) <= 0xDA00 && (c & 0x00FF) <= 0xCF && ((c & 0xFF00) != 0xDA00 || (c & 0x00FF) <= 0x77)) { return(font.Glyphs[(int)((((c & 0xFF00) >> 8) - 0xD0) * 0xD0 + (c & 0x00FF))].Width); } else { return(0); } }
public FFTFontWidths(FFTFont owner) { this.owner = owner; }
public static IList<PatchedByteArray> GeneratePsxDtePatches( IEnumerable<KeyValuePair<string, byte>> dteEncodings ) { // BATTLE.BIN -> 0xE7614 // FONT.BIN -> 0 // WORLD.BIN -> 0x5B8F8 var charSet = PSXResources.CharacterSet; FFTFont font = new FFTFont( PSXResources.FontBin, PSXResources.FontWidthsBin ); byte[] fontBytes; byte[] widthBytes; GenerateFontBinPatches( dteEncodings, font, charSet, out fontBytes, out widthBytes ); fontBytes = fontBytes.Sub( minDteByte * characterSize, ( maxDteByte + 1 ) * characterSize - 1 ).ToArray(); // widths: // 0x363234 => 1510 = BATTLE.BIN // 0xBD84908 => 84497 = WORLD.BIN var result = new List<PatchedByteArray>(); result.AddRange( psxDtePatches ); result.AddRange( new PatchedByteArray[] { new PatchedByteArray(PsxIso.Sectors.BATTLE_BIN, 0xE7614+minDteByte*characterSize, fontBytes), new PatchedByteArray(PsxIso.Sectors.EVENT_FONT_BIN, 0x00+minDteByte*characterSize, fontBytes), new PatchedByteArray(PsxIso.Sectors.WORLD_WORLD_BIN, 0x5B8f8+minDteByte*characterSize, fontBytes), new PatchedByteArray(PsxIso.Sectors.BATTLE_BIN, 0xFF0FC, widthBytes), new PatchedByteArray(PsxIso.Sectors.WORLD_WORLD_BIN, 0x733E0, widthBytes), new PatchedByteArray(PsxIso.Sectors.SCUS_942_21, 0x228e0, GeneratePsxLookupTable(dteEncodings, charSet).ToArray()) } ); return result; }
private static void GenerateFontBinPatches( IEnumerable<KeyValuePair<string, byte>> dteEncodings, FFTFont baseFont, IList<string> baseCharSet, out byte[] fontBytes, out byte[] widthBytes ) { FFTFont font = new FFTFont( baseFont.ToByteArray(), baseFont.ToWidthsByteArray() ); IList<string> charSet = new List<string>( baseCharSet ); foreach ( var kvp in dteEncodings ) { int[] chars = new int[] { charSet.IndexOf( kvp.Key.Substring( 0, 1 ) ), charSet.IndexOf( kvp.Key.Substring( 1, 1 ) ) }; int[] widths = new int[] { font.Glyphs[chars[0]].Width, font.Glyphs[chars[1]].Width }; int newWidth = widths[0] + widths[1]; font.Glyphs[kvp.Value].Width = (byte)newWidth; IList<FontColor> newPixels = font.Glyphs[kvp.Value].Pixels; for ( int i = 0; i < newPixels.Count; i++ ) { newPixels[i] = FontColor.Transparent; } const int fontHeight = 14; const int fontWidth = 10; int offset = 0; for ( int c = 0; c < chars.Length; c++ ) { var pix = font.Glyphs[chars[c]].Pixels; for ( int x = 0; x < widths[c]; x++ ) { for ( int y = 0; y < fontHeight; y++ ) { newPixels[y * fontWidth + x + offset] = pix[y * fontWidth + x]; } } offset += widths[c]; } } fontBytes = font.ToByteArray(); widthBytes = font.ToWidthsByteArray(); }
public static IList<PatchedByteArray> GeneratePspDtePatches( IEnumerable<KeyValuePair<string, byte>> dteEncodings ) { var charSet = PSPResources.CharacterSet; FFTFont font = new FFTFont( PSPResources.FontBin, PSPResources.FontWidthsBin ); byte[] fontBytes; byte[] widthBytes; GenerateFontBinPatches( dteEncodings, font, charSet, out fontBytes, out widthBytes ); fontBytes = fontBytes.Sub( minDteByte * characterSize, ( maxDteByte + 1 ) * characterSize - 1 ).ToArray(); return new PatchedByteArray[] { new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_BOOT_BIN, 0x27b80c+minDteByte*characterSize, fontBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_BOOT_BIN, 0x2f73b8+minDteByte*characterSize, fontBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_EBOOT_BIN, 0x27b80c+minDteByte*characterSize, fontBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_EBOOT_BIN, 0x2f73b8+minDteByte*characterSize, fontBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_BOOT_BIN, 0x293f40, widthBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_BOOT_BIN, 0x30fac0, widthBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_EBOOT_BIN, 0x293f40, widthBytes), new PatchedByteArray(PspIso.Sectors.PSP_GAME_SYSDIR_EBOOT_BIN, 0x30fac0, widthBytes) }; }
private static Set<string> GetDteGroups( FFTFont font, GenericCharMap charmap, IList<string> charset ) { var f = new FFTFont( font.ToByteArray(), font.ToWidthsByteArray() ); List<int> widths = new List<int>( 2200 ); f.Glyphs.ForEach( g => widths.Add( g.Width ) ); return TextUtilities.GetGroups( charmap, charset, widths ); }
private static void GenerateFontBinPatches( IEnumerable<KeyValuePair<string, byte>> dteEncodings, FFTFont baseFont, IList<string> baseCharSet, out byte[] fontBytes, out byte[] widthBytes ) { // Make a copy of the font FFTFont font = new FFTFont( baseFont.ToByteArray(), baseFont.ToWidthsByteArray() ); IList<string> charSet = new List<string>( baseCharSet ); charSet.Add( " " ); var myGlyphs = new List<Glyph>( font.Glyphs ); myGlyphs.Add( new Glyph( 0, 4, new byte[14 * 10 / 4] ) ); foreach (var kvp in dteEncodings) { int[] chars = new int[] { charSet.IndexOf( kvp.Key.Substring( 0, 1 ) ), // Find the index of the first character in the pair charSet.IndexOf( kvp.Key.Substring( 1, 1 ) ) // Second character in the pair }; int[] widths = new int[] { myGlyphs[chars[0]].Width, // width of first char myGlyphs[chars[1]].Width // width of secont char }; // The width of the concatenated character is the sum... int newWidth = widths[0] + widths[1]; myGlyphs[kvp.Value].Width = (byte)newWidth; // Erase all the pixels of the character to replace IList<FontColor> newPixels = myGlyphs[kvp.Value].Pixels; for (int i = 0; i < newPixels.Count; i++) { newPixels[i] = FontColor.Transparent; } const int fontHeight = 14; const int fontWidth = 10; int offset = 0; // for each character in the pair... for (int c = 0; c < chars.Length; c++) { var pix = myGlyphs[chars[c]].Pixels; // ... copy the pixels to the concatenated character for (int x = 0; x < widths[c]; x++) { for (int y = 0; y < fontHeight; y++) { newPixels[y * fontWidth + x + offset] = pix[y * fontWidth + x]; } } offset += widths[c]; } } // Return the new font and widths arrays fontBytes = font.ToByteArray(); widthBytes = font.ToWidthsByteArray(); }
/// <summary> /// Generates a list of patches for PSP based on the set of DTE encodings passed. /// Generates font patches and ASM patches. /// </summary> public static IList<PatchedByteArray> GeneratePspDtePatches( IEnumerable<KeyValuePair<string, byte>> dteEncodings ) { var charSet = PSPResources.CharacterSet; FFTFont font = new FFTFont( PSPResources.Binaries.Font, PSPResources.Binaries.FontWidths ); byte[] fontBytes; byte[] widthBytes; GenerateFontBinPatches( dteEncodings, font, charSet, out fontBytes, out widthBytes ); widthBytes = widthBytes.Sub( MinDteByte, MaxDteByte ).ToArray(); fontBytes = fontBytes.Sub( MinDteByte * characterSize, (MaxDteByte + 1) * characterSize - 1 ).ToArray(); var widths = PspFontWidths; var fontDteSection = PspFontDteSection; return new PatchedByteArray[] { fontDteSection[0].GetPatchedByteArray(fontBytes), fontDteSection[1].GetPatchedByteArray(fontBytes), widths[0].GetPatchedByteArray(widthBytes), widths[1].GetPatchedByteArray(widthBytes), }; }
public FFTFontWidths( FFTFont owner ) { this.owner = owner; }