| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- using ChocolArm64.Exceptions;
- using ChocolArm64.Memory;
- using Ryujinx.HLE.Logging;
- using Ryujinx.HLE.OsHle;
- using Ryujinx.HLE.OsHle.Handles;
- using Ryujinx.HLE.Resource;
- using System;
- using System.Collections.Generic;
- using System.IO;
- namespace Ryujinx.HLE.Font
- {
- public class SharedFontManager
- {
- private const uint SharedMemorySize = 0x1100000;
- private Logger Log;
- private string FontsPath;
- private object ShMemLock;
- private (AMemory, long, long)[] ShMemPositions;
- private Dictionary<SharedFontType, byte[]> FontData;
- private uint[] LoadedFonts;
- public SharedFontManager(Logger Log, string SystemPath)
- {
- this.Log = Log;
- this.FontsPath = Path.Combine(SystemPath, "fonts");
- ShMemLock = new object();
- ShMemPositions = new(AMemory, long, long)[0];
- FontData = new Dictionary<SharedFontType, byte[]>()
- {
- { SharedFontType.JapanUsEurope, GetData("FontStandard") },
- { SharedFontType.SimplifiedChinese, GetData("FontChineseSimplified") },
- { SharedFontType.SimplifiedChineseEx, GetData("FontExtendedChineseSimplified") },
- { SharedFontType.TraditionalChinese, GetData("FontChineseTraditional") },
- { SharedFontType.Korean, GetData("FontKorean") },
- { SharedFontType.NintendoEx, GetData("FontNintendoExtended") }
- };
- int FontMemoryUsage = 0;
- foreach (byte[] data in FontData.Values)
- {
- FontMemoryUsage += data.Length;
- FontMemoryUsage += 0x8;
- }
- if (FontMemoryUsage > SharedMemorySize)
- {
- throw new InvalidSystemResourceException($"The sum of all fonts size exceed the shared memory size. Please make sure that the fonts don't exceed {SharedMemorySize} bytes in total. (actual size: {FontMemoryUsage} bytes)");
- }
- LoadedFonts = new uint[FontData.Count];
- }
- public byte[] GetData(string FontName)
- {
- string FontFilePath = Path.Combine(FontsPath, $"{FontName}.ttf");
- if (File.Exists(FontFilePath))
- {
- return File.ReadAllBytes(FontFilePath);
- }
- else
- {
- throw new InvalidSystemResourceException($"Font \"{FontName}.ttf\" not found. Please provide it in \"{FontsPath}\".");
- }
- }
- public void MapFont(SharedFontType FontType, AMemory Memory, long Position)
- {
- uint SharedMemoryAddressOffset = GetSharedMemoryAddressOffset(FontType);
- // TODO: find what are the 8 bytes before the font
- Memory.WriteUInt64(Position + SharedMemoryAddressOffset - 8, 0);
- Memory.WriteBytes(Position + SharedMemoryAddressOffset, FontData[FontType]);
- }
- public void PropagateNewMapFont(SharedFontType Type)
- {
- lock (ShMemLock)
- {
- foreach ((AMemory Memory, long Position, long Size) in ShMemPositions)
- {
- AMemoryMapInfo MemoryInfo = Memory.Manager.GetMapInfo(Position);
- if (MemoryInfo == null)
- {
- throw new VmmPageFaultException(Position);
- }
- // The memory is read only, we need to changes that to add the new font
- AMemoryPerm originalPerms = MemoryInfo.Perm;
- Memory.Manager.Reprotect(Position, Size, AMemoryPerm.RW);
- MapFont(Type, Memory, Position);
- Memory.Manager.Reprotect(Position, Size, originalPerms);
- }
- }
- }
- internal void ShMemMap(object sender, EventArgs e)
- {
- HSharedMem SharedMem = (HSharedMem)sender;
- lock (ShMemLock)
- {
- ShMemPositions = SharedMem.GetVirtualPositions();
- (AMemory Memory, long Position, long Size) = ShMemPositions[ShMemPositions.Length - 1];
- for (int Type = 0; Type < LoadedFonts.Length; Type++)
- {
- if (LoadedFonts[(int)Type] == 1)
- {
- MapFont((SharedFontType)Type, Memory, Position);
- }
- }
- }
- }
- internal void ShMemUnmap(object sender, EventArgs e)
- {
- HSharedMem SharedMem = (HSharedMem)sender;
- lock (ShMemLock)
- {
- ShMemPositions = SharedMem.GetVirtualPositions();
- }
- }
- public void Load(SharedFontType FontType)
- {
- if (LoadedFonts[(int)FontType] == 0)
- {
- PropagateNewMapFont(FontType);
- }
- LoadedFonts[(int)FontType] = 1;
- }
- public uint GetLoadState(SharedFontType FontType)
- {
- if (LoadedFonts[(int)FontType] != 1)
- {
- // Some games don't request a load, so we need to load it here.
- Load(FontType);
- return 0;
- }
- return LoadedFonts[(int)FontType];
- }
- public uint GetFontSize(SharedFontType FontType)
- {
- return (uint)FontData[FontType].Length;
- }
- public uint GetSharedMemoryAddressOffset(SharedFontType FontType)
- {
- uint Pos = 0x8;
- for (SharedFontType Type = SharedFontType.JapanUsEurope; Type < FontType; Type++)
- {
- Pos += GetFontSize(Type);
- Pos += 0x8;
- }
- return Pos;
- }
- public int Count => FontData.Count;
- }
- }
|