public void NativeInit(LibsnesApi api)
 {
     for (int i = 0; i < 2; i++)
     {
         api.SetInputPortBeforeInit(i, _ports[i].PortType);
     }
 }
示例#2
0
 public SNESGraphicsDecoder(LibsnesApi api, SnesColors.ColorType pal)
 {
     this.api = api;
     colortable = SnesColors.GetLUT(pal);
     IntPtr block = (IntPtr)api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.VRAM);
     vram = (byte*)block;
     vram16 = (ushort*)block;
     block = (IntPtr)api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.CGRAM);
     cgram = (ushort*)block;
     block = (IntPtr)api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.OAM);
     oam = (byte*)block;
 }
        public SNESGraphicsDecoder(LibsnesApi api, SnesColors.ColorType pal)
        {
            this.api   = api;
            colortable = SnesColors.GetLUT(pal);
            IntPtr block = (IntPtr)api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.VRAM);

            vram   = (byte *)block;
            vram16 = (ushort *)block;
            block  = (IntPtr)api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.CGRAM);
            cgram  = (ushort *)block;
            block  = (IntPtr)api.QUERY_get_memory_data(LibsnesApi.SNES_MEMORY.OAM);
            oam    = (byte *)block;
        }
示例#4
0
        public LibsnesCore(GameInfo game, byte[] romData, byte[] xmlData, CoreComm comm, object settings, object syncSettings)
        {
            var ser = new BasicServiceProvider(this);

            ServiceProvider = ser;

            _tracer = new TraceBuffer
            {
                Header = "65816: PC, mnemonic, operands, registers (A, X, Y, S, D, DB, flags (NVMXDIZC), V, H)"
            };

            ser.Register <IDisassemblable>(new W65816_DisassemblerService());

            _game    = game;
            CoreComm = comm;
            byte[] sgbRomData = null;

            if (game["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     = (SnesSettings)settings ?? new SnesSettings();
            _syncSettings = (SnesSyncSettings)syncSettings ?? new SnesSyncSettings();

            // TODO: pass profile here
            Api = new LibsnesApi(CoreComm.CoreFileProvider.DllPath())
            {
                ReadHook  = ReadHook,
                ExecHook  = ExecHook,
                WriteHook = WriteHook
            };

            ScanlineHookManager = new MyScanlineHookManager(this);

            _controllerDeck = new LibsnesControllerDeck(_syncSettings);
            _controllerDeck.NativeInit(Api);

            Api.CMD_init();

            Api.QUERY_set_path_request(snes_path_request);

            _scanlineStartCb = new LibsnesApi.snes_scanlineStart_t(snes_scanlineStart);
            _tracecb         = new LibsnesApi.snes_trace_t(snes_trace);

            _soundcb = new LibsnesApi.snes_audio_sample_t(snes_audio_sample);

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

            // strip header
            if ((romData?.Length & 0x7FFF) == 512)
            {
                var newData = new byte[romData.Length - 512];
                Array.Copy(romData, 512, newData, 0, newData.Length);
                romData = newData;
            }

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

                _currLoadParams = new LoadParams()
                {
                    type     = LoadParamType.SuperGameBoy,
                    rom_xml  = null,
                    rom_data = sgbRomData,
                    rom_size = (uint)sgbRomData.Length,
                    dmg_data = romData,
                };

                if (!LoadCurrent())
                {
                    throw new Exception("snes_load_cartridge_normal() failed");
                }
            }
            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 :/
                    if (_romxml["cartridge"]?["rom"] != null)
                    {
                        romData = File.ReadAllBytes(CoreComm.CoreFileProvider.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,
                    xml_data = xmlData,
                    rom_data = romData
                };

                if (!LoadCurrent())
                {
                    throw new Exception("snes_load_cartridge_normal() failed");
                }
            }

            if (Api.Region == LibsnesApi.SNES_REGION.NTSC)
            {
                // similar to what aviout reports from snes9x and seems logical from bsnes first principles. bsnes uses that numerator (ntsc master clockrate) for sure.
                VsyncNumerator   = 21477272;
                VsyncDenominator = 4 * 341 * 262;
            }
            else
            {
                // http://forums.nesdev.com/viewtopic.php?t=5367&start=19
                VsyncNumerator   = 21281370;
                VsyncDenominator = 4 * 341 * 312;
            }

            Api.CMD_power();

            SetupMemoryDomains(romData, sgbRomData);

            if (CurrentProfile == "Compatibility")
            {
                ser.Register <ITraceable>(_tracer);
            }

            Api.QUERY_set_path_request(null);
            Api.QUERY_set_video_refresh(snes_video_refresh);
            Api.QUERY_set_input_poll(snes_input_poll);
            Api.QUERY_set_input_state(snes_input_state);
            Api.QUERY_set_input_notify(snes_input_notify);
            Api.QUERY_set_audio_sample(_soundcb);
            Api.Seal();
            RefreshPalette();
        }
示例#5
0
            public static ScreenInfo GetScreenInfo(LibsnesApi api)
            {
                var si = new ScreenInfo();

                si.Mode1_BG3_Priority = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_PRIORITY) == 1;

                si.OBSEL_Size = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.OBSEL_SIZE);
                si.OBSEL_NameSel = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.OBSEL_NAMESEL);
                si.OBSEL_NameBase = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.OBSEL_NAMEBASE);

                si.ObjSizeBounds = ObjSizes[si.OBSEL_Size,1];
                int square = Math.Max(si.ObjSizeBounds.Width, si.ObjSizeBounds.Height);
                si.ObjSizeBoundsSquare = new Dimensions(square, square);

                si.OBJTable0Addr = si.OBSEL_NameBase << 14;
                si.OBJTable1Addr = (si.OBJTable0Addr + ((si.OBSEL_NameSel + 1) << 13)) & 0xFFFF;

                si.SETINI_Mode7ExtBG = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_MODE7_EXTBG) == 1;
                si.SETINI_HiRes = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_HIRES) == 1;
                si.SETINI_Overscan = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_OVERSCAN) == 1;
                si.SETINI_ObjInterlace = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_OBJ_INTERLACE) == 1;
                si.SETINI_ScreenInterlace = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_SCREEN_INTERLACE) == 1;

                si.CGWSEL_ColorMask = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_COLORMASK);
                si.CGWSEL_ColorSubMask = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_COLORSUBMASK);
                si.CGWSEL_AddSubMode = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_ADDSUBMODE);
                si.CGWSEL_DirectColor = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_DIRECTCOLOR) == 1;

                si.CGADSUB_AddSub = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_MODE);
                si.CGADSUB_Half = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_HALF) == 1;

                si.OBJ_MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_OBJ) == 1;
                si.OBJ_SubEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_OBJ) == 1;
                si.OBJ_MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_OBJ) == 1;
                si.BK_MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BACKDROP) == 1;

                si.Mode.MODE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG_MODE);
                si.BG.BG1.Bpp = ModeBpps[si.Mode.MODE, 0];
                si.BG.BG2.Bpp = ModeBpps[si.Mode.MODE, 1];
                si.BG.BG3.Bpp = ModeBpps[si.Mode.MODE, 2];
                si.BG.BG4.Bpp = ModeBpps[si.Mode.MODE, 3];

                //initial setting of mode type (derived from bpp table.. mode7 bg types will be fixed up later)
                for(int i=1;i<=4;i++)
                    si.BG[i].BGMode = si.BG[i].Bpp == 0 ? BGMode.Unavailable : BGMode.Text;

                si.BG.BG1.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_TILESIZE);
                si.BG.BG2.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_TILESIZE);
                si.BG.BG3.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_TILESIZE);
                si.BG.BG4.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_TILESIZE);

                si.BG.BG1.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_SCSIZE);
                si.BG.BG2.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_SCSIZE);
                si.BG.BG3.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_SCSIZE);
                si.BG.BG4.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_SCSIZE);
                si.BG.BG1.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_SCADDR);
                si.BG.BG2.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_SCADDR);
                si.BG.BG3.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_SCADDR);
                si.BG.BG4.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_SCADDR);
                si.BG.BG1.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_TDADDR);
                si.BG.BG2.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_TDADDR);
                si.BG.BG3.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_TDADDR);
                si.BG.BG4.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_TDADDR);

                si.BG.BG1.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG1) == 1;
                si.BG.BG2.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG2) == 1;
                si.BG.BG3.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG3) == 1;
                si.BG.BG4.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG4) == 1;
                si.BG.BG1.SubEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG1) == 1;
                si.BG.BG2.SubEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG2) == 1;
                si.BG.BG3.SubEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG3) == 1;
                si.BG.BG4.SubEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG4) == 1;
                si.BG.BG1.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG1) == 1;
                si.BG.BG2.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG2) == 1;
                si.BG.BG3.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG3) == 1;
                si.BG.BG4.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG4) == 1;

                si.BG.BG1.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1HOFS);
                si.BG.BG1.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1VOFS);
                si.BG.BG2.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2HOFS);
                si.BG.BG2.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2VOFS);
                si.BG.BG3.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3HOFS);
                si.BG.BG3.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3VOFS);
                si.BG.BG4.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4HOFS);
                si.BG.BG4.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4VOFS);

                si.M7HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7HOFS);
                si.M7VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7VOFS);
                si.M7A = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7A);
                si.M7B = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7B);
                si.M7C = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7C);
                si.M7D = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7D);
                si.M7X = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7X);
                si.M7Y = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7Y);
                si.M7Y = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7Y);
                si.M7SEL_REPEAT = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7SEL_REPEAT);
                si.M7SEL_HFLIP = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7SEL_HFLIP)!=0;
                si.M7SEL_VFLIP = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7SEL_VFLIP)!=0;

                for (int i = 1; i <= 4; i++)
                {
                    si.BG[i].Mode = si.Mode.MODE;
                    si.BG[i].TiledataAddr = si.BG[i].TDADDR << 13;
                    si.BG[i].ScreenAddr = si.BG[i].SCADDR << 9;
                }

                //fixup irregular things for mode 7
                if (si.Mode.MODE == 7)
                {
                    si.BG.BG1.TiledataAddr = 0;
                    si.BG.BG1.ScreenAddr = 0;

                    if (si.CGWSEL_DirectColor)
                    {
                        si.BG.BG1.BGMode = BGMode.Mode7DC;
                    }
                    else
                        si.BG.BG1.BGMode = BGMode.Mode7;

                    if (si.SETINI_Mode7ExtBG)
                    {
                        si.BG.BG2.BGMode = BGMode.Mode7Ext;
                        si.BG.BG2.Bpp = 7;
                        si.BG.BG2.TiledataAddr = 0;
                        si.BG.BG2.ScreenAddr = 0;
                    }
                }

                //determine which colors each BG could use
                switch (si.Mode.MODE)
                {
                    case 0:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 32);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(32, 32);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(64, 32);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(96, 32);
                        break;
                    case 1:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 32);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;
                    case 2:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;
                    case 3:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 256);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;
                    case 4:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 256);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 32);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;
                    case 5:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 32);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;
                    case 6:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 32);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;
                    case 7:
                        si.BG.BG1.PaletteSelection = new PaletteSelection(0, 256);
                        si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                        si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                        si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                        break;

                }

                return si;
            }
