SharedFontManager.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. using Ryujinx.HLE.Memory;
  2. using Ryujinx.HLE.Resource;
  3. using Ryujinx.HLE.Utilities;
  4. using System.Collections.Generic;
  5. using System.IO;
  6. namespace Ryujinx.HLE.HOS.Font
  7. {
  8. class SharedFontManager
  9. {
  10. private DeviceMemory Memory;
  11. private long PhysicalAddress;
  12. private string FontsPath;
  13. private struct FontInfo
  14. {
  15. public int Offset;
  16. public int Size;
  17. public FontInfo(int Offset, int Size)
  18. {
  19. this.Offset = Offset;
  20. this.Size = Size;
  21. }
  22. }
  23. private Dictionary<SharedFontType, FontInfo> FontData;
  24. public SharedFontManager(Switch Device, long PhysicalAddress)
  25. {
  26. this.PhysicalAddress = PhysicalAddress;
  27. Memory = Device.Memory;
  28. FontsPath = Path.Combine(Device.FileSystem.GetSystemPath(), "fonts");
  29. }
  30. public void EnsureInitialized()
  31. {
  32. if (FontData == null)
  33. {
  34. Memory.FillWithZeros(PhysicalAddress, Horizon.FontSize);
  35. uint FontOffset = 0;
  36. FontInfo CreateFont(string Name)
  37. {
  38. string FontFilePath = Path.Combine(FontsPath, Name + ".ttf");
  39. if (File.Exists(FontFilePath))
  40. {
  41. byte[] Data = File.ReadAllBytes(FontFilePath);
  42. FontInfo Info = new FontInfo((int)FontOffset, Data.Length);
  43. WriteMagicAndSize(PhysicalAddress + FontOffset, Data.Length);
  44. FontOffset += 8;
  45. uint Start = FontOffset;
  46. for (; FontOffset - Start < Data.Length; FontOffset++)
  47. {
  48. Memory.WriteByte(PhysicalAddress + FontOffset, Data[FontOffset - Start]);
  49. }
  50. return Info;
  51. }
  52. else
  53. {
  54. throw new InvalidSystemResourceException($"Font \"{Name}.ttf\" not found. Please provide it in \"{FontsPath}\".");
  55. }
  56. }
  57. FontData = new Dictionary<SharedFontType, FontInfo>()
  58. {
  59. { SharedFontType.JapanUsEurope, CreateFont("FontStandard") },
  60. { SharedFontType.SimplifiedChinese, CreateFont("FontChineseSimplified") },
  61. { SharedFontType.SimplifiedChineseEx, CreateFont("FontExtendedChineseSimplified") },
  62. { SharedFontType.TraditionalChinese, CreateFont("FontChineseTraditional") },
  63. { SharedFontType.Korean, CreateFont("FontKorean") },
  64. { SharedFontType.NintendoEx, CreateFont("FontNintendoExtended") }
  65. };
  66. if (FontOffset > Horizon.FontSize)
  67. {
  68. throw new InvalidSystemResourceException(
  69. $"The sum of all fonts size exceed the shared memory size. " +
  70. $"Please make sure that the fonts don't exceed {Horizon.FontSize} bytes in total. " +
  71. $"(actual size: {FontOffset} bytes).");
  72. }
  73. }
  74. }
  75. private void WriteMagicAndSize(long Position, int Size)
  76. {
  77. const int DecMagic = 0x18029a7f;
  78. const int Key = 0x49621806;
  79. int EncryptedSize = EndianSwap.Swap32(Size ^ Key);
  80. Memory.WriteInt32(Position + 0, DecMagic);
  81. Memory.WriteInt32(Position + 4, EncryptedSize);
  82. }
  83. public int GetFontSize(SharedFontType FontType)
  84. {
  85. EnsureInitialized();
  86. return FontData[FontType].Size;
  87. }
  88. public int GetSharedMemoryAddressOffset(SharedFontType FontType)
  89. {
  90. EnsureInitialized();
  91. return FontData[FontType].Offset + 8;
  92. }
  93. }
  94. }