saturnus: settings

This commit is contained in:
nattthebear 2017-06-09 16:42:08 -04:00
parent f4c5c53c8a
commit 1c46b79bbb
5 changed files with 343 additions and 25 deletions

View File

@ -501,7 +501,8 @@ namespace BizHawk.Client.Common
break;
case "SAT":
//nextEmulator = new Yabause(nextComm, disc, GetCoreSyncSettings<Yabause>());
nextEmulator = new Saturnus(nextComm, new[] { disc });
nextEmulator = new Saturnus(nextComm, new[] { disc }, Deterministic,
(Saturnus.Settings)GetCoreSettings<Saturnus>(), (Saturnus.SyncSettings)GetCoreSyncSettings<Saturnus>());
break;
case "PSP":
nextEmulator = new PSP(nextComm, file.Name);

View File

@ -79,7 +79,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
[BizImport(CC)]
public abstract void SetCDCallbacks(CDTOCCallback toccallback, CDSectorCallback sectorcallback);
[BizImport(CC)]
public abstract bool Init(int numDisks);
public abstract bool Init(
int numDisks,
Saturnus.SyncSettings.CartType cartType,
Saturnus.SyncSettings.RegionType regionDefault,
bool regionAutodetect);
[BizImport(CC)]
public abstract void HardReset();
[BizImport(CC)]
@ -92,5 +96,9 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
public abstract void SetInputCallback(InputCallback callback);
[BizImport(CC)]
public abstract void SetAddMemoryDomainCallback(AddMemoryDomainCallback callback);
[BizImport(CC)]
public abstract void SetRtc(long ticks, Saturnus.SyncSettings.LanguageType language);
[BizImport(CC)]
public abstract void SetVideoParameters(bool correctAspect, bool hBlend, bool hOverscan, int sls, int sle);
}
}

View File

