public ColecoVision(CoreComm comm, GameInfo game, byte[] rom, object SyncSettings) { CoreComm = comm; this.SyncSettings = (ColecoSyncSettings)SyncSettings ?? new ColecoSyncSettings(); bool skipbios = this.SyncSettings.SkipBiosIntro; Cpu = new Z80A(); Cpu.ReadMemory = ReadMemory; Cpu.WriteMemory = WriteMemory; Cpu.ReadHardware = ReadPort; Cpu.WriteHardware = WritePort; VDP = new TMS9918A(Cpu); PSG = new SN76489(); // TODO: hack to allow bios-less operation would be nice, no idea if its feasible string biosPath = CoreComm.CoreFileProvider.GetFirmwarePath("Coleco", "Bios", true, "Coleco BIOS file is required."); BiosRom = File.ReadAllBytes(biosPath); // gamedb can overwrite the syncsettings; this is ok if (game["NoSkip"]) skipbios = false; LoadRom(rom, skipbios); this.game = game; SetupMemoryDomains(); }
public Genesis(CoreComm comm, GameInfo game, byte[] rom) { CoreComm = comm; MainCPU = new MC68000(); SoundCPU = new Z80A(); YM2612 = new YM2612() { MaxVolume = 23405 }; PSG = new SN76489() { MaxVolume = 4681 }; VDP = new GenVDP(); VDP.DmaReadFrom68000 = ReadWord; SoundMixer = new SoundMixer(YM2612, PSG); MainCPU.ReadByte = ReadByte; MainCPU.ReadWord = ReadWord; MainCPU.ReadLong = ReadLong; MainCPU.WriteByte = WriteByte; MainCPU.WriteWord = WriteWord; MainCPU.WriteLong = WriteLong; MainCPU.IrqCallback = InterruptCallback; // ---------------------- musashi ----------------------- #if MUSASHI _vdp = vdpcallback; read8 = Read8; read16 = Read16; read32 = Read32; write8 = Write8; write16 = Write16; write32 = Write32; Musashi.RegisterVdpCallback(Marshal.GetFunctionPointerForDelegate(_vdp)); Musashi.RegisterRead8(Marshal.GetFunctionPointerForDelegate(read8)); Musashi.RegisterRead16(Marshal.GetFunctionPointerForDelegate(read16)); Musashi.RegisterRead32(Marshal.GetFunctionPointerForDelegate(read32)); Musashi.RegisterWrite8(Marshal.GetFunctionPointerForDelegate(write8)); Musashi.RegisterWrite16(Marshal.GetFunctionPointerForDelegate(write16)); Musashi.RegisterWrite32(Marshal.GetFunctionPointerForDelegate(write32)); #endif // ---------------------- musashi ----------------------- SoundCPU.ReadMemory = ReadMemoryZ80; SoundCPU.WriteMemory = WriteMemoryZ80; SoundCPU.WriteHardware = (a, v) => { Console.WriteLine("Z80: Attempt I/O Write {0:X2}:{1:X2}", a, v); }; SoundCPU.ReadHardware = x => 0xFF; SoundCPU.IRQCallback = () => SoundCPU.Interrupt = false; Z80Reset = true; RomData = new byte[0x400000]; for (int i = 0; i < rom.Length; i++) RomData[i] = rom[i]; SetupMemoryDomains(); #if MUSASHI Musashi.Init(); Musashi.Reset(); VDP.GetPC = () => Musashi.PC; #else MainCPU.Reset(); VDP.GetPC = () => MainCPU.PC; #endif InitializeCartHardware(game); }
public NES(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings) { byte[] fdsbios = comm.CoreFileProvider.GetFirmware("NES", "Bios_FDS", false); if (fdsbios != null && fdsbios.Length == 40976) { comm.ShowMessage("Your FDS BIOS is a bad dump. BizHawk will attempt to use it, but no guarantees! You should find a new one."); var tmp = new byte[8192]; Buffer.BlockCopy(fdsbios, 16 + 8192 * 3, tmp, 0, 8192); fdsbios = tmp; } this.SyncSettings = (NESSyncSettings)SyncSettings ?? new NESSyncSettings(); this.ControllerSettings = this.SyncSettings.Controls; CoreComm = comm; CoreComm.CpuTraceAvailable = true; BootGodDB.Initialize(); videoProvider = new MyVideoProvider(this); Init(game, rom, fdsbios); if (board is FDS) { CoreComm.UsesDriveLed = true; (board as FDS).SetDriveLightCallback((val) => CoreComm.DriveLED = val); } PutSettings(Settings ?? new NESSettings()); }
public AppleII(CoreComm comm, GameInfo game, byte[] rom, Settings settings) { GameInfoSet = new List<GameInfo>(); var ser = new BasicServiceProvider(this); ServiceProvider = ser; CoreComm = comm; _disk1 = rom; RomSet.Add(rom); _appleIIRom = comm.CoreFileProvider.GetFirmware( SystemId, "AppleIIe", true, "The Apple IIe BIOS firmware is required"); _diskIIRom = comm.CoreFileProvider.GetFirmware( SystemId, "DiskII", true, "The DiskII firmware is required"); _machine = new Machine(_appleIIRom, _diskIIRom); _machine.BizInitialize(); //make a writeable memory stream cloned from the rom. //for junk.dsk the .dsk is important because it determines the format from that InitDisk(); //trace logger stuff Tracer = new TraceBuffer(); ser.Register<ITraceable>(Tracer); InitSaveStates(); SetupMemoryDomains(); PutSettings(settings ?? new Settings()); }
void InitializeSaveRam(GameInfo game) { if (EepromEnabled) return; if (game["DisableSaveRam"] || RH_SRamPresent == false) return; SaveRamEnabled = true; SaveRamEveryOtherByte = RH_SRamCode != 0; SaveRamStartOffset = RH_SRamStart; SaveRamEndOffset = RH_SRamEnd; if (game["SaveRamStartOffset"]) SaveRamStartOffset = game.GetHexValue("SaveRamStartOffset"); if (game["SaveRamEndOffset"]) SaveRamEndOffset = game.GetHexValue("SaveRamEndOffset"); SaveRamLength = (SaveRamEndOffset - SaveRamStartOffset) + 1; if (SaveRamEveryOtherByte) SaveRamLength = ((SaveRamEndOffset - SaveRamStartOffset) / 2) + 1; SaveRAM = new byte[SaveRamLength]; Console.WriteLine("SaveRAM enabled. Start: ${0:X6} End: ${1:X6} Length: ${2:X} Mode: {3}", SaveRamStartOffset, SaveRamEndOffset, SaveRamLength, RH_SRamInterpretation()); }
public Intellivision(CoreComm comm, GameInfo game, byte[] rom) { CoreComm = comm; Rom = rom; Game = game; Cart = new Intellicart(); if (Cart.Parse(Rom) == -1) { Cart = new Cartridge(); Cart.Parse(Rom); } Cpu = new CP1610(); Cpu.ReadMemory = ReadMemory; Cpu.WriteMemory = WriteMemory; Cpu.Reset(); Stic = new STIC(); Stic.ReadMemory = ReadMemory; Stic.WriteMemory = WriteMemory; Stic.Reset(); Psg = new PSG(); Psg.ReadMemory = ReadMemory; Psg.WriteMemory = WriteMemory; Connect(); Cpu.LogData(); LoadExecutiveRom(CoreComm.CoreFileProvider.GetFirmwarePath("INTV", "EROM", true, "Executive ROM is required.")); LoadGraphicsRom(CoreComm.CoreFileProvider.GetFirmwarePath("INTV", "GROM", true, "Graphics ROM is required.")); }
// Code void InitializeEeprom(GameInfo game) { if (game["EEPROM"] == false) return; EepromEnabled = true; EepromAddrMask = game.GetHexValue("EEPROM_ADDR_MASK"); EepromSize = EepromAddrMask + 1; var t = game.OptionValue("SDA_IN").Split(':'); SdaInAddr = int.Parse(t[0], NumberStyles.HexNumber); SdaInBit = int.Parse(t[1]); t = game.OptionValue("SDA_OUT").Split(':'); SdaOutAddr = int.Parse(t[0], NumberStyles.HexNumber); SdaOutBit = int.Parse(t[1]); t = game.OptionValue("SCL").Split(':'); SclAddr = int.Parse(t[0], NumberStyles.HexNumber); SclBit = int.Parse(t[1]); SaveRAM = new byte[EepromSize]; Console.WriteLine("EEPROM enabled. Size: ${0:X} SDA_IN: ${1:X}:{2} SDA_OUT: ${3:X}:{4}, SCL: ${5:X}:{6}", EepromSize, SdaInAddr, SdaInBit, SdaOutAddr, SdaOutBit, SclAddr, SclBit); }
public void FillPerGameHacks(GameInfo game) { if (UseDefaultHacks) { resolution_width = game.GetInt("Jabo_Resolution_Width", -1); resolution_height = game.GetInt("Jabo_Resolution_Height", -1); clear_mode = (Direct3DClearMode)game.GetInt("Jabo_Clear_Frame", (int)Direct3DClearMode.Default); } }
// framework public C64(CoreComm comm, GameInfo game, byte[] rom, string romextension) { inputFileInfo = new InputFileInfo(); inputFileInfo.Data = rom; inputFileInfo.Extension = romextension; CoreComm = comm; Init(Region.PAL); cyclesPerFrame = board.vic.CyclesPerFrame; CoreComm.UsesDriveLed = true; SetupMemoryDomains(); HardReset(); }
// framework public C64(CoreComm comm, GameInfo game, byte[] rom, string romextension) { ServiceProvider = new BasicServiceProvider(this); InputCallbacks = new InputCallbackSystem(); inputFileInfo = new InputFileInfo(); inputFileInfo.Data = rom; inputFileInfo.Extension = romextension; CoreComm = comm; Init(Region.PAL); cyclesPerFrame = board.vic.CyclesPerFrame; SetupMemoryDomains(); HardReset(); (ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(board.vic); }
// get mupenapi internal object public VideoPluginSettings GetVPS(GameInfo game, int videoSizeX, int videoSizeY) { var ret = new VideoPluginSettings(VideoPlugin, videoSizeX, videoSizeY); IPluginSettings ips = null; switch (VideoPlugin) { // clone so per game hacks don't overwrite our settings object case PluginType.Glide: ips = GlidePlugin.Clone(); break; case PluginType.GlideMk2: ips = Glide64mk2Plugin.Clone(); break; case PluginType.Rice: ips = RicePlugin.Clone(); break; case PluginType.Jabo: ips = JaboPlugin.Clone(); break; } ips.FillPerGameHacks(game); ret.Parameters = ips.GetPluginSettings(); return ret; }
public static string FilesystemSafeName(GameInfo game) { var filesystemSafeName = game.Name.Replace("|", "+"); filesystemSafeName = RemoveInvalidFileSystemChars(filesystemSafeName); // zero 22-jul-2012 - i dont think this is used the same way it used to. game.Name shouldnt be a path, so this stuff is illogical. // if game.Name is a path, then someone shouldve made it not-a-path already. // return Path.Combine(Path.GetDirectoryName(filesystemSafeName), Path.GetFileNameWithoutExtension(filesystemSafeName)); // adelikat: // This hack is to prevent annoying things like Super Mario Bros..bk2 if (filesystemSafeName.EndsWith(".")) { return filesystemSafeName.Remove(filesystemSafeName.Length - 1, 1); } return filesystemSafeName; }
// 21,477,270 Machine clocks / sec // 7,159,090 Cpu cycles / sec public PCEngine(CoreComm comm, GameInfo game, byte[] rom, object Settings, object syncSettings) { CoreComm = comm; CoreComm.CpuTraceAvailable = true; switch (game.System) { case "PCE": systemid = "PCE"; Type = NecSystemType.TurboGrafx; break; case "SGX": systemid = "SGX"; Type = NecSystemType.SuperGrafx; break; } this._settings = (PCESettings)Settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings(); Init(game, rom); SetControllerButtons(); }
public Atari7800(CoreComm comm, GameInfo game, byte[] rom, string GameDBfn) { ServiceProvider = new BasicServiceProvider(this); (ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(avProvider); InputCallbacks = new InputCallbackSystem(); CoreComm = comm; byte[] highscoreBIOS = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS."); byte[] pal_bios = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available."); byte[] ntsc_bios = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available."); if (EMU7800.Win.GameProgramLibrary.EMU7800DB == null) { EMU7800.Win.GameProgramLibrary.EMU7800DB = new EMU7800.Win.GameProgramLibrary(new StreamReader(GameDBfn)); } if (rom.Length % 1024 == 128) { Console.WriteLine("Trimming 128 byte .a78 header..."); byte[] newrom = new byte[rom.Length - 128]; Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length); rom = newrom; } GameInfo = EMU7800.Win.GameProgramLibrary.EMU7800DB.TryRecognizeRom(rom); CoreComm.RomStatusDetails = GameInfo.ToString(); Console.WriteLine("Rom Determiniation from 7800DB:"); Console.WriteLine(GameInfo.ToString()); this.rom = rom; this.game = game; this.hsbios = highscoreBIOS; this.bios = GameInfo.MachineType == MachineType.A7800PAL ? pal_bios : ntsc_bios; _pal = GameInfo.MachineType == MachineType.A7800PAL || GameInfo.MachineType == MachineType.A2600PAL; if (bios == null) { throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games."); } HardReset(); }
/// <summary> /// instatiate an emulator core /// </summary> /// <param name="comm"></param> /// <param name="game"></param> /// <param name="rom"></param> /// <param name="deterministic"></param> /// <param name="settings"></param> /// <param name="syncsettings"></param> /// <returns></returns> public IEmulator Create ( CoreComm comm, GameInfo game, byte[] rom, byte[] file, bool deterministic, object settings, object syncsettings ) { object[] o = new object[parammap.Count]; bp(o, "comm", comm); bp(o, "game", game); bp(o, "rom", rom); bp(o, "file", file); bp(o, "deterministic", deterministic); bp(o, "settings", settings); bp(o, "syncsettings", syncsettings); return (IEmulator)CTor.Invoke(o); }
public GambatteLink(CoreComm comm, GameInfo leftinfo, byte[] leftrom, GameInfo rightinfo, byte[] rightrom, object Settings, object SyncSettings, bool deterministic) { GambatteLinkSettings _Settings = (GambatteLinkSettings)Settings ?? new GambatteLinkSettings(); GambatteLinkSyncSettings _SyncSettings = (GambatteLinkSyncSettings)SyncSettings ?? new GambatteLinkSyncSettings(); CoreComm = comm; L = new Gameboy(new CoreComm(comm.ShowMessage, comm.Notify), leftinfo, leftrom, _Settings.L, _SyncSettings.L, deterministic); R = new Gameboy(new CoreComm(comm.ShowMessage, comm.Notify), rightinfo, rightrom, _Settings.R, _SyncSettings.R, deterministic); // connect link cable LibGambatte.gambatte_linkstatus(L.GambatteState, 259); LibGambatte.gambatte_linkstatus(R.GambatteState, 259); L.Controller = LCont; R.Controller = RCont; comm.VsyncNum = L.CoreComm.VsyncNum; comm.VsyncDen = L.CoreComm.VsyncDen; comm.RomStatusAnnotation = null; comm.RomStatusDetails = "LEFT:\r\n" + L.CoreComm.RomStatusDetails + "RIGHT:\r\n" + R.CoreComm.RomStatusDetails; comm.CpuTraceAvailable = false; // TODO comm.NominalWidth = L.CoreComm.NominalWidth + R.CoreComm.NominalWidth; comm.NominalHeight = L.CoreComm.NominalHeight; Frame = 0; LagCount = 0; IsLagFrame = false; blip_left = new BlipBuffer(1024); blip_right = new BlipBuffer(1024); blip_left.SetRates(2097152 * 2, 44100); blip_right.SetRates(2097152 * 2, 44100); SetMemoryDomains(); L.CoreComm.InputCallback = CoreComm.InputCallback; R.CoreComm.InputCallback = CoreComm.InputCallback; }
// framework public C64(CoreComm comm, GameInfo game, byte[] rom, string romextension, object settings, object syncSettings) { PutSyncSettings((C64SyncSettings)syncSettings ?? new C64SyncSettings()); PutSettings((C64Settings)settings ?? new C64Settings()); ServiceProvider = new BasicServiceProvider(this); InputCallbacks = new InputCallbackSystem(); _inputFileInfo = new InputFileInfo { Data = rom, Extension = romextension }; CoreComm = comm; Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType); _cyclesPerFrame = _board.Vic.CyclesPerFrame; SetupMemoryDomains(_board.DiskDrive != null); _memoryCallbacks = new MemoryCallbackSystem(); HardReset(); switch (SyncSettings.VicType) { case VicType.Ntsc: case VicType.Drean: case VicType.NtscOld: Region = DisplayType.NTSC; break; case VicType.Pal: Region = DisplayType.PAL; break; } ((BasicServiceProvider) ServiceProvider).Register<IVideoProvider>(_board.Vic); ((BasicServiceProvider) ServiceProvider).Register<IDriveLight>(_board.Serial); }
public Intellivision(CoreComm comm, GameInfo game, byte[] rom) { ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; _rom = rom; _gameInfo = game; _cart = new Intellicart(); if (_cart.Parse(_rom) == -1) { _cart = new Cartridge(); _cart.Parse(_rom); } _cpu = new CP1610(); _cpu.ReadMemory = ReadMemory; _cpu.WriteMemory = WriteMemory; _cpu.Reset(); _stic = new STIC(); _stic.ReadMemory = ReadMemory; _stic.WriteMemory = WriteMemory; _stic.Reset(); (ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(_stic); _psg = new PSG(); _psg.ReadMemory = ReadMemory; _psg.WriteMemory = WriteMemory; Connect(); _cpu.LogData(); LoadExecutiveRom(CoreComm.CoreFileProvider.GetFirmware("INTV", "EROM", true, "Executive ROM is required.")); LoadGraphicsRom(CoreComm.CoreFileProvider.GetFirmware("INTV", "GROM", true, "Graphics ROM is required.")); }
public Lynx(byte[] file, GameInfo game, CoreComm comm) { ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; byte[] bios = CoreComm.CoreFileProvider.GetFirmware("Lynx", "Boot", true, "Boot rom is required"); if (bios.Length != 512) throw new MissingFirmwareException("Lynx Bootrom must be 512 bytes!"); int pagesize0 = 0; int pagesize1 = 0; byte[] realfile = null; { var ms = new MemoryStream(file, false); var br = new BinaryReader(ms); string header = Encoding.ASCII.GetString(br.ReadBytes(4)); int p0 = br.ReadUInt16(); int p1 = br.ReadUInt16(); int ver = br.ReadUInt16(); string cname = Encoding.ASCII.GetString(br.ReadBytes(32)).Trim(); string mname = Encoding.ASCII.GetString(br.ReadBytes(16)).Trim(); int rot = br.ReadByte(); ms.Position = 6; string bs93 = Encoding.ASCII.GetString(br.ReadBytes(6)); if (bs93 == "BS93") throw new InvalidOperationException("Unsupported BS93 Lynx ram image"); if (header == "LYNX" && (ver & 255) == 1) { Console.WriteLine("Processing Handy-Lynx header"); pagesize0 = p0; pagesize1 = p1; Console.WriteLine("TODO: Rotate {0}", rot); Console.WriteLine("Cart: {0} Manufacturer: {1}", cname, mname); realfile = new byte[file.Length - 64]; Buffer.BlockCopy(file, 64, realfile, 0, realfile.Length); Console.WriteLine("Header Listed banking: {0} {1}", p0, p1); } else { Console.WriteLine("No Handy-Lynx header found! Assuming raw rom image."); realfile = file; } } if (game.OptionPresent("pagesize0")) { pagesize0 = int.Parse(game.OptionValue("pagesize0")); pagesize1 = int.Parse(game.OptionValue("pagesize1")); Console.WriteLine("Loading banking options {0} {1} from gamedb", pagesize0, pagesize1); } if (pagesize0 == 0 && pagesize1 == 0) { switch (realfile.Length) { case 0x10000: pagesize0 = 0x100; break; case 0x20000: pagesize0 = 0x200; break; // case 0x40000: pagesize0 = 0x400; break; // all known good dumps fall in one of these three categories case 0x80000: pagesize0 = 0x800; break; // case 0x30000: pagesize0 = 0x200; pagesize1 = 0x100; break; case 0x50000: pagesize0 = 0x400; pagesize1 = 0x100; break; case 0x60000: pagesize0 = 0x400; pagesize1 = 0x200; break; case 0x90000: pagesize0 = 0x800; pagesize1 = 0x100; break; case 0xa0000: pagesize0 = 0x800; pagesize1 = 0x200; break; case 0xc0000: pagesize0 = 0x800; pagesize1 = 0x400; break; case 0x100000: pagesize0 = 0x800; pagesize1 = 0x800; break; } Console.WriteLine("Auto-guessed banking options {0} {1}", pagesize0, pagesize1); } Core = LibLynx.Create(realfile, realfile.Length, bios, bios.Length, pagesize0, pagesize1, false); try { CoreComm.VsyncNum = 16000000; // 16.00 mhz refclock CoreComm.VsyncDen = 16 * 105 * 159; savebuff = new byte[LibLynx.BinStateSize(Core)]; savebuff2 = new byte[savebuff.Length + 13]; int rot = game.OptionPresent("rotate") ? int.Parse(game.OptionValue("rotate")) : 0; LibLynx.SetRotation(Core, rot); if ((rot & 1) != 0) { BufferWidth = HEIGHT; BufferHeight = WIDTH; } else { BufferWidth = WIDTH; BufferHeight = HEIGHT; } SetupMemoryDomains(); } catch { Dispose(); throw; } }
void InitializeCartHardware(GameInfo game) { LogCartInfo(); InitializeEeprom(game); InitializeSaveRam(game); }
public PCEngine(CoreComm comm, GameInfo game, Disc disc, object Settings, object syncSettings) { CoreComm = comm; CoreComm.CpuTraceAvailable = true; CoreComm.UsesDriveLed = true; systemid = "PCECD"; Type = NecSystemType.TurboCD; this.disc = disc; this._settings = (PCESettings)Settings ?? new PCESettings(); _syncSettings = (PCESyncSettings)syncSettings ?? new PCESyncSettings(); GameInfo biosInfo; byte[] rom = CoreComm.CoreFileProvider.GetFirmwareWithGameInfo("PCECD", "Bios", true, out biosInfo, "PCE-CD System Card not found. Please check the BIOS settings in Config->Firmwares."); if (biosInfo.Status == RomStatus.BadDump) { CoreComm.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) { CoreComm.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. CoreComm.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"]) { game.AddOption("SuperSysCard"); } if (game["NeedSuperSysCard"] && game["SuperSysCard"] == false) { CoreComm.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(); } game.FirmwareHash = rom.HashSHA1(); Init(game, rom); // the default RomStatusDetails don't do anything with Disc CoreComm.RomStatusDetails = string.Format("{0}\r\nDisk partial hash:{1}", game.Name, disc.GetHash()); SetControllerButtons(); }
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(); } }
public static string GetCheatsPath(GameInfo game) { var pathEntry = Global.Config.PathEntries[game.System, "Cheats"] ?? Global.Config.PathEntries[game.System, "Base"]; return MakeAbsolutePath(pathEntry.Path, game.System); }
public static string ScreenshotPrefix(GameInfo game) { var name = FilesystemSafeName(game); var pathEntry = Global.Config.PathEntries[game.System, "Screenshots"] ?? Global.Config.PathEntries[game.System, "Base"]; return Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name); }
public static string SaveStatePrefix(GameInfo game) { var name = FilesystemSafeName(game); // Neshawk and Quicknes have incompatible savestates, store the name to keep them separate if (Global.Emulator.SystemId == "NES") { name += "." + Global.Emulator.Attributes().CoreName; } // Bsnes profiles have incompatible savestates so save the profile name if (Global.Emulator is LibsnesCore) { name += "." + (Global.Emulator as LibsnesCore).CurrentProfile; } if (Global.Emulator.SystemId == "GBA") { name += "." + Global.Emulator.Attributes().CoreName; } if (Global.MovieSession.Movie.IsActive) { name += "." + Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename); } var pathEntry = Global.Config.PathEntries[game.System, "Savestates"] ?? Global.Config.PathEntries[game.System, "Base"]; return Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name); }
public static string SaveRamPath(GameInfo game) { var name = FilesystemSafeName(game); if (Global.MovieSession.Movie.IsActive) { name += "." + Path.GetFileNameWithoutExtension(Global.MovieSession.Movie.Filename); } var pathEntry = Global.Config.PathEntries[game.System, "Save RAM"] ?? Global.Config.PathEntries[game.System, "Base"]; return Path.Combine(MakeAbsolutePath(pathEntry.Path, game.System), name) + ".SaveRAM"; }
public static GameInfo GetGameInfo(byte[] romData, string fileName) { CompactGameInfo cgi; var hash = $"{CRC32.Calculate(romData):X8}"; if (DB.TryGetValue(hash, out cgi)) { return(new GameInfo(cgi)); } hash = romData.HashMD5(); if (DB.TryGetValue(hash, out cgi)) { return(new GameInfo(cgi)); } hash = romData.HashSHA1(); if (DB.TryGetValue(hash, out cgi)) { return(new GameInfo(cgi)); } // rom is not in database. make some best-guesses var game = new GameInfo { Hash = hash, Status = RomStatus.NotInDatabase, NotInDatabase = true }; Console.WriteLine( "Game was not in DB. CRC: {0:X8} MD5: {1}", CRC32.Calculate(romData), System.Security.Cryptography.MD5.Create().ComputeHash(romData).BytesToHexString()); var ext = Path.GetExtension(fileName)?.ToUpperInvariant(); switch (ext) { case ".NES": case ".UNF": case ".FDS": game.System = "NES"; break; case ".SFC": case ".SMC": game.System = "SNES"; break; case ".GB": game.System = "GB"; break; case ".GBC": game.System = "GBC"; break; case ".GBA": game.System = "GBA"; break; case ".SMS": game.System = "SMS"; break; case ".GG": game.System = "GG"; break; case ".SG": game.System = "SG"; break; case ".GEN": case ".MD": case ".SMD": game.System = "GEN"; break; case ".PSF": case ".MINIPSF": game.System = "PSX"; break; case ".PCE": game.System = "PCE"; break; case ".SGX": game.System = "SGX"; break; case ".A26": game.System = "A26"; break; case ".A78": game.System = "A78"; break; case ".COL": game.System = "Coleco"; break; case ".INT": game.System = "INTV"; break; case ".PRG": case ".D64": case ".T64": case ".G64": case ".CRT": game.System = "C64"; break; case ".TZX": case ".PZX": case ".CSW": case ".WAV": game.System = "ZXSpectrum"; break; case ".CDT": game.System = "AmstradCPC"; break; case ".TAP": byte[] head = romData.Take(8).ToArray(); if (System.Text.Encoding.Default.GetString(head).Contains("C64-TAPE")) { game.System = "C64"; } else { game.System = "ZXSpectrum"; } break; case ".Z64": case ".V64": case ".N64": game.System = "N64"; break; case ".DEBUG": game.System = "DEBUG"; break; case ".WS": case ".WSC": game.System = "WSWAN"; break; case ".LNX": game.System = "Lynx"; break; case ".83P": game.System = "83P"; break; case ".DSK": var dId = new DSKIdentifier(romData); game.System = dId.IdentifiedSystem; break; case ".PO": case ".DO": game.System = "AppleII"; break; case ".VB": game.System = "VB"; break; case ".NGP": case ".NGC": game.System = "NGP"; break; case ".O2": game.System = "O2"; break; case ".UZE": game.System = "UZE"; break; case ".32X": game.System = "32X"; game.AddOption("32X", "true"); break; case ".VEC": game.System = "VEC"; game.AddOption("VEC", "true"); break; // refactor to use mame db (output of "mame -listxml" command) // there's no good definition for Arcade anymore, so we might limit to coin-based machines? case ".ZIP": game.System = "Arcade"; break; } game.Name = Path.GetFileNameWithoutExtension(fileName)?.Replace('_', ' '); // If filename is all-caps, then attempt to proper-case the title. if (!string.IsNullOrWhiteSpace(game.Name) && game.Name == game.Name.ToUpperInvariant()) { game.Name = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(game.Name.ToLower()); } return(game); }
public XmlGame() { Assets = new List<KeyValuePair<string, byte[]>>(); AssetFullPaths = new List<string>(); GI = new GameInfo(); }
public byte[] GetFirmwareWithGameInfo(string sysID, string firmwareID, bool required, out GameInfo gi, string msg = null) { string path; byte[] ret = GetFirmwareWithPath(sysID, firmwareID, required, msg, out path); if (ret != null && path != null) { gi = Database.GetGameInfo(ret, path); } else { gi = null; } return ret; }
public void FillPerGameHacks(GameInfo game) { if (UseDefaultHacks) { alt_tex_size = game.GetBool("Glide_alt_tex_size", false); buff_clear = game.GetBool("Glide_buff_clear", true); decrease_fillrect_edge = game.GetBool("Glide_decrease_fillrect_edge", false); detect_cpu_write = game.GetBool("Glide_detect_cpu_write", false); fb_clear = game.GetBool("Glide_fb_clear", false); fb_hires = game.GetBool("Glide_fb_clear", true); fb_read_alpha = game.GetBool("Glide_fb_read_alpha", false); fb_smart = game.GetBool("Glide_fb_smart", false); fillcolor_fix = game.GetBool("Glide_fillcolor_fix", false); fog = game.GetBool("Glide_fog", true); force_depth_compare = game.GetBool("Glide_force_depth_compare", false); force_microcheck = game.GetBool("Glide_force_microcheck", false); fb_hires_buf_clear = game.GetBool("Glide_fb_hires_buf_clear", true); fb_ignore_aux_copy = game.GetBool("Glide_fb_ignore_aux_copy", false); fb_ignore_previous = game.GetBool("Glide_fb_ignore_previous", false); increase_primdepth = game.GetBool("Glide_increase_primdepth", false); increase_texrect_edge = game.GetBool("Glide_increase_texrect_edge", false); fb_optimize_texrect = game.GetBool("Glide_fb_optimize_texrect", true); fb_optimize_write = game.GetBool("Glide_fb_optimize_write", false); PPL = game.GetBool("Glide_PPL", false); soft_depth_compare = game.GetBool("Glide_soft_depth_compare", false); use_sts1_only = game.GetBool("Glide_use_sts1_only", false); wrap_big_tex = game.GetBool("Glide_wrap_big_tex", false); depth_bias = game.GetInt("Glide_depth_bias", 20); filtering = game.GetInt("Glide_filtering", 1); fix_tex_coord = game.GetInt("Glide_fix_tex_coord", 0); lodmode = game.GetInt("Glide_lodmode", 0); stipple_mode = game.GetInt("Glide_stipple_mode", 2); stipple_pattern = game.GetInt("Glide_stipple_pattern", 1041204192); swapmode = game.GetInt("Glide_swapmode", 1); enable_hacks_for_game = game.GetInt("Glide_enable_hacks_for_game", 0); } }
public static GameInfo GetGameInfo(byte[] romData, string fileName) { CompactGameInfo cgi; var hash = string.Format("{0:X8}", CRC32.Calculate(romData)); if (db.TryGetValue(hash, out cgi)) { return(new GameInfo(cgi)); } hash = romData.HashMD5(); if (db.TryGetValue(hash, out cgi)) { return(new GameInfo(cgi)); } hash = romData.HashSHA1(); if (db.TryGetValue(hash, out cgi)) { return(new GameInfo(cgi)); } // rom is not in database. make some best-guesses var game = new GameInfo { Hash = hash, Status = RomStatus.NotInDatabase, NotInDatabase = true }; Console.WriteLine( "Game was not in DB. CRC: {0:X8} MD5: {1}", CRC32.Calculate(romData), System.Security.Cryptography.MD5.Create().ComputeHash(romData).BytesToHexString()); var ext = Path.GetExtension(fileName).ToUpperInvariant(); switch (ext) { case ".NES": case ".UNF": case ".FDS": game.System = "NES"; break; case ".SFC": case ".SMC": game.System = "SNES"; break; case ".GB": game.System = "GB"; break; case ".GBC": game.System = "GBC"; break; case ".GBA": game.System = "GBA"; break; case ".SMS": game.System = "SMS"; break; case ".GG": game.System = "GG"; break; case ".SG": game.System = "SG"; break; case ".GEN": case ".MD": case ".SMD": game.System = "GEN"; break; case ".PSF": case ".MINIPSF": game.System = "PSX"; break; case ".PCE": game.System = "PCE"; break; case ".SGX": game.System = "SGX"; break; case ".A26": game.System = "A26"; break; case ".A78": game.System = "A78"; break; case ".COL": game.System = "Coleco"; break; case ".INT": game.System = "INTV"; break; case ".PRG": case ".D64": case ".T64": case ".G64": case ".CRT": case ".TAP": game.System = "C64"; break; case ".Z64": case ".V64": case ".N64": game.System = "N64"; break; case ".DEBUG": game.System = "DEBUG"; break; case ".WS": case ".WSC": game.System = "WSWAN"; break; case ".LNX": game.System = "Lynx"; break; case ".83P": game.System = "83P"; break; case ".DSK": case ".PO": case ".DO": game.System = "AppleII"; break; } game.Name = Path.GetFileNameWithoutExtension(fileName).Replace('_', ' '); // If filename is all-caps, then attempt to proper-case the title. if (game.Name == game.Name.ToUpperInvariant()) { game.Name = Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(game.Name.ToLower()); } return(game); }
void Init(GameInfo game, byte[] rom) { Controller = NullController.GetNullController(); Cpu = new HuC6280(CoreComm); VCE = new VCE(); VDC1 = new VDC(this, Cpu, VCE); PSG = new HuC6280PSG(); SCSI = new ScsiCDBus(this, disc); Cpu.Logger = (s) => CoreComm.Tracer.Put(s); if (TurboGrafx) { Ram = new byte[0x2000]; Cpu.ReadMemory21 = ReadMemory; Cpu.WriteMemory21 = WriteMemory; Cpu.WriteVDC = VDC1.WriteVDC; soundProvider = PSG; CDAudio = new CDAudio(null, 0); } else if (SuperGrafx) { VDC2 = new VDC(this, Cpu, VCE); VPC = new VPC(this, VDC1, VDC2, VCE, Cpu); Ram = new byte[0x8000]; Cpu.ReadMemory21 = ReadMemorySGX; Cpu.WriteMemory21 = WriteMemorySGX; Cpu.WriteVDC = VDC1.WriteVDC; soundProvider = PSG; CDAudio = new CDAudio(null, 0); } else if (TurboCD) { Ram = new byte[0x2000]; CDRam = new byte[0x10000]; ADPCM = new ADPCM(this, SCSI); Cpu.ReadMemory21 = ReadMemoryCD; Cpu.WriteMemory21 = WriteMemoryCD; Cpu.WriteVDC = VDC1.WriteVDC; CDAudio = new CDAudio(disc); SetCDAudioCallback(); PSG.MaxVolume = short.MaxValue * 3 / 4; SoundMixer = new SoundMixer(PSG, CDAudio, ADPCM); SoundSynchronizer = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V); soundProvider = SoundSynchronizer; Cpu.ThinkAction = (cycles) => { SCSI.Think(); ADPCM.Think(cycles); }; } if (rom.Length == 0x60000) { // 384k roms require special loading code. Why ;_; // In memory, 384k roms look like [1st 256k][Then full 384k] RomData = new byte[0xA0000]; var origRom = rom; for (int i = 0; i < 0x40000; i++) RomData[i] = origRom[i]; for (int i = 0; i < 0x60000; i++) RomData[i + 0x40000] = origRom[i]; RomLength = RomData.Length; } else if (rom.Length > 1024 * 1024) { // If the rom is bigger than 1 megabyte, switch to Street Fighter 2 mapper Cpu.ReadMemory21 = ReadMemorySF2; Cpu.WriteMemory21 = WriteMemorySF2; RomData = rom; RomLength = RomData.Length; // user request: current value of the SF2MapperLatch on the tracelogger Cpu.Logger = (s) => CoreComm.Tracer.Put(string.Format("{0:X1}:{1}", SF2MapperLatch, s)); } else { // normal rom. RomData = rom; RomLength = RomData.Length; } if (game["BRAM"] || Type == NecSystemType.TurboCD) { BramEnabled = true; BRAM = new byte[2048]; // pre-format BRAM. damn are we helpful. BRAM[0] = 0x48; BRAM[1] = 0x55; BRAM[2] = 0x42; BRAM[3] = 0x4D; BRAM[4] = 0x00; BRAM[5] = 0x88; BRAM[6] = 0x10; BRAM[7] = 0x80; } if (game["SuperSysCard"]) SuperRam = new byte[0x30000]; if (game["ArcadeCard"]) { ArcadeRam = new byte[0x200000]; ArcadeCard = true; ArcadeCardRewindHack = _settings.ArcadeCardRewindHack; for (int i = 0; i < 4; i++) ArcadePage[i] = new ArcadeCardPage(); } if (game["PopulousSRAM"]) { PopulousRAM = new byte[0x8000]; Cpu.ReadMemory21 = ReadMemoryPopulous; Cpu.WriteMemory21 = WriteMemoryPopulous; } // the gamedb can force sprite limit on, ignoring settings if (game["ForceSpriteLimit"] || game.NotInDatabase) ForceSpriteLimit = true; if (game["CdVol"]) CDAudio.MaxVolume = int.Parse(game.OptionValue("CdVol")); if (game["PsgVol"]) PSG.MaxVolume = int.Parse(game.OptionValue("PsgVol")); if (game["AdpcmVol"]) ADPCM.MaxVolume = int.Parse(game.OptionValue("AdpcmVol")); // the gamedb can also force equalizevolumes on if (TurboCD && (_settings.EqualizeVolume || game["EqualizeVolumes"] || game.NotInDatabase)) SoundMixer.EqualizeVolumes(); // Ok, yes, HBlankPeriod's only purpose is game-specific hax. // 1) At least they're not coded directly into the emulator, but instead data-driven. // 2) The games which have custom HBlankPeriods work without it, the override only // serves to clean up minor gfx anomalies. // 3) There's no point in haxing the timing with incorrect values in an attempt to avoid this. // The proper fix is cycle-accurate/bus-accurate timing. That isn't coming to the C# // version of this core. Let's just acknolwedge that the timing is imperfect and fix // it in the least intrusive and most honest way we can. if (game["HBlankPeriod"]) VDC1.HBlankCycles = game.GetIntValue("HBlankPeriod"); // This is also a hack. Proper multi-res/TV emulation will be a native-code core feature. if (game["MultiResHack"]) VDC1.MultiResHack = game.GetIntValue("MultiResHack"); Cpu.ResetPC(); SetupMemoryDomains(); }