NES: Move boardproperties into movie 2.0 syncsettings objects, and add a rudimentary UI for changing them

This commit is contained in:
goyuken 2014-01-01 03:03:10 +00:00
parent fcbcbc2ac4
commit a399dbe91e
15 changed files with 508 additions and 110 deletions

View File

@ -380,7 +380,7 @@ namespace BizHawk.Client.Common
game,
rom.FileData,
GetCoreSettings<NES>(),
Global.MovieSession.Movie.Header.BoardProperties);
GetCoreSyncSettings<NES>());
break;
case "GB":
case "GBC":

View File

@ -266,6 +266,7 @@
<Compile Include="config\N64\N64VideoPluginconfig.Designer.cs">
<DependentUpon>N64VideoPluginconfig.cs</DependentUpon>
</Compile>
<Compile Include="config\NES\DataTableDictionaryBind.cs" />
<Compile Include="config\NES\NESGraphicsConfig.cs">
<SubType>Form</SubType>
</Compile>
@ -278,6 +279,12 @@
<Compile Include="config\NES\NESSoundConfig.Designer.cs">
<DependentUpon>NESSoundConfig.cs</DependentUpon>
</Compile>
<Compile Include="config\NES\NESSyncSettingsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="config\NES\NESSyncSettingsForm.Designer.cs">
<DependentUpon>NESSyncSettingsForm.cs</DependentUpon>
</Compile>
<Compile Include="config\PathConfig.cs">
<SubType>Form</SubType>
</Compile>
@ -887,6 +894,9 @@
<EmbeddedResource Include="config\NES\NESSoundConfig.resx">
<DependentUpon>NESSoundConfig.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="config\NES\NESSyncSettingsForm.resx">
<DependentUpon>NESSyncSettingsForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="config\PathConfig.resx">
<DependentUpon>PathConfig.cs</DependentUpon>
</EmbeddedResource>

View File

@ -346,6 +346,7 @@
this.ClearSRAMContextMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.ShowMenuContextMenuSeparator = new System.Windows.Forms.ToolStripSeparator();
this.ShowMenuContextMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.moiveSettingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.MainformMenu.SuspendLayout();
this.MainStatusBar.SuspendLayout();
this.MainFormContextMenu.SuspendLayout();
@ -1958,7 +1959,8 @@
this.toolStripSeparator17,
this.NESGraphicSettingsMenuItem,
this.NESSoundChannelsMenuItem,
this.FDSControlsMenuItem});
this.FDSControlsMenuItem,
this.moiveSettingsToolStripMenuItem});
this.NESSubMenu.Name = "NESSubMenu";
this.NESSubMenu.Size = new System.Drawing.Size(38, 17);
this.NESSubMenu.Text = "&NES";
@ -2212,7 +2214,7 @@
// AtariSettingsToolStripMenuItem
//
this.AtariSettingsToolStripMenuItem.Name = "AtariSettingsToolStripMenuItem";
this.AtariSettingsToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.AtariSettingsToolStripMenuItem.Size = new System.Drawing.Size(125, 22);
this.AtariSettingsToolStripMenuItem.Text = "Settings...";
this.AtariSettingsToolStripMenuItem.Click += new System.EventHandler(this.AtariSettingsToolStripMenuItem_Click);
//
@ -3019,6 +3021,13 @@
this.ShowMenuContextMenuItem.Text = "Show Menu";
this.ShowMenuContextMenuItem.Click += new System.EventHandler(this.ShowMenuContextMenuItem_Click);
//
// moiveSettingsToolStripMenuItem
//
this.moiveSettingsToolStripMenuItem.Name = "moiveSettingsToolStripMenuItem";
this.moiveSettingsToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.moiveSettingsToolStripMenuItem.Text = "Moive Settings...";
this.moiveSettingsToolStripMenuItem.Click += new System.EventHandler(this.moiveSettingsToolStripMenuItem_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 14F);
@ -3376,6 +3385,7 @@
private System.Windows.Forms.ToolStripMenuItem GenesisSubMenu;
private System.Windows.Forms.ToolStripMenuItem GenesisSettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem AtariSettingsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem moiveSettingsToolStripMenuItem;
}
}

