Beispiel #1
0
        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();
        }
Beispiel #2
0
        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>();
        }
Beispiel #3
0
        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;
        }
Beispiel #7
0
        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();
        }
Beispiel #8
0
 protected T DoInit <T>(
     CoreLoadParameters <NymaSettings, NymaSyncSettings> lp,
     string wbxFilename,
     IDictionary <string, (string SystemID, string FirmwareID)> firmwares = null
Beispiel #9
0
        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();
        }
Beispiel #10
0
        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);
        }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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();
        }
Beispiel #14
0
        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);
        }