public TIC80(CoreLoadParameters <TIC80Settings, object> lp) : base(lp.Comm, new Configuration { DefaultWidth = 240, DefaultHeight = 136, MaxWidth = 256, MaxHeight = 144, MaxSamples = 1024, DefaultFpsNumerator = 60, DefaultFpsDenominator = 1, SystemId = VSystemID.Raw.TIC80, }) { _settings = lp.Settings ?? new(); if (!_settings.Crop) { BufferWidth = 256; BufferHeight = 144; } _core = PreInit <LibTIC80>(new WaterboxOptions { Filename = "tic80.wbx", SbrkHeapSizeKB = 2 * 1024, SealedHeapSizeKB = 4, InvisibleHeapSizeKB = 4, PlainHeapSizeKB = 4, MmapHeapSizeKB = 64 * 1024, SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }); var rom = lp.Roms[0].FileData; if (!_core.Init(rom, rom.Length)) { throw new InvalidOperationException("Init returned false!"); } PostInit(); }
public GGHawkLink(CoreLoadParameters <GGLinkSettings, GGLinkSyncSettings> lp) { if (lp.Roms.Count != 2) { throw new InvalidOperationException("Wrong number of roms"); } var ser = new BasicServiceProvider(this); linkSettings = (GGLinkSettings)lp.Settings ?? new GGLinkSettings(); linkSyncSettings = (GGLinkSyncSettings)lp.SyncSettings ?? new GGLinkSyncSettings(); _controllerDeck = new GGHawkLinkControllerDeck(GGHawkLinkControllerDeck.DefaultControllerName, GGHawkLinkControllerDeck.DefaultControllerName); var temp_set_L = new SMS.SmsSettings(); var temp_set_R = new SMS.SmsSettings(); var temp_sync_L = new SMS.SmsSyncSettings(); var temp_sync_R = new SMS.SmsSyncSettings(); L = new SMS(lp.Comm, lp.Roms[0].Game, lp.Roms[0].RomData, temp_set_L, temp_sync_L); R = new SMS(lp.Comm, lp.Roms[1].Game, lp.Roms[1].RomData, temp_set_R, temp_sync_R); ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(this); _tracer = new TraceBuffer { Header = L.Cpu.TraceHeader }; ser.Register(_tracer); ServiceProvider = ser; SetupMemoryDomains(); HardReset(); L.stand_alone = false; R.stand_alone = false; _lStates = L.ServiceProvider.GetService <IStatable>(); _rStates = R.ServiceProvider.GetService <IStatable>(); }
public GambatteLink(CoreLoadParameters <GambatteLink.GambatteLinkSettings, GambatteLink.GambatteLinkSyncSettings> lp) { if (lp.Roms.Count != 2) { throw new InvalidOperationException("Wrong number of roms"); } ServiceProvider = new BasicServiceProvider(this); GambatteLinkSettings linkSettings = (GambatteLinkSettings)lp.Settings ?? new GambatteLinkSettings(); GambatteLinkSyncSettings linkSyncSettings = (GambatteLinkSyncSettings)lp.SyncSettings ?? new GambatteLinkSyncSettings(); L = new Gameboy(lp.Comm, lp.Roms[0].Game, lp.Roms[0].RomData, linkSettings.L, linkSyncSettings.L, lp.DeterministicEmulationRequested); R = new Gameboy(lp.Comm, lp.Roms[1].Game, lp.Roms[1].RomData, linkSettings.R, linkSyncSettings.R, lp.DeterministicEmulationRequested); // connect link cable LibGambatte.gambatte_linkstatus(L.GambatteState, 259); LibGambatte.gambatte_linkstatus(R.GambatteState, 259); L.ConnectInputCallbackSystem(_inputCallbacks); R.ConnectInputCallbackSystem(_inputCallbacks); L.ConnectMemoryCallbackSystem(_memorycallbacks); R.ConnectMemoryCallbackSystem(_memorycallbacks); RomDetails = "LEFT:\r\n" + L.RomDetails + "RIGHT:\r\n" + R.RomDetails; LinkConnected = true; Frame = 0; LagCount = 0; IsLagFrame = false; _blipLeft = new BlipBuffer(1024); _blipRight = new BlipBuffer(1024); _blipLeft.SetRates(2097152 * 2, 44100); _blipRight.SetRates(2097152 * 2, 44100); SetMemoryDomains(); }
public PCEngine(CoreLoadParameters <PCESettings, PCESyncSettings> lp) { if (lp.Discs.Count == 1 && lp.Roms.Count == 0) { SystemId = "PCECD"; Type = NecSystemType.TurboCD; this.disc = lp.Discs[0].DiscData; Settings = (PCESettings)lp.Settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)lp.SyncSettings ?? new PCESyncSettings(); byte[] rom = lp.Comm.CoreFileProvider.GetFirmwareWithGameInfo("PCECD", "Bios", true, out var biosInfo, "PCE-CD System Card not found. Please check the BIOS settings in Config->Firmwares."); if (biosInfo.Status == RomStatus.BadDump) { lp.Comm.ShowMessage( "The PCE-CD System Card you have selected is known to be a bad dump. This may cause problems playing PCE-CD games.\n\n" + "It is recommended that you find a good dump of the system card. Sorry to be the bearer of bad news!"); } else if (biosInfo.NotInDatabase) { lp.Comm.ShowMessage( "The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom."); } else if (biosInfo["BIOS"] == false) { // zeromus says: someone please write a note about how this could possibly happen. // it seems like this is a relic of using gameDB for storing whether something is a bios? firmwareDB should be handling it now. lp.Comm.ShowMessage( "The PCE-CD System Card you have selected is not a BIOS image. You may have selected the wrong rom. FYI-Please report this to developers, I don't think this error message should happen."); } if (biosInfo["SuperSysCard"]) { lp.Game.AddOption("SuperSysCard", ""); } if (lp.Game["NeedSuperSysCard"] && lp.Game["SuperSysCard"] == false) { lp.Comm.ShowMessage( "This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in the firmware configuration."); throw new Exception(); } lp.Game.FirmwareHash = rom.HashSHA1(); Init(lp.Game, rom); // the default RomStatusDetails don't do anything with Disc RomDetails = $"{lp.Game.Name}\r\nDisk partial hash:{new DiscHasher(disc).OldHash()}"; _controllerDeck = new PceControllerDeck( _syncSettings.Port1, _syncSettings.Port2, _syncSettings.Port3, _syncSettings.Port4, _syncSettings.Port5); } else if (lp.Discs.Count == 0 && lp.Roms.Count == 1) { switch (lp.Game.System) { default: case "PCE": SystemId = "PCE"; Type = NecSystemType.TurboGrafx; break; case "SGX": SystemId = "SGX"; Type = NecSystemType.SuperGrafx; break; } Settings = (PCESettings)lp.Settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)lp.SyncSettings ?? new PCESyncSettings(); Init(lp.Game, lp.Roms[0].RomData); _controllerDeck = new PceControllerDeck( _syncSettings.Port1, _syncSettings.Port2, _syncSettings.Port3, _syncSettings.Port4, _syncSettings.Port5); } else { throw new InvalidOperationException("PCEHawk can only load exactly one CD or exactly one ROM"); } }
public GBHawkLink4x(CoreLoadParameters <GBLink4xSettings, GBLink4xSyncSettings> lp) { if (lp.Roms.Count != 4) { throw new InvalidOperationException("Wrong number of roms"); } var ser = new BasicServiceProvider(this); Link4xSettings = (GBLink4xSettings)lp.Settings ?? new GBLink4xSettings(); Link4xSyncSettings = (GBLink4xSyncSettings)lp.SyncSettings ?? new GBLink4xSyncSettings(); _controllerDeck = new GBHawkLink4xControllerDeck(GBHawkLink4xControllerDeck.DefaultControllerName, GBHawkLink4xControllerDeck.DefaultControllerName, GBHawkLink4xControllerDeck.DefaultControllerName, GBHawkLink4xControllerDeck.DefaultControllerName); var tempSetA = new GBHawk.GBHawk.GBSettings(); var tempSetB = new GBHawk.GBHawk.GBSettings(); var tempSetC = new GBHawk.GBHawk.GBSettings(); var tempSetD = new GBHawk.GBHawk.GBSettings(); var tempSyncA = new GBHawk.GBHawk.GBSyncSettings(); var tempSyncB = new GBHawk.GBHawk.GBSyncSettings(); var tempSyncC = new GBHawk.GBHawk.GBSyncSettings(); var tempSyncD = new GBHawk.GBHawk.GBSyncSettings(); tempSyncA.ConsoleMode = Link4xSyncSettings.ConsoleMode_A; tempSyncB.ConsoleMode = Link4xSyncSettings.ConsoleMode_B; tempSyncC.ConsoleMode = Link4xSyncSettings.ConsoleMode_C; tempSyncD.ConsoleMode = Link4xSyncSettings.ConsoleMode_D; tempSyncA.GBACGB = Link4xSyncSettings.GBACGB; tempSyncB.GBACGB = Link4xSyncSettings.GBACGB; tempSyncC.GBACGB = Link4xSyncSettings.GBACGB; tempSyncD.GBACGB = Link4xSyncSettings.GBACGB; tempSyncA.RTCInitialTime = Link4xSyncSettings.RTCInitialTime_A; tempSyncB.RTCInitialTime = Link4xSyncSettings.RTCInitialTime_B; tempSyncC.RTCInitialTime = Link4xSyncSettings.RTCInitialTime_C; tempSyncD.RTCInitialTime = Link4xSyncSettings.RTCInitialTime_D; tempSyncA.RTCOffset = Link4xSyncSettings.RTCOffset_A; tempSyncB.RTCOffset = Link4xSyncSettings.RTCOffset_B; tempSyncC.RTCOffset = Link4xSyncSettings.RTCOffset_C; tempSyncD.RTCOffset = Link4xSyncSettings.RTCOffset_D; A = new GBHawk.GBHawk(lp.Comm, lp.Roms[0].Game, lp.Roms[0].RomData, tempSetA, tempSyncA); B = new GBHawk.GBHawk(lp.Comm, lp.Roms[1].Game, lp.Roms[1].RomData, tempSetB, tempSyncB); C = new GBHawk.GBHawk(lp.Comm, lp.Roms[2].Game, lp.Roms[2].RomData, tempSetC, tempSyncC); D = new GBHawk.GBHawk(lp.Comm, lp.Roms[3].Game, lp.Roms[3].RomData, tempSetD, tempSyncD); ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(this); _tracer = new TraceBuffer { Header = A.cpu.TraceHeader }; ser.Register(_tracer); ServiceProvider = ser; _aStates = A.ServiceProvider.GetService <IStatable>(); _bStates = B.ServiceProvider.GetService <IStatable>(); _cStates = C.ServiceProvider.GetService <IStatable>(); _dStates = D.ServiceProvider.GetService <IStatable>(); SetupMemoryDomains(); HardReset(); }
public GPGX(CoreLoadParameters <GPGXSettings, GPGXSyncSettings> lp) { LoadCallback = new LibGPGX.load_archive_cb(load_archive); _inputCallback = new LibGPGX.input_cb(input_callback); InitMemCallbacks(); // ExecCallback, ReadCallback, WriteCallback CDCallback = new LibGPGX.CDCallback(CDCallbackProc); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally (autodetect romtype, etc) string romextension = "GEN"; // three or six button? // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds //hack, don't use if (lp.Roms.FirstOrDefault()?.RomData.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } _elf = new WaterboxHost(new WaterboxOptions { Path = lp.Comm.CoreFileProvider.DllPath(), Filename = "gpgx.wbx", SbrkHeapSizeKB = 512, SealedHeapSizeKB = 4 * 1024, InvisibleHeapSizeKB = 4 * 1024, PlainHeapSizeKB = 34 * 1024, MmapHeapSizeKB = 1 * 1024, SkipCoreConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }); var callingConventionAdapter = CallingConventionAdapters.MakeWaterbox(new Delegate[] { LoadCallback, _inputCallback, ExecCallback, ReadCallback, WriteCallback, CDCallback, cd_callback_handle, }, _elf); using (_elf.EnterExit()) { Core = BizInvoker.GetInvoker <LibGPGX>(_elf, _elf, callingConventionAdapter); _syncSettings = lp.SyncSettings ?? new GPGXSyncSettings(); _settings = lp.Settings ?? new GPGXSettings(); CoreComm = lp.Comm; _romfile = lp.Roms.FirstOrDefault()?.RomData; if (lp.Discs.Count > 0) { _cds = lp.Discs.Select(d => d.DiscData).ToArray(); _cdReaders = _cds.Select(c => new DiscSectorReader(c)).ToArray(); Core.gpgx_set_cdd_callback(cd_callback_handle); DriveLightEnabled = true; } LibGPGX.INPUT_SYSTEM system_a = SystemForSystem(_syncSettings.ControlTypeLeft); LibGPGX.INPUT_SYSTEM system_b = SystemForSystem(_syncSettings.ControlTypeRight); var initResult = Core.gpgx_init(romextension, LoadCallback, _syncSettings.GetNativeSettings(lp.Game)); if (!initResult) { throw new Exception($"{nameof(Core.gpgx_init)}() failed"); } { int fpsnum = 60; int fpsden = 1; Core.gpgx_get_fps(ref fpsnum, ref fpsden); VsyncNumerator = fpsnum; VsyncDenominator = fpsden; Region = VsyncNumerator / VsyncDenominator > 55 ? DisplayType.NTSC : DisplayType.PAL; } // when we call Seal, ANY pointer passed from managed code must be 0. // this is so the initial state is clean // the only two pointers set so far are LoadCallback, which the core zeroed itself, // and CdCallback Core.gpgx_set_cdd_callback(null); _elf.Seal(); Core.gpgx_set_cdd_callback(cd_callback_handle); SetControllerDefinition(); // pull the default video size from the core UpdateVideo(); SetMemoryDomains(); Core.gpgx_set_input_callback(_inputCallback); // process the non-init settings now PutSettings(_settings); KillMemCallbacks(); _tracer = new GPGXTraceBuffer(this, _memoryDomains, this); (ServiceProvider as BasicServiceProvider).Register <ITraceable>(_tracer); } _romfile = null; }
public ZXSpectrum( CoreLoadParameters <ZXSpectrumSettings, ZXSpectrumSyncSettings> lp) { var ser = new BasicServiceProvider(this); ServiceProvider = ser; CoreComm = lp.Comm; _gameInfo = lp.Roms.Select(r => r.Game).ToList(); _cpu = new Z80A(); _tracer = new TraceBuffer { Header = _cpu.TraceHeader }; _files = lp.Roms.Select(r => r.RomData).ToList(); var settings = lp.Settings ?? new ZXSpectrumSettings(); var syncSettings = lp.SyncSettings ?? new ZXSpectrumSyncSettings(); PutSyncSettings(lp.SyncSettings); PutSettings(lp.Settings); var joysticks = new List <JoystickType> { ((ZXSpectrumSyncSettings)syncSettings).JoystickType1, ((ZXSpectrumSyncSettings)syncSettings).JoystickType2, ((ZXSpectrumSyncSettings)syncSettings).JoystickType3 }; DeterministicEmulation = ((ZXSpectrumSyncSettings)syncSettings).DeterministicEmulation; if (lp.DeterministicEmulationRequested) { if (!DeterministicEmulation) { CoreComm.Notify("Forcing Deterministic Emulation"); } DeterministicEmulation = lp.DeterministicEmulationRequested; } MachineType = SyncSettings.MachineType; switch (MachineType) { case MachineType.ZXSpectrum16: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.ZXSpectrum16, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; case MachineType.ZXSpectrum48: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.ZXSpectrum48, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; case MachineType.ZXSpectrum128: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.ZXSpectrum128, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; case MachineType.ZXSpectrum128Plus2: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.ZXSpectrum128Plus2, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; case MachineType.ZXSpectrum128Plus2a: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.ZXSpectrum128Plus2a, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; case MachineType.ZXSpectrum128Plus3: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.ZXSpectrum128Plus3, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; case MachineType.Pentagon128: ControllerDefinition = ZXSpectrumControllerDefinition; Init(MachineType.Pentagon128, SyncSettings.BorderType, SyncSettings.TapeLoadSpeed, _files, joysticks); break; default: throw new InvalidOperationException("Machine not yet emulated"); } _cpu.MemoryCallbacks = MemoryCallbacks; HardReset = _machine.HardReset; SoftReset = _machine.SoftReset; _cpu.FetchMemory = _machine.ReadMemory; _cpu.ReadMemory = _machine.ReadMemory; _cpu.WriteMemory = _machine.WriteMemory; _cpu.ReadHardware = _machine.ReadPort; _cpu.WriteHardware = _machine.WritePort; _cpu.FetchDB = _machine.PushBus; _cpu.OnExecFetch = _machine.CPUMon.OnExecFetch; ser.Register <ITraceable>(_tracer); ser.Register <IDisassemblable>(_cpu); ser.Register <IVideoProvider>(_machine.ULADevice); // initialize sound mixer and attach the various ISoundProvider devices SoundMixer = new SyncSoundMixer(targetSampleCount: 882); SoundMixer.PinSource(_machine.BuzzerDevice, "System Beeper", (int)(32767 / 10)); SoundMixer.PinSource(_machine.TapeBuzzer, "Tape Audio", (int)(32767 / 10)); if (_machine.AYDevice != null) { SoundMixer.PinSource(_machine.AYDevice, "AY-3-3912"); } // set audio device settings if (_machine.AYDevice != null && _machine.AYDevice.GetType() == typeof(AY38912)) { ((AY38912)_machine.AYDevice).PanningConfiguration = ((ZXSpectrumSettings)settings).AYPanConfig; _machine.AYDevice.Volume = ((ZXSpectrumSettings)settings).AYVolume; } if (_machine.BuzzerDevice != null) { _machine.BuzzerDevice.Volume = ((ZXSpectrumSettings)settings).EarVolume; } if (_machine.TapeBuzzer != null) { _machine.TapeBuzzer.Volume = ((ZXSpectrumSettings)settings).TapeVolume; } DCFilter dc = new DCFilter(SoundMixer, 512); ser.Register <ISoundProvider>(dc); ser.Register <IStatable>(new StateSerializer(SyncState)); HardReset(); SetupMemoryDomains(); }
protected T DoInit <T>( CoreLoadParameters <NymaSettings, NymaSyncSettings> lp, string wbxFilename, IDictionary <string, (string SystemID, string FirmwareID)> firmwares = null
public AmstradCPC(CoreLoadParameters <AmstradCPCSettings, AmstradCPCSyncSettings> lp) { var ser = new BasicServiceProvider(this); ServiceProvider = ser; CoreComm = lp.Comm; _gameInfo = lp.Roms.Select(r => r.Game).ToList(); _cpu = new Z80A(); _tracer = new TraceBuffer { Header = _cpu.TraceHeader }; _files = lp.Roms.Select(r => r.RomData).ToList(); var settings = lp.Settings ?? new AmstradCPCSettings(); var syncSettings = lp.SyncSettings ?? new AmstradCPCSyncSettings(); PutSyncSettings((AmstradCPCSyncSettings)syncSettings); PutSettings((AmstradCPCSettings)settings); DeterministicEmulation = ((AmstradCPCSyncSettings)syncSettings).DeterministicEmulation; switch (SyncSettings.MachineType) { case MachineType.CPC464: ControllerDefinition = AmstradCPCControllerDefinition; Init(MachineType.CPC464, _files, ((AmstradCPCSyncSettings)syncSettings).AutoStartStopTape, ((AmstradCPCSyncSettings)syncSettings).BorderType); break; case MachineType.CPC6128: ControllerDefinition = AmstradCPCControllerDefinition; Init(MachineType.CPC6128, _files, ((AmstradCPCSyncSettings)syncSettings).AutoStartStopTape, ((AmstradCPCSyncSettings)syncSettings).BorderType); break; default: throw new InvalidOperationException("Machine not yet emulated"); } _cpu.MemoryCallbacks = MemoryCallbacks; HardReset = _machine.HardReset; SoftReset = _machine.SoftReset; _cpu.FetchMemory = _machine.ReadMemory; _cpu.ReadMemory = _machine.ReadMemory; _cpu.WriteMemory = _machine.WriteMemory; _cpu.ReadHardware = _machine.ReadPort; _cpu.WriteHardware = _machine.WritePort; _cpu.FetchDB = _machine.PushBus; _cpu.IRQACKCallback = _machine.GateArray.IORQA; //_cpu.OnExecFetch = _machine.CPUMon.OnExecFetch; ser.Register <ITraceable>(_tracer); ser.Register <IDisassemblable>(_cpu); ser.Register <IVideoProvider>(_machine.GateArray); ser.Register <IStatable>(new StateSerializer(SyncState)); // initialize sound mixer and attach the various ISoundProvider devices SoundMixer = new SoundProviderMixer((int)(32767 / 10), "Tape Audio", (ISoundProvider)_machine.TapeBuzzer); if (_machine.AYDevice != null) { SoundMixer.AddSource(_machine.AYDevice, "AY-3-3912"); } // set audio device settings if (_machine.AYDevice != null && _machine.AYDevice.GetType() == typeof(AY38912)) { ((AY38912)_machine.AYDevice).PanningConfiguration = ((AmstradCPCSettings)settings).AYPanConfig; _machine.AYDevice.Volume = ((AmstradCPCSettings)settings).AYVolume; } if (_machine.TapeBuzzer != null) { ((Beeper)_machine.TapeBuzzer).Volume = ((AmstradCPCSettings)settings).TapeVolume; } ser.Register <ISoundProvider>(SoundMixer); HardReset(); SetupMemoryDomains(); }
public NDS(CoreLoadParameters <NDSSettings, NDSSyncSettings> lp) : base(lp.Comm, new Configuration { DefaultWidth = 256, DefaultHeight = 384, MaxWidth = 256, MaxHeight = 384, MaxSamples = 1024, DefaultFpsNumerator = 33513982, DefaultFpsDenominator = 560190, SystemId = VSystemID.Raw.NDS, }) { var roms = lp.Roms.Select(r => r.RomData).ToList(); if (roms.Count > 3) { throw new InvalidOperationException("Wrong number of ROMs!"); } bool gbacartpresent = roms.Count > 1; bool gbasrampresent = roms.Count == 3; _tracecb = MakeTrace; _core = PreInit <LibMelonDS>(new WaterboxOptions { Filename = "melonDS.wbx", SbrkHeapSizeKB = 2 * 1024, SealedHeapSizeKB = 4, InvisibleHeapSizeKB = 4, PlainHeapSizeKB = 4, MmapHeapSizeKB = 1024 * 1024, SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }, new Delegate[] { _tracecb }); _syncSettings = lp.SyncSettings ?? new NDSSyncSettings(); _settings = lp.Settings ?? new NDSSettings(); var bios7 = _syncSettings.UseRealBIOS ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7")) : null; var bios9 = _syncSettings.UseRealBIOS ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9")) : null; var fw = CoreComm.CoreFileProvider.GetFirmware(new("NDS", "firmware")); bool skipfw = _syncSettings.SkipFirmware || !_syncSettings.UseRealBIOS || fw == null; LibMelonDS.LoadFlags flags = LibMelonDS.LoadFlags.NONE; if (_syncSettings.UseRealBIOS) { flags |= LibMelonDS.LoadFlags.USE_REAL_BIOS; } if (skipfw) { flags |= LibMelonDS.LoadFlags.SKIP_FIRMWARE; } if (gbacartpresent) { flags |= LibMelonDS.LoadFlags.GBA_CART_PRESENT; } if (_settings.AccurateAudioBitrate) { flags |= LibMelonDS.LoadFlags.ACCURATE_AUDIO_BITRATE; } if (_syncSettings.FirmwareOverride || lp.DeterministicEmulationRequested) { flags |= LibMelonDS.LoadFlags.FIRMWARE_OVERRIDE; } var fwSettings = new LibMelonDS.FirmwareSettings(); var name = Encoding.UTF8.GetBytes(_syncSettings.FirmwareUsername); fwSettings.FirmwareUsernameLength = name.Length; fwSettings.FirmwareLanguage = _syncSettings.FirmwareLanguage; if (_syncSettings.FirmwareStartUp == NDSSyncSettings.StartUp.AutoBoot) { fwSettings.FirmwareLanguage |= (NDSSyncSettings.Language) 0x40; } fwSettings.FirmwareBirthdayMonth = _syncSettings.FirmwareBirthdayMonth; fwSettings.FirmwareBirthdayDay = _syncSettings.FirmwareBirthdayDay; fwSettings.FirmwareFavouriteColour = _syncSettings.FirmwareFavouriteColour; var message = _syncSettings.FirmwareMessage.Length != 0 ? Encoding.UTF8.GetBytes(_syncSettings.FirmwareMessage) : new byte[1] { 0 }; fwSettings.FirmwareMessageLength = message.Length; _exe.AddReadonlyFile(roms[0], "game.rom"); if (gbacartpresent) { _exe.AddReadonlyFile(roms[1], "gba.rom"); if (gbasrampresent) { _exe.AddReadonlyFile(roms[2], "gba.ram"); } } if (_syncSettings.UseRealBIOS) { _exe.AddReadonlyFile(bios7, "bios7.rom"); _exe.AddReadonlyFile(bios9, "bios9.rom"); } if (fw != null) { if (NDSFirmware.MaybeWarnIfBadFw(fw, CoreComm)) { if (_syncSettings.FirmwareOverride || lp.DeterministicEmulationRequested) { NDSFirmware.SanitizeFw(fw); } } _exe.AddReadonlyFile(fw, "firmware.bin"); } unsafe { fixed(byte *namePtr = &name[0], messagePtr = &message[0]) { fwSettings.FirmwareUsername = (IntPtr)namePtr; fwSettings.FirmwareMessage = (IntPtr)messagePtr; if (!_core.Init(flags, fwSettings)) { throw new InvalidOperationException("Init returned false!"); } } } _exe.RemoveReadonlyFile("game.rom"); if (gbacartpresent) { _exe.RemoveReadonlyFile("gba.rom"); if (gbasrampresent) { _exe.RemoveReadonlyFile("gba.ram"); } } if (_syncSettings.UseRealBIOS) { _exe.RemoveReadonlyFile("bios7.rom"); _exe.RemoveReadonlyFile("bios9.rom"); } if (fw != null) { _exe.RemoveReadonlyFile("firmware.bin"); } PostInit(); ((MemoryDomainList)this.AsMemoryDomains()).SystemBus = new NDSSystemBus(this.AsMemoryDomains()["ARM9 System Bus"], this.AsMemoryDomains()["ARM7 System Bus"]); DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime); InitializeRtc(_syncSettings.InitialTime); _resampler = new SpeexResampler(SpeexResampler.Quality.QUALITY_DEFAULT, 32768, 44100, 32768, 44100, null, this); _serviceProvider.Register <ISoundProvider>(_resampler); _disassembler = new NDSDisassembler(); _serviceProvider.Register <IDisassemblable>(_disassembler); const string TRACE_HEADER = "ARM9+ARM7: PC, opcode, registers (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, Cy, CpuMode)"; Tracer = new TraceBuffer(TRACE_HEADER); _serviceProvider.Register <ITraceable>(Tracer); }
public GambatteLink(CoreLoadParameters <GambatteLinkSettings, GambatteLinkSyncSettings> lp) { if (lp.Roms.Count < MIN_PLAYERS || lp.Roms.Count > MAX_PLAYERS) { throw new InvalidOperationException("Wrong number of roms"); } _numCores = lp.Roms.Count; _serviceProvider = new BasicServiceProvider(this); _settings = lp.Settings ?? new GambatteLinkSettings(); _syncSettings = lp.SyncSettings ?? new GambatteLinkSyncSettings(); _linkedCores = new Gameboy[_numCores]; _linkedConts = new SaveController[_numCores]; _linkedBlips = new BlipBuffer[_numCores]; _linkedLatches = new int[_numCores]; _linkedOverflow = new int[_numCores]; RomDetails = ""; var scopes = new string[_numCores * 7]; for (int i = 0; i < _numCores; i++) { scopes[i * 7 + 0] = $"P{i + 1} System Bus"; scopes[i * 7 + 1] = $"P{i + 1} ROM"; scopes[i * 7 + 2] = $"P{i + 1} VRAM"; scopes[i * 7 + 3] = $"P{i + 1} SRAM"; scopes[i * 7 + 4] = $"P{i + 1} WRAM"; scopes[i * 7 + 5] = $"P{i + 1} OAM"; scopes[i * 7 + 6] = $"P{i + 1} HRAM"; } _memoryCallbacks = new MemoryCallbackSystem(scopes); for (int i = 0; i < _numCores; i++) { _linkedCores[i] = new Gameboy(lp.Comm, lp.Roms[i].Game, lp.Roms[i].RomData, _settings._linkedSettings[i], _syncSettings._linkedSyncSettings[i], lp.DeterministicEmulationRequested); _linkedCores[i].ConnectInputCallbackSystem(_inputCallbacks); _linkedCores[i].ConnectMemoryCallbackSystem(_memoryCallbacks, i); _linkedConts[i] = new SaveController(Gameboy.CreateControllerDefinition(false, false)); _linkedBlips[i] = new BlipBuffer(1024); _linkedBlips[i].SetRates(2097152 * 2, 44100); _linkedOverflow[i] = 0; _linkedLatches[i] = 0; RomDetails += $"P{i + 1}:\r\n" + _linkedCores[i].RomDetails; } LinkConnected = true; Frame = 0; LagCount = 0; IsLagFrame = false; SoundBuffer = new short[MaxSampsPerFrame * _numCores]; FrameBuffer = CreateVideoBuffer(); VideoBuffer = CreateVideoBuffer(); GBLinkController = CreateControllerDefinition(); _linkedSaveRam = new LinkedSaveRam(_linkedCores, _numCores); _serviceProvider.Register <ISaveRam>(_linkedSaveRam); _linkedMemoryDomains = new LinkedMemoryDomains(_linkedCores, _numCores); _serviceProvider.Register <IMemoryDomains>(_linkedMemoryDomains); _linkedDebuggable = new LinkedDebuggable(_linkedCores, _numCores, _memoryCallbacks); _serviceProvider.Register <IDebuggable>(_linkedDebuggable); }
public Ares64(CoreLoadParameters <Ares64Settings, Ares64SyncSettings> lp) : base(lp.Comm, new Configuration { DefaultWidth = 640, DefaultHeight = 480, MaxWidth = 640, MaxHeight = 576, MaxSamples = 1024, DefaultFpsNumerator = 60, DefaultFpsDenominator = 1, SystemId = VSystemID.Raw.N64, }) { _settings = lp.Settings ?? new(); _syncSettings = lp.SyncSettings ?? new(); ControllerSettings = new[] { _syncSettings.P1Controller, _syncSettings.P2Controller, _syncSettings.P3Controller, _syncSettings.P4Controller, }; N64Controller = CreateControllerDefinition(ControllerSettings); _core = PreInit <LibAres64>(new WaterboxOptions { Filename = "ares64.wbx", SbrkHeapSizeKB = 2 * 1024, SealedHeapSizeKB = 4, InvisibleHeapSizeKB = 6 * 1024, PlainHeapSizeKB = 4, MmapHeapSizeKB = 512 * 1024, SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }); var rom = lp.Roms[0].RomData; Region = rom[0x3E] switch { 0x44 or 0x46 or 0x49 or 0x50 or 0x53 or 0x55 or 0x58 or 0x59 => DisplayType.PAL, _ => DisplayType.NTSC, }; var pal = Region == DisplayType.PAL; if (pal) { VsyncNumerator = 50; VsyncDenominator = 1; } LibAres64.LoadFlags loadFlags = 0; if (_syncSettings.RestrictAnalogRange) { loadFlags |= LibAres64.LoadFlags.RestrictAnalogRange; } if (pal) { loadFlags |= LibAres64.LoadFlags.Pal; } if (_settings.Deinterlacer == LibAres64.DeinterlacerType.Bob) { loadFlags |= LibAres64.LoadFlags.BobDeinterlace; } var pif = Util.DecompressGzipFile(new MemoryStream(pal ? Resources.PIF_PAL_ROM.Value : Resources.PIF_NTSC_ROM.Value)); var gbRoms = new byte[][] { null, null, null, null }; var numGbRoms = lp.Roms.Count - 1; for (int i = 0; i < numGbRoms; i++) { gbRoms[i] = lp.Roms[i + 1].RomData; } unsafe { fixed(byte *pifPtr = pif, romPtr = rom, gb1RomPtr = gbRoms[0], gb2RomPtr = gbRoms[1], gb3RomPtr = gbRoms[2], gb4RomPtr = gbRoms[3]) { var loadData = new LibAres64.LoadData() { PifData = (IntPtr)pifPtr, PifLen = pif.Length, RomData = (IntPtr)romPtr, RomLen = rom.Length, Gb1RomData = (IntPtr)gb1RomPtr, Gb1RomLen = gbRoms[0]?.Length ?? 0, Gb2RomData = (IntPtr)gb2RomPtr, Gb2RomLen = gbRoms[1]?.Length ?? 0, Gb3RomData = (IntPtr)gb3RomPtr, Gb3RomLen = gbRoms[2]?.Length ?? 0, Gb4RomData = (IntPtr)gb4RomPtr, Gb4RomLen = gbRoms[3]?.Length ?? 0, }; if (!_core.Init(ref loadData, ControllerSettings, loadFlags)) { throw new InvalidOperationException("Init returned false!"); } } } PostInit(); DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime); InitializeRtc(_syncSettings.InitialTime); }
public BsnesCore(CoreLoadParameters <SnesSettings, SnesSyncSettings> loadParameters) { var ser = new BasicServiceProvider(this); ServiceProvider = ser; this._romPath = Path.Combine(loadParameters.Roms[0].RomDirectory, loadParameters.Game.Name); CoreComm = loadParameters.Comm; _settings = loadParameters.Settings ?? new SnesSettings(); _syncSettings = loadParameters.SyncSettings ?? new SnesSyncSettings(); IsSGB = loadParameters.Game.System == VSystemID.Raw.SGB; byte[] sgbRomData = null; if (IsSGB) { if ((loadParameters.Roms[0].RomData[0x143] & 0xc0) == 0xc0) { throw new CGBNotSupportedException(); } sgbRomData = _syncSettings.UseSGB2 ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("SNES", "Rom_SGB2"), "SGB2 Rom is required for SGB2 emulation.") : CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("SNES", "Rom_SGB"), "SGB1 Rom is required for SGB1 emulation."); loadParameters.Game.FirmwareHash = SHA1Checksum.ComputeDigestHex(sgbRomData); } BsnesApi.SnesCallbacks callbacks = new() { inputPollCb = snes_input_poll, noLagCb = snes_no_lag, controllerLatchCb = snes_controller_latch, videoFrameCb = snes_video_refresh, audioSampleCb = snes_audio_sample, pathRequestCb = snes_path_request, traceCb = snes_trace, readHookCb = ReadHook, writeHookCb = WriteHook, execHookCb = ExecHook, msuOpenCb = msu_open, msuSeekCb = msu_seek, msuReadCb = msu_read, msuEndCb = msu_end }; Api = new BsnesApi(CoreComm.CoreFileProvider.DllPath(), CoreComm, callbacks.AllDelegatesInMemoryOrder()); _controllers = new BsnesControllers(_syncSettings); generate_palette(); BsnesApi.SnesInitData snesInitData = new() { entropy = _syncSettings.Entropy, left_port = _syncSettings.LeftPort, right_port = _syncSettings.RightPort, hotfixes = _syncSettings.Hotfixes, fast_ppu = _syncSettings.FastPPU, fast_dsp = _syncSettings.FastDSP, fast_coprocessors = _syncSettings.FastCoprocessors, region_override = _syncSettings.RegionOverride, }; Api.core.snes_init(ref snesInitData); Api.SetCallbacks(callbacks); // start up audio resampler InitAudio(); ser.Register <ISoundProvider>(_resampler); if (IsSGB) { ser.Register <IBoardInfo>(new SGBBoardInfo()); Api.core.snes_load_cartridge_super_gameboy(sgbRomData, loadParameters.Roms[0].RomData, sgbRomData !.Length, loadParameters.Roms[0].RomData.Length); } else { Api.core.snes_load_cartridge_normal(loadParameters.Roms[0].RomData, loadParameters.Roms[0].RomData.Length); } _region = Api.core.snes_get_region(); if (_region == BsnesApi.SNES_REGION.NTSC) { // taken from bsnes source VsyncNumerator = 21477272; VsyncDenominator = 357366; } else { // http://forums.nesdev.com/viewtopic.php?t=5367&start=19 VsyncNumerator = 21281370; VsyncDenominator = 4 * 341 * 312; } SetMemoryDomains(); const string TRACE_HEADER = "65816: PC, mnemonic, operands, registers (A, X, Y, S, D, B, flags (NVMXDIZC), V, H)"; _tracer = new TraceBuffer(TRACE_HEADER); ser.Register <IDisassemblable>(new W65816_DisassemblerService()); ser.Register(_tracer); Api.Seal(); }
public NDS(CoreLoadParameters <NDSSettings, NDSSyncSettings> lp) : base(lp.Comm, new Configuration { DefaultWidth = 256, DefaultHeight = 384, MaxWidth = 256, MaxHeight = 384, MaxSamples = 1024, DefaultFpsNumerator = 33513982, DefaultFpsDenominator = 560190, SystemId = VSystemID.Raw.NDS, }) { _syncSettings = lp.SyncSettings ?? new NDSSyncSettings(); _settings = lp.Settings ?? new NDSSettings(); IsDSi = _syncSettings.UseDSi; var roms = lp.Roms.Select(r => r.RomData).ToList(); if (roms.Count > (IsDSi ? 1 : 3)) { throw new InvalidOperationException("Wrong number of ROMs!"); } IsDSiWare = IsDSi && RomIsWare(roms[0]); bool gbacartpresent = roms.Count > 1; bool gbasrampresent = roms.Count == 3; InitMemoryCallbacks(); _tracecb = MakeTrace; _threadstartcb = ThreadStartCallback; _core = PreInit <LibMelonDS>(new WaterboxOptions { Filename = "melonDS.wbx", SbrkHeapSizeKB = 2 * 1024, SealedHeapSizeKB = 4, InvisibleHeapSizeKB = 4 * 1024, PlainHeapSizeKB = 4, MmapHeapSizeKB = 1024 * 1024, SkipCoreConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = CoreComm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }, new Delegate[] { _readcb, _writecb, _execcb, _tracecb, _threadstartcb }); var bios7 = IsDSi || _syncSettings.UseRealBIOS ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7")) : null; var bios9 = IsDSi || _syncSettings.UseRealBIOS ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9")) : null; var bios7i = IsDSi ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios7i")) : null; var bios9i = IsDSi ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "bios9i")) : null; var nand = IsDSi ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "nand")) : null; var fw = IsDSi ? CoreComm.CoreFileProvider.GetFirmwareOrThrow(new("NDS", "firmwarei")) : CoreComm.CoreFileProvider.GetFirmware(new("NDS", "firmware")); var tmd = IsDSi && IsDSiWare ? GetTMDData(roms[0]) : null; bool skipfw = _syncSettings.SkipFirmware || !_syncSettings.UseRealBIOS || fw == null; LibMelonDS.LoadFlags loadFlags = LibMelonDS.LoadFlags.NONE; if (_syncSettings.UseRealBIOS || IsDSi) { loadFlags |= LibMelonDS.LoadFlags.USE_REAL_BIOS; } if (skipfw && !IsDSi) { loadFlags |= LibMelonDS.LoadFlags.SKIP_FIRMWARE; } if (gbacartpresent) { loadFlags |= LibMelonDS.LoadFlags.GBA_CART_PRESENT; } if (_syncSettings.FirmwareOverride || lp.DeterministicEmulationRequested) { loadFlags |= LibMelonDS.LoadFlags.FIRMWARE_OVERRIDE; } if (IsDSi) { loadFlags |= LibMelonDS.LoadFlags.IS_DSI; } if (IsDSi && IsDSiWare) { loadFlags |= LibMelonDS.LoadFlags.LOAD_DSIWARE; } if (_syncSettings.ThreadedRendering) { loadFlags |= LibMelonDS.LoadFlags.THREADED_RENDERING; } var fwSettings = new LibMelonDS.FirmwareSettings(); var name = Encoding.UTF8.GetBytes(_syncSettings.FirmwareUsername); fwSettings.FirmwareUsernameLength = name.Length; fwSettings.FirmwareLanguage = _syncSettings.FirmwareLanguage; if (!IsDSi && _syncSettings.FirmwareStartUp == NDSSyncSettings.StartUp.AutoBoot) { fwSettings.FirmwareLanguage |= (NDSSyncSettings.Language) 0x40; } fwSettings.FirmwareBirthdayMonth = _syncSettings.FirmwareBirthdayMonth; fwSettings.FirmwareBirthdayDay = _syncSettings.FirmwareBirthdayDay; fwSettings.FirmwareFavouriteColour = _syncSettings.FirmwareFavouriteColour; var message = _syncSettings.FirmwareMessage.Length != 0 ? Encoding.UTF8.GetBytes(_syncSettings.FirmwareMessage) : new byte[1] { 0 }; fwSettings.FirmwareMessageLength = message.Length; var loadData = new LibMelonDS.LoadData { DsRomLength = roms[0].Length, GbaRomLength = gbacartpresent ? roms[1].Length : 0, GbaRamLength = gbasrampresent ? roms[2].Length : 0, NandLength = nand?.Length ?? 0, AudioBitrate = _settings.AudioBitrate, }; if (_syncSettings.UseRealBIOS || IsDSi) { _exe.AddReadonlyFile(bios7, "bios7.rom"); _exe.AddReadonlyFile(bios9, "bios9.rom"); } if (IsDSi) { _exe.AddReadonlyFile(bios7i, "bios7i.rom"); _exe.AddReadonlyFile(bios9i, "bios9i.rom"); if (IsDSiWare) { _exe.AddReadonlyFile(roms[0], "dsiware.rom"); } } if (fw != null) { if (IsDSi || NDSFirmware.MaybeWarnIfBadFw(fw, CoreComm)) // fw checks dont work on dsi firmware, don't bother { if (_syncSettings.FirmwareOverride || lp.DeterministicEmulationRequested) { NDSFirmware.SanitizeFw(fw); } } _exe.AddReadonlyFile(fw, IsDSi ? "firmwarei.bin" : "firmware.bin"); } unsafe { fixed(byte * dsRomPtr = roms[0], gbaRomPtr = gbacartpresent?roms[1] : null, gbaRamPtr = gbasrampresent?roms[2] : null, nandPtr = nand, tmdPtr = tmd, namePtr = name, messagePtr = message) { loadData.DsRomData = (IntPtr)dsRomPtr; loadData.GbaRomData = (IntPtr)gbaRomPtr; loadData.GbaRamData = (IntPtr)gbaRamPtr; loadData.NandData = (IntPtr)nandPtr; loadData.TmdData = (IntPtr)tmdPtr; fwSettings.FirmwareUsername = (IntPtr)namePtr; fwSettings.FirmwareMessage = (IntPtr)messagePtr; if (!_core.Init(loadFlags, ref loadData, ref fwSettings)) { throw new InvalidOperationException("Init returned false!"); } } } if (fw != null) { _exe.RemoveReadonlyFile(IsDSi ? "firmwarei.bin" : "firmware.bin"); } if (IsDSi && IsDSiWare) { _exe.RemoveReadonlyFile("dsiware.rom"); } PostInit(); ((MemoryDomainList)this.AsMemoryDomains()).SystemBus = new NDSSystemBus(this.AsMemoryDomains()["ARM9 System Bus"], this.AsMemoryDomains()["ARM7 System Bus"]); DeterministicEmulation = lp.DeterministicEmulationRequested || (!_syncSettings.UseRealTime); InitializeRtc(_syncSettings.InitialTime); _frameThreadPtr = _core.GetFrameThreadProc(); if (_frameThreadPtr != IntPtr.Zero) { Console.WriteLine($"Setting up waterbox thread for 0x{_frameThreadPtr:X16}"); _frameThreadStart = CallingConventionAdapters.GetWaterboxUnsafeUnwrapped().GetDelegateForFunctionPointer <Action>(_frameThreadPtr); _core.SetThreadStartCallback(_threadstartcb); } _resampler = new SpeexResampler(SpeexResampler.Quality.QUALITY_DEFAULT, 32768, 44100, 32768, 44100, null, this); _serviceProvider.Register <ISoundProvider>(_resampler); _disassembler = new NDSDisassembler(); _serviceProvider.Register <IDisassemblable>(_disassembler); const string TRACE_HEADER = "ARM9+ARM7: PC, opcode, registers (r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, Cy, CpuMode)"; Tracer = new TraceBuffer(TRACE_HEADER); _serviceProvider.Register(Tracer); }