View File

@ -69,13 +69,13 @@ namespace BizHawk.Client.EmuHawk
SaveState3MenuItem.Font.Size,
_stateSlots.HasSlot(3) ? (FontStyle.Italic | FontStyle.Bold) : FontStyle.Regular
);
SaveState4MenuItem.Font = new Font(
SaveState4MenuItem.Font.FontFamily,
SaveState4MenuItem.Font.Size,
_stateSlots.HasSlot(4) ? (FontStyle.Italic | FontStyle.Bold) : FontStyle.Regular
);
SaveState5MenuItem.Font = new Font(
SaveState5MenuItem.Font.FontFamily,
SaveState5MenuItem.Font.Size,
@ -580,7 +580,7 @@ namespace BizHawk.Client.EmuHawk
x2SAIMenuItem.Checked = Global.Config.TargetDisplayFilter == 1;
SuperX2SAIMenuItem.Checked = Global.Config.TargetDisplayFilter == 2;
SuperEagleMenuItem.Checked = Global.Config.TargetDisplayFilter == 3;
scanlines2xToolStripMenuItem.Checked = Global.Config.TargetDisplayFilter == 4;
scanlines2xToolStripMenuItem.Checked = Global.Config.TargetDisplayFilter == 4;
}
private void DisplayFilterMenuItem_Click(object sender, EventArgs e)
@ -589,10 +589,10 @@ namespace BizHawk.Client.EmuHawk
if (sender == x2SAIMenuItem) Global.Config.TargetDisplayFilter = 1;
if (sender == SuperX2SAIMenuItem) Global.Config.TargetDisplayFilter = 2;
if (sender == SuperEagleMenuItem) Global.Config.TargetDisplayFilter = 3;
if (sender == Scanlines25MenuItem) { Global.Config.TargetDisplayFilter = 4; Global.Config.TargetScanlineFilterIntensity = 192; }
if (sender == Scanlines50MenuItem) { Global.Config.TargetDisplayFilter = 4; Global.Config.TargetScanlineFilterIntensity = 128; }
if (sender == Scanlines75MenuItem) { Global.Config.TargetDisplayFilter = 4; Global.Config.TargetScanlineFilterIntensity = 64; }
if (sender == ScanlinesCustomMenuItem) { Global.Config.TargetDisplayFilter = 4; new ScanlineSlider().Show(); }
if (sender == Scanlines25MenuItem) { Global.Config.TargetDisplayFilter = 4; Global.Config.TargetScanlineFilterIntensity = 192; }
if (sender == Scanlines50MenuItem) { Global.Config.TargetDisplayFilter = 4; Global.Config.TargetScanlineFilterIntensity = 128; }
if (sender == Scanlines75MenuItem) { Global.Config.TargetDisplayFilter = 4; Global.Config.TargetScanlineFilterIntensity = 64; }
if (sender == ScanlinesCustomMenuItem) { Global.Config.TargetDisplayFilter = 4; new ScanlineSlider().Show(); }
}
private void WindowSizeSubMenu_DropDownOpened(object sender, EventArgs e)
@ -670,7 +670,7 @@ namespace BizHawk.Client.EmuHawk
private void DisplayStatusBarMenuItem_Click(object sender, EventArgs e)
{
Global.Config.DisplayStatusBar ^= true;
if (!_inFullscreen)
{
MainStatusBar.Visible = Global.Config.DisplayStatusBar;
@ -875,8 +875,8 @@ namespace BizHawk.Client.EmuHawk
{
Global.Config.SaveScreenshotWithStates ^= true;
GlobalWin.OSD.AddMessage(Global.Config.SaveScreenshotWithStates
? "Screenshots will be saved in savestates"
: "Screenshots will not be saved in savestates");
? "Screenshots will be saved in savestates"
: "Screenshots will not be saved in savestates");
}
private void frameAdvanceSkipLagFramesToolStripMenuItem_Click(object sender, EventArgs e)
@ -1100,7 +1100,7 @@ namespace BizHawk.Client.EmuHawk
VirtualPadMenuItem.ShortcutKeyDisplayString = Global.Config.HotkeyBindings["Virtual Pad"].Bindings;
TraceLoggerMenuItem.ShortcutKeyDisplayString = Global.Config.HotkeyBindings["Trace Logger"].Bindings;
TraceLoggerMenuItem.Enabled = Global.Emulator.CoreComm.CpuTraceAvailable;
CheatsMenuItem.Enabled =
CheatsMenuItem.Enabled =
HexEditorMenuItem.Enabled =
RamSearchMenuItem.Enabled =
RamWatchMenuItem.Enabled =
@ -1232,6 +1232,16 @@ namespace BizHawk.Client.EmuHawk
}
}
private void moiveSettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
using (var dlg = new config.NES.NESSyncSettingsForm())
{
dlg.ShowDialog(this);
}
}
#endregion
#region PCE
@ -1698,12 +1708,12 @@ namespace BizHawk.Client.EmuHawk
CloseRomContextMenuItem.Visible =
UndoSavestateContextMenuItem.Visible =
!(Global.Emulator is NullEmulator);
RecordMovieContextMenuItem.Visible =
PlayMovieContextMenuItem.Visible =
RecordMovieContextMenuItem.Visible =
PlayMovieContextMenuItem.Visible =
LoadLastMovieContextMenuItem.Visible =
!(Global.Emulator is NullEmulator) && !Global.MovieSession.Movie.IsActive;
RestartMovieContextMenuItem.Visible =
StopMovieContextMenuItem.Visible =
ViewSubtitlesContextMenuItem.Visible =
@ -1718,7 +1728,7 @@ namespace BizHawk.Client.EmuHawk
AddSubtitleContextMenuItem.Visible = !(Global.Emulator is NullEmulator) && Global.MovieSession.Movie.IsActive && !Global.MovieSession.ReadOnly;
ConfigContextMenuItem.Visible = _inFullscreen;
ClearSRAMContextMenuItem.Visible = File.Exists(PathManager.SaveRamPath(Global.Game));
ContextSeparator_AfterROM.Visible = OpenRomContextMenuItem.Visible || LoadLastRomContextMenuItem.Visible;
@ -1741,12 +1751,12 @@ namespace BizHawk.Client.EmuHawk
}
var file = new FileInfo(
PathManager.SaveStatePrefix(Global.Game) +
".QuickSave" +
PathManager.SaveStatePrefix(Global.Game) +
".QuickSave" +
Global.Config.SaveSlot +
".State.bak"
);
if (file.Exists)
{
UndoSavestateContextMenuItem.Enabled = true;

View File

@ -48,6 +48,12 @@ namespace BizHawk.Client.EmuHawk
};
}
}
else if (!record && Global.Emulator.SystemId == "NES")
{
var s = new Emulation.Cores.Nintendo.NES.NES.NESSyncSettings();
s.BoardProperties = new System.Collections.Generic.Dictionary<string, string>(Global.MovieSession.Movie.Header.BoardProperties);
this._syncSettingsHack = s;
}
// load the rom in any case
LoadRom(GlobalWin.MainForm.CurrentlyOpenRom, true, !record);

