public override string GetRomFormatName(byte[] rom) { var swapped = N64.IsByteswapped(rom); if (swapped == N64ByteSwap.NotSwapped) { return("N64 ROM image"); } if (swapped == N64ByteSwap.Swapped) { return("N64 ROM image (byte-swapped)"); } return("N64 ROM image (byte-swapping unknown)"); }
public mupen64plusApi(N64 bizhawkCore, byte[] rom, VideoPluginSettings video_settings, int SaveType, int CoreType, bool DisableExpansionSlot) { // There can only be one core (otherwise breaks mupen64plus) if (AttachedCore != null) { AttachedCore.Dispose(); AttachedCore = null; } this.bizhawkCore = bizhawkCore; CoreDll = LoadLibrary("mupen64plus.dll"); if (CoreDll == IntPtr.Zero) { throw new InvalidOperationException(string.Format("Failed to load mupen64plus.dll")); } connectFunctionPointers(); // Start up the core m64p_error result = m64pCoreStartup(0x20001, "", "", "Core", null, "", IntPtr.Zero); // Open the core settings section in the config system IntPtr core_section = IntPtr.Zero; m64pConfigOpenSection("Core", ref core_section); // Set the savetype if needed if (DisableExpansionSlot) { int disable = 1; m64pConfigSetParameter(core_section, "DisableExtraMem", m64p_type.M64TYPE_INT, ref disable); } // Set the savetype if needed if (SaveType != 0) { m64pConfigSetParameter(core_section, "SaveType", m64p_type.M64TYPE_INT, ref SaveType); } m64pConfigSetParameter(core_section, "R4300Emulator", m64p_type.M64TYPE_INT, ref CoreType); // Pass the rom to the core result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom); // Open the general video settings section in the config system IntPtr video_section = IntPtr.Zero; m64pConfigOpenSection("Video-General", ref video_section); // Set the desired width and height for mupen64plus result = m64pConfigSetParameter(video_section, "ScreenWidth", m64p_type.M64TYPE_INT, ref video_settings.Width); result = m64pConfigSetParameter(video_section, "ScreenHeight", m64p_type.M64TYPE_INT, ref video_settings.Height); set_video_parameters(video_settings); InitSaveram(); // Initialize event invoker m64pFrameCallback = new FrameCallback(FireFrameFinishedEvent); result = m64pCoreDoCommandFrameCallback(m64p_command.M64CMD_SET_FRAME_CALLBACK, 0, m64pFrameCallback); m64pVICallback = new VICallback(FireVIEvent); result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback); m64pRenderCallback = new RenderCallback(FireRenderEvent); result = m64pCoreDoCommandRenderCallback(m64p_command.M64CMD_SET_RENDER_CALLBACK, 0, m64pRenderCallback); // Prepare to start the emulator in a different thread m64pEmulator = new Thread(ExecuteEmulator); AttachedCore = this; }
public mupen64plusApi(N64 bizhawkCore, byte[] rom, VideoPluginSettings video_settings, int SaveType, int CoreType, bool DisableExpansionSlot) { // There can only be one core (otherwise breaks mupen64plus) if (AttachedCore != null) { AttachedCore.Dispose(); AttachedCore = null; } this.bizhawkCore = bizhawkCore; CoreDll = LoadLibrary("mupen64plus.dll"); if (CoreDll == IntPtr.Zero) throw new InvalidOperationException(string.Format("Failed to load mupen64plus.dll")); connectFunctionPointers(); // Start up the core m64p_error result = m64pCoreStartup(0x20001, "", "", "Core", null, "", IntPtr.Zero); // Set the savetype if needed if (DisableExpansionSlot) { IntPtr core_section = IntPtr.Zero; int disable = 1; m64pConfigOpenSection("Core", ref core_section); m64pConfigSetParameter(core_section, "DisableExtraMem", m64p_type.M64TYPE_INT, ref disable); } // Set the savetype if needed if (SaveType != 0) { IntPtr core_section = IntPtr.Zero; m64pConfigOpenSection("Core", ref core_section); m64pConfigSetParameter(core_section, "SaveType", m64p_type.M64TYPE_INT, ref SaveType); } IntPtr coreSection = IntPtr.Zero; m64pConfigOpenSection("Core", ref coreSection); m64pConfigSetParameter(coreSection, "R4300Emulator", m64p_type.M64TYPE_INT, ref CoreType); // Pass the rom to the core result = m64pCoreDoCommandByteArray(m64p_command.M64CMD_ROM_OPEN, rom.Length, rom); // Open the general video settings section in the config system IntPtr video_section = IntPtr.Zero; m64pConfigOpenSection("Video-General", ref video_section); // Set the desired width and height for mupen64plus result = m64pConfigSetParameter(video_section, "ScreenWidth", m64p_type.M64TYPE_INT, ref video_settings.Width); result = m64pConfigSetParameter(video_section, "ScreenHeight", m64p_type.M64TYPE_INT, ref video_settings.Height); set_video_parameters(video_settings); InitSaveram(); // Initialize event invoker m64pFrameCallback = new FrameCallback(FireFrameFinishedEvent); result = m64pCoreDoCommandFrameCallback(m64p_command.M64CMD_SET_FRAME_CALLBACK, 0, m64pFrameCallback); m64pVICallback = new VICallback(FireVIEvent); result = m64pCoreDoCommandVICallback(m64p_command.M64CMD_SET_VI_CALLBACK, 0, m64pVICallback); m64pRenderCallback = new RenderCallback(FireRenderEvent); result = m64pCoreDoCommandRenderCallback(m64p_command.M64CMD_SET_RENDER_CALLBACK, 0, m64pRenderCallback); // Prepare to start the emulator in a different thread m64pEmulator = new Thread(ExecuteEmulator); AttachedCore = this; }
public override void CalculateHashes(byte[] rom, IHashWorkManager worker, float startProgress, float endProgress) { // N64 hashes are calculated using the thread pool because the ROMs tend to be large bool byteswapped = N64.IsByteswapped(rom) == N64ByteSwap.Swapped; byte[] swappedRom = new byte[rom.Length]; // Watch out for odd # of bytes! int len = rom.Length & (~1); for (int i = 0; i < len; i += 2) { swappedRom[i] = rom[i + 1]; swappedRom[i + 1] = rom[i]; } HashFlags originalType = byteswapped ? HashFlags.RomHash_ByteSwap : HashFlags.RomHash; HashFlags swappedType = byteswapped ? HashFlags.RomHash : HashFlags.RomHash_ByteSwap; worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(rom, 0, rom.Length, () => worker.AbortPending, HashFlags.SHA256, originalType, HashFlags.FileHash); } }); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(rom, 0, rom.Length, () => worker.AbortPending, HashFlags.SHA1, originalType, HashFlags.FileHash); } }); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(rom, 0, rom.Length, () => worker.AbortPending, HashFlags.CRC32, originalType, HashFlags.FileHash); } }); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(rom, 0, rom.Length, () => worker.AbortPending, HashFlags.MD5, originalType, HashFlags.FileHash); } }); // We can not byte-swap the ROM while it is being hashed worker.WaitAll(); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(swappedRom, 0, swappedRom.Length, () => worker.AbortPending, HashFlags.SHA256, swappedType); } }); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(swappedRom, 0, swappedRom.Length, () => worker.AbortPending, HashFlags.SHA1, swappedType); } }); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(swappedRom, 0, swappedRom.Length, () => worker.AbortPending, HashFlags.CRC32, swappedType); } }); worker.QueueTask((SimpleDelegate) delegate { if (!worker.AbortPending) { worker.AddHashes(swappedRom, 0, swappedRom.Length, () => worker.AbortPending, HashFlags.MD5, swappedType); } }); // We can not return until all hashes are calculated worker.WaitAll(); }
public override bool IsPlatformMatch(byte[] rom) { // Check for a valid normal or byteswapped header return(N64.IsByteswapped(rom) != N64ByteSwap.Unknown); }
internal override void InitRomData(RomData data, byte[] rom) { base.InitRomData(data, rom); data.MiscData.Add(ByteswapTagID, N64.IsByteswapped(rom)); }
protected override void AddPlatformExtendedData(Platform.RomExDataBuilder builder, byte[] rom, RomData data) { builder.AddData(RomExDataBuilder.GeneralCat, "Byte-swapped", N64.IsByteswapped(rom).GetDescription()); }
public bool LoadRom(string path, CoreComm nextComm, bool forceAccurateCore = false) // forceAccurateCore is currently just for Quicknes vs Neshawk but could be used for other situations { if (path == null) { return(false); } using (var file = new HawkFile()) { var romExtensions = new[] { "SMS", "SMC", "SFC", "PCE", "SGX", "GG", "SG", "BIN", "GEN", "MD", "SMD", "GB", "NES", "FDS", "ROM", "INT", "GBC", "UNF", "A78", "CRT", "COL", "XML", "Z64", "V64", "N64", "WS", "WSC" }; // lets not use this unless we need to // file.NonArchiveExtensions = romExtensions; file.Open(path); // if the provided file doesnt even exist, give up! if (!file.Exists) { return(false); } // try binding normal rom extensions first if (!file.IsBound) { file.BindSoleItemOf(romExtensions); } // if we have an archive and need to bind something, then pop the dialog if (file.IsArchive && !file.IsBound) { var result = HandleArchive(file); if (result.HasValue) { file.BindArchiveMember(result.Value); } else { return(false); } } // set this here so we can see what file we tried to load even if an error occurs CanonicalFullPath = file.CanonicalFullPath; IEmulator nextEmulator = null; RomGame rom = null; GameInfo game = null; try { var ext = file.Extension.ToLower(); if (ext == ".iso" || ext == ".cue") { var disc = ext == ".iso" ? Disc.FromIsoPath(path) : Disc.FromCuePath(path, new CueBinPrefs()); var hash = disc.GetHash(); game = Database.CheckDatabase(hash); if (game == null) { // try to use our wizard methods game = new GameInfo { Name = Path.GetFileNameWithoutExtension(file.Name), Hash = hash }; switch (disc.DetectDiscType()) { case DiscType.SegaSaturn: game.System = "SAT"; break; case DiscType.SonyPSP: game.System = "PSP"; break; case DiscType.SonyPSX: game.System = "PSX"; break; case DiscType.MegaCD: game.System = "GEN"; break; case DiscType.TurboCD: case DiscType.UnknownCDFS: case DiscType.UnknownFormat: default: // PCECD was bizhawk's first CD core, // and during that time, all CDs were blindly sent to it // so this prevents regressions game.System = "PCECD"; break; } } switch (game.System) { case "GEN": var genesis = new GPGX( nextComm, null, disc, "GEN", GetCoreSettings <GPGX>(), GetCoreSyncSettings <GPGX>()); nextEmulator = genesis; break; case "SAT": nextEmulator = new Yabause(nextComm, disc, GetCoreSyncSettings <Yabause>()); break; case "PSP": nextEmulator = new PSP(nextComm, file.Name); break; case "PSX": nextEmulator = new Octoshock(nextComm); (nextEmulator as Octoshock).LoadCuePath(file.CanonicalFullPath); nextEmulator.CoreComm.RomStatusDetails = "PSX etc."; break; case "PCE": case "PCECD": nextEmulator = new PCEngine(nextComm, game, disc, GetCoreSettings <PCEngine>(), GetCoreSyncSettings <PCEngine>()); break; } } else if (file.Extension.ToLower() == ".xml") { try { var xmlGame = XmlGame.Create(file); // if load fails, are we supposed to retry as a bsnes XML???????? game = xmlGame.GI; switch (game.System) { case "DGB": var left = Database.GetGameInfo(xmlGame.Assets["LeftRom"], "left.gb"); var right = Database.GetGameInfo(xmlGame.Assets["RightRom"], "right.gb"); nextEmulator = new GambatteLink( nextComm, left, xmlGame.Assets["LeftRom"], right, xmlGame.Assets["RightRom"], GetCoreSettings <GambatteLink>(), GetCoreSyncSettings <GambatteLink>(), Deterministic); // other stuff todo break; default: return(false); } } catch (Exception ex) { DoLoadErrorCallback(ex.ToString(), "DGB", LoadErrorType.XML); return(false); } } else // most extensions { rom = new RomGame(file); if (string.IsNullOrEmpty(rom.GameInfo.System)) { // Has the user picked a preference for this extension? if (PreferredPlatformIsDefined(rom.Extension.ToLower())) { rom.GameInfo.System = Global.Config.PreferredPlatformsForExtensions[rom.Extension.ToLower()]; } else if (ChoosePlatform != null) { rom.GameInfo.System = ChoosePlatform(rom); } } game = rom.GameInfo; var isXml = false; // other xml has already been handled if (file.Extension.ToLower() == ".xml") { game.System = "SNES"; isXml = true; } switch (game.System) { case "SNES": if (Global.Config.SNES_InSnes9x && VersionInfo.DeveloperBuild) { var snes = new Emulation.Cores.Nintendo.SNES9X.Snes9x(nextComm, rom.FileData); nextEmulator = snes; } else { // need to get rid of this hack at some point ((CoreFileProvider)nextComm.CoreFileProvider).SubfileDirectory = Path.GetDirectoryName(path.Replace("|", String.Empty)); // Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename var romData = isXml ? null : rom.FileData; var xmlData = isXml ? rom.FileData : null; var snes = new LibsnesCore(game, romData, Deterministic, xmlData, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>()); nextEmulator = snes; } RACore.OnLoad(RAConsoleID.SNES, rom.GameInfo.Name, rom.GameInfo.Hash); break; case "SMS": case "SG": case "GG": nextEmulator = new SMS(nextComm, game, rom.RomData, GetCoreSettings <SMS>(), GetCoreSyncSettings <SMS>()); RACore.OnLoad(RAConsoleID.MasterSystem, rom.GameInfo.Name, rom.GameInfo.Hash); break; case "A26": nextEmulator = new Atari2600( nextComm, game, rom.FileData, GetCoreSettings <Atari2600>(), GetCoreSyncSettings <Atari2600>()); break; case "PCE": case "PCECD": case "SGX": nextEmulator = new PCEngine(nextComm, game, rom.RomData, GetCoreSettings <PCEngine>(), GetCoreSyncSettings <PCEngine>()); RACore.OnLoad(RAConsoleID.PCEngine, rom.GameInfo.Name, rom.GameInfo.Hash); break; case "GEN": nextEmulator = new GPGX(nextComm, rom.RomData, null, "GEN", GetCoreSettings <GPGX>(), GetCoreSyncSettings <GPGX>()); RACore.OnLoad(RAConsoleID.MegaDrive, rom.GameInfo.Name, rom.GameInfo.Hash); break; case "TI83": nextEmulator = new TI83(nextComm, game, rom.RomData, GetCoreSettings <TI83>()); break; case "NES": if (!Global.Config.NES_InQuickNES || forceAccurateCore) { nextEmulator = new NES( nextComm, game, rom.FileData, GetCoreSettings <NES>(), GetCoreSyncSettings <NES>()); } else { nextEmulator = new QuickNES(nextComm, rom.FileData, GetCoreSettings <QuickNES>()); } RACore.OnLoad(RAConsoleID.NES, rom.GameInfo.Name, rom.GameInfo.Hash); break; case "GB": case "GBC": if (!Global.Config.GB_AsSGB) { nextEmulator = new Gameboy( nextComm, game, rom.FileData, GetCoreSettings <Gameboy>(), GetCoreSyncSettings <Gameboy>(), Deterministic); } else { try { game.System = "SNES"; game.AddOption("SGB"); var snes = new LibsnesCore(game, rom.FileData, Deterministic, null, nextComm, GetCoreSettings <LibsnesCore>(), GetCoreSyncSettings <LibsnesCore>()); nextEmulator = snes; } catch { // failed to load SGB bios or game does not support SGB mode. // To avoid catch-22, disable SGB mode Global.Config.GB_AsSGB = false; throw; } } if (game.System == "GB") { RACore.OnLoad(RAConsoleID.Gameboy, rom.GameInfo.Name, rom.GameInfo.Hash); } else if (game.System == "GBC") { RACore.OnLoad(RAConsoleID.GameboyColor, rom.GameInfo.Name, rom.GameInfo.Hash); } break; case "Coleco": nextEmulator = new ColecoVision(nextComm, game, rom.RomData, GetCoreSyncSettings <ColecoVision>()); break; case "INTV": nextEmulator = new Intellivision(nextComm, game, rom.RomData); break; case "A78": var gamedbpath = Path.Combine(PathManager.GetExeDirectoryAbsolute(), "gamedb", "EMU7800.csv"); nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath); break; case "C64": var c64 = new C64(nextComm, game, rom.RomData, rom.Extension); nextEmulator = c64; break; case "GBA": if (false) { //var gba = new GBA(nextComm); //gba.Load(rom.RomData); //nextEmulator = gba; } else { var gba = new VBANext(rom.RomData, nextComm); nextEmulator = gba; RACore.OnLoad(RAConsoleID.GameboyAdvance, rom.GameInfo.Name, rom.GameInfo.Hash); } break; case "N64": nextEmulator = new N64(nextComm, game, rom.RomData, GetCoreSettings <N64>(), GetCoreSyncSettings <N64>()); RACore.OnLoad(RAConsoleID.Nintendo64, rom.GameInfo.Name, rom.GameInfo.Hash); break; case "WSWAN": nextEmulator = new WonderSwan(nextComm, rom.RomData, Deterministic, GetCoreSettings <WonderSwan>(), GetCoreSyncSettings <WonderSwan>()); break; case "DEBUG": if (VersionInfo.DeveloperBuild) { nextEmulator = LibRetroEmulator.CreateDebug(nextComm, rom.RomData); } break; } } if (nextEmulator == null) { DoLoadErrorCallback("No core could load the rom.", null); return(false); } } catch (Exception ex) { string system = null; if (game != null) { system = game.System; } // Specific hack here, as we get more cores of the same system, this isn't scalable if (ex is UnsupportedMapperException) { return(LoadRom(path, nextComm, forceAccurateCore: true)); } else if (ex is MissingFirmwareException) { DoLoadErrorCallback(ex.Message, system, LoadErrorType.MissingFirmware); } else if (ex is CGBNotSupportedException) { // Note: GB as SGB was set to false by this point, otherwise we would want to do it here DoMessageCallback("Failed to load a GB rom in SGB mode. Disabling SGB Mode."); return(LoadRom(path, nextComm)); } else { DoLoadErrorCallback("A core accepted the rom, but threw an exception while loading it:\n\n" + ex, system); } return(false); } Rom = rom; LoadedEmulator = nextEmulator; Game = game; return(true); } }