private T ReadObjectFromSharedMemory <T>(ulong offset, ulong padding) where T : unmanaged { T result; uint index; uint possiblyNewIndex; do { index = _timeSharedMemoryStorage.GetRef <uint>(offset); ulong objectOffset = offset + 4 + padding + (ulong)((index & 1) * Unsafe.SizeOf <T>()); result = _timeSharedMemoryStorage.GetRef <T>(objectOffset); Thread.MemoryBarrier(); possiblyNewIndex = _device.Memory.Read <uint>(offset); } while (index != possiblyNewIndex); return(result); }
public void EnsureInitialized(ContentManager contentManager) { if (_fontData == null) { _storage.ZeroFill(); uint fontOffset = 0; FontInfo CreateFont(string name) { if (contentManager.TryGetFontTitle(name, out ulong fontTitle) && contentManager.TryGetFontFilename(name, out string fontFilename)) { string contentPath = contentManager.GetInstalledContentPath(fontTitle, StorageId.BuiltInSystem, NcaContentType.Data); string fontPath = _device.FileSystem.SwitchPathToSystemPath(contentPath); if (!string.IsNullOrWhiteSpace(fontPath)) { byte[] data; using (IStorage ncaFileStream = new LocalStorage(fontPath, FileAccess.Read, FileMode.Open)) { Nca nca = new Nca(_device.System.KeySet, ncaFileStream); IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel); using var fontFile = new UniqueRef <IFile>(); romfs.OpenFile(ref fontFile.Ref(), ("/" + fontFilename).ToU8Span(), OpenMode.Read).ThrowIfFailure(); data = DecryptFont(fontFile.Get.AsStream()); } FontInfo info = new FontInfo((int)fontOffset, data.Length); WriteMagicAndSize(fontOffset, data.Length); fontOffset += 8; uint start = fontOffset; for (; fontOffset - start < data.Length; fontOffset++) { _storage.GetRef <byte>(fontOffset) = data[fontOffset - start]; } return(info); } else { if (!contentManager.TryGetSystemTitlesName(fontTitle, out string titleName)) { titleName = "Unknown"; } throw new InvalidSystemResourceException($"{titleName} ({fontTitle:x8}) system title not found! This font will not work, provide the system archive to fix this error. (See https://github.com/Ryujinx/Ryujinx#requirements for more information)"); } } else { throw new ArgumentException($"Unknown font \"{name}\"!"); } } _fontData = new Dictionary <SharedFontType, FontInfo> { { SharedFontType.JapanUsEurope, CreateFont("FontStandard") }, { SharedFontType.SimplifiedChinese, CreateFont("FontChineseSimplified") }, { SharedFontType.SimplifiedChineseEx, CreateFont("FontExtendedChineseSimplified") }, { SharedFontType.TraditionalChinese, CreateFont("FontChineseTraditional") }, { SharedFontType.Korean, CreateFont("FontKorean") }, { SharedFontType.NintendoEx, CreateFont("FontNintendoExtended") } }; if (fontOffset > Horizon.FontSize) { throw new InvalidSystemResourceException("The sum of all fonts size exceed the shared memory size. " + $"Please make sure that the fonts don't exceed {Horizon.FontSize} bytes in total. (actual size: {fontOffset} bytes)."); } } }