View File

@ -77,7 +77,7 @@ namespace BizHawk.Client.EmuHawk
Global.CheatList = new CheatCollection();
Global.CheatList.Changed += ToolHelpers.UpdateCheatRelatedTools;
UpdateStatusSlots();
UpdateKeyPriorityIcon();
@ -385,7 +385,7 @@ namespace BizHawk.Client.EmuHawk
CheckMessages();
LogConsole.PositionConsole();
for (;;)
for (; ; )
{
Input.Instance.Update();
@ -454,7 +454,7 @@ namespace BizHawk.Client.EmuHawk
}
#endregion`
#region Properties
public string CurrentlyOpenRom;
@ -515,7 +515,7 @@ namespace BizHawk.Client.EmuHawk
for (; ; )
{
// loop through all available events
var ie = Input.Instance.DequeueEvent();
if (ie == null) { break; }
@ -685,7 +685,7 @@ namespace BizHawk.Client.EmuHawk
for (; zoom >= 1; zoom--)
{
if ((((video.BufferWidth * zoom) + borderWidth) < area.Width)
&& (((video.BufferHeight * zoom) + borderHeight) < area.Height))
&& (((video.BufferHeight * zoom) + borderHeight) < area.Height))
{
break;
}
@ -2144,7 +2144,7 @@ namespace BizHawk.Client.EmuHawk
{
var oldp = Global.Config.SpeedPercent;
int newp;
if (oldp < 3)
{
newp = 3;
@ -2201,7 +2201,7 @@ namespace BizHawk.Client.EmuHawk
{
var oldp = Global.Config.SpeedPercent;
int newp;
if (oldp > 800)
{
newp = 800;
@ -2274,8 +2274,8 @@ namespace BizHawk.Client.EmuHawk
LedLightStatusLabel.Visible = true;
}
LedLightStatusLabel.Image = Global.Emulator.CoreComm.DriveLED
? Properties.Resources.LightOn
LedLightStatusLabel.Image = Global.Emulator.CoreComm.DriveLED
? Properties.Resources.LightOn
: Properties.Resources.LightOff;
}
else
@ -2318,8 +2318,8 @@ namespace BizHawk.Client.EmuHawk
{
Global.Config.AcceptBackgroundInput ^= true;
GlobalWin.OSD.AddMessage(Global.Config.AcceptBackgroundInput
? "Background Input enabled"
: "Background Input disabled");
? "Background Input enabled"
: "Background Input disabled");
}
private static void LimitFrameRateMessage()
@ -2786,8 +2786,8 @@ namespace BizHawk.Client.EmuHawk
}
// do sound rewire. the plan is to eventually have AVI writing support syncsound input, but it doesn't for the moment
_aviSoundInput = !Global.Emulator.StartAsyncSound()
? new MetaspuAsync(Global.Emulator.SyncSoundProvider, ESynchMethod.ESynchMethod_V)
_aviSoundInput = !Global.Emulator.StartAsyncSound()
? new MetaspuAsync(Global.Emulator.SyncSoundProvider, ESynchMethod.ESynchMethod_V)
: Global.Emulator.SoundProvider;
_dumpProxy = new MetaspuSoundProvider(ESynchMethod.ESynchMethod_V);
@ -2887,8 +2887,8 @@ namespace BizHawk.Client.EmuHawk
}
else
{
output = Global.Config.AVI_CaptureOSD
? new BmpVideoProvder(CaptureOSD())
output = Global.Config.AVI_CaptureOSD
? new BmpVideoProvder(CaptureOSD())
: Global.Emulator.VideoProvider;
}
@ -2940,7 +2940,7 @@ namespace BizHawk.Client.EmuHawk
// Still needs a good bit of refactoring
public bool LoadRom(string path, bool deterministicemulation = false, bool hasmovie = false)
{
var loader = new RomLoader
var loader = new RomLoader
{
ChooseArchive = LoadArhiveChooser,
CoreCommMessageCallback = ShowMessageCoreComm
@ -3080,7 +3080,7 @@ namespace BizHawk.Client.EmuHawk
file.Directory.Create();
}
// Make backup first
if (Global.Config.BackupSavestates && file.Exists)
{
@ -3107,7 +3107,7 @@ namespace BizHawk.Client.EmuHawk
// save settings object
var t = Global.Emulator.GetType();
Global.Config.PutCoreSettings(Global.Emulator.GetSettings(), t);
// don't trample config with loaded-from-movie settings
if (!Global.MovieSession.Movie.IsActive)
{
@ -3186,7 +3186,7 @@ namespace BizHawk.Client.EmuHawk
string errorMsg;
string warningMsg;
var m = MovieImport.ImportFile(fn, out errorMsg, out warningMsg);
if (!String.IsNullOrWhiteSpace(errorMsg))
{
MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error);
@ -3199,7 +3199,7 @@ namespace BizHawk.Client.EmuHawk
else
{
GlobalWin.OSD.AddMessage(Path.GetFileName(fn) + " imported as " + "Movies\\" +
Path.GetFileName(fn) + "." + Global.Config.MovieExtension);
Path.GetFileName(fn) + "." + Global.Config.MovieExtension);
}
if (!Directory.Exists(d))

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace BizHawk.Client.EmuHawk.config.NES
{
public class DataTableDictionaryBind<TKey, TValue>
{
public DataTable Table { get; private set; }
public IDictionary<TKey, TValue> Dictionary { get; private set; }
public bool WasModified { get; private set; }
public DataTableDictionaryBind(IDictionary<TKey, TValue> Dictionary)
{
this.Dictionary = Dictionary;
CreateTable();
}
void CreateTable()
{
Table = new DataTable();
Table.Columns.Add("Key", typeof(TKey));
Table.Columns.Add("Value", typeof(TValue));
foreach (var kvp in Dictionary)
Table.Rows.Add(kvp.Key, kvp.Value);
Table.RowChanged += new DataRowChangeEventHandler(Table_RowChanged);
WasModified = false;
}
void Table_RowChanged(object sender, DataRowChangeEventArgs e)
{
var key = (TKey)e.Row[0];
var value = (TValue)e.Row[1];
switch (e.Action)
{
case DataRowAction.Add:
if (Dictionary.ContainsKey(key))
{
e.Row.RejectChanges();
}
else
{
Dictionary.Add(key, value);
WasModified = true;
}
break;
case DataRowAction.Change:
Dictionary[key] = value;
WasModified = true;
break;
case DataRowAction.Delete:
Dictionary.Remove(key);
WasModified = true;
break;
}
}
}
}

View File

@ -0,0 +1,122 @@
namespace BizHawk.Client.EmuHawk.config.NES
{
partial class NESSyncSettingsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.buttonOK = new System.Windows.Forms.Button();
this.buttonCancel = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.dataGridView1 = new System.Windows.Forms.DataGridView();
this.buttonHelp = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
this.SuspendLayout();
//
// buttonOK
//
this.buttonOK.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonOK.Location = new System.Drawing.Point(124, 238);
this.buttonOK.Name = "buttonOK";
this.buttonOK.Size = new System.Drawing.Size(75, 23);
this.buttonOK.TabIndex = 0;
this.buttonOK.Text = "OK";
this.buttonOK.UseVisualStyleBackColor = true;
this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click);
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.Location = new System.Drawing.Point(205, 238);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 1;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 9);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(88, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Board Properties:";
//
// dataGridView1
//
this.dataGridView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dataGridView1.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dataGridView1.Location = new System.Drawing.Point(12, 25);
this.dataGridView1.MultiSelect = false;
this.dataGridView1.Name = "dataGridView1";
this.dataGridView1.Size = new System.Drawing.Size(268, 207);
this.dataGridView1.TabIndex = 3;
//
// buttonHelp
//
this.buttonHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonHelp.Location = new System.Drawing.Point(12, 238);
this.buttonHelp.Name = "buttonHelp";
this.buttonHelp.Size = new System.Drawing.Size(23, 23);
this.buttonHelp.TabIndex = 4;
this.buttonHelp.Text = "?";
this.buttonHelp.UseVisualStyleBackColor = true;
this.buttonHelp.Click += new System.EventHandler(this.buttonHelp_Click);
//
// NESSyncSettingsForm
//
this.AcceptButton = this.buttonOK;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.buttonCancel;
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.buttonHelp);
this.Controls.Add(this.dataGridView1);
this.Controls.Add(this.label1);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.buttonOK);
this.Name = "NESSyncSettingsForm";
this.Text = "NES Movie Settings";
((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button buttonOK;
private System.Windows.Forms.Button buttonCancel;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.DataGridView dataGridView1;
private System.Windows.Forms.Button buttonHelp;
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BizHawk.Client.Common;
namespace BizHawk.Client.EmuHawk.config.NES
{
public partial class NESSyncSettingsForm : Form
{
DataTableDictionaryBind<string, string> DTDB;
BizHawk.Emulation.Cores.Nintendo.NES.NES.NESSyncSettings SyncSettings;
public NESSyncSettingsForm()
{
InitializeComponent();
SyncSettings = (BizHawk.Emulation.Cores.Nintendo.NES.NES.NESSyncSettings)Global.Emulator.GetSyncSettings();
DTDB = new DataTableDictionaryBind<string, string>(SyncSettings.BoardProperties);
dataGridView1.DataSource = DTDB.Table;
}
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
private void buttonOK_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.OK;
if (DTDB.WasModified)
GlobalWin.MainForm.PutCoreSyncSettings(SyncSettings);
}
private void buttonHelp_Click(object sender, EventArgs e)
{
MessageBox.Show(this, "Board Properties are special per-mapper system settings. They are only useful to advanced users creating Tool Assisted Superplays. No support will be provided if you break something with them.", "Help");
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
namespace BizHawk.Common
{
@ -8,9 +9,9 @@ namespace BizHawk.Common
{
private static readonly char[] HexConvArr = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
private static System.Runtime.InteropServices.GCHandle HexConvHandle;
public static char* HexConvPtr { get; set; }
static Util()
{
HexConvHandle = System.Runtime.InteropServices.GCHandle.Alloc(HexConvArr, System.Runtime.InteropServices.GCHandleType.Pinned);
@ -83,7 +84,7 @@ namespace BizHawk.Common
public static string ReadStringAsciiZ(this BinaryReader r)
{
var sb = new StringBuilder();
for (;;)
for (; ; )
{
int b = r.ReadByte();
if (b <= 0)
@ -375,6 +376,41 @@ namespace BizHawk.Common
var precision = "2";
return String.Format("{0:N" + precision + "}{1}", size, suffix);
}
// http://stackoverflow.com/questions/3928822/comparing-2-dictionarystring-string-instances
public static bool DictionaryEqual<TKey, TValue>(
IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second)
{
if (first == second) return true;
if ((first == null) || (second == null)) return false;
if (first.Count != second.Count) return false;
var comparer = EqualityComparer<TValue>.Default;
foreach (KeyValuePair<TKey, TValue> kvp in first)
{
TValue secondValue;
if (!second.TryGetValue(kvp.Key, out secondValue)) return false;
if (!comparer.Equals(kvp.Value, secondValue)) return false;
}
return true;
}
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key)
{
TValue ret;
dict.TryGetValue(key, out ret);
return ret;
}
public static TValue GetValueOrDefault<TKey, TValue>(this IDictionary<TKey, TValue> dict, TKey key, TValue defaultvalue)
{
TValue ret;
if (!dict.TryGetValue(key, out ret))
return defaultvalue;
else
return ret;
}
}
[Serializable]

View File

@ -50,7 +50,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//mixes the board's custom audio into the supplied sample buffer
void ApplyCustomAudio(short[] samples);
MapperProperties InitialRegisterValues { get; set; }
Dictionary<string, string> InitialRegisterValues { get; set; }
};
@ -77,8 +77,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
private MapperProperties _initialRegisterValues = new MapperProperties();
public MapperProperties InitialRegisterValues { get { return _initialRegisterValues; } set { _initialRegisterValues = value; } }
Dictionary<string, string> _initialRegisterValues = new Dictionary<string, string>();
public Dictionary<string, string> InitialRegisterValues { get { return _initialRegisterValues; } set { _initialRegisterValues = value; } }
public abstract bool Configure(NES.EDetectionOrigin origin);
public virtual void ClockPPU() { }
@ -351,7 +351,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
newboard = CreateBoardInstance(board.GetType());
}
newboard.Create(this);
newboard.InitialRegisterValues = InitialMapperRegisterValues;
// i suppose the old board could have changed its initial register values, although it really shouldn't
// you can't use SyncSettings.BoardProperties here because they very well might be different than before
// in case the user actually changed something in the UI
newboard.InitialRegisterValues = board.InitialRegisterValues;
newboard.Configure(origin);
newboard.ROM = board.ROM;
newboard.VROM = board.VROM;
@ -441,7 +444,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
/// <summary>
/// finds a board class which can handle the provided cart
/// </summary>
static Type FindBoard(CartInfo cart, EDetectionOrigin origin, MapperProperties properties)
static Type FindBoard(CartInfo cart, EDetectionOrigin origin, Dictionary<string, string> properties)
{
NES nes = new NES();
nes.cart = cart;

View File

@ -104,8 +104,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
cheetahmen = true;
}
prg_mode = bool.Parse(InitialRegisterValues["prg_mode"] ?? "false");
prg_reg = int.Parse(InitialRegisterValues["prg_reg"] ?? "0");
prg_mode = bool.Parse(InitialRegisterValues.GetValueOrDefault("prg_mode", "false"));
prg_reg = int.Parse(InitialRegisterValues.GetValueOrDefault("prg_reg", "0"));
return true;
}

View File

@ -402,22 +402,5 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (addr < 0x6000)
WRAM[addr + 0x2000] = value;
}
/*
public override void ApplyCustomAudio(short[] samples)
{
audio.ApplyCustomAudio(samples);
}
public override void Dispose()
{
base.Dispose();
if (audio != null)
{
audio.Dispose();
audio = null;
}
}
*/
}
}