示例#6
0
		public LibsnesCore(GameInfo game, byte[] romData, bool deterministicEmulation, byte[] xmlData, CoreComm comm, object Settings, object SyncSettings)
		{
			CoreComm = comm;
			byte[] sgbRomData = null;
			if (game["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();
			}

			this.Settings = (SnesSettings)Settings ?? new SnesSettings();
			this.SyncSettings = (SnesSyncSettings)SyncSettings ?? new SnesSyncSettings();

			api = new LibsnesApi(GetExePath());
			api.CMD_init();
			api.ReadHook = ReadHook;
			api.ExecHook = ExecHook;
			api.WriteHook = WriteHook;

			ScanlineHookManager = new MyScanlineHookManager(this);

			api.CMD_init();

			api.QUERY_set_video_refresh(snes_video_refresh);
			api.QUERY_set_input_poll(snes_input_poll);
			api.QUERY_set_input_state(snes_input_state);
			api.QUERY_set_input_notify(snes_input_notify);
			api.QUERY_set_path_request(snes_path_request);
			
			scanlineStart_cb = new LibsnesApi.snes_scanlineStart_t(snes_scanlineStart);
			tracecb = new LibsnesApi.snes_trace_t(snes_trace);

			soundcb = new LibsnesApi.snes_audio_sample_t(snes_audio_sample);
			api.QUERY_set_audio_sample(soundcb);

			RefreshPalette();

			// start up audio resampler
			InitAudio();

			//strip header
			if(romData != null)
				if ((romData.Length & 0x7FFF) == 512)
				{
					var newData = new byte[romData.Length - 512];
					Array.Copy(romData, 512, newData, 0, newData.Length);
					romData = newData;
				}

			if (game["SGB"])
			{
				IsSGB = true;
				SystemId = "SNES";
				BoardName = "SGB";

				CurrLoadParams = new LoadParams()
				{
					type = LoadParamType.SuperGameBoy,
					rom_xml = null,
					rom_data = sgbRomData,
					rom_size = (uint)sgbRomData.Length,
					dmg_xml = null,
					dmg_data = romData,
					dmg_size = (uint)romData.Length
				};

				if (!LoadCurrent())
					throw new Exception("snes_load_cartridge_normal() failed");
			}
			else
			{
				//we may need to get some information out of the cart, even during the following bootup/load process
				if (xmlData != null)
				{
					romxml = new System.Xml.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 :/
					if (romxml["cartridge"] != null && romxml["cartridge"]["rom"] != null)
						romData = File.ReadAllBytes(CoreComm.CoreFileProvider.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,
					xml_data = xmlData,
					rom_data = romData
				};

				if(!LoadCurrent())
					throw new Exception("snes_load_cartridge_normal() failed");
			}

			if (api.QUERY_get_region() == LibsnesApi.SNES_REGION.NTSC)
			{
				//similar to what aviout reports from snes9x and seems logical from bsnes first principles. bsnes uses that numerator (ntsc master clockrate) for sure.
				CoreComm.VsyncNum = 21477272;
				CoreComm.VsyncDen = 4 * 341 * 262;
			}
			else
			{
				//http://forums.nesdev.com/viewtopic.php?t=5367&start=19
				CoreComm.VsyncNum = 21281370;
				CoreComm.VsyncDen = 4 * 341 * 312;
			}

			CoreComm.CpuTraceAvailable = true;

			api.CMD_power();

			SetupMemoryDomains(romData,sgbRomData);

			DeterministicEmulation = deterministicEmulation;
			if (DeterministicEmulation) // save frame-0 savestate now
			{
				MemoryStream ms = new MemoryStream();
				BinaryWriter bw = new BinaryWriter(ms);
				bw.Write(CoreSaveState());
				bw.Write(true); // framezero, so no controller follows and don't frameadvance on load
				// hack: write fake dummy controller info
				bw.Write(new byte[536]);
				bw.Close();
				savestatebuff = ms.ToArray();
			}
		}
示例#7
0
		// ----- Client Debugging API stuff -----
		unsafe MemoryDomain MakeMemoryDomain(string name, LibsnesApi.SNES_MEMORY id, MemoryDomain.Endian endian)
		{
			int size = api.QUERY_get_memory_size(id);
			int mask = size - 1;
			bool pow2 = Util.IsPowerOfTwo(size);

			//if this type of memory isnt available, dont make the memory domain (most commonly save ram)
			if (size == 0)
				return null;

			byte* blockptr = api.QUERY_get_memory_data(id);

			MemoryDomain md;

			if(id == LibsnesApi.SNES_MEMORY.OAM)
			{
				//OAM is actually two differently sized banks of memory which arent truly considered adjacent. 
				//maybe a better way to visualize it is with an empty bus and adjacent banks
				//so, we just throw away everything above its size of 544 bytes
				if (size != 544) throw new InvalidOperationException("oam size isnt 544 bytes.. wtf?");
				md = new MemoryDomain(name, size, endian,
				   (addr) => (addr < 544) ? blockptr[addr] : (byte)0x00,
					 (addr, value) => { if (addr < 544) blockptr[addr] = value; }
					 );
			}
			else if(pow2)
				md = new MemoryDomain(name, size, endian,
						(addr) => blockptr[addr & mask],
						(addr, value) => blockptr[addr & mask] = value);
			else
				md = new MemoryDomain(name, size, endian,
						(addr) => blockptr[addr % size],
						(addr, value) => blockptr[addr % size] = value);

			_memoryDomains.Add(md);

			return md;
		}
            public static ScreenInfo GetScreenInfo(LibsnesApi api)
            {
                var si = new ScreenInfo();

                si.Mode1_BG3_Priority = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_PRIORITY) == 1;

                si.OBSEL_Size     = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.OBSEL_SIZE);
                si.OBSEL_NameSel  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.OBSEL_NAMESEL);
                si.OBSEL_NameBase = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.OBSEL_NAMEBASE);

                si.ObjSizeBounds = ObjSizes[si.OBSEL_Size, 1];
                int square = Math.Max(si.ObjSizeBounds.Width, si.ObjSizeBounds.Height);

                si.ObjSizeBoundsSquare = new Dimensions(square, square);


                si.OBJTable0Addr = si.OBSEL_NameBase << 14;
                si.OBJTable1Addr = (si.OBJTable0Addr + ((si.OBSEL_NameSel + 1) << 13)) & 0xFFFF;

                si.SETINI_Mode7ExtBG      = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_MODE7_EXTBG) == 1;
                si.SETINI_HiRes           = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_HIRES) == 1;
                si.SETINI_Overscan        = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_OVERSCAN) == 1;
                si.SETINI_ObjInterlace    = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_OBJ_INTERLACE) == 1;
                si.SETINI_ScreenInterlace = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.SETINI_SCREEN_INTERLACE) == 1;

                si.CGWSEL_ColorMask    = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_COLORMASK);
                si.CGWSEL_ColorSubMask = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_COLORSUBMASK);
                si.CGWSEL_AddSubMode   = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_ADDSUBMODE);
                si.CGWSEL_DirectColor  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGWSEL_DIRECTCOLOR) == 1;

                si.CGADSUB_AddSub = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_MODE);
                si.CGADSUB_Half   = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_HALF) == 1;

                si.OBJ_MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_OBJ) == 1;
                si.OBJ_SubEnabled  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_OBJ) == 1;
                si.OBJ_MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_OBJ) == 1;
                si.BK_MathEnabled  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BACKDROP) == 1;

                si.Mode.MODE  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG_MODE);
                si.BG.BG1.Bpp = ModeBpps[si.Mode.MODE, 0];
                si.BG.BG2.Bpp = ModeBpps[si.Mode.MODE, 1];
                si.BG.BG3.Bpp = ModeBpps[si.Mode.MODE, 2];
                si.BG.BG4.Bpp = ModeBpps[si.Mode.MODE, 3];

                //initial setting of mode type (derived from bpp table.. mode7 bg types will be fixed up later)
                for (int i = 1; i <= 4; i++)
                {
                    si.BG[i].BGMode = si.BG[i].Bpp == 0 ? BGMode.Unavailable : BGMode.Text;
                }

                si.BG.BG1.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_TILESIZE);
                si.BG.BG2.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_TILESIZE);
                si.BG.BG3.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_TILESIZE);
                si.BG.BG4.TILESIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_TILESIZE);

                si.BG.BG1.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_SCSIZE);
                si.BG.BG2.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_SCSIZE);
                si.BG.BG3.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_SCSIZE);
                si.BG.BG4.SCSIZE = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_SCSIZE);
                si.BG.BG1.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_SCADDR);
                si.BG.BG2.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_SCADDR);
                si.BG.BG3.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_SCADDR);
                si.BG.BG4.SCADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_SCADDR);
                si.BG.BG1.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1_TDADDR);
                si.BG.BG2.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2_TDADDR);
                si.BG.BG3.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3_TDADDR);
                si.BG.BG4.TDADDR = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4_TDADDR);

                si.BG.BG1.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG1) == 1;
                si.BG.BG2.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG2) == 1;
                si.BG.BG3.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG3) == 1;
                si.BG.BG4.MainEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TM_BG4) == 1;
                si.BG.BG1.SubEnabled  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG1) == 1;
                si.BG.BG2.SubEnabled  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG2) == 1;
                si.BG.BG3.SubEnabled  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG3) == 1;
                si.BG.BG4.SubEnabled  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.TS_BG4) == 1;
                si.BG.BG1.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG1) == 1;
                si.BG.BG2.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG2) == 1;
                si.BG.BG3.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG3) == 1;
                si.BG.BG4.MathEnabled = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.CGADSUB_BG4) == 1;

                si.BG.BG1.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1HOFS);
                si.BG.BG1.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG1VOFS);
                si.BG.BG2.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2HOFS);
                si.BG.BG2.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG2VOFS);
                si.BG.BG3.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3HOFS);
                si.BG.BG3.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG3VOFS);
                si.BG.BG4.HOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4HOFS);
                si.BG.BG4.VOFS = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.BG4VOFS);

                si.M7HOFS       = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7HOFS);
                si.M7VOFS       = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7VOFS);
                si.M7A          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7A);
                si.M7B          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7B);
                si.M7C          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7C);
                si.M7D          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7D);
                si.M7X          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7X);
                si.M7Y          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7Y);
                si.M7Y          = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7Y);
                si.M7SEL_REPEAT = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7SEL_REPEAT);
                si.M7SEL_HFLIP  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7SEL_HFLIP) != 0;
                si.M7SEL_VFLIP  = api.QUERY_peek_logical_register(LibsnesApi.SNES_REG.M7SEL_VFLIP) != 0;

                for (int i = 1; i <= 4; i++)
                {
                    si.BG[i].Mode         = si.Mode.MODE;
                    si.BG[i].TiledataAddr = si.BG[i].TDADDR << 13;
                    si.BG[i].ScreenAddr   = si.BG[i].SCADDR << 9;
                }

                //fixup irregular things for mode 7
                if (si.Mode.MODE == 7)
                {
                    si.BG.BG1.TiledataAddr = 0;
                    si.BG.BG1.ScreenAddr   = 0;

                    if (si.CGWSEL_DirectColor)
                    {
                        si.BG.BG1.BGMode = BGMode.Mode7DC;
                    }
                    else
                    {
                        si.BG.BG1.BGMode = BGMode.Mode7;
                    }

                    if (si.SETINI_Mode7ExtBG)
                    {
                        si.BG.BG2.BGMode       = BGMode.Mode7Ext;
                        si.BG.BG2.Bpp          = 7;
                        si.BG.BG2.TiledataAddr = 0;
                        si.BG.BG2.ScreenAddr   = 0;
                    }
                }

                //determine which colors each BG could use
                switch (si.Mode.MODE)
                {
                case 0:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 32);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(32, 32);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(64, 32);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(96, 32);
                    break;

                case 1:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 32);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;

                case 2:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;

                case 3:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 256);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;

                case 4:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 256);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 32);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;

                case 5:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 32);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;

                case 6:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 32);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;

                case 7:
                    si.BG.BG1.PaletteSelection = new PaletteSelection(0, 256);
                    si.BG.BG2.PaletteSelection = new PaletteSelection(0, 128);
                    si.BG.BG3.PaletteSelection = new PaletteSelection(0, 0);
                    si.BG.BG4.PaletteSelection = new PaletteSelection(0, 0);
                    break;
                }

                return(si);
            }
