Пример #1
0
        public BsnesCore(GameInfo game, byte[] romData, byte[] xmlData, string baseRomPath, CoreComm comm,
                         SnesSettings settings, SnesSyncSettings syncSettings)
        {
            _baseRomPath = baseRomPath;
            var ser = new BasicServiceProvider(this);

            ServiceProvider = ser;

            CoreComm = comm;
            byte[] sgbRomData = null;

            if (game.System == "SGB")
            {
                if ((romData[0x143] & 0xc0) == 0xc0)
                {
                    throw new CGBNotSupportedException();
                }

                sgbRomData        = CoreComm.CoreFileProvider.GetFirmware("SNES", "Rom_SGB", true, "SGB Rom is required for SGB emulation.");
                game.FirmwareHash = sgbRomData.HashSHA1();
            }

            _settings     = settings ?? new SnesSettings();
            _syncSettings = syncSettings ?? new SnesSyncSettings();

            BsnesApi.SnesCallbacks callbacks = new()
            {
                inputPollCb   = snes_input_poll,
                inputStateCb  = snes_input_state,
                noLagCb       = snes_no_lag,
                videoFrameCb  = snes_video_refresh,
                audioSampleCb = snes_audio_sample,
                pathRequestCb = snes_path_request,
                snesTraceCb   = snes_trace
            };

            Api = new BsnesApi(CoreComm.CoreFileProvider.DllPath(), CoreComm, callbacks.AllDelegatesInMemoryOrder());

            _controllers = new BsnesControllers(_syncSettings);

            generate_palette();
            // TODO: massive random hack till waterboxhost gets fixed to support 5+ args
            ushort mergedBools = (ushort)((_syncSettings.Hotfixes ? 1 << 8 : 0) | (_syncSettings.FastPPU ? 1 : 0));

            Api.core.snes_init(_syncSettings.Entropy, _syncSettings.LeftPort, _syncSettings.RightPort, mergedBools);
            Api.SetCallbacks(callbacks);

            // start up audio resampler
            InitAudio();
            ser.Register <ISoundProvider>(_resampler);

            if (game.System == "SGB")
            {
                IsSGB    = true;
                SystemId = "SNES";
                ser.Register <IBoardInfo>(new SGBBoardInfo());

                _currLoadParams = new LoadParams
                {
                    type        = LoadParamType.SuperGameBoy,
                    baseRomPath = baseRomPath,
                    romData     = sgbRomData,
                    sgbRomData  = romData
                };
            }
            else
            {
                // we may need to get some information out of the cart, even during the following bootup/load process
                if (xmlData != null)
                {
                    _romxml = new XmlDocument();
                    _romxml.Load(new MemoryStream(xmlData));

                    // bsnes wont inspect the xml to load the necessary sfc file.
                    // so, we have to do that here and pass it in as the romData :/

                    // TODO: uhh i have no idea what the xml is or whether this below code is needed
                    if (_romxml["cartridge"]?["rom"] != null)
                    {
                        romData = File.ReadAllBytes(PathSubfile(_romxml["cartridge"]["rom"].Attributes["name"].Value));
                    }
                    else
                    {
                        throw new Exception("Could not find rom file specification in xml file. Please check the integrity of your xml file");
                    }
                }

                SystemId        = "SNES";
                _currLoadParams = new LoadParams
                {
                    type        = LoadParamType.Normal,
                    baseRomPath = baseRomPath,
                    romData     = romData
                };
            }

            LoadCurrent();

            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();

            _tracer = new TraceBuffer
            {
                Header = "65816: PC, mnemonic, operands, registers (A, X, Y, S, D, B, flags (NVMXDIZC), V, H)"
            };
            ser.Register <IDisassemblable>(new W65816_DisassemblerService());
            ser.Register(_tracer);

            Api.Seal();
        }
Пример #2
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();
        }