View File

@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
static readonly bool USE_DATABASE = true;
public RomStatus RomStatus;
public NES(CoreComm comm, GameInfo game, byte[] rom, object Settings, Dictionary<string, string> boardProperties = null)
public NES(CoreComm comm, GameInfo game, byte[] rom, object Settings, object SyncSettings)
{
byte[] fdsbios = comm.CoreFileProvider.GetFirmware("NES", "Bios_FDS", false);
if (fdsbios != null && fdsbios.Length == 40976)
@ -26,11 +26,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
fdsbios = tmp;
}
if (boardProperties != null)
{
InitialMapperRegisterValues.Set(boardProperties);
}
this.SyncSettings = (NESSyncSettings)SyncSettings ?? new NESSyncSettings();
CoreComm = comm;
CoreComm.CpuTraceAvailable = true;
BootGodDB.Initialize();
@ -78,39 +74,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
return null;
}
MapperProperties InitialMapperRegisterValues = new MapperProperties();
public class MapperProperties
{
private List<KeyValuePair<string, string>> _properties = new List<KeyValuePair<string, string>>();
public string this[string key]
{
get
{
if(_properties.Any(x => x.Key == key))
{
return _properties.FirstOrDefault(x => x.Key == key).Value;
}
else
{
return null;
}
}
}
public void Set(Dictionary<string, string> values)
{
_properties.Clear();
_properties.AddRange(values);
}
public void Add(string key, string value)
{
_properties.Add(new KeyValuePair<string, string>(key, value));
}
}
class NESWatch
{
public enum EDomain
@ -546,6 +509,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
string hash_sha1 = null, hash_md5 = null;
Unif unif = null;
Dictionary<string, string> InitialMapperRegisterValues = new Dictionary<string, string>(SyncSettings.BoardProperties);
origin = EDetectionOrigin.None;
if (file.Length < 16) throw new Exception("Alleged NES rom too small to be anything useful");
@ -873,9 +838,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
}
NESSettings Settings = new NESSettings();
NESSyncSettings SyncSettings = new NESSyncSettings();
public object GetSettings() { return Settings.Clone(); }
public object GetSyncSettings() { return null; }
public object GetSyncSettings() { return SyncSettings.Clone(); }
public bool PutSettings(object o)
{
Settings = (NESSettings)o;
@ -902,7 +868,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
return false;
}
public bool PutSyncSettings(object o) { return false; }
public bool PutSyncSettings(object o)
{
var n = (NESSyncSettings)o;
bool ret = NESSyncSettings.NeedsReboot(SyncSettings, n);
SyncSettings = n;
return ret;
}
public class NESSettings
{
@ -947,6 +919,25 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
this.Palette = Palette;
}
}
public class NESSyncSettings
{
public Dictionary<string, string> BoardProperties = new Dictionary<string, string>();
public NESSyncSettings Clone()
{
var ret = (NESSyncSettings)MemberwiseClone();
ret.BoardProperties = new Dictionary<string, string>(BoardProperties);
return ret;
}
public static bool NeedsReboot(NESSyncSettings x, NESSyncSettings y)
{
return !Util.DictionaryEqual(x.BoardProperties, y.BoardProperties);
}
}
}
}