示例#9
0
        public LibsnesCore(GameInfo game, byte[] romData, bool deterministicEmulation, byte[] xmlData, CoreComm comm, object Settings, object SyncSettings)
        {
            CoreComm = comm;
            byte[] sgbRomData = null;
            if (game["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();
            }

            this.Settings     = (SnesSettings)Settings ?? new SnesSettings();
            this.SyncSettings = (SnesSyncSettings)SyncSettings ?? new SnesSyncSettings();

            api = new LibsnesApi(GetExePath());
            api.CMD_init();
            api.ReadHook  = ReadHook;
            api.ExecHook  = ExecHook;
            api.WriteHook = WriteHook;

            ScanlineHookManager = new MyScanlineHookManager(this);

            api.CMD_init();

            api.QUERY_set_video_refresh(snes_video_refresh);
            api.QUERY_set_input_poll(snes_input_poll);
            api.QUERY_set_input_state(snes_input_state);
            api.QUERY_set_input_notify(snes_input_notify);
            api.QUERY_set_path_request(snes_path_request);

            scanlineStart_cb = new LibsnesApi.snes_scanlineStart_t(snes_scanlineStart);
            tracecb          = new LibsnesApi.snes_trace_t(snes_trace);

            soundcb = new LibsnesApi.snes_audio_sample_t(snes_audio_sample);
            api.QUERY_set_audio_sample(soundcb);

            RefreshPalette();

            // start up audio resampler
            InitAudio();

            //strip header
            if (romData != null)
            {
                if ((romData.Length & 0x7FFF) == 512)
                {
                    var newData = new byte[romData.Length - 512];
                    Array.Copy(romData, 512, newData, 0, newData.Length);
                    romData = newData;
                }
            }

            if (game["SGB"])
            {
                IsSGB     = true;
                SystemId  = "SNES";
                BoardName = "SGB";

                CurrLoadParams = new LoadParams()
                {
                    type     = LoadParamType.SuperGameBoy,
                    rom_xml  = null,
                    rom_data = sgbRomData,
                    rom_size = (uint)sgbRomData.Length,
                    dmg_xml  = null,
                    dmg_data = romData,
                    dmg_size = (uint)romData.Length
                };

                if (!LoadCurrent())
                {
                    throw new Exception("snes_load_cartridge_normal() failed");
                }
            }
            else
            {
                //we may need to get some information out of the cart, even during the following bootup/load process
                if (xmlData != null)
                {
                    romxml = new System.Xml.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 :/
                    if (romxml["cartridge"] != null && romxml["cartridge"]["rom"] != null)
                    {
                        romData = File.ReadAllBytes(CoreComm.CoreFileProvider.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,
                    xml_data = xmlData,
                    rom_data = romData
                };

                if (!LoadCurrent())
                {
                    throw new Exception("snes_load_cartridge_normal() failed");
                }
            }

            if (api.QUERY_get_region() == LibsnesApi.SNES_REGION.NTSC)
            {
                //similar to what aviout reports from snes9x and seems logical from bsnes first principles. bsnes uses that numerator (ntsc master clockrate) for sure.
                CoreComm.VsyncNum = 21477272;
                CoreComm.VsyncDen = 4 * 341 * 262;
            }
            else
            {
                //http://forums.nesdev.com/viewtopic.php?t=5367&start=19
                CoreComm.VsyncNum = 21281370;
                CoreComm.VsyncDen = 4 * 341 * 312;
            }

            CoreComm.CpuTraceAvailable = true;

            api.CMD_power();

            SetupMemoryDomains(romData, sgbRomData);

            DeterministicEmulation = deterministicEmulation;
            if (DeterministicEmulation)             // save frame-0 savestate now
            {
                MemoryStream ms = new MemoryStream();
                BinaryWriter bw = new BinaryWriter(ms);
                bw.Write(CoreSaveState());
                bw.Write(true);                 // framezero, so no controller follows and don't frameadvance on load
                // hack: write fake dummy controller info
                bw.Write(new byte[536]);
                bw.Close();
                savestatebuff = ms.ToArray();
            }
        }