@ -6,6 +6,8 @@ using BizHawk.Emulation.Cores.Waterbox;
using BizHawk.Emulation.DiscSystem;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
@ -18,7 +20,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
[CoreAttributes("Saturnus", "Ryphecha", true, false, "0.9.44.1",
"https://mednafen.github.io/releases/", false)]
public class Saturnus : IEmulator, IVideoProvider, ISoundProvider,
IInputPollable, IDriveLight, IStatable, IRegionable, ISaveRam
IInputPollable, IDriveLight, IStatable, IRegionable, ISaveRam,
ISettable<Saturnus.Settings, Saturnus.SyncSettings>
{
private static readonly DiscSectorReaderPolicy _diskPolicy = new DiscSectorReaderPolicy
{
@ -56,10 +59,13 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
return true;
}
public Saturnus(CoreComm comm, IEnumerable<Disc> disks)
public Saturnus(CoreComm comm, IEnumerable<Disc> disks, bool deterministic, Settings settings,
SyncSettings syncSettings)
{
ServiceProvider = new BasicServiceProvider(this);
CoreComm = comm;
settings = settings ?? new Settings();
syncSettings = syncSettings ?? new SyncSettings();
_disks = disks.ToArray();
_diskReaders = disks.Select(d => new DiscSectorReader(d) { Policy = _diskPolicy }).ToArray();
@ -83,18 +89,37 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
SetFirmwareCallbacks();
SetCdCallbacks();
_core.SetAddMemoryDomainCallback(_addMemoryDomainCallback);
if (!_core.Init(_disks.Length))
if (!_core.Init(_disks.Length, syncSettings.ExpansionCart, syncSettings.Region, syncSettings.RegionAutodetect))
throw new InvalidOperationException("Core rejected the disks!");
ClearAllCallbacks();
_controllerDeck = new SaturnusControllerDeck(new[] { false, false },
new[] { SaturnusControllerDeck.Device.Gamepad, SaturnusControllerDeck.Device.None },
_core);
_controllerDeck = new SaturnusControllerDeck(new[]
{
syncSettings.Port1Multitap,
syncSettings.Port2Multitap
}, new[]
{
syncSettings.Port1,
syncSettings.Port2,
syncSettings.Port3,
syncSettings.Port4,
syncSettings.Port5,
syncSettings.Port6,
syncSettings.Port7,
syncSettings.Port8,
syncSettings.Port9,
syncSettings.Port10,
syncSettings.Port11,
syncSettings.Port12
}, _core);
ControllerDefinition = _controllerDeck.Definition;
ControllerDefinition.Name = "Saturn Controller";
ControllerDefinition.BoolButtons.Add("Power");
ControllerDefinition.BoolButtons.Add("Reset");
_core.SetRtc((long)syncSettings.InitialTime.Subtract(new DateTime(1970, 1, 1)).TotalSeconds,
syncSettings.Language);
_exe.Seal();
SetCdCallbacks();
_core.SetDisk(0, false);
@ -103,10 +128,20 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
{
MainMemory = _memoryDomains["Work Ram Low"]
});
PutSettings(settings);
_syncSettings = syncSettings;
DeterministicEmulation = deterministic || !_syncSettings.UseRealTime;
}
public unsafe void FrameAdvance(IController controller, bool render, bool rendersound = true)
{
// if not reset, the core will maintain its own deterministic increasing time each frame
if (!DeterministicEmulation)
{
_core.SetRtc((long)DateTime.Now.Subtract(new DateTime(1970, 1, 1)).TotalSeconds,
_syncSettings.Language);
}
DriveLightOn = false;
if (controller.IsPressed("Power"))
_core.HardReset();
@ -166,6 +201,250 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
public CoreComm CoreComm { get; }
public ControllerDefinition ControllerDefinition { get; }
#region ISettable
public class Settings
{
// extern bool setting_ss_correct_aspect;
[DefaultValue(true)]
public bool CorrectAspectRatio { get; set; }
// extern bool setting_ss_h_blend;
[DisplayName("Horizontal Blend")]
[DefaultValue(false)]
[Description("Use horizontal blend filter")]
public bool HBlend { get; set; }
// extern bool setting_ss_h_overscan;
[DisplayName("Horizontal Overscan")]
[DefaultValue(true)]
[Description("Show horiziontal overscan area")]
public bool HOverscan { get; set; }
// extern int setting_ss_slstart;
[DefaultValue(0)]
[Description("First scanline to display in NTSC mode")]
[Range(0, 239)]
public int ScanlineStartNtsc { get; set; }
// extern int setting_ss_slend;
[DefaultValue(239)]
[Description("Last scanline to display in NTSC mode")]
[Range(0, 239)]
public int ScanlineEndNtsc { get; set; }
// extern int setting_ss_slstartp;
[DefaultValue(0)]
[Description("First scanline to display in PAL mode")]
[Range(-16, 271)]
public int ScanlineStartPal { get; set; }
// extern int setting_ss_slendp;
[DefaultValue(255)]
[Description("Last scanline to display in PAL mode")]
[Range(-16, 271)]
public int ScanlineEndPal { get; set; }
public Settings()
{
SettingsUtil.SetDefaultValues(this);
}
public Settings Clone()
{
return (Settings)MemberwiseClone();
}
public static bool NeedsReboot(Settings x, Settings y)
{
return false;
}
}
public class SyncSettings
{
public enum CartType
{
[Display(Name = "Autodetect. Will use Backup Ram Cart if no others are appropriate")]
Autodetect = -1,
[Display(Name = "None")]
None,
[Display(Name = "Backup Ram Cart")]
Backup,
[Display(Name = "1 Meg Ram Cart")]
Ram1Meg,
[Display(Name = "4 Meg Ram Cart")]
Ram4Meg,
[Display(Name = "King of Fighters 95 Rom Cart")]
Kof95,
[Display(Name = "Ultraman Rom Cart")]
Ultraman,
[Display(Name = "CS1 16 Meg Ram Cart")]
Ram16Meg
}
// extern int setting_ss_cart;
[DefaultValue(CartType.Autodetect)]
[Description("What to plug into the Saturn expansion slot")]
public CartType ExpansionCart { get; set; }
[DisplayName("Port 1 Device")]
[DefaultValue(SaturnusControllerDeck.Device.Gamepad)]
public SaturnusControllerDeck.Device Port1 { get; set; }
[DisplayName("Port 2 Device")]
[DefaultValue(SaturnusControllerDeck.Device.Gamepad)]
public SaturnusControllerDeck.Device Port2 { get; set; }
[DisplayName("Port 3 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if one or both multitaps are set")]
public SaturnusControllerDeck.Device Port3 { get; set; }
[DisplayName("Port 4 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if one or both multitaps are set")]
public SaturnusControllerDeck.Device Port4 { get; set; }
[DisplayName("Port 5 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if one or both multitaps are set")]
public SaturnusControllerDeck.Device Port5 { get; set; }
[DisplayName("Port 6 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if one or both multitaps are set")]
public SaturnusControllerDeck.Device Port6 { get; set; }
[DisplayName("Port 7 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if one or both multitaps are set")]
public SaturnusControllerDeck.Device Port7 { get; set; }
[DisplayName("Port 8 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if both multitaps are set")]
public SaturnusControllerDeck.Device Port8 { get; set; }
[DisplayName("Port 9 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if both multitaps are set")]
public SaturnusControllerDeck.Device Port9 { get; set; }
[DisplayName("Port 10 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if both multitaps are set")]
public SaturnusControllerDeck.Device Port10 { get; set; }
[DisplayName("Port 11 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if both multitaps are set")]
public SaturnusControllerDeck.Device Port11 { get; set; }
[DisplayName("Port 12 Device")]
[DefaultValue(SaturnusControllerDeck.Device.None)]
[Description("Only used if both multitaps are set")]
public SaturnusControllerDeck.Device Port12 { get; set; }
[DisplayName("Port 1 Multitap")]
[Description("If true, Ports 1-6 will be used for multitap")]
[DefaultValue(false)]
public bool Port1Multitap { get; set; }
[DisplayName("Port 2 Multitap")]
[Description("If true, Ports 2-7 (or 7-12, depending on Port 1 Multitap) will be used for multitap")]
[DefaultValue(false)]
public bool Port2Multitap { get; set; }
// extern bool setting_ss_region_autodetect;
[DisplayName("Region Autodetect")]
[Description("Attempt to guess the game region")]
[DefaultValue(true)]
public bool RegionAutodetect { get; set; }
public enum RegionType
{
[Display(Name = "Japan")]
Japan = 1,
[Display(Name = "Asia NTSC (Taiwan, Phillipines)")]
Taiwan = 2,
[Display(Name = "North America")]
Murka = 4,
[Display(Name = "Latin America NTSC (Brazil)")]
Brazil = 5,
[Display(Name = "South Korea")]
Korea = 6,
[Display(Name = "Asia PAL (China, Middle East)")]
China = 10,
[Display(Name = "Europe")]
Yurop = 12,
[Display(Name = "Latin America PAL")]
SouthAmerica = 13
}
// extern int setting_ss_region_default;
[DisplayName("Default Region")]
[Description("Used when Region Autodetect is disabled or fails")]
[DefaultValue(RegionType.Japan)]
public RegionType Region { get; set; }
public enum LanguageType
{
English = 0,
German = 1,
French = 2,
Spanish = 3,
Italian = 4,
Japanese = 5,
}
[DisplayName("Language")]
[Description("Language of the system. Only affects some games in some regions.")]
[DefaultValue(LanguageType.Japanese)]
public LanguageType Language { get; set; }
[DisplayName("Initial Time")]
[Description("Initial time of emulation. Only relevant when UseRealTime is false.")]
[DefaultValue(typeof(DateTime), "2010-01-01")]
public DateTime InitialTime { get; set; }
[DisplayName("Use RealTime")]
[Description("If true, RTC clock will be based off of real time instead of emulated time. Ignored (set to false) when recording a movie.")]
[DefaultValue(false)]
public bool UseRealTime { get; set; }
public SyncSettings()
{
SettingsUtil.SetDefaultValues(this);
}
public SyncSettings Clone()
{
return (SyncSettings)MemberwiseClone();
}
public static bool NeedsReboot(SyncSettings x, SyncSettings y)
{
return !DeepEquality.DeepEquals(x, y);
}
}
private Settings _settings;
private SyncSettings _syncSettings;
public Settings GetSettings()
{
return _settings.Clone();
}
public bool PutSettings(Settings s)
{
var ret = Settings.NeedsReboot(_settings, s);
_settings = s;
var sls = _isPal ? s.ScanlineStartPal + 16 : s.ScanlineStartNtsc;
var sle = _isPal ? s.ScanlineEndPal + 16 : s.ScanlineEndNtsc;
_core.SetVideoParameters(s.CorrectAspectRatio, s.HBlend, s.HOverscan, sls, sle);
return ret;
}
public SyncSettings GetSyncSettings()
{
return _syncSettings.Clone();
}
public bool PutSyncSettings(SyncSettings s)
{
var ret = SyncSettings.NeedsReboot(_syncSettings, s);
_syncSettings = s;
return ret;
}
#endregion
#region IMemoryDomains
private readonly Dictionary<string, MemoryDomainIntPtrMonitor> _memoryDomains = new Dictionary<string, MemoryDomainIntPtrMonitor>();

View File

@ -1,6 +1,7 @@
using BizHawk.Emulation.Common;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
@ -67,10 +68,14 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.Saturn
{
None,
Gamepad,
[Display(Name = "3D Pad")]
ThreeDeePad,
Mouse,
[Display(Name = "Racing Controller")]
Wheel,
[Display(Name = "Mission Stick")]
Mission,
[Display(Name = "Two Mission Sticks")]
DualMission,
Keyboard
}

View File

@ -5,6 +5,7 @@
#include "cdb.h"
#include "smpc.h"
#include "cart.h"
#include <ctime>
#define EXPORT extern "C" ECL_EXPORT
using namespace MDFN_IEN_SS;
@ -86,8 +87,12 @@ namespace MDFN_IEN_SS
{
extern bool LoadCD(std::vector<CDIF *> *CDInterfaces);
}
EXPORT bool Init(int numDisks)
EXPORT bool Init(int numDisks, int cartType, int regionDefault, int regionAutodetect)
{
setting_ss_cart = cartType;
setting_ss_region_autodetect = regionAutodetect;
setting_ss_region_default = regionDefault;
FrameBuffer = (uint32 *)alloc_invisible(1024 * 1024 * sizeof(*FrameBuffer));
for (int i = 0; i < numDisks; i++)
CDInterfaces.push_back(new MyCDIF(i));
@ -132,7 +137,7 @@ struct FrameAdvanceInfo
uint32 *Pixels;
uint8* Controllers;
uint8 *Controllers;
int64 MasterCycles;
@ -197,18 +202,17 @@ EXPORT void FrameAdvance(FrameAdvanceInfo &f)
}
static const char *DeviceNames[] =
{
"none",
"gamepad",
"3dpad",
"mouse",
"wheel",
"mission",
"dmission",
"keyboard"
};
{
"none",
"gamepad",
"3dpad",
"mouse",
"wheel",
"mission",
"dmission",
"keyboard"};
EXPORT void SetupInput(const int* portdevices, const int* multitaps)
EXPORT void SetupInput(const int *portdevices, const int *multitaps)
{
for (int i = 0; i < 2; i++)
SMPC_SetMultitap(i, multitaps[i]);
@ -222,19 +226,40 @@ EXPORT void SetInputCallback(void (*callback)())
InputCallback = callback;
}
void (*AddMemoryDomain)(const char* name, const void* ptr, int size, bool writable);
void (*AddMemoryDomain)(const char *name, const void *ptr, int size, bool writable);
EXPORT void SetAddMemoryDomainCallback(void (*callback)(const char* name, const void* ptr, int size, bool writable))
EXPORT void SetAddMemoryDomainCallback(void (*callback)(const char *name, const void *ptr, int size, bool writable))
{
AddMemoryDomain = callback;
}
EXPORT void SetRtc(int64 ticks, int language)
{
time_t time = ticks;
const struct tm *tm = gmtime(&time);
SMPC_SetRTC(tm, language);
}
namespace MDFN_IEN_SS
{
extern bool CorrectAspect;
extern bool ShowHOverscan;
extern bool DoHBlend;
extern int LineVisFirst;
extern int LineVisLast;
}
EXPORT void SetVideoParameters(bool correctAspect, bool hBlend, bool hOverscan, int sls, int sle)
{
CorrectAspect = correctAspect;
ShowHOverscan = hOverscan;
DoHBlend = hBlend;
LineVisFirst = sls;
LineVisLast = sle;
}
// if (BackupRAM_Dirty)SaveBackupRAM();
// if (CART_GetClearNVDirty())SaveCartNV();
/*static MDFN_COLD void CloseGame(void)
{
try { SaveBackupRAM(); } catch(std::exception& e) { MDFN_PrintError("%s", e.what()); }