public PSP(CoreComm comm, string isopath) { ServiceProvider = new BasicServiceProvider(this); if (attachedcore != null) { attachedcore.Dispose(); attachedcore = null; } CoreComm = comm; logcallback = new PPSSPPDll.LogCB(LogCallbackFunc); bool good = PPSSPPDll.init(isopath, logcallback); LogFlush(); if (!good) throw new Exception("PPSSPP Init failed!"); vidhandle = GCHandle.Alloc(screenbuffer, GCHandleType.Pinned); PPSSPPDll.setvidbuff(vidhandle.AddrOfPinnedObject()); CoreComm.VsyncDen = 1; CoreComm.VsyncNum = 60; CoreComm.RomStatusDetails = "It puts the scythe in the chicken or it gets the abyss again!"; attachedcore = this; }
public PSP(CoreComm comm, string isopath) { ServiceProvider = new BasicServiceProvider(this); if (attachedcore != null) { attachedcore.Dispose(); attachedcore = null; } CoreComm = comm; glcontext = CoreComm.RequestGLContext(3, 0, true); CoreComm.ActivateGLContext(glcontext); logcallback = new PPSSPPDll.LogCB(LogCallbackFunc); bool good = PPSSPPDll.BizInit(isopath, logcallback); LogFlush(); if (!good) throw new Exception("PPSSPP Init failed!"); CoreComm.VsyncDen = 1; CoreComm.VsyncNum = 60; CoreComm.RomStatusDetails = "It puts the scythe in the chicken or it gets the abyss again!"; attachedcore = this; }
public GBA(CoreComm comm, byte[] file) { ServiceProvider = new BasicServiceProvider(this); Tracer = new TraceBuffer { Header = " -Addr--- -Opcode- -Instruction------------------- -R0----- -R1----- -R2----- -R3----- -R4----- -R5----- -R6----- -R7----- -R8----- -R9----- -R10---- -R11---- -R12---- -R13(SP) -R14(LR) -R15(PC) -CPSR--- -SPSR---" }; (ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer); CoreComm = comm; comm.VsyncNum = 262144; comm.VsyncDen = 4389; comm.NominalWidth = 240; comm.NominalHeight = 160; byte[] bios = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory."); if (bios.Length != 16384) throw new InvalidDataException("GBA bios must be exactly 16384 bytes!"); if (file.Length > 32 * 1024 * 1024) throw new InvalidDataException("Rom file is too big! No GBA game is larger than 32MB"); Init(); LibMeteor.libmeteor_hardreset(); LibMeteor.libmeteor_loadbios(bios, (uint)bios.Length); LibMeteor.libmeteor_loadrom(file, (uint)file.Length); SetUpMemoryDomains(); }
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()); }
public Snes9x(CoreComm comm, byte[] rom) { if (!LibSnes9x.debug_init(rom, rom.Length)) throw new Exception(); ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; }
// 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); }
public WonderSwan(CoreComm comm, byte[] file, bool deterministic, object Settings, object SyncSettings) { ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; _Settings = (Settings)Settings ?? new Settings(); _SyncSettings = (SyncSettings)SyncSettings ?? new SyncSettings(); DeterministicEmulation = deterministic; // when true, remember to force the RTC flag! Core = BizSwan.bizswan_new(); if (Core == IntPtr.Zero) throw new InvalidOperationException("bizswan_new() returned NULL!"); try { var ss = _SyncSettings.GetNativeSettings(); if (deterministic) ss.userealtime = false; bool rotate = false; if (!BizSwan.bizswan_load(Core, file, file.Length, ref ss, ref rotate)) throw new InvalidOperationException("bizswan_load() returned FALSE!"); CoreComm.VsyncNum = 3072000; // master CPU clock, also pixel clock CoreComm.VsyncDen = (144 + 15) * (224 + 32); // 144 vislines, 15 vblank lines; 224 vispixels, 32 hblank pixels InitISaveRam(); InitVideo(rotate); PutSettings(_Settings); InitIMemoryDomains(); InitIStatable(); InitDebugCallbacks(); } catch { Dispose(); throw; } }
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(); }
public LibRetroEmulator(CoreComm nextComm, string modulename) { ServiceProvider = new BasicServiceProvider(this); retro_environment_cb = new LibRetro.retro_environment_t(retro_environment); retro_video_refresh_cb = new LibRetro.retro_video_refresh_t(retro_video_refresh); retro_audio_sample_cb = new LibRetro.retro_audio_sample_t(retro_audio_sample); retro_audio_sample_batch_cb = new LibRetro.retro_audio_sample_batch_t(retro_audio_sample_batch); retro_input_poll_cb = new LibRetro.retro_input_poll_t(retro_input_poll); retro_input_state_cb = new LibRetro.retro_input_state_t(retro_input_state); retro = new LibRetro(modulename); try { CoreComm = nextComm; LibRetro.retro_system_info sys = new LibRetro.retro_system_info(); retro.retro_get_system_info(ref sys); if (sys.need_fullpath) throw new ArgumentException("This libretro core needs filepaths"); if (sys.block_extract) throw new ArgumentException("This libretro needs non-blocked extract"); retro.retro_set_environment(retro_environment_cb); retro.retro_init(); retro.retro_set_video_refresh(retro_video_refresh_cb); retro.retro_set_audio_sample(retro_audio_sample_cb); retro.retro_set_audio_sample_batch(retro_audio_sample_batch_cb); retro.retro_set_input_poll(retro_input_poll_cb); retro.retro_set_input_state(retro_input_state_cb); } catch { retro.Dispose(); throw; } }
public C64(CoreComm comm, IEnumerable<byte[]> roms, object settings, object syncSettings) { PutSyncSettings((C64SyncSettings)syncSettings ?? new C64SyncSettings()); PutSettings((C64Settings)settings ?? new C64Settings()); ServiceProvider = new BasicServiceProvider(this); InputCallbacks = new InputCallbackSystem(); CoreComm = comm; Roms = roms; 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; } if (_board.Sid != null) { SyncSoundProvider = DCFilter.AsISyncSoundProvider(_board.Sid, 512); } DeterministicEmulation = true; ((BasicServiceProvider) ServiceProvider).Register<IVideoProvider>(_board.Vic); ((BasicServiceProvider) ServiceProvider).Register<IDriveLight>(this); }
// 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 NES(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { var ser = new BasicServiceProvider(this); ServiceProvider = ser; 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; } SyncSettings = (NESSyncSettings)syncSettings ?? new NESSyncSettings(); ControllerSettings = SyncSettings.Controls; BootGodDb.Initialize(); videoProvider = new MyVideoProvider(this); Init(game, rom, fdsBios); if (Board is FDS fds) { DriveLightEnabled = true; fds.SetDriveLightCallback(val => DriveLightOn = val); // bit of a hack: we don't have a private gamedb for FDS, but the frontend // expects this to be set. RomStatus = game.Status; } PutSettings((NESSettings)settings ?? new NESSettings()); // we need to put this here because the line directly above will overwrite palette intialization anywhere else // TODO: What if settings are later loaded? if (_isVS) { PickVSPalette(cart); } ser.Register <IDisassemblable>(cpu); Tracer = new TraceBuffer { Header = cpu.TraceHeader }; ser.Register <ITraceable>(Tracer); ser.Register <IVideoProvider>(videoProvider); ser.Register <ISoundProvider>(this); ser.Register <IStatable>(new StateSerializer(SyncState) { LoadStateCallback = SetupMemoryDomains }); if (Board is BANDAI_FCG_1 bandai) { var reader = bandai.reader; // not all BANDAI FCG 1 boards have a barcode reader if (reader != null) { ser.Register(reader); } } }
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 { _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; } }
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, ReadHook_SMP = ReadHook_SMP, ExecHook_SMP = ExecHook_SMP, WriteHook_SMP = WriteHook_SMP, }; 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(); }
public A7800Hawk(CoreComm comm, byte[] rom, object settings, object syncSettings) { var ser = new BasicServiceProvider(this); maria = new Maria(); tia = new TIA(); m6532 = new M6532(); pokey = new Pokey(); cpu = new MOS6502X <CpuLink>(new CpuLink(this)); maria = new Maria { ReadMemory = ReadMemory }; _blip.SetRates(1789773, 44100); _settings = (A7800Settings)settings ?? new A7800Settings(); _syncSettings = (A7800SyncSettings)syncSettings ?? new A7800SyncSettings(); _controllerDeck = new A7800HawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2); byte[] highscoreBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_HSC", false, "Some functions may not work without the high score BIOS."); byte[] palBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_PAL", false, "The game will not run if the correct region BIOS is not available."); byte[] ntscBios = comm.CoreFileProvider.GetFirmware("A78", "Bios_NTSC", false, "The game will not run if the correct region BIOS is not available."); byte[] header = new byte[128]; bool is_header = false; if (rom.Length % 1024 == 128) { Console.WriteLine("128 byte header detected"); byte[] newrom = new byte[rom.Length - 128]; is_header = true; Buffer.BlockCopy(rom, 0, header, 0, 128); Buffer.BlockCopy(rom, 128, newrom, 0, newrom.Length); rom = newrom; } _isPAL = false; // look up hash in gamedb to see what mapper to use // if none found default is zero // also check for PAL region string hash_md5 = null; s_mapper = null; hash_md5 = "md5:" + rom.HashMD5(0, rom.Length); var gi = Database.CheckDatabase(hash_md5); if (gi != null) { var dict = gi.GetOptionsDict(); if (dict.ContainsKey("PAL")) { _isPAL = true; } if (dict.ContainsKey("board")) { s_mapper = dict["board"]; } else { throw new Exception("No Board selected for this game"); } // check if the game uses pokey or RAM if (dict.ContainsKey("RAM")) { int.TryParse(dict["RAM"], out cart_RAM); Console.WriteLine(cart_RAM); } if (dict.ContainsKey("Pokey")) { bool.TryParse(dict["Pokey"], out is_pokey); } // some games will not function with the high score bios // if such a game is being played, tell the user and disable it if (dict.ContainsKey("No_HS")) { bool.TryParse(dict["No_HS"], out var no_hs); if (no_hs) { Console.WriteLine("This game is incompatible with the High Score BIOS, disabling it"); highscoreBios = null; } } } else if (is_header) { Console.WriteLine("ROM not in DB, inferring mapper info from header"); byte cart_1 = header[0x35]; byte cart_2 = header[0x36]; _isPAL = (header[0x39] > 0); if (cart_2.Bit(1)) { if (cart_2.Bit(3)) { s_mapper = "2"; } else { s_mapper = "1"; } if (cart_2.Bit(2)) { cart_RAM = 8; } } else { s_mapper = "0"; } if (cart_2.Bit(0)) { is_pokey = true; } } else { throw new Exception("ROM not in gamedb and has no header"); } // some games that use the Super Game mapper only have 4 banks, so let's set a flag to limit bank size if (rom.Length < 0x14000) { small_flag = true; // additionally, PAL Karateka has bank 6 (actually 2) at 0x4000 if (rom.HashMD5() == "5E0A1E832BBCEA6FACB832FDE23A440A") { PAL_Kara = true; } } _rom = rom; Reset_Mapper(s_mapper); _hsbios = highscoreBios; _bios = _isPAL ? palBios : ntscBios; if (_bios == null) { throw new MissingFirmwareException("The BIOS corresponding to the region of the game you loaded is required to run Atari 7800 games."); } // set up palette and frame rate if (_isPAL) { _frameHz = 50; _screen_width = 320; _screen_height = 313; _vblanklines = 20; maria._palette = PALPalette; } else { _frameHz = 60; _screen_width = 320; _screen_height = 263; _vblanklines = 20; maria._palette = NTSCPalette; } maria.Core = this; m6532.Core = this; tia.Core = this; pokey.Core = this; ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(this); ServiceProvider = ser; _tracer = new TraceBuffer { Header = cpu.TraceHeader }; ser.Register <ITraceable>(_tracer); ser.Register <IStatable>(new StateSerializer(SyncState)); SetupMemoryDomains(); ser.Register <IDisassemblable>(cpu); HardReset(); }
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings) { 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 (rom != null && rom.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } try { Elf = new ElfRunner(Path.Combine(comm.CoreFileProvider.DllPath(), "gpgx.elf"), 8 * 1024 * 1024, 36 * 1024 * 1024, 4 * 1024 * 1024); if (Elf.ShouldMonitor) { Core = BizInvoker.GetInvoker <LibGPGX>(Elf, Elf); } else { Core = BizInvoker.GetInvoker <LibGPGX>(Elf); } _syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings(); _settings = (GPGXSettings)Settings ?? new GPGXSettings(); CoreComm = comm; LoadCallback = new LibGPGX.load_archive_cb(load_archive); this.romfile = rom; this.CD = CD; if (CD != null) { this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); Core.gpgx_set_cdd_callback(cd_callback_handle); } LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; switch (_syncSettings.ControlType) { case ControlType.None: default: break; case ControlType.Activator: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; break; case ControlType.Normal: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.OnePlayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.Xea1p: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; break; case ControlType.Teamplayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; break; case ControlType.Wayplay: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; break; case ControlType.Mouse: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; // seems like mouse in port 1 would be supported, but not both at the same time system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; break; } if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings())) { throw new Exception("gpgx_init() failed"); } { int fpsnum = 60; int fpsden = 1; Core.gpgx_get_fps(ref fpsnum, ref fpsden); CoreComm.VsyncNum = fpsnum; CoreComm.VsyncDen = fpsden; Region = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL; } // compute state size InitStateBuffers(); SetControllerDefinition(); // pull the default video size from the core UpdateVideoInitial(); SetMemoryDomains(); InputCallback = new LibGPGX.input_cb(input_callback); Core.gpgx_set_input_callback(InputCallback); if (CD != null) { DriveLightEnabled = true; } // process the non-init settings now PutSettings(_settings); //TODO - this hits performance, we need to make it controllable CDCallback = new LibGPGX.CDCallback(CDCallbackProc); InitMemCallbacks(); KillMemCallbacks(); Tracer = new GPGXTraceBuffer(this, MemoryDomains, this); (ServiceProvider as BasicServiceProvider).Register <ITraceable>(Tracer); Elf.Seal(); } catch { Dispose(); throw; } }
public SMS(CoreComm comm, GameInfo game, byte[] rom, SmsSettings settings, SmsSyncSettings syncSettings) { var ser = new BasicServiceProvider(this); ServiceProvider = ser; Settings = (SmsSettings)settings ?? new SmsSettings(); SyncSettings = (SmsSyncSettings)syncSettings ?? new SmsSyncSettings(); IsGameGear = game.System == "GG"; IsGameGear_C = game.System == "GG"; IsSG1000 = game.System == "SG"; RomData = rom; if (RomData.Length % BankSize != 0) { Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } RomBanks = (byte)(RomData.Length / BankSize); Region = DetermineDisplayType(SyncSettings.DisplayType, game.Region); if (game["PAL"] && Region != DisplayType.PAL) { Region = DisplayType.PAL; comm.Notify("Display was forced to PAL mode for game compatibility."); } if (IsGameGear) { Region = DisplayType.NTSC; // all game gears run at 60hz/NTSC mode } _region = SyncSettings.ConsoleRegion; if (_region == SmsSyncSettings.Regions.Auto) { _region = DetermineRegion(game.Region); } if (game["Japan"] && _region != SmsSyncSettings.Regions.Japan) { _region = SmsSyncSettings.Regions.Japan; comm.Notify("Region was forced to Japan for game compatibility."); } if (game["Korea"] && _region != SmsSyncSettings.Regions.Korea) { _region = SmsSyncSettings.Regions.Korea; comm.Notify("Region was forced to Korea for game compatibility."); } if ((game.NotInDatabase || game["FM"]) && SyncSettings.EnableFm && !IsGameGear) { HasYM2413 = true; } Cpu = new Z80A { ReadHardware = ReadPort, WriteHardware = WritePort, FetchMemory = FetchMemory, ReadMemory = ReadMemory, WriteMemory = WriteMemory, MemoryCallbacks = MemoryCallbacks, OnExecFetch = OnExecMemory }; if (game["GG_in_SMS"]) { // skip setting the BIOS because this is a game gear game that puts the system // in SMS compatibility mode (it will fail the check sum if played on an actual SMS though.) IsGameGear = false; IsGameGear_C = true; game.System = "GG"; Console.WriteLine("Using SMS Compatibility mode for Game Gear System"); } Vdp = new VDP(this, Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, Region); ser.Register <IVideoProvider>(Vdp); PSG = new SN76489sms(); YM2413 = new YM2413(); //SoundMixer = new SoundMixer(YM2413, PSG); if (HasYM2413 && game["WhenFMDisablePSG"]) { disablePSG = true; } BlipL.SetRates(3579545, 44100); BlipR.SetRates(3579545, 44100); ser.Register <ISoundProvider>(this); SystemRam = new byte[0x2000]; if (game["CMMapper"]) { InitCodeMastersMapper(); } else if (game["CMMapperWithRam"]) { InitCodeMastersMapperRam(); } else if (game["ExtRam"]) { InitExt2kMapper(int.Parse(game.OptionValue("ExtRam"))); } else if (game["KoreaMapper"]) { InitKoreaMapper(); } else if (game["MSXMapper"]) { InitMSXMapper(); } else if (game["NemesisMapper"]) { InitNemesisMapper(); } else if (game["TerebiOekaki"]) { InitTerebiOekaki(); } else if (game["EEPROM"]) { InitEEPROMMapper(); } else { InitSegaMapper(); } if (Settings.ForceStereoSeparation && !IsGameGear) { if (game["StereoByte"]) { ForceStereoByte = byte.Parse(game.OptionValue("StereoByte")); } PSG.Set_Panning(ForceStereoByte); } if (SyncSettings.AllowOverClock && game["OverclockSafe"]) { Vdp.IPeriod = 512; } if (Settings.SpriteLimit) { Vdp.SpriteLimit = true; } if (game["3D"]) { IsGame3D = true; } if (game["BIOS"]) { Port3E = 0xF7; // Disable cartridge, enable BIOS rom InitBiosMapper(); } else if (game.System == "SMS" && !game["GG_in_SMS"]) { BiosRom = comm.CoreFileProvider.GetFirmware("SMS", _region.ToString(), false); if (BiosRom == null) { throw new MissingFirmwareException("No BIOS found"); } if (!game["RequireBios"] && !SyncSettings.UseBios) { // we are skipping the BIOS // but only if it won't break the game } else { Port3E = 0xF7; } } if (game["SRAM"]) { SaveRAM = new byte[int.Parse(game.OptionValue("SRAM"))]; Console.WriteLine(SaveRAM.Length); } else if (game.NotInDatabase) { SaveRAM = new byte[0x8000]; } SetupMemoryDomains(); //this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete ((ICodeDataLogger)this).SetCDL(null); Tracer = new TraceBuffer { Header = Cpu.TraceHeader }; ser.Register(Tracer); ser.Register <IDisassemblable>(Cpu); ser.Register <IStatable>(new StateSerializer(SyncState)); Vdp.ProcessOverscan(); Cpu.ReadMemory = ReadMemory; Cpu.WriteMemory = WriteMemory; // Z80 SP initialization // stops a few SMS and GG games from crashing Cpu.Regs[Cpu.SPl] = 0xF0; Cpu.Regs[Cpu.SPh] = 0xDF; if (!IsSG1000) { ser.Register <ISmsGpuView>(new SmsGpuView(Vdp)); } }
public Gameboy(CoreComm comm, GameInfo game, byte[] file, GambatteSettings settings, GambatteSyncSettings syncSettings, bool deterministic) { var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(_disassembler); ServiceProvider = ser; const string TRACE_HEADER = "LR35902: PC, opcode, registers (A, F, B, C, D, E, H, L, LY, SP, CY)"; Tracer = new TraceBuffer(TRACE_HEADER); ser.Register <ITraceable>(Tracer); InitMemoryCallbacks(); ThrowExceptionForBadRom(file); BoardName = MapperName(file); DeterministicEmulation = deterministic; GambatteState = LibGambatte.gambatte_create(); if (GambatteState == IntPtr.Zero) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_create)}() returned null???"); } Console.WriteLine(game.System); try { _syncSettings = syncSettings ?? new GambatteSyncSettings(); LibGambatte.LoadFlags flags = LibGambatte.LoadFlags.READONLY_SAV; switch (_syncSettings.ConsoleMode) { case GambatteSyncSettings.ConsoleModeType.GB: break; case GambatteSyncSettings.ConsoleModeType.GBC: flags |= LibGambatte.LoadFlags.CGB_MODE; break; case GambatteSyncSettings.ConsoleModeType.GBA: flags |= LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG; break; default: if (game.System == VSystemID.Raw.GBC) { flags |= LibGambatte.LoadFlags.CGB_MODE; } break; } if (game.System == VSystemID.Raw.SGB) { flags &= ~(LibGambatte.LoadFlags.CGB_MODE | LibGambatte.LoadFlags.GBA_FLAG); flags |= LibGambatte.LoadFlags.SGB_MODE; IsSgb = true; } if (_syncSettings.MulticartCompat) { flags |= LibGambatte.LoadFlags.MULTICART_COMPAT; } IsCgb = (flags & LibGambatte.LoadFlags.CGB_MODE) == LibGambatte.LoadFlags.CGB_MODE; if (_syncSettings.EnableBIOS) { FirmwareID fwid = new( IsCgb ? "GBC" : "GB", IsSgb ? "SGB2" : _syncSettings.ConsoleMode is GambatteSyncSettings.ConsoleModeType.GBA ? "AGB" : "World"); var bios = comm.CoreFileProvider.GetFirmwareOrThrow(fwid, "BIOS Not Found, Cannot Load. Change SyncSettings to run without BIOS."); // https://github.com/TASEmulators/BizHawk/issues/2832 tho if (LibGambatte.gambatte_loadbiosbuf(GambatteState, bios, (uint)bios.Length) != 0) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbiosbuf)}() returned non-zero (bios error)"); } } else { if (DeterministicEmulation) // throw a warning if a movie is being recorded with the bios disabled { comm.ShowMessage("Detected disabled BIOS during movie recording. It is recommended to use a BIOS for movie recording. Change Sync Settings to run with a BIOS."); } flags |= LibGambatte.LoadFlags.NO_BIOS; } if (LibGambatte.gambatte_loadbuf(GambatteState, file, (uint)file.Length, flags) != 0) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbuf)}() returned non-zero (is this not a gb or gbc rom?)"); } if (IsSgb) { ResetStallTicks = 128 * (2 << 14); } else if (_syncSettings.EnableBIOS && (_syncSettings.ConsoleMode is GambatteSyncSettings.ConsoleModeType.GBA)) { ResetStallTicks = 485808; // GBA takes 971616 cycles to switch to CGB mode; CGB CPU is inactive during this time. } else { ResetStallTicks = 0; } // set real default colors (before anyone mucks with them at all) PutSettings((GambatteSettings)settings ?? new GambatteSettings()); InitSound(); Frame = 0; LagCount = 0; IsLagFrame = false; InputCallback = new LibGambatte.InputGetter(ControllerCallback); LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback); InitMemoryDomains(); RomDetails = $"{game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(file)}\r\n{MD5Checksum.ComputePrefixedHex(file)}\r\n"; byte[] buff = new byte[32]; LibGambatte.gambatte_romtitle(GambatteState, buff); string romname = System.Text.Encoding.ASCII.GetString(buff); Console.WriteLine("Core reported rom name: {0}", romname); if (!_syncSettings.EnableBIOS && IsCgb && IsCGBDMGMode()) // without a bios, we need to set the palette for cgbdmg ourselves { int[] cgbDmgColors = new int[] { 0xFFFFFF, 0x7BFF31, 0x0063C5, 0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000, 0xFFFFFF, 0xFF8484, 0x943A3A, 0x000000 }; if (file[0x14B] == 0x01 || (file[0x14B] == 0x33 && file[0x144] == '0' && file[0x145] == '1')) // Nintendo licencees get special palettes { cgbDmgColors = ColorsFromTitleHash(file); } ChangeDMGColors(cgbDmgColors); } if (!DeterministicEmulation && _syncSettings.RealTimeRTC) { LibGambatte.gambatte_settimemode(GambatteState, false); } if (DeterministicEmulation) { int[] rtcRegs = new int[11]; rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] = 0; if (_syncSettings.InternalRTCOverflow) { rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] |= 0x80; } if (_syncSettings.InternalRTCHalt) { rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] |= 0x40; } rtcRegs[(int)LibGambatte.RtcRegIndices.Dh] |= _syncSettings.InternalRTCDays >> 8; rtcRegs[(int)LibGambatte.RtcRegIndices.Dl] = _syncSettings.InternalRTCDays & 0xFF; rtcRegs[(int)LibGambatte.RtcRegIndices.H] = (_syncSettings.InternalRTCHours < 0) ? (_syncSettings.InternalRTCHours + 0x20) : _syncSettings.InternalRTCHours; rtcRegs[(int)LibGambatte.RtcRegIndices.M] = (_syncSettings.InternalRTCMinutes < 0) ? (_syncSettings.InternalRTCMinutes + 0x40) : _syncSettings.InternalRTCMinutes; rtcRegs[(int)LibGambatte.RtcRegIndices.S] = (_syncSettings.InternalRTCSeconds < 0) ? (_syncSettings.InternalRTCSeconds + 0x40) : _syncSettings.InternalRTCSeconds; rtcRegs[(int)LibGambatte.RtcRegIndices.C] = _syncSettings.InternalRTCCycles; rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] = 0; if (_syncSettings.LatchedRTCOverflow) { rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] |= 0x80; } if (_syncSettings.LatchedRTCHalt) { rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] |= 0x40; } rtcRegs[(int)LibGambatte.RtcRegIndices.Dh_L] |= _syncSettings.LatchedRTCDays >> 8; rtcRegs[(int)LibGambatte.RtcRegIndices.Dl_L] = _syncSettings.LatchedRTCDays & 0xFF; rtcRegs[(int)LibGambatte.RtcRegIndices.H_L] = _syncSettings.LatchedRTCHours; rtcRegs[(int)LibGambatte.RtcRegIndices.M_L] = _syncSettings.LatchedRTCMinutes; rtcRegs[(int)LibGambatte.RtcRegIndices.S_L] = _syncSettings.LatchedRTCSeconds; LibGambatte.gambatte_setrtcregs(GambatteState, rtcRegs); } LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset); LibGambatte.gambatte_setcartbuspulluptime(GambatteState, (uint)_syncSettings.CartBusPullUpTime); _cdCallback = new LibGambatte.CDCallback(CDCallbackProc); ControllerDefinition = CreateControllerDefinition(IsSgb, _syncSettings.FrameLength is GambatteSyncSettings.FrameLengthType.UserDefinedFrames); NewSaveCoreSetBuff(); } catch { Dispose(); throw; } }
public O2Hawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings) { var ser = new BasicServiceProvider(this); cpu = new I8048 { ReadMemory = ReadMemory, WriteMemory = WriteMemory, PeekMemory = PeekMemory, DummyReadMemory = ReadMemory, ReadPort = ReadPort, WritePort = WritePort, OnExecFetch = ExecFetch, }; serialport = new SerialPort(); _settings = (O2Settings)settings ?? new O2Settings(); _syncSettings = (O2SyncSettings)syncSettings ?? new O2SyncSettings(); _controllerDeck = new O2HawkControllerDeck("O2 Controller", "O2 Controller"); byte[] Bios = null; Bios = comm.CoreFileProvider.GetFirmware("O2", "BIOS", true, "BIOS Not Found, Cannot Load"); ppu = new PPU(); if (Bios == null) { throw new MissingFirmwareException("Missing Odyssey2 Bios"); } _bios = Bios; Buffer.BlockCopy(rom, 0x100, header, 0, 0x50); Console.WriteLine("MD5: " + rom.HashMD5(0, rom.Length)); Console.WriteLine("SHA1: " + rom.HashSHA1(0, rom.Length)); _rom = rom; Setup_Mapper(); _frameHz = 60; ppu.Core = this; cpu.Core = this; serialport.Core = this; ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(ppu); ServiceProvider = ser; _settings = (O2Settings)settings ?? new O2Settings(); _syncSettings = (O2SyncSettings)syncSettings ?? new O2SyncSettings(); _tracer = new TraceBuffer { Header = cpu.TraceHeader }; ser.Register <ITraceable>(_tracer); ser.Register <IStatable>(new StateSerializer(SyncState)); SetupMemoryDomains(); HardReset(); /* * for (int i = 0; i < 64; i++) * { * cpu.Regs[i] = (byte)i; * } * * * for (int j = 0; j < 0x80; j++) * { * RAM[j] = (byte)j; * } * * for (int k = 0; k < 0x100; k++) * { * ppu.WriteReg(k, (byte)k); * } */ }
public GPGX(CoreComm comm, byte[] rom, IEnumerable <Disc> cds, object settings, object syncSettings) { 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 (rom != null && rom.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } _elf = new PeRunner(new PeRunnerOptions { Path = comm.CoreFileProvider.DllPath(), Filename = "gpgx.wbx", SbrkHeapSizeKB = 512, SealedHeapSizeKB = 36 * 1024, InvisibleHeapSizeKB = 4 * 1024, PlainHeapSizeKB = 64, MmapHeapSizeKB = 1 * 1024 }); using (_elf.EnterExit()) { Core = BizInvoker.GetInvoker <LibGPGX>(_elf, _elf, CallingConventionAdapters.Waterbox); _syncSettings = (GPGXSyncSettings)syncSettings ?? new GPGXSyncSettings(); _settings = (GPGXSettings)settings ?? new GPGXSettings(); CoreComm = comm; LoadCallback = new LibGPGX.load_archive_cb(load_archive); _romfile = rom; if (cds != null) { _cds = cds.ToArray(); _cdReaders = cds.Select(c => new DiscSectorReader(c)).ToArray(); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); Core.gpgx_set_cdd_callback(cd_callback_handle); DriveLightEnabled = true; } LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; switch (_syncSettings.ControlType) { case ControlType.None: default: break; case ControlType.Activator: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; break; case ControlType.Normal: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.OnePlayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.Xea1p: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; break; case ControlType.Teamplayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; break; case ControlType.Wayplay: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; break; case ControlType.Mouse: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; // seems like mouse in port 1 would be supported, but not both at the same time system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; break; } if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _syncSettings.GetNativeSettings())) { 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(); InputCallback = new LibGPGX.input_cb(input_callback); Core.gpgx_set_input_callback(InputCallback); // process the non-init settings now PutSettings(_settings); //TODO - this hits performance, we need to make it controllable CDCallback = new LibGPGX.CDCallback(CDCallbackProc); InitMemCallbacks(); KillMemCallbacks(); Tracer = new GPGXTraceBuffer(this, MemoryDomains, this); (ServiceProvider as BasicServiceProvider).Register <ITraceable>(Tracer); } _romfile = null; }
public Genesis(CoreComm comm, GameInfo game, byte[] rom) { ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; MainCPU = new MC68000(); SoundCPU = new Z80A(); YM2612 = new YM2612() { MaxVolume = 23405 }; PSG = new SN76489() { MaxVolume = 4681 }; VDP = new GenVDP(); VDP.DmaReadFrom68000 = ReadWord; (ServiceProvider as BasicServiceProvider).Register<IVideoProvider>(VDP); 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 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 VBANext(byte[] file, CoreComm comm, GameInfo game, bool deterministic, object syncsettings) { var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(new ArmV4Disassembler()); ServiceProvider = ser; CoreComm = comm; byte[] biosfile = CoreComm.CoreFileProvider.GetFirmware("GBA", "Bios", true, "GBA bios file is mandatory."); if (file.Length > 32 * 1024 * 1024) { throw new ArgumentException("ROM is too big to be a GBA ROM!"); } if (biosfile.Length != 16 * 1024) { throw new ArgumentException("BIOS file is not exactly 16K!"); } var FES = new LibVBANext.FrontEndSettings { saveType = (LibVBANext.FrontEndSettings.SaveType)game.GetInt("saveType", 0), flashSize = (LibVBANext.FrontEndSettings.FlashSize)game.GetInt("flashSize", 0x10000), enableRtc = game.GetInt("rtcEnabled", 0) != 0, mirroringEnable = game.GetInt("mirroringEnabled", 0) != 0 }; Console.WriteLine("GameDB loaded settings: saveType={0}, flashSize={1}, rtcEnabled={2}, mirroringEnabled={3}", FES.saveType, FES.flashSize, FES.enableRtc, FES.mirroringEnable); _syncSettings = (SyncSettings)syncsettings ?? new SyncSettings(); DeterministicEmulation = deterministic; FES.skipBios = _syncSettings.SkipBios; FES.RTCUseRealTime = _syncSettings.RTCUseRealTime; FES.RTCwday = (int)_syncSettings.RTCInitialDay; FES.RTCyear = _syncSettings.RTCInitialTime.Year % 100; FES.RTCmonth = _syncSettings.RTCInitialTime.Month - 1; FES.RTCmday = _syncSettings.RTCInitialTime.Day; FES.RTChour = _syncSettings.RTCInitialTime.Hour; FES.RTCmin = _syncSettings.RTCInitialTime.Minute; FES.RTCsec = _syncSettings.RTCInitialTime.Second; if (DeterministicEmulation) { // FES.skipBios = false; // this is OK; it is deterministic and probably accurate FES.RTCUseRealTime = false; } Core = LibVBANext.Create(); if (Core == IntPtr.Zero) { throw new InvalidOperationException("Create() returned nullptr!"); } try { if (!LibVBANext.LoadRom(Core, file, (uint)file.Length, biosfile, (uint)biosfile.Length, FES)) { throw new InvalidOperationException("LoadRom() returned false!"); } Tracer = new TraceBuffer() { Header = "ARM7: PC, machine code, mnemonic, operands, registers (r0-r16)" }; ser.Register <ITraceable>(Tracer); CoreComm.VsyncNum = 262144; CoreComm.VsyncDen = 4389; CoreComm.NominalWidth = 240; CoreComm.NominalHeight = 160; GameCode = Encoding.ASCII.GetString(file, 0xac, 4); Console.WriteLine("Game code \"{0}\"", GameCode); _savebuff = new byte[LibVBANext.BinStateSize(Core)]; _savebuff2 = new byte[_savebuff.Length + 13]; InitMemoryDomains(); InitRegisters(); InitCallbacks(); // todo: hook me up as a setting SetupColors(); } catch { Dispose(); throw; } }
public GBHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings) { var ser = new BasicServiceProvider(this); cpu = new LR35902 { ReadMemory = ReadMemory, WriteMemory = WriteMemory, PeekMemory = PeekMemory, DummyReadMemory = ReadMemory, OnExecFetch = ExecFetch, SpeedFunc = SpeedFunc, }; timer = new Timer(); audio = new Audio(); serialport = new SerialPort(); CoreComm = comm; _settings = (GBSettings)settings ?? new GBSettings(); _syncSettings = (GBSyncSettings)syncSettings ?? new GBSyncSettings(); _controllerDeck = new GBHawkControllerDeck(_syncSettings.Port1); byte[] Bios = null; // Load up a BIOS and initialize the correct PPU if (_syncSettings.ConsoleMode == GBSyncSettings.ConsoleModeType.Auto) { if (game.System == "GB") { Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load"); ppu = new GB_PPU(); } else { Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load"); ppu = new GBC_PPU(); is_GBC = true; } } else if (_syncSettings.ConsoleMode == GBSyncSettings.ConsoleModeType.GB) { Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load"); ppu = new GB_PPU(); } else { Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load"); ppu = new GBC_PPU(); is_GBC = true; } if (Bios == null) { throw new MissingFirmwareException("Missing Gamboy Bios"); } _bios = Bios; // Here we modify the BIOS if GBA mode is set (credit to ExtraTricky) if (is_GBC && _syncSettings.GBACGB) { for (int i = 0; i < 13; i++) { _bios[i + 0xF3] = (byte)((GBA_override[i] + _bios[i + 0xF3]) & 0xFF); } } // CPU needs to know about GBC status too cpu.is_GBC = is_GBC; Buffer.BlockCopy(rom, 0x100, header, 0, 0x50); string hash_md5 = null; hash_md5 = "md5:" + rom.HashMD5(0, rom.Length); Console.WriteLine(hash_md5); _rom = rom; Setup_Mapper(); _frameHz = 60; timer.Core = this; audio.Core = this; ppu.Core = this; serialport.Core = this; ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(audio); ServiceProvider = ser; _settings = (GBSettings)settings ?? new GBSettings(); _syncSettings = (GBSyncSettings)syncSettings ?? new GBSyncSettings(); _tracer = new TraceBuffer { Header = cpu.TraceHeader }; ser.Register <ITraceable>(_tracer); SetupMemoryDomains(); HardReset(); iptr0 = Marshal.AllocHGlobal(VRAM.Length + 1); iptr1 = Marshal.AllocHGlobal(OAM.Length + 1); iptr2 = Marshal.AllocHGlobal(color_palette.Length * 8 * 8 + 1); iptr3 = Marshal.AllocHGlobal(color_palette.Length * 8 * 8 + 1); _scanlineCallback = null; }
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings) { ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally 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 (rom != null && rom.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } try { _syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings(); CoreComm = comm; if (AttachedCore != null) { AttachedCore.Dispose(); AttachedCore = null; } AttachedCore = this; LoadCallback = new LibGPGX.load_archive_cb(load_archive); this.romfile = rom; this.CD = CD; this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; switch (_syncSettings.ControlType) { case ControlType.None: default: break; case ControlType.Activator: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; break; case ControlType.Normal: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.OnePlayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.Xea1p: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; break; case ControlType.Teamplayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; break; case ControlType.Wayplay: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; break; case ControlType.Mouse: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; // seems like mouse in port 1 would be supported, but not both at the same time system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; break; } if (!LibGPGX.gpgx_init(romextension, LoadCallback, this._syncSettings.UseSixButton, system_a, system_b, this._syncSettings.Region)) throw new Exception("gpgx_init() failed"); { int fpsnum = 60; int fpsden = 1; LibGPGX.gpgx_get_fps(ref fpsnum, ref fpsden); CoreComm.VsyncNum = fpsnum; CoreComm.VsyncDen = fpsden; Region = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL; } // compute state size { byte[] tmp = new byte[LibGPGX.gpgx_state_max_size()]; int size = LibGPGX.gpgx_state_size(tmp, tmp.Length); if (size <= 0) throw new Exception("Couldn't Determine GPGX internal state size!"); _savebuff = new byte[size]; _savebuff2 = new byte[_savebuff.Length + 13]; Console.WriteLine("GPGX Internal State Size: {0}", size); } SetControllerDefinition(); // pull the default video size from the core UpdateVideoInitial(); SetMemoryDomains(); InputCallback = new LibGPGX.input_cb(input_callback); LibGPGX.gpgx_set_input_callback(InputCallback); if (CD != null) DriveLightEnabled = true; PutSettings((GPGXSettings)Settings ?? new GPGXSettings()); //TODO - this hits performance, we need to make it controllable CDCallback = new LibGPGX.CDCallback(CDCallbackProc); InitMemCallbacks(); KillMemCallbacks(); Tracer = new CallbackBasedTraceBuffer(this); (ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer); } catch { Dispose(); throw; } }
public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); Settings = (SMSSettings)settings ?? new SMSSettings(); SyncSettings = (SMSSyncSettings)syncSettings ?? new SMSSyncSettings(); CoreComm = comm; MemoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus" }); IsGameGear = game.System == "GG"; IsGameGear_C = game.System == "GG"; IsSG1000 = game.System == "SG"; RomData = rom; if (RomData.Length % BankSize != 0) { Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } RomBanks = (byte)(RomData.Length / BankSize); Region = DetermineDisplayType(SyncSettings.DisplayType, game.Region); if (game["PAL"] && Region != DisplayType.PAL) { Region = DisplayType.PAL; CoreComm.Notify("Display was forced to PAL mode for game compatibility."); } if (IsGameGear) { Region = DisplayType.NTSC; // all game gears run at 60hz/NTSC mode } RegionStr = SyncSettings.ConsoleRegion; if (RegionStr == "Auto") { RegionStr = DetermineRegion(game.Region); } if (game["Japan"] && RegionStr != "Japan") { RegionStr = "Japan"; CoreComm.Notify("Region was forced to Japan for game compatibility."); } if (game["Korea"] && RegionStr != "Korea") { RegionStr = "Korea"; CoreComm.Notify("Region was forced to Korea for game compatibility."); } if ((game.NotInDatabase || game["FM"]) && SyncSettings.EnableFM && !IsGameGear) { HasYM2413 = true; } Cpu = new Z80A() { ReadHardware = ReadPort, WriteHardware = WritePort, FetchMemory = FetchMemory, ReadMemory = ReadMemory, WriteMemory = WriteMemory, MemoryCallbacks = MemoryCallbacks, OnExecFetch = OnExecMemory }; if (game["GG_in_SMS"]) { // skip setting the BIOS because this is a game gear game that puts the system // in SMS compatibility mode (it will fail the check sum if played on an actual SMS though.) IsGameGear = false; IsGameGear_C = true; game.System = "GG"; Console.WriteLine("Using SMS Compatibility mode for Game Gear System"); } Vdp = new VDP(this, Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, Region); (ServiceProvider as BasicServiceProvider).Register <IVideoProvider>(Vdp); PSG = new SN76489(); YM2413 = new YM2413(); SoundMixer = new SoundMixer(YM2413, PSG); if (HasYM2413 && game["WhenFMDisablePSG"]) { SoundMixer.DisableSource(PSG); } ActiveSoundProvider = HasYM2413 ? (IAsyncSoundProvider)SoundMixer : PSG; _fakeSyncSound = new FakeSyncSound(ActiveSoundProvider, 735); (ServiceProvider as BasicServiceProvider).Register <ISoundProvider>(_fakeSyncSound); SystemRam = new byte[0x2000]; if (game["CMMapper"]) { InitCodeMastersMapper(); } else if (game["CMMapperWithRam"]) { InitCodeMastersMapperRam(); } else if (game["ExtRam"]) { InitExt2kMapper(int.Parse(game.OptionValue("ExtRam"))); } else if (game["KoreaMapper"]) { InitKoreaMapper(); } else if (game["MSXMapper"]) { InitMSXMapper(); } else if (game["NemesisMapper"]) { InitNemesisMapper(); } else if (game["TerebiOekaki"]) { InitTerebiOekaki(); } else if (game["EEPROM"]) { InitEEPROMMapper(); } else { InitSegaMapper(); } if (Settings.ForceStereoSeparation && !IsGameGear) { if (game["StereoByte"]) { ForceStereoByte = byte.Parse(game.OptionValue("StereoByte")); } PSG.StereoPanning = ForceStereoByte; } if (SyncSettings.AllowOverlock && game["OverclockSafe"]) { Vdp.IPeriod = 512; } if (Settings.SpriteLimit) { Vdp.SpriteLimit = true; } if (game["3D"]) { IsGame3D = true; } if (game["BIOS"]) { Port3E = 0xF7; // Disable cartridge, enable BIOS rom InitBiosMapper(); } else if ((game.System == "SMS") && !game["GG_in_SMS"]) { BiosRom = comm.CoreFileProvider.GetFirmware("SMS", RegionStr, false); if (BiosRom == null) { throw new MissingFirmwareException("No BIOS found"); } else if (!game["RequireBios"] && !SyncSettings.UseBIOS) { // we are skipping the BIOS // but only if it won't break the game } else { Port3E = 0xF7; } } if (game["SRAM"]) { SaveRAM = new byte[int.Parse(game.OptionValue("SRAM"))]; Console.WriteLine(SaveRAM.Length); } else if (game.NotInDatabase) { SaveRAM = new byte[0x8000]; } SetupMemoryDomains(); //this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete ((ICodeDataLogger)this).SetCDL(null); InputCallbacks = new InputCallbackSystem(); Tracer = new TraceBuffer { Header = Cpu.TraceHeader }; var serviceProvider = ServiceProvider as BasicServiceProvider; serviceProvider.Register <ITraceable>(Tracer); serviceProvider.Register <IDisassemblable>(Cpu); Vdp.ProcessOverscan(); Cpu.ReadMemory = ReadMemory; Cpu.WriteMemory = WriteMemory; }
public ZXSpectrum(CoreComm comm, IEnumerable <byte[]> files, List <GameInfo> game, object settings, object syncSettings, bool?deterministic) { var ser = new BasicServiceProvider(this); ServiceProvider = ser; InputCallbacks = new InputCallbackSystem(); MemoryCallbacks = new MemoryCallbackSystem(new[] { "System Bus" }); CoreComm = comm; _gameInfo = game; _cpu = new Z80A(); _tracer = new TraceBuffer { Header = _cpu.TraceHeader }; _files = files?.ToList() ?? new List <byte[]>(); if (settings == null) { settings = new ZXSpectrumSettings(); } if (syncSettings == null) { syncSettings = new ZXSpectrumSyncSettings(); } PutSyncSettings((ZXSpectrumSyncSettings)syncSettings ?? new ZXSpectrumSyncSettings()); PutSettings((ZXSpectrumSettings)settings ?? new ZXSpectrumSettings()); List <JoystickType> joysticks = new List <JoystickType>(); joysticks.Add(((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).JoystickType1); joysticks.Add(((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).JoystickType2); joysticks.Add(((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).JoystickType3); deterministicEmulation = ((ZXSpectrumSyncSettings)syncSettings as ZXSpectrumSyncSettings).DeterministicEmulation; if (deterministic != null && deterministic == true) { if (deterministicEmulation == false) { CoreComm.Notify("Forcing Deterministic Emulation"); } deterministicEmulation = deterministic.Value; } 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 SoundProviderMixer((int)(32767 / 10), "System Beeper", (ISoundProvider)_machine.BuzzerDevice); SoundMixer.AddSource((ISoundProvider)_machine.TapeBuzzer, "Tape Audio"); 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 as AY38912).PanningConfiguration = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).AYPanConfig; _machine.AYDevice.Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).AYVolume; } if (_machine.BuzzerDevice != null) { ((Beeper)_machine.BuzzerDevice as Beeper).Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).EarVolume; } if (_machine.TapeBuzzer != null) { ((Beeper)_machine.TapeBuzzer as Beeper).Volume = ((ZXSpectrumSettings)settings as ZXSpectrumSettings).TapeVolume; } DCFilter dc = new DCFilter(SoundMixer, 512); ser.Register <ISoundProvider>(dc); HardReset(); SetupMemoryDomains(); }
public NullEmulator(CoreComm comm) { ServiceProvider = new BasicServiceProvider(this); CoreComm = comm; }
public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings, bool deterministic) { var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(new GBDisassembler()); ServiceProvider = ser; Tracer = new TraceBuffer { Header = "Z80: PC, opcode, registers (A, B, C, D, E, F, H, L, LY, SP, CY)" }; ser.Register <ITraceable>(Tracer); InitMemoryCallbacks(); CoreComm = comm; comm.RomStatusAnnotation = null; comm.RomStatusDetails = null; comm.NominalWidth = 160; comm.NominalHeight = 144; ThrowExceptionForBadRom(file); BoardName = MapperName(file); DeterministicEmulation = deterministic; GambatteState = LibGambatte.gambatte_create(); if (GambatteState == IntPtr.Zero) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_create)}() returned null???"); } Console.WriteLine(game.System); try { _syncSettings = (GambatteSyncSettings)syncSettings ?? new GambatteSyncSettings(); LibGambatte.LoadFlags flags = 0; switch (_syncSettings.ConsoleMode) { case GambatteSyncSettings.ConsoleModeType.GB: flags |= LibGambatte.LoadFlags.FORCE_DMG; break; case GambatteSyncSettings.ConsoleModeType.GBC: break; default: if (game.System == "GB") { flags |= LibGambatte.LoadFlags.FORCE_DMG; } break; } if (_syncSettings.GBACGB) { flags |= LibGambatte.LoadFlags.GBA_CGB; } if (_syncSettings.MulticartCompat) { flags |= LibGambatte.LoadFlags.MULTICART_COMPAT; } if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, flags) != 0) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_load)}() returned non-zero (is this not a gb or gbc rom?)"); } byte[] Bios; if ((flags & LibGambatte.LoadFlags.FORCE_DMG) == LibGambatte.LoadFlags.FORCE_DMG) { Bios = comm.CoreFileProvider.GetFirmware("GB", "World", true, "BIOS Not Found, Cannot Load"); IsCgb = false; } else { Bios = comm.CoreFileProvider.GetFirmware("GBC", "World", true, "BIOS Not Found, Cannot Load"); IsCgb = true; } if (LibGambatte.gambatte_loadbios(GambatteState, Bios, (uint)Bios.Length) != 0) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbios)}() returned non-zero (bios error)"); } // set real default colors (before anyone mucks with them at all) PutSettings((GambatteSettings)settings ?? new GambatteSettings()); InitSound(); Frame = 0; LagCount = 0; IsLagFrame = false; InputCallback = new LibGambatte.InputGetter(ControllerCallback); LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback); InitMemoryDomains(); CoreComm.RomStatusDetails = $"{game.Name}\r\nSHA1:{file.HashSHA1()}\r\nMD5:{file.HashMD5()}\r\n"; byte[] buff = new byte[32]; LibGambatte.gambatte_romtitle(GambatteState, buff); string romname = System.Text.Encoding.ASCII.GetString(buff); Console.WriteLine("Core reported rom name: {0}", romname); if (!DeterministicEmulation && _syncSettings.RealTimeRTC) { LibGambatte.gambatte_settimemode(GambatteState, false); } LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset); _cdCallback = new LibGambatte.CDCallback(CDCallbackProc); NewSaveCoreSetBuff(); } catch { Dispose(); throw; } }
public SMS(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); Settings = (SMSSettings)settings ?? new SMSSettings(); SyncSettings = (SMSSyncSettings)syncSettings ?? new SMSSyncSettings(); CoreComm = comm; MemoryCallbacks = new MemoryCallbackSystem(); IsGameGear = game.System == "GG"; IsSG1000 = game.System == "SG"; RomData = rom; Tracer = new TraceBuffer(); (ServiceProvider as BasicServiceProvider).Register <ITraceable>(Tracer); if (RomData.Length % BankSize != 0) { Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } RomBanks = (byte)(RomData.Length / BankSize); Region = DetermineDisplayType(SyncSettings.DisplayType, game.Region); if (game["PAL"] && Region != DisplayType.PAL) { Region = DisplayType.PAL; CoreComm.Notify("Display was forced to PAL mode for game compatibility."); } if (IsGameGear) { Region = DisplayType.NTSC; // all game gears run at 60hz/NTSC mode } CoreComm.VsyncNum = Region == DisplayType.NTSC ? 60 : 50; CoreComm.VsyncDen = 1; RegionStr = SyncSettings.ConsoleRegion; if (RegionStr == "Auto") { RegionStr = DetermineRegion(game.Region); } if (game["Japan"] && RegionStr != "Japan") { RegionStr = "Japan"; CoreComm.Notify("Region was forced to Japan for game compatibility."); } if ((game.NotInDatabase || game["FM"]) && SyncSettings.EnableFM && !IsGameGear) { HasYM2413 = true; } if (Controller == null) { Controller = NullController.GetNullController(); } Cpu = new Z80A(); Cpu.RegisterSP = 0xDFF0; Cpu.ReadHardware = ReadPort; Cpu.WriteHardware = WritePort; Cpu.MemoryCallbacks = MemoryCallbacks; Vdp = new VDP(this, Cpu, IsGameGear ? VdpMode.GameGear : VdpMode.SMS, Region); (ServiceProvider as BasicServiceProvider).Register <IVideoProvider>(Vdp); PSG = new SN76489(); YM2413 = new YM2413(); SoundMixer = new SoundMixer(YM2413, PSG); if (HasYM2413 && game["WhenFMDisablePSG"]) { SoundMixer.DisableSource(PSG); } ActiveSoundProvider = HasYM2413 ? (ISoundProvider)SoundMixer : PSG; SystemRam = new byte[0x2000]; if (game["CMMapper"]) { InitCodeMastersMapper(); } else if (game["CMMapperWithRam"]) { InitCodeMastersMapperRam(); } else if (game["ExtRam"]) { InitExt2kMapper(int.Parse(game.OptionValue("ExtRam"))); } else if (game["KoreaMapper"]) { InitKoreaMapper(); } else if (game["MSXMapper"]) { InitMSXMapper(); } else if (game["NemesisMapper"]) { InitNemesisMapper(); } else if (game["TerebiOekaki"]) { InitTerebiOekaki(); } else { InitSegaMapper(); } if (Settings.ForceStereoSeparation && !IsGameGear) { if (game["StereoByte"]) { ForceStereoByte = byte.Parse(game.OptionValue("StereoByte")); } PSG.StereoPanning = ForceStereoByte; } if (SyncSettings.AllowOverlock && game["OverclockSafe"]) { Vdp.IPeriod = 512; } if (Settings.SpriteLimit) { Vdp.SpriteLimit = true; } if (game["3D"]) { IsGame3D = true; } if (game["BIOS"]) { Port3E = 0xF7; // Disable cartridge, enable BIOS rom InitBiosMapper(); } else if (game.System == "SMS") { BiosRom = comm.CoreFileProvider.GetFirmware("SMS", RegionStr, false); if (BiosRom != null && (game["RequireBios"] || SyncSettings.UseBIOS)) { Port3E = 0xF7; } if (BiosRom == null && game["RequireBios"]) { throw new MissingFirmwareException("BIOS image not available. This game requires BIOS to function."); } if (SyncSettings.UseBIOS && BiosRom == null) { CoreComm.Notify("BIOS was selected, but rom image not available. BIOS not enabled."); } } if (game["SRAM"]) { SaveRAM = new byte[int.Parse(game.OptionValue("SRAM"))]; } else if (game.NotInDatabase) { SaveRAM = new byte[0x8000]; } SetupMemoryDomains(); //this manages the linkage between the cpu and mapper callbacks so it needs running before bootup is complete ((ICodeDataLogger)this).SetCDL(null); (ServiceProvider as BasicServiceProvider).Register <IDisassemblable>(new Disassembler()); }
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; } }
public N64(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); InputCallbacks = new InputCallbackSystem(); _memorycallbacks.CallbackAdded += AddBreakpoint; _memorycallbacks.CallbackRemoved += RemoveBreakpoint; int SaveType = 0; if (game.OptionValue("SaveType") == "EEPROM_16K") { SaveType = 1; } CoreComm = comm; _syncSettings = (N64SyncSettings)syncSettings ?? new N64SyncSettings(); _settings = (N64Settings)settings ?? new N64Settings(); _disableExpansionSlot = _syncSettings.DisableExpansionSlot; // Override the user's expansion slot setting if it is mentioned in the gamedb (it is mentioned but the game MUST have this setting or else not work if (game.OptionValue("expansionpak") != null && game.OptionValue("expansionpak") == "1") { _disableExpansionSlot = false; IsOverridingUserExpansionSlotSetting = true; } byte country_code = file[0x3E]; switch (country_code) { // PAL codes case 0x44: case 0x46: case 0x49: case 0x50: case 0x53: case 0x55: case 0x58: case 0x59: _display_type = DisplayType.PAL; break; // NTSC codes case 0x37: case 0x41: case 0x45: case 0x4a: default: // Fallback for unknown codes _display_type = DisplayType.NTSC; break; } StartThreadLoop(); var videosettings = _syncSettings.GetVPS(game, _settings.VideoSizeX, _settings.VideoSizeY); var coreType = _syncSettings.Core; //zero 19-apr-2014 - added this to solve problem with SDL initialization corrupting the main thread (I think) and breaking subsequent emulators (for example, NES) //not sure why this works... if we put the plugin initializations in here, we get deadlocks in some SDL initialization. doesnt make sense to me... RunThreadAction(() => { api = new mupen64plusApi(this, file, videosettings, SaveType, (int)coreType, _disableExpansionSlot); }); // Order is important because the register with the mupen core _videoProvider = new N64VideoProvider(api, videosettings); _audioProvider = new N64Audio(api); _inputProvider = new N64Input(this.AsInputPollable(), api, comm, this._syncSettings.Controllers); (ServiceProvider as BasicServiceProvider).Register <IVideoProvider>(_videoProvider); (ServiceProvider as BasicServiceProvider).Register <ISoundProvider>(_audioProvider.Resampler); switch (Region) { case DisplayType.NTSC: _videoProvider.VsyncNumerator = 60000; _videoProvider.VsyncDenominator = 1001; break; default: _videoProvider.VsyncNumerator = 50; _videoProvider.VsyncDenominator = 1; break; } string rsp; switch (_syncSettings.Rsp) { default: case N64SyncSettings.RspType.Rsp_Hle: rsp = "mupen64plus-rsp-hle.dll"; break; //case N64SyncSettings.RspType.Rsp_cxd4: // rsp = "mupen64plus-rsp-cxd4.dll"; // break; } api.AttachPlugin(mupen64plusApi.m64p_plugin_type.M64PLUGIN_RSP, rsp); InitMemoryDomains(); //if (_syncSettings.Core != N64SyncSettings.CoreType.Dynarec) { ConnectTracer(); SetBreakpointHandler(); } api.AsyncExecuteEmulator(); // Hack: Saving a state on frame 0 has been shown to not be sync stable. Advance past that frame to avoid the problem. // Advancing 2 frames was chosen to deal with a problem with the dynamic recompiler. The dynarec seems to take 2 frames to set // things up correctly. If a state is loaded on frames 0 or 1 mupen tries to access null pointers and the emulator crashes, so instead // advance past both to again avoid the problem. api.frame_advance(); api.frame_advance(); SetControllerButtons(); }
public MGBAHawk(byte[] file, CoreComm comm, SyncSettings syncSettings, Settings settings, bool deterministic) { _syncSettings = syncSettings ?? new SyncSettings(); _settings = settings ?? new Settings(); DeterministicEmulation = deterministic; byte[] bios = comm.CoreFileProvider.GetFirmware("GBA", "Bios", false); DeterministicEmulation &= bios != null; if (DeterministicEmulation != deterministic) { throw new InvalidOperationException("A BIOS is required for deterministic recordings!"); } if (!DeterministicEmulation && bios != null && !_syncSettings.RTCUseRealTime && !_syncSettings.SkipBios) { // in these situations, this core is deterministic even though it wasn't asked to be DeterministicEmulation = true; } if (bios != null && bios.Length != 16384) { throw new InvalidOperationException("BIOS must be exactly 16384 bytes!"); } core = LibmGBA.BizCreate(bios); if (core == IntPtr.Zero) { throw new InvalidOperationException("BizCreate() returned NULL! Bad BIOS?"); } try { if (!LibmGBA.BizLoad(core, file, file.Length)) { throw new InvalidOperationException("BizLoad() returned FALSE! Bad ROM?"); } if (!DeterministicEmulation && _syncSettings.SkipBios) { LibmGBA.BizSkipBios(core); } CreateMemoryDomains(file.Length); var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(new ArmV4Disassembler()); ser.Register <IMemoryDomains>(MemoryDomains); ServiceProvider = ser; CoreComm = comm; CoreComm.VsyncNum = 262144; CoreComm.VsyncDen = 4389; CoreComm.NominalWidth = 240; CoreComm.NominalHeight = 160; InitStates(); } catch { LibmGBA.BizDestroy(core); throw; } }
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(); }
public O2Hawk(CoreComm comm, GameInfo game, byte[] rom, O2Settings settings, O2SyncSettings syncSettings) { var ser = new BasicServiceProvider(this); cpu = new I8048 { ReadMemory = ReadMemory, WriteMemory = WriteMemory, PeekMemory = PeekMemory, DummyReadMemory = ReadMemory, ReadPort = ReadPort, WritePort = WritePort, OnExecFetch = ExecFetch, }; _settings = settings ?? new O2Settings(); _syncSettings = syncSettings ?? new O2SyncSettings(); is_G7400 = _syncSettings.G7400_Enable; _controllerDeck = new O2HawkControllerDeck("O2 Controller", "O2 Controller", is_G7400); _bios = comm.CoreFileProvider.GetFirmwareOrThrow(new("O2", is_G7400 ? "BIOS-G7400" : "BIOS-O2"), "BIOS Not Found, Cannot Load"); Buffer.BlockCopy(rom, 0x100, header, 0, 0x50); Console.WriteLine("MD5: " + rom.HashMD5(0, rom.Length)); Console.WriteLine("SHA1: " + rom.HashSHA1(0, rom.Length)); _rom = rom; if (game["XROM"]) { is_XROM = true; } Setup_Mapper(); _frameHz = 60; ser.Register <IVideoProvider>(this); ServiceProvider = ser; _tracer = new TraceBuffer(cpu.TraceHeader); ser.Register(_tracer); ser.Register <IStatable>(new StateSerializer(SyncState)); SetupMemoryDomains(); cpu.SetCallbacks(ReadMemory, PeekMemory, PeekMemory, WriteMemory); // set up differences between PAL and NTSC systems if ((game.Region == "US" || game.Region == "EU-US" || game.Region == null) && !is_G7400) { is_pal = false; pic_height = 240; _frameHz = 60; ppu = new NTSC_PPU(); } else { is_pal = true; pic_height = 240; _frameHz = 50; ppu = new PAL_PPU(); } ppu.Core = this; ppu.set_region(is_pal, is_G7400); ser.Register <ISoundProvider>(ppu); _vidbuffer = new int[372 * pic_height]; frame_buffer = new int[320 * pic_height]; HardReset(); }
public MSX(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { ServiceProvider = new BasicServiceProvider(this); Settings = (MSXSettings)settings ?? new MSXSettings(); SyncSettings = (MSXSyncSettings)syncSettings ?? new MSXSyncSettings(); RomData = rom; int size = RomData.Length; if (RomData.Length % BankSize != 0) { Array.Resize(ref RomData, ((RomData.Length / BankSize) + 1) * BankSize); } // we want all ROMS to be multiples of 64K for easy memory mapping later if (RomData.Length != 0x10000) { Array.Resize(ref RomData, 0x10000); } // if the original was not 64 or 48 k, move it (may need to do this case by case) if (size == 0x8000) { for (int i = 0x7FFF; i >= 0; i--) { RomData[i + 0x4000] = RomData[i]; } for (int i = 0; i < 0x4000; i++) { RomData[i] = 0; } } if (size == 0x4000) { for (int i = 0; i < 0x4000; i++) { RomData[i + 0x4000] = RomData[i]; RomData[i + 0x8000] = RomData[i]; RomData[i + 0xC000] = RomData[i]; } } Bios = comm.CoreFileProvider.GetFirmware("MSX", "bios_jp", false, "BIOS Not Found, Cannot Load"); if (Bios == null) { Bios = comm.CoreFileProvider.GetFirmware("MSX", "bios_test_ext", true, "BIOS Not Found, Cannot Load"); } //Basic = comm.CoreFileProvider.GetFirmware("MSX", "basic_test", true, "BIOS Not Found, Cannot Load"); Basic = new byte[0x4000]; MSX_Pntr = LibMSX.MSX_create(); LibMSX.MSX_load_bios(MSX_Pntr, Bios, Basic); LibMSX.MSX_load(MSX_Pntr, RomData, (uint)RomData.Length, 0, RomData, (uint)RomData.Length, 0); blip.SetRates(3579545, 44100); (ServiceProvider as BasicServiceProvider).Register <ISoundProvider>(this); SetupMemoryDomains(); Header_Length = LibMSX.MSX_getheaderlength(MSX_Pntr); Disasm_Length = LibMSX.MSX_getdisasmlength(MSX_Pntr); Reg_String_Length = LibMSX.MSX_getregstringlength(MSX_Pntr); var newHeader = new StringBuilder(Header_Length); LibMSX.MSX_getheader(MSX_Pntr, newHeader, Header_Length); Console.WriteLine(Header_Length + " " + Disasm_Length + " " + Reg_String_Length); Tracer = new TraceBuffer { Header = newHeader.ToString() }; var serviceProvider = ServiceProvider as BasicServiceProvider; serviceProvider.Register <ITraceable>(Tracer); serviceProvider.Register <IStatable>(new StateSerializer(SyncState)); current_controller = SyncSettings.Contr_Setting == MSXSyncSettings.ContrType.Keyboard ? MSXControllerKB : MSXControllerJS; }
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings) { 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 (rom != null && rom.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } try { Elf = new ElfRunner(Path.Combine(comm.CoreFileProvider.DllPath(), "gpgx.elf"), 8 * 1024 * 1024, 36 * 1024 * 1024, 4 * 1024 * 1024); if (Elf.ShouldMonitor) Core = BizInvoker.GetInvoker<LibGPGX>(Elf, Elf); else Core = BizInvoker.GetInvoker<LibGPGX>(Elf); _syncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings(); _settings = (GPGXSettings)Settings ?? new GPGXSettings(); CoreComm = comm; LoadCallback = new LibGPGX.load_archive_cb(load_archive); this.romfile = rom; this.CD = CD; if (CD != null) { this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); Core.gpgx_set_cdd_callback(cd_callback_handle); } LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; switch (_syncSettings.ControlType) { case ControlType.None: default: break; case ControlType.Activator: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; break; case ControlType.Normal: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.OnePlayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.Xea1p: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; break; case ControlType.Teamplayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; break; case ControlType.Wayplay: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; break; case ControlType.Mouse: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; // seems like mouse in port 1 would be supported, but not both at the same time system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; break; } if (!Core.gpgx_init(romextension, LoadCallback, _syncSettings.UseSixButton, system_a, system_b, _syncSettings.Region, _settings.GetNativeSettings())) throw new Exception("gpgx_init() failed"); { int fpsnum = 60; int fpsden = 1; Core.gpgx_get_fps(ref fpsnum, ref fpsden); CoreComm.VsyncNum = fpsnum; CoreComm.VsyncDen = fpsden; Region = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL; } // compute state size InitStateBuffers(); SetControllerDefinition(); // pull the default video size from the core UpdateVideoInitial(); SetMemoryDomains(); InputCallback = new LibGPGX.input_cb(input_callback); Core.gpgx_set_input_callback(InputCallback); if (CD != null) DriveLightEnabled = true; // process the non-init settings now PutSettings(_settings); //TODO - this hits performance, we need to make it controllable CDCallback = new LibGPGX.CDCallback(CDCallbackProc); InitMemCallbacks(); KillMemCallbacks(); Tracer = new GPGXTraceBuffer(this, MemoryDomains, this); (ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer); Elf.Seal(); } catch { Dispose(); throw; } }
public VectrexHawk(CoreComm comm, GameInfo game, byte[] rom, /*string gameDbFn,*/ object settings, object syncSettings) { var ser = new BasicServiceProvider(this); cpu = new MC6809 { ReadMemory = ReadMemory, WriteMemory = WriteMemory, PeekMemory = PeekMemory, DummyReadMemory = ReadMemory, OnExecFetch = ExecFetch, }; audio = new Audio(); ppu = new PPU(); serialport = new SerialPort(); CoreComm = comm; _settings = (VectrexSettings)settings ?? new VectrexSettings(); _syncSettings = (VectrexSyncSettings)syncSettings ?? new VectrexSyncSettings(); _controllerDeck = new VectrexHawkControllerDeck(_syncSettings.Port1, _syncSettings.Port2); byte[] Bios = null; byte[] Mine = null; Bios = comm.CoreFileProvider.GetFirmware("Vectrex", "Bios", true, "BIOS Not Found, Cannot Load"); _bios = Bios; Mine = comm.CoreFileProvider.GetFirmware("Vectrex", "Minestorm", true, "Minestorm Not Found, Cannot Load"); minestorm = Mine; Console.WriteLine("SHA1:" + rom.HashSHA1(0, rom.Length)); _rom = rom; // If the game is minstorm, then no cartridge is inserted, retun 0xFF if (rom.HashSHA1(0, rom.Length) == "65D07426B520DDD3115D40F255511E0FD2E20AE7") { _rom = new byte[0x8000]; for (int i = 0; i < 0x8000; i++) { _rom[i] = 0xFF; } } // mirror games that are too small if (_rom.Length < 0x8000) { _rom = new byte[0x8000]; for (int i = 0; i < 0x8000 / rom.Length; i++) { for (int j = 0; j < rom.Length; j++) { _rom[j + i * rom.Length] = rom[j]; } } } // RAM appears to power up to either random values or 0xFF, otherwise all the asteroids in minestorm are on the same side if RAM[0x7E]=0 for (int i = 0; i < RAM.Length; i++) { RAM[i] = 0xFF; } Setup_Mapper(); _frameHz = 50; audio.Core = this; ppu.Core = this; serialport.Core = this; ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(audio); ServiceProvider = ser; _settings = (VectrexSettings)settings ?? new VectrexSettings(); _syncSettings = (VectrexSyncSettings)syncSettings ?? new VectrexSyncSettings(); _tracer = new TraceBuffer { Header = cpu.TraceHeader }; ser.Register <ITraceable>(_tracer); SetupMemoryDomains(); HardReset(); cpu.SetCallbacks(ReadMemory, PeekMemory, PeekMemory, WriteMemory); }
//[CoreConstructor("GB", "GBC")] public GBHawkLink3x(CoreComm comm, GameInfo game_L, byte[] rom_L, GameInfo game_C, byte[] rom_C, GameInfo game_R, byte[] rom_R, /*string gameDbFn,*/ object settings, object syncSettings) { var ser = new BasicServiceProvider(this); Link3xSettings = (GBLink3xSettings)settings ?? new GBLink3xSettings(); Link3xSyncSettings = (GBLink3xSyncSettings)syncSettings ?? new GBLink3xSyncSettings(); _controllerDeck = new GBHawkLink3xControllerDeck(GBHawkLink3xControllerDeck.DefaultControllerName, GBHawkLink3xControllerDeck.DefaultControllerName, GBHawkLink3xControllerDeck.DefaultControllerName); CoreComm = comm; var temp_set_L = new GBHawk.GBHawk.GBSettings(); var temp_set_C = new GBHawk.GBHawk.GBSettings(); var temp_set_R = new GBHawk.GBHawk.GBSettings(); var temp_sync_L = new GBHawk.GBHawk.GBSyncSettings(); var temp_sync_C = new GBHawk.GBHawk.GBSyncSettings(); var temp_sync_R = new GBHawk.GBHawk.GBSyncSettings(); temp_sync_L.ConsoleMode = Link3xSyncSettings.ConsoleMode_L; temp_sync_C.ConsoleMode = Link3xSyncSettings.ConsoleMode_C; temp_sync_R.ConsoleMode = Link3xSyncSettings.ConsoleMode_R; temp_sync_L.GBACGB = Link3xSyncSettings.GBACGB; temp_sync_C.GBACGB = Link3xSyncSettings.GBACGB; temp_sync_R.GBACGB = Link3xSyncSettings.GBACGB; temp_sync_L.RTCInitialTime = Link3xSyncSettings.RTCInitialTime_L; temp_sync_C.RTCInitialTime = Link3xSyncSettings.RTCInitialTime_C; temp_sync_R.RTCInitialTime = Link3xSyncSettings.RTCInitialTime_R; temp_sync_L.RTCOffset = Link3xSyncSettings.RTCOffset_L; temp_sync_C.RTCOffset = Link3xSyncSettings.RTCOffset_C; temp_sync_R.RTCOffset = Link3xSyncSettings.RTCOffset_R; L = new GBHawk.GBHawk(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider }, game_L, rom_L, temp_set_L, temp_sync_L); C = new GBHawk.GBHawk(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider }, game_C, rom_C, temp_set_C, temp_sync_C); R = new GBHawk.GBHawk(new CoreComm(comm.ShowMessage, comm.Notify) { CoreFileProvider = comm.CoreFileProvider }, game_R, rom_R, temp_set_R, temp_sync_R); ser.Register <IVideoProvider>(this); ser.Register <ISoundProvider>(this); _tracer = new TraceBuffer { Header = L.cpu.TraceHeader }; ser.Register <ITraceable>(_tracer); ServiceProvider = ser; SetupMemoryDomains(); HardReset(); }
void Init(GameInfo game, byte[] rom) { Controller = NullController.GetNullController(); Cpu = new HuC6280(MemoryCallbacks); VCE = new VCE(); VDC1 = new VDC(this, Cpu, VCE); PSG = new HuC6280PSG(); SCSI = new ScsiCDBus(this, disc); Cpu.Logger = (s) => 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) => Tracer.Put(new TraceInfo { Disassembly = string.Format("{0:X1}:{1}", SF2MapperLatch, s), RegisterInfo = "" }); } 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(); Tracer = new TraceBuffer { Header = Cpu.TraceHeader }; var ser = new BasicServiceProvider(this); ServiceProvider = ser; ser.Register <ITraceable>(Tracer); ser.Register <IDisassemblable>(Cpu); ser.Register <IVideoProvider>((IVideoProvider)VPC ?? VDC1); SetupMemoryDomains(); }
public GPGX(CoreComm comm, byte[] rom, DiscSystem.Disc CD, object Settings, object SyncSettings) { ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally 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 //romfile = File.ReadAllBytes(@"D:\encodes\bizhawksrc\output\SANIC CD\PierSolar (E).bin"); if (rom != null && rom.Length > 16 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } try { _SyncSettings = (GPGXSyncSettings)SyncSettings ?? new GPGXSyncSettings(); CoreComm = comm; if (AttachedCore != null) { AttachedCore.Dispose(); AttachedCore = null; } AttachedCore = this; LoadCallback = new LibGPGX.load_archive_cb(load_archive); this.romfile = rom; this.CD = CD; this.DiscSectorReader = new DiscSystem.DiscSectorReader(CD); LibGPGX.INPUT_SYSTEM system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; LibGPGX.INPUT_SYSTEM system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_NONE; switch (this._SyncSettings.ControlType) { case ControlType.None: default: break; case ControlType.Activator: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_ACTIVATOR; break; case ControlType.Normal: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.OnePlayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; break; case ControlType.Xea1p: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_XE_A1P; break; case ControlType.Teamplayer: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_TEAMPLAYER; break; case ControlType.Wayplay: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_WAYPLAY; break; case ControlType.Mouse: system_a = LibGPGX.INPUT_SYSTEM.SYSTEM_MD_GAMEPAD; // seems like mouse in port 1 would be supported, but not both at the same time system_b = LibGPGX.INPUT_SYSTEM.SYSTEM_MOUSE; break; } if (!LibGPGX.gpgx_init(romextension, LoadCallback, this._SyncSettings.UseSixButton, system_a, system_b, this._SyncSettings.Region)) { throw new Exception("gpgx_init() failed"); } { int fpsnum = 60; int fpsden = 1; LibGPGX.gpgx_get_fps(ref fpsnum, ref fpsden); CoreComm.VsyncNum = fpsnum; CoreComm.VsyncDen = fpsden; Region = CoreComm.VsyncRate > 55 ? DisplayType.NTSC : DisplayType.PAL; } // compute state size { byte[] tmp = new byte[LibGPGX.gpgx_state_max_size()]; int size = LibGPGX.gpgx_state_size(tmp, tmp.Length); if (size <= 0) { throw new Exception("Couldn't Determine GPGX internal state size!"); } savebuff = new byte[size]; savebuff2 = new byte[savebuff.Length + 13]; Console.WriteLine("GPGX Internal State Size: {0}", size); } SetControllerDefinition(); // pull the default video size from the core update_video_initial(); SetMemoryDomains(); InputCallback = new LibGPGX.input_cb(input_callback); LibGPGX.gpgx_set_input_callback(InputCallback); if (CD != null) { DriveLightEnabled = true; } PutSettings((GPGXSettings)Settings ?? new GPGXSettings()); InitMemCallbacks(); KillMemCallbacks(); } catch { Dispose(); throw; } }
public Gameboy(CoreComm comm, GameInfo game, byte[] file, Gameboy.GambatteSettings settings, Gameboy.GambatteSyncSettings syncSettings, bool deterministic) { var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(new GBDisassembler()); ServiceProvider = ser; Tracer = new TraceBuffer { Header = "Z80: PC, opcode, registers (A, B, C, D, E, F, H, L, LY, SP, CY)" }; ser.Register <ITraceable>(Tracer); InitMemoryCallbacks(); ThrowExceptionForBadRom(file); BoardName = MapperName(file); DeterministicEmulation = deterministic; GambatteState = LibGambatte.gambatte_create(); if (GambatteState == IntPtr.Zero) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_create)}() returned null???"); } Console.WriteLine(game.System); try { _syncSettings = (GambatteSyncSettings)syncSettings ?? new GambatteSyncSettings(); LibGambatte.LoadFlags flags = 0; switch (_syncSettings.ConsoleMode) { case GambatteSyncSettings.ConsoleModeType.GB: flags |= LibGambatte.LoadFlags.FORCE_DMG; break; case GambatteSyncSettings.ConsoleModeType.GBC: break; case GambatteSyncSettings.ConsoleModeType.GBA: flags |= LibGambatte.LoadFlags.GBA_CGB; break; default: if (game.System == "GB") { flags |= LibGambatte.LoadFlags.FORCE_DMG; } break; } if (_syncSettings.MulticartCompat) { flags |= LibGambatte.LoadFlags.MULTICART_COMPAT; } if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, flags) != 0) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_load)}() returned non-zero (is this not a gb or gbc rom?)"); } byte[] bios; string biosSystemId; string biosId; if ((flags & LibGambatte.LoadFlags.FORCE_DMG) == LibGambatte.LoadFlags.FORCE_DMG) { biosSystemId = "GB"; biosId = "World"; IsCgb = false; } else { biosSystemId = "GBC"; biosId = _syncSettings.ConsoleMode == GambatteSyncSettings.ConsoleModeType.GBA ? "AGB" : "World"; IsCgb = true; } if (_syncSettings.EnableBIOS) { bios = comm.CoreFileProvider.GetFirmware(biosSystemId, biosId, true, "BIOS Not Found, Cannot Load. Change SyncSettings to run without BIOS."); } else { var builtinBios = (biosSystemId, biosId) switch { ("GB", "World") => Resources.FastDmgBoot, ("GBC", "World") => Resources.FastCgbBoot, ("GBC", "AGB") => Resources.FastAgbBoot, (_, _) => throw new Exception("Internal GB Error (BIOS??)"), }; bios = BizHawk.Common.Util.DecompressGzipFile(new MemoryStream(builtinBios.Value, false)); } if (LibGambatte.gambatte_loadbios(GambatteState, bios, (uint)bios.Length) != 0) { throw new InvalidOperationException($"{nameof(LibGambatte.gambatte_loadbios)}() returned non-zero (bios error)"); } // set real default colors (before anyone mucks with them at all) PutSettings((GambatteSettings)settings ?? new GambatteSettings()); InitSound(); Frame = 0; LagCount = 0; IsLagFrame = false; InputCallback = new LibGambatte.InputGetter(ControllerCallback); LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback); InitMemoryDomains(); RomDetails = $"{game.Name}\r\nSHA1:{file.HashSHA1()}\r\nMD5:{file.HashMD5()}\r\n"; byte[] buff = new byte[32]; LibGambatte.gambatte_romtitle(GambatteState, buff); string romname = System.Text.Encoding.ASCII.GetString(buff); Console.WriteLine("Core reported rom name: {0}", romname); if (!DeterministicEmulation && _syncSettings.RealTimeRTC) { LibGambatte.gambatte_settimemode(GambatteState, false); } LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset); _cdCallback = new LibGambatte.CDCallback(CDCallbackProc); NewSaveCoreSetBuff(); }
public GPGX(CoreLoadParameters <GPGXSettings, GPGXSyncSettings> lp) { LoadCallback = new LibGPGX.load_archive_cb(load_archive); _inputCallback = new LibGPGX.input_cb(input_callback); InitMemCallbacks(); // ExecCallback, ReadCallback, WriteCallback CDCallback = new LibGPGX.CDCallback(CDCallbackProc); cd_callback_handle = new LibGPGX.cd_read_cb(CDRead); ServiceProvider = new BasicServiceProvider(this); // this can influence some things internally (autodetect romtype, etc) string romextension = "GEN"; // three or six button? // http://www.sega-16.com/forum/showthread.php?4398-Forgotten-Worlds-giving-you-GAME-OVER-immediately-Fix-inside&highlight=forgotten%20worlds //hack, don't use if (lp.Roms.FirstOrDefault()?.RomData.Length > 32 * 1024 * 1024) { throw new InvalidOperationException("ROM too big! Did you try to load a CD as a ROM?"); } _elf = new WaterboxHost(new WaterboxOptions { Path = lp.Comm.CoreFileProvider.DllPath(), Filename = "gpgx.wbx", SbrkHeapSizeKB = 512, SealedHeapSizeKB = 4 * 1024, InvisibleHeapSizeKB = 4 * 1024, PlainHeapSizeKB = 34 * 1024, MmapHeapSizeKB = 1 * 1024, SkipCoreConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxCoreConsistencyCheck), SkipMemoryConsistencyCheck = lp.Comm.CorePreferences.HasFlag(CoreComm.CorePreferencesFlags.WaterboxMemoryConsistencyCheck), }); var callingConventionAdapter = CallingConventionAdapters.MakeWaterbox(new Delegate[] { LoadCallback, _inputCallback, ExecCallback, ReadCallback, WriteCallback, CDCallback, cd_callback_handle, }, _elf); using (_elf.EnterExit()) { Core = BizInvoker.GetInvoker <LibGPGX>(_elf, _elf, callingConventionAdapter); _syncSettings = lp.SyncSettings ?? new GPGXSyncSettings(); _settings = lp.Settings ?? new GPGXSettings(); CoreComm = lp.Comm; _romfile = lp.Roms.FirstOrDefault()?.RomData; if (lp.Discs.Count > 0) { _cds = lp.Discs.Select(d => d.DiscData).ToArray(); _cdReaders = _cds.Select(c => new DiscSectorReader(c)).ToArray(); Core.gpgx_set_cdd_callback(cd_callback_handle); DriveLightEnabled = true; } LibGPGX.INPUT_SYSTEM system_a = SystemForSystem(_syncSettings.ControlTypeLeft); LibGPGX.INPUT_SYSTEM system_b = SystemForSystem(_syncSettings.ControlTypeRight); var initResult = Core.gpgx_init(romextension, LoadCallback, _syncSettings.GetNativeSettings(lp.Game)); if (!initResult) { throw new Exception($"{nameof(Core.gpgx_init)}() failed"); } { int fpsnum = 60; int fpsden = 1; Core.gpgx_get_fps(ref fpsnum, ref fpsden); VsyncNumerator = fpsnum; VsyncDenominator = fpsden; Region = VsyncNumerator / VsyncDenominator > 55 ? DisplayType.NTSC : DisplayType.PAL; } // when we call Seal, ANY pointer passed from managed code must be 0. // this is so the initial state is clean // the only two pointers set so far are LoadCallback, which the core zeroed itself, // and CdCallback Core.gpgx_set_cdd_callback(null); _elf.Seal(); Core.gpgx_set_cdd_callback(cd_callback_handle); SetControllerDefinition(); // pull the default video size from the core UpdateVideo(); SetMemoryDomains(); Core.gpgx_set_input_callback(_inputCallback); // process the non-init settings now PutSettings(_settings); KillMemCallbacks(); _tracer = new GPGXTraceBuffer(this, _memoryDomains, this); (ServiceProvider as BasicServiceProvider).Register <ITraceable>(_tracer); } _romfile = null; }
public Gameboy(CoreComm comm, GameInfo game, byte[] file, object Settings, object SyncSettings, bool deterministic) { var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(new GBDisassembler()); ServiceProvider = ser; Tracer = new TraceBuffer { Header = "Z80: PC, opcode, registers (A, B, C, D, E, F, H, L, LY, SP, CY)" }; ser.Register <ITraceable>(Tracer); InitMemoryCallbacks(); CoreComm = comm; comm.VsyncNum = 262144; comm.VsyncDen = 4389; comm.RomStatusAnnotation = null; comm.RomStatusDetails = null; comm.NominalWidth = 160; comm.NominalHeight = 144; ThrowExceptionForBadRom(file); BoardName = MapperName(file); DeterministicEmulation = deterministic; GambatteState = LibGambatte.gambatte_create(); if (GambatteState == IntPtr.Zero) { throw new InvalidOperationException("gambatte_create() returned null???"); } try { this._syncSettings = (GambatteSyncSettings)SyncSettings ?? new GambatteSyncSettings(); // copy over non-loadflag syncsettings now; they won't take effect if changed later zerotime = (uint)this._syncSettings.RTCInitialTime; real_rtc_time = DeterministicEmulation ? false : this._syncSettings.RealTimeRTC; LibGambatte.LoadFlags flags = 0; if (this._syncSettings.ForceDMG) { flags |= LibGambatte.LoadFlags.FORCE_DMG; } if (this._syncSettings.GBACGB) { flags |= LibGambatte.LoadFlags.GBA_CGB; } if (this._syncSettings.MulticartCompat) { flags |= LibGambatte.LoadFlags.MULTICART_COMPAT; } if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, GetCurrentTime(), flags) != 0) { throw new InvalidOperationException("gambatte_load() returned non-zero (is this not a gb or gbc rom?)"); } // set real default colors (before anyone mucks with them at all) PutSettings((GambatteSettings)Settings ?? new GambatteSettings()); InitSound(); Frame = 0; LagCount = 0; IsLagFrame = false; InputCallback = new LibGambatte.InputGetter(ControllerCallback); LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback); InitMemoryDomains(); CoreComm.RomStatusDetails = string.Format("{0}\r\nSHA1:{1}\r\nMD5:{2}\r\n", game.Name, file.HashSHA1(), file.HashMD5()); { byte[] buff = new byte[32]; LibGambatte.gambatte_romtitle(GambatteState, buff); string romname = System.Text.Encoding.ASCII.GetString(buff); Console.WriteLine("Core reported rom name: {0}", romname); } TimeCallback = new LibGambatte.RTCCallback(GetCurrentTime); LibGambatte.gambatte_setrtccallback(GambatteState, TimeCallback); CDCallback = new LibGambatte.CDCallback(CDCallbackProc); NewSaveCoreSetBuff(); } catch { Dispose(); throw; } }
public Gameboy(CoreComm comm, GameInfo game, byte[] file, object settings, object syncSettings, bool deterministic) { var ser = new BasicServiceProvider(this); ser.Register <IDisassemblable>(new GBDisassembler()); ServiceProvider = ser; Tracer = new TraceBuffer { Header = "Z80: PC, opcode, registers (A, B, C, D, E, F, H, L, LY, SP, CY)" }; ser.Register <ITraceable>(Tracer); InitMemoryCallbacks(); CoreComm = comm; comm.RomStatusAnnotation = null; comm.RomStatusDetails = null; comm.NominalWidth = 160; comm.NominalHeight = 144; ThrowExceptionForBadRom(file); BoardName = MapperName(file); DeterministicEmulation = deterministic; GambatteState = LibGambatte.gambatte_create(); if (GambatteState == IntPtr.Zero) { throw new InvalidOperationException("gambatte_create() returned null???"); } Console.WriteLine(game.System); byte[] BiosRom; if (game.System == "GB") { BiosRom = comm.CoreFileProvider.GetFirmware("GB", "World", false); } else { BiosRom = comm.CoreFileProvider.GetFirmware("GBC", "World", false); } int bios_length = BiosRom == null ? 0 : BiosRom.Length; try { _syncSettings = (GambatteSyncSettings)syncSettings ?? new GambatteSyncSettings(); // copy over non-loadflag syncsettings now; they won't take effect if changed later zerotime = (uint)_syncSettings.RTCInitialTime; real_rtc_time = !DeterministicEmulation && _syncSettings.RealTimeRTC; LibGambatte.LoadFlags flags = 0; switch (_syncSettings.ConsoleMode) { case GambatteSyncSettings.ConsoleModeType.GB: flags |= LibGambatte.LoadFlags.FORCE_DMG; // we need to change the BIOS to GB bios if (game.System == "GBC") { BiosRom = comm.CoreFileProvider.GetFirmware("GB", "World", false); bios_length = BiosRom.Length; } break; case GambatteSyncSettings.ConsoleModeType.GBC: BiosRom = comm.CoreFileProvider.GetFirmware("GBC", "World", false); bios_length = BiosRom.Length; break; default: if (game.System == "GB") { flags |= LibGambatte.LoadFlags.FORCE_DMG; } break; } if (_syncSettings.EnableBIOS && BiosRom == null) { throw new MissingFirmwareException("Boot Rom not found"); } // to disable BIOS loading into gambatte, just set bios_length to 0 if (!_syncSettings.EnableBIOS) { bios_length = 0; } if (_syncSettings.GBACGB) { flags |= LibGambatte.LoadFlags.GBA_CGB; } if (_syncSettings.MulticartCompat) { flags |= LibGambatte.LoadFlags.MULTICART_COMPAT; } if (LibGambatte.gambatte_load(GambatteState, file, (uint)file.Length, BiosRom, (uint)bios_length, GetCurrentTime(), flags) != 0) { throw new InvalidOperationException("gambatte_load() returned non-zero (is this not a gb or gbc rom?)"); } // set real default colors (before anyone mucks with them at all) PutSettings((GambatteSettings)settings ?? new GambatteSettings()); InitSound(); Frame = 0; LagCount = 0; IsLagFrame = false; InputCallback = new LibGambatte.InputGetter(ControllerCallback); LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback); InitMemoryDomains(); CoreComm.RomStatusDetails = $"{game.Name}\r\nSHA1:{file.HashSHA1()}\r\nMD5:{file.HashMD5()}\r\n"; byte[] buff = new byte[32]; LibGambatte.gambatte_romtitle(GambatteState, buff); string romname = System.Text.Encoding.ASCII.GetString(buff); Console.WriteLine("Core reported rom name: {0}", romname); TimeCallback = new LibGambatte.RTCCallback(GetCurrentTime); LibGambatte.gambatte_setrtccallback(GambatteState, TimeCallback); _cdCallback = new LibGambatte.CDCallback(CDCallbackProc); NewSaveCoreSetBuff(); } catch { Dispose(); throw; } }