BizHawk/BizHawk.Emulation.Cores/Consoles/Nintendo/QuickNES/QuickNES.ISettable.cs

171 lines
4.4 KiB
C#

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
using BizHawk.Common;
using BizHawk.Emulation.Common;
namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
{
public partial class QuickNES : ISettable<QuickNES.QuickNESSettings, QuickNES.QuickNESSyncSettings>
{
public QuickNESSettings GetSettings()
{
return _settings.Clone();
}
public QuickNESSyncSettings GetSyncSettings()
{
return _syncSettingsNext.Clone();
}
public bool PutSettings(QuickNESSettings o)
{
_settings = o;
LibQuickNES.qn_set_sprite_limit(Context, _settings.NumSprites);
RecalculateCrops();
CalculatePalette();
return false;
}
public bool PutSyncSettings(QuickNESSyncSettings o)
{
bool ret = QuickNESSyncSettings.NeedsReboot(_syncSettings, o);
_syncSettingsNext = o;
return ret;
}
private QuickNESSettings _settings;
/// <summary>
/// the syncsettings that this run of emulation is using (was passed to ctor)
/// </summary>
private QuickNESSyncSettings _syncSettings;
/// <summary>
/// the syncsettings that were requested but won't be used yet
/// </summary>
private QuickNESSyncSettings _syncSettingsNext;
public class QuickNESSettings
{
[DefaultValue(8)]
[Description("Set the number of sprites visible per line. 0 hides all sprites, 8 behaves like a normal NES, and 64 is maximum.")]
[DisplayName("Visible Sprites")]
public int NumSprites
{
get { return _NumSprites; }
set { _NumSprites = Math.Min(64, Math.Max(0, value)); }
}
[JsonIgnore]
private int _NumSprites;
[DefaultValue(false)]
[Description("Clip the left and right 8 pixels of the display, which sometimes contain nametable garbage.")]
[DisplayName("Clip Left and Right")]
public bool ClipLeftAndRight { get; set; }
[DefaultValue(true)]
[Description("Clip the top and bottom 8 pixels of the display, which sometimes contain nametable garbage.")]
[DisplayName("Clip Top and Bottom")]
public bool ClipTopAndBottom { get; set; }
[Browsable(false)]
public byte[] Palette
{
get { return _Palette; }
set
{
if (value == null)
throw new ArgumentNullException();
else if (value.Length == 64 * 8 * 3)
_Palette = value;
else
throw new ArgumentOutOfRangeException();
}
}
[JsonIgnore]
private byte[] _Palette;
public QuickNESSettings Clone()
{
var ret = (QuickNESSettings)MemberwiseClone();
ret._Palette = (byte[])_Palette.Clone();
return ret;
}
public QuickNESSettings()
{
SettingsUtil.SetDefaultValues(this);
SetDefaultColors();
}
public void SetNesHawkPalette(int[,] pal)
{
if (pal.GetLength(0) != 64 || pal.GetLength(1) != 3)
{
throw new ArgumentOutOfRangeException();
}
for (int c = 0; c < 512; c++)
{
int a = c & 63;
byte[] inp = { (byte)pal[a, 0], (byte)pal[a, 1], (byte)pal[a, 2] };
byte[] outp = new byte[3];
Nes_NTSC_Colors.Emphasis(inp, outp, c);
_Palette[c * 3] = outp[0];
_Palette[c * 3 + 1] = outp[1];
_Palette[c * 3 + 2] = outp[2];
}
}
private static byte[] GetDefaultColors()
{
IntPtr src = LibQuickNES.qn_get_default_colors();
byte[] ret = new byte[1536];
Marshal.Copy(src, ret, 0, 1536);
return ret;
}
public void SetDefaultColors()
{
_Palette = GetDefaultColors();
}
}
public class QuickNESSyncSettings
{
[DefaultValue(true)]
[DisplayName("Left Port Connected")]
[Description("Specifies whether or not the Left (Player 1) Controller is connected")]
public bool LeftPortConnected { get; set; }
[DefaultValue(false)]
[DisplayName("Right Port Connected")]
[Description("Specifies whether or not the Right (Player 2) Controller is connected")]
public bool RightPortConnected { get; set; }
public QuickNESSyncSettings()
{
SettingsUtil.SetDefaultValues(this);
}
public QuickNESSyncSettings Clone()
{
return (QuickNESSyncSettings)MemberwiseClone();
}
public static bool NeedsReboot(QuickNESSyncSettings x, QuickNESSyncSettings y)
{
// the core can handle dynamic plugging and unplugging, but that changes
// the controllerdefinition, and we're not ready for that
return !DeepEquality.DeepEquals(x, y);
}
}
}
}