public bool PutSyncSettings(GambatteSyncSettings o) { bool ret = GambatteSyncSettings.NeedsReboot(_syncSettings, o); _syncSettings = o; return(ret); }
public PutSettingsDirtyBits PutSyncSettings(GambatteSyncSettings o) { bool ret = GambatteSyncSettings.NeedsReboot(_syncSettings, o); _syncSettings = o; return(ret ? PutSettingsDirtyBits.RebootCore : PutSettingsDirtyBits.None); }
public bool PutSyncSettings(object o) { var s = (GambatteSyncSettings)o; bool ret = GambatteSyncSettings.NeedsReboot(_SyncSettings, s); _SyncSettings = s; return(ret); }
public static bool NeedsReboot(GambatteSyncSettings x, GambatteSyncSettings y) { return(!DeepEquality.DeepEquals(x, y)); }
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 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(); 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; } 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(settings ?? new GambatteSettings()); InitSound(); Frame = 0; LagCount = 0; IsLagFrame = false; InputCallback = new LibGambatte.InputGetter(ControllerCallback); LibGambatte.gambatte_setinputgetter(GambatteState, InputCallback, IntPtr.Zero); InitMemoryDomains(); byte[] mbcBuf = new byte[32]; uint rambanks = 0; uint rombanks = 0; uint crc = 0; uint headerchecksumok = 0; LibGambatte.gambatte_pakinfo(GambatteState, mbcBuf, ref rambanks, ref rombanks, ref crc, ref headerchecksumok); byte[] romNameBuf = new byte[32]; LibGambatte.gambatte_romtitle(GambatteState, romNameBuf); string romname = Encoding.ASCII.GetString(romNameBuf); RomDetails = $"{game.Name}\r\n{SHA1Checksum.ComputePrefixedHex(file)}\r\n{MD5Checksum.ComputePrefixedHex(file)}\r\n\r\n"; BoardName = Encoding.ASCII.GetString(mbcBuf); RomDetails += $"Core reported Header Name: {romname}\r\n"; RomDetails += $"Core reported RAM Banks: {rambanks}\r\n"; RomDetails += $"Core reported ROM Banks: {rombanks}\r\n"; RomDetails += $"Core reported CRC32: {crc:X8}\r\n"; RomDetails += $"Core reported Header Checksum Status: {(headerchecksumok != 0 ? "OK" : "BAD")}\r\n"; if (_syncSettings.EnableBIOS && headerchecksumok == 0) { comm.ShowMessage("Core reports the header checksum is bad. This ROM will not boot with the official BIOS.\n" + "Disable BIOS in sync settings to boot this game"); } 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) { ulong dividers = _syncSettings.InitialTime * (0x400000UL + (ulong)_syncSettings.RTCDivisorOffset) / 2UL; LibGambatte.gambatte_settime(GambatteState, dividers); } LibGambatte.gambatte_setrtcdivisoroffset(GambatteState, _syncSettings.RTCDivisorOffset); LibGambatte.gambatte_setcartbuspulluptime(GambatteState, (uint)_syncSettings.CartBusPullUpTime); _cdCallback = new LibGambatte.CDCallback(CDCallbackProc); ControllerDefinition = CreateControllerDefinition(sgb: IsSgb, sub: _syncSettings.FrameLength is GambatteSyncSettings.FrameLengthType.UserDefinedFrames, tilt: false); NewSaveCoreSetBuff(); } catch { Dispose(); throw; } }
public static bool NeedsReboot(GambatteSyncSettings x, GambatteSyncSettings y) { return !DeepEquality.DeepEquals(x, y); }
public bool PutSyncSettings(object o) { var s = (GambatteSyncSettings)o; bool ret = GambatteSyncSettings.NeedsReboot(_SyncSettings, s); _SyncSettings = s; return ret; }