protected override void LoadStateBinaryInternal(BinaryReader reader) { _controllerAdapter.LoadStateBinary(reader); _nyma.SetFrontendSettingQuery(_settingsQueryDelegate); if (_disks != null) { _nyma.SetCDCallbacks(_cdTocCallback, _cdSectorCallback); } if (_frameThreadPtr != _nyma.GetFrameThreadProc()) { throw new InvalidOperationException("_frameThreadPtr mismatch"); } }
protected T DoInit <T>(GameInfo game, byte[] rom, Disc[] discs, string wbxFilename, string extension, bool deterministic, IDictionary <string, FirmwareID> firmwares = null) where T : LibNymaCore { _settingsQueryDelegate = SettingsQuery; _cdTocCallback = CDTOCCallback; _cdSectorCallback = CDSectorCallback; var filesToRemove = new List <string>(); var firmwareDelegate = new LibNymaCore.FrontendFirmwareNotify((name) => { if (firmwares != null && firmwares.TryGetValue(name, out var id)) { var data = CoreComm.CoreFileProvider.GetFirmwareOrThrow(id, "Firmware files are usually required and may stop your game from loading"); _exe.AddReadonlyFile(data, name); filesToRemove.Add(name); } else { throw new InvalidOperationException($"Core asked for firmware `{name}`, but that was not understood by the system"); } }); var t = PreInit <T>(new WaterboxOptions { Filename = wbxFilename, // WaterboxHost only saves parts of memory that have changed, so not much to be gained by making these precisely sized SbrkHeapSizeKB = 1024 * 16, SealedHeapSizeKB = 1024 * 48, InvisibleHeapSizeKB = 1024 * 48, PlainHeapSizeKB = 1024 * 48, MmapHeapSizeKB = 1024 * 48, SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }, new Delegate[] { _settingsQueryDelegate, _cdTocCallback, _cdSectorCallback, firmwareDelegate }); _nyma = t; using (_exe.EnterExit()) { _nyma.PreInit(); _nyma.SetFrontendFirmwareNotify(firmwareDelegate); var portData = GetInputPortsData(); InitAllSettingsInfo(portData); _nyma.SetFrontendSettingQuery(_settingsQueryDelegate); if (discs?.Length > 0) { _disks = discs; _diskReaders = _disks.Select(d => new DiscSectorReader(d) { Policy = _diskPolicy }).ToArray(); _nyma.SetCDCallbacks(_cdTocCallback, _cdSectorCallback); var didInit = _nyma.InitCd(_disks.Length); if (!didInit) { throw new InvalidOperationException("Core rejected the CDs!"); } } else { var fn = game.FilesystemSafeName(); _exe.AddReadonlyFile(rom, fn); var didInit = _nyma.InitRom(new LibNymaCore.InitData { // TODO: Set these as some cores need them FileNameBase = "", FileNameExt = extension.Trim('.').ToLowerInvariant(), FileNameFull = fn }); if (!didInit) { throw new InvalidOperationException("Core rejected the rom!"); } _exe.RemoveReadonlyFile(fn); } foreach (var s in filesToRemove) { _exe.RemoveReadonlyFile(s); } // any later attempts to request a firmware will crash _nyma.SetFrontendFirmwareNotify(null); var info = *_nyma.GetSystemInfo(); _videoBuffer = new int[Math.Max(info.MaxWidth * info.MaxHeight, info.LcmWidth * info.LcmHeight)]; BufferWidth = info.NominalWidth; BufferHeight = info.NominalHeight; _mdfnNominalWidth = info.NominalWidth; _mdfnNominalHeight = info.NominalHeight; switch (info.VideoSystem) { // TODO: There seriously isn't any region besides these? case LibNymaCore.VideoSystem.PAL: case LibNymaCore.VideoSystem.SECAM: Region = DisplayType.PAL; break; case LibNymaCore.VideoSystem.PAL_M: Region = DisplayType.Dendy; // sort of... break; default: Region = DisplayType.NTSC; break; } VsyncNumerator = info.FpsFixed; VsyncDenominator = 1 << 24; _soundBuffer = new short[22050 * 2]; InitControls(portData, discs?.Length > 0, ref info); PostInit(); SettingsInfo.LayerNames = GetLayerData(); _settings.Normalize(SettingsInfo); _syncSettings.Normalize(SettingsInfo); _nyma.SetFrontendSettingQuery(_settingsQueryDelegate); if (_disks != null) { _nyma.SetCDCallbacks(_cdTocCallback, _cdSectorCallback); } PutSettings(_settings); DateTime RtcStart = DateTime.Parse("2010-01-01"); try { RtcStart = DateTime.Parse(SettingsQuery("nyma.rtcinitialtime")); } catch { Console.Error.WriteLine($"Couldn't parse DateTime \"{SettingsQuery("nyma.rtcinitialtime")}\""); } // Don't optimistically set deterministic, as some cores like faust can change this DeterministicEmulation = deterministic; // || SettingsQuery("nyma.rtcrealtime") == "0"; InitializeRtc(RtcStart); _frameThreadPtr = _nyma.GetFrameThreadProc(); if (_frameThreadPtr != IntPtr.Zero) { // This will probably be fine, right? TODO: Revisit // if (deterministic) // throw new InvalidOperationException("Internal error: Core set a frame thread proc in deterministic mode"); Console.WriteLine($"Setting up waterbox thread for {_frameThreadPtr}"); _frameThreadStart = CallingConventionAdapters.GetWaterboxUnsafeUnwrapped().GetDelegateForFunctionPointer <Action>(_frameThreadPtr); } } return(t); }
protected T DoInit <T>(GameInfo game, byte[] rom, Disc[] discs, string wbxFilename, string extension, bool deterministic, ICollection <KeyValuePair <string, byte[]> > firmwares = null) where T : LibNymaCore { var t = PreInit <T>(new WaterboxOptions { Filename = wbxFilename, // MemoryBlock understands reserve vs commit semantics, so nothing to be gained by making these precisely sized SbrkHeapSizeKB = 1024 * 16, SealedHeapSizeKB = 1024 * 48, InvisibleHeapSizeKB = 1024 * 48, PlainHeapSizeKB = 1024 * 48, MmapHeapSizeKB = 1024 * 48, SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }); _nyma = t; _settingsQueryDelegate = new LibNymaCore.FrontendSettingQuery(SettingsQuery); using (_exe.EnterExit()) { _nyma.PreInit(); var portData = GetInputPortsData(); InitSyncSettingsInfo(portData); _nyma.SetFrontendSettingQuery(_settingsQueryDelegate); if (firmwares != null) { foreach (var kvp in firmwares) { _exe.AddReadonlyFile(kvp.Value, kvp.Key); } } if (discs?.Length > 0) { _disks = discs; _diskReaders = _disks.Select(d => new DiscSectorReader(d) { Policy = _diskPolicy }).ToArray(); _cdTocCallback = CDTOCCallback; _cdSectorCallback = CDSectorCallback; _nyma.SetCDCallbacks(_cdTocCallback, _cdSectorCallback); var didInit = _nyma.InitCd(_disks.Length); if (!didInit) { throw new InvalidOperationException("Core rejected the CDs!"); } } else { var fn = game.FilesystemSafeName(); _exe.AddReadonlyFile(rom, fn); var didInit = _nyma.InitRom(new LibNymaCore.InitData { // TODO: Set these as some cores need them FileNameBase = "", FileNameExt = extension.Trim('.').ToLowerInvariant(), FileNameFull = fn }); if (!didInit) { throw new InvalidOperationException("Core rejected the rom!"); } _exe.RemoveReadonlyFile(fn); } if (firmwares != null) { foreach (var kvp in firmwares) { _exe.RemoveReadonlyFile(kvp.Key); } } var info = *_nyma.GetSystemInfo(); _videoBuffer = new int[info.MaxWidth * info.MaxHeight]; BufferWidth = info.NominalWidth; BufferHeight = info.NominalHeight; switch (info.VideoSystem) { // TODO: There seriously isn't any region besides these? case LibNymaCore.VideoSystem.PAL: case LibNymaCore.VideoSystem.SECAM: Region = DisplayType.PAL; break; case LibNymaCore.VideoSystem.PAL_M: Region = DisplayType.Dendy; // sort of... break; default: Region = DisplayType.NTSC; break; } VsyncNumerator = info.FpsFixed; VsyncDenominator = 1 << 24; _soundBuffer = new short[22050 * 2]; InitControls(portData); _nyma.SetFrontendSettingQuery(null); if (_disks != null) { _nyma.SetCDCallbacks(null, null); } PostInit(); SettingsInfo.LayerNames = GetLayerData(); _nyma.SetFrontendSettingQuery(_settingsQueryDelegate); if (_disks != null) { _nyma.SetCDCallbacks(_cdTocCallback, _cdSectorCallback); } PutSettings(_settings); DateTime RtcStart = DateTime.Parse("2010-01-01"); try { RtcStart = DateTime.Parse(SettingsQuery("nyma.rtcinitialtime")); } catch { Console.Error.WriteLine($"Couldn't parse DateTime \"{SettingsQuery("nyma.rtcinitialtime")}\""); } // Don't optimistically set deterministic, as some cores like faust can change this DeterministicEmulation = deterministic; // || SettingsQuery("nyma.rtcrealtime") == "0"; InitializeRtc(RtcStart); _frameThreadPtr = _nyma.GetFrameThreadProc(); if (_frameThreadPtr != IntPtr.Zero) { if (deterministic) { throw new InvalidOperationException("Internal error: Core set a frame thread proc in deterministic mode"); } Console.WriteLine($"Setting up waterbox thread for {_frameThreadPtr}"); _frameThreadStart = CallingConventionAdapters.Waterbox.GetDelegateForFunctionPointer <Action>(_frameThreadPtr); } } return(t); }