Fix mixed line endings.
This commit is contained in:
parent
5b41b7260b
commit
ed3bf0e62b
|
@ -1,198 +1,198 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Windows.Forms;
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// This static class handle all ExternalTools
|
||||
/// </summary>
|
||||
public static class ExternalToolManager
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static FileSystemWatcher directoryMonitor;
|
||||
private static List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region cTor(s)
|
||||
|
||||
/// <summary>
|
||||
/// Initilization
|
||||
/// </summary>
|
||||
static ExternalToolManager()
|
||||
{
|
||||
if(!Directory.Exists(Global.Config.PathEntries["Global", "External Tools"].Path))
|
||||
{
|
||||
Directory.CreateDirectory(Global.Config.PathEntries["Global", "External Tools"].Path);
|
||||
}
|
||||
directoryMonitor = new FileSystemWatcher(Global.Config.PathEntries["Global", "External Tools"].Path, "*.dll");
|
||||
directoryMonitor.IncludeSubdirectories = false;
|
||||
directoryMonitor.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
|
||||
directoryMonitor.Filter = "*.dll";
|
||||
directoryMonitor.Created += new FileSystemEventHandler(DirectoryMonitor_Created);
|
||||
directoryMonitor.EnableRaisingEvents = true;
|
||||
|
||||
ClientApi.RomLoaded += delegate { BuildToolStrip(); };
|
||||
|
||||
BuildToolStrip();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Build the toolstrip menu
|
||||
/// </summary>
|
||||
private static void BuildToolStrip()
|
||||
{
|
||||
menuItems.Clear();
|
||||
if (Directory.Exists(directoryMonitor.Path))
|
||||
{
|
||||
DirectoryInfo dInfo = new DirectoryInfo(directoryMonitor.Path);
|
||||
|
||||
foreach (FileInfo fi in dInfo.GetFiles("*.dll"))
|
||||
{
|
||||
menuItems.Add(GenerateToolTipFromFileName(fi.FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a <see cref="ToolStripMenuItem"/> from an
|
||||
/// external tool dll.
|
||||
/// The assembly must have <see cref="BizHawkExternalToolAttribute"/> in its
|
||||
/// assembly attributes
|
||||
/// </summary>
|
||||
/// <param name="fileName">File that will be reflected</param>
|
||||
/// <returns>A new <see cref="ToolStripMenuItem"/>; assembly path can be found in the Tag property</returns>
|
||||
/// <remarks>For the moment, you could only load a dll that have a form (which implements <see cref="BizHawk.Client.EmuHawk.IExternalToolForm"/>)</remarks>
|
||||
private static ToolStripMenuItem GenerateToolTipFromFileName(string fileName)
|
||||
{
|
||||
Type customFormType;
|
||||
Assembly externalToolFile;
|
||||
ToolStripMenuItem item = null;
|
||||
|
||||
try
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
using System.Windows.Forms;
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
namespace BizHawk.Client.ApiHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// This static class handle all ExternalTools
|
||||
/// </summary>
|
||||
public static class ExternalToolManager
|
||||
{
|
||||
#region Fields
|
||||
|
||||
private static FileSystemWatcher directoryMonitor;
|
||||
private static List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region cTor(s)
|
||||
|
||||
/// <summary>
|
||||
/// Initilization
|
||||
/// </summary>
|
||||
static ExternalToolManager()
|
||||
{
|
||||
if(!Directory.Exists(Global.Config.PathEntries["Global", "External Tools"].Path))
|
||||
{
|
||||
BizHawk.Common.Win32Hacks.RemoveMOTW(fileName);
|
||||
externalToolFile = Assembly.LoadFrom(fileName);
|
||||
object[] attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolAttribute), false);
|
||||
if (attributes != null && attributes.Count() == 1)
|
||||
{
|
||||
BizHawkExternalToolAttribute attribute = (BizHawkExternalToolAttribute)attributes[0];
|
||||
item = new ToolStripMenuItem(attribute.Name);
|
||||
item.ToolTipText = attribute.Description;
|
||||
if (attribute.IconResourceName != string.Empty)
|
||||
{
|
||||
Stream s = externalToolFile.GetManifestResourceStream(string.Format("{0}.{1}", externalToolFile.GetName().Name, attribute.IconResourceName));
|
||||
if (s != null)
|
||||
{
|
||||
item.Image = new Bitmap(s);
|
||||
}
|
||||
}
|
||||
|
||||
customFormType = externalToolFile.GetTypes().FirstOrDefault<Type>(t => t != null && t.FullName == "BizHawk.Client.EmuHawk.CustomMainForm");
|
||||
if (customFormType == null)
|
||||
{
|
||||
item.ToolTipText = "Does not have a CustomMainForm";
|
||||
item.Enabled = false;
|
||||
}
|
||||
item.Tag = fileName;
|
||||
|
||||
attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolUsageAttribute), false);
|
||||
if (attributes != null && attributes.Count() == 1)
|
||||
{
|
||||
BizHawkExternalToolUsageAttribute attribute2 = (BizHawkExternalToolUsageAttribute)attributes[0];
|
||||
if(Global.Emulator.SystemId == "NULL" && attribute2.ToolUsage != BizHawkExternalToolUsage.Global)
|
||||
{
|
||||
item.ToolTipText = "This tool doesn't work if nothing is loaded";
|
||||
item.Enabled = false;
|
||||
}
|
||||
else if(attribute2.ToolUsage == BizHawkExternalToolUsage.EmulatorSpecific && Global.Emulator.SystemId != ClientApi.SystemIdConverter.ConvertBack(attribute2.System))
|
||||
{
|
||||
item.ToolTipText = "This tool doesn't work for current system";
|
||||
item.Enabled = false;
|
||||
}
|
||||
else if (attribute2.ToolUsage == BizHawkExternalToolUsage.GameSpecific && Global.Game.Hash != attribute2.GameHash)
|
||||
{
|
||||
item.ToolTipText = "This tool doesn't work for current game";
|
||||
item.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new ToolStripMenuItem(externalToolFile.GetName().Name);
|
||||
item.ToolTipText = "BizHawkExternalTool attribute hasn't been found";
|
||||
item.Enabled = false;
|
||||
}
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
item = new ToolStripMenuItem(fileName);
|
||||
item.ToolTipText = "This is not an assembly";
|
||||
item.Enabled = false;
|
||||
}
|
||||
|
||||
#if DEBUG //I added special debug stuff to get additionnal informations. Don(t think it can be usefull for released versions
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
foreach (Exception e in ex.LoaderExceptions)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
}
|
||||
item.ToolTipText = "Something goes wrong while trying to load";
|
||||
item.Enabled = false;
|
||||
}
|
||||
#else
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
item.ToolTipText = "Something goes wrong while trying to load";
|
||||
item.Enabled = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when we add a dll file into
|
||||
/// the external tools path.
|
||||
/// It will automatically load the assembly and add it into the list
|
||||
/// </summary>
|
||||
/// <param name="sender">Object that raised the event</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private static void DirectoryMonitor_Created(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
menuItems.Add(GenerateToolTipFromFileName(e.FullPath));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a prebuild <see cref="ToolStripMenuItem"/>
|
||||
/// This list auto-updated by the <see cref="ExternalToolManager"/> itself
|
||||
/// </summary>
|
||||
public static IEnumerable<ToolStripMenuItem> ToolStripMenu
|
||||
{
|
||||
get
|
||||
{
|
||||
return menuItems;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Directory.CreateDirectory(Global.Config.PathEntries["Global", "External Tools"].Path);
|
||||
}
|
||||
directoryMonitor = new FileSystemWatcher(Global.Config.PathEntries["Global", "External Tools"].Path, "*.dll");
|
||||
directoryMonitor.IncludeSubdirectories = false;
|
||||
directoryMonitor.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
|
||||
directoryMonitor.Filter = "*.dll";
|
||||
directoryMonitor.Created += new FileSystemEventHandler(DirectoryMonitor_Created);
|
||||
directoryMonitor.EnableRaisingEvents = true;
|
||||
|
||||
ClientApi.RomLoaded += delegate { BuildToolStrip(); };
|
||||
|
||||
BuildToolStrip();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <summary>
|
||||
/// Build the toolstrip menu
|
||||
/// </summary>
|
||||
private static void BuildToolStrip()
|
||||
{
|
||||
menuItems.Clear();
|
||||
if (Directory.Exists(directoryMonitor.Path))
|
||||
{
|
||||
DirectoryInfo dInfo = new DirectoryInfo(directoryMonitor.Path);
|
||||
|
||||
foreach (FileInfo fi in dInfo.GetFiles("*.dll"))
|
||||
{
|
||||
menuItems.Add(GenerateToolTipFromFileName(fi.FullName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a <see cref="ToolStripMenuItem"/> from an
|
||||
/// external tool dll.
|
||||
/// The assembly must have <see cref="BizHawkExternalToolAttribute"/> in its
|
||||
/// assembly attributes
|
||||
/// </summary>
|
||||
/// <param name="fileName">File that will be reflected</param>
|
||||
/// <returns>A new <see cref="ToolStripMenuItem"/>; assembly path can be found in the Tag property</returns>
|
||||
/// <remarks>For the moment, you could only load a dll that have a form (which implements <see cref="BizHawk.Client.EmuHawk.IExternalToolForm"/>)</remarks>
|
||||
private static ToolStripMenuItem GenerateToolTipFromFileName(string fileName)
|
||||
{
|
||||
Type customFormType;
|
||||
Assembly externalToolFile;
|
||||
ToolStripMenuItem item = null;
|
||||
|
||||
try
|
||||
{
|
||||
BizHawk.Common.Win32Hacks.RemoveMOTW(fileName);
|
||||
externalToolFile = Assembly.LoadFrom(fileName);
|
||||
object[] attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolAttribute), false);
|
||||
if (attributes != null && attributes.Count() == 1)
|
||||
{
|
||||
BizHawkExternalToolAttribute attribute = (BizHawkExternalToolAttribute)attributes[0];
|
||||
item = new ToolStripMenuItem(attribute.Name);
|
||||
item.ToolTipText = attribute.Description;
|
||||
if (attribute.IconResourceName != string.Empty)
|
||||
{
|
||||
Stream s = externalToolFile.GetManifestResourceStream(string.Format("{0}.{1}", externalToolFile.GetName().Name, attribute.IconResourceName));
|
||||
if (s != null)
|
||||
{
|
||||
item.Image = new Bitmap(s);
|
||||
}
|
||||
}
|
||||
|
||||
customFormType = externalToolFile.GetTypes().FirstOrDefault<Type>(t => t != null && t.FullName == "BizHawk.Client.EmuHawk.CustomMainForm");
|
||||
if (customFormType == null)
|
||||
{
|
||||
item.ToolTipText = "Does not have a CustomMainForm";
|
||||
item.Enabled = false;
|
||||
}
|
||||
item.Tag = fileName;
|
||||
|
||||
attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolUsageAttribute), false);
|
||||
if (attributes != null && attributes.Count() == 1)
|
||||
{
|
||||
BizHawkExternalToolUsageAttribute attribute2 = (BizHawkExternalToolUsageAttribute)attributes[0];
|
||||
if(Global.Emulator.SystemId == "NULL" && attribute2.ToolUsage != BizHawkExternalToolUsage.Global)
|
||||
{
|
||||
item.ToolTipText = "This tool doesn't work if nothing is loaded";
|
||||
item.Enabled = false;
|
||||
}
|
||||
else if(attribute2.ToolUsage == BizHawkExternalToolUsage.EmulatorSpecific && Global.Emulator.SystemId != ClientApi.SystemIdConverter.ConvertBack(attribute2.System))
|
||||
{
|
||||
item.ToolTipText = "This tool doesn't work for current system";
|
||||
item.Enabled = false;
|
||||
}
|
||||
else if (attribute2.ToolUsage == BizHawkExternalToolUsage.GameSpecific && Global.Game.Hash != attribute2.GameHash)
|
||||
{
|
||||
item.ToolTipText = "This tool doesn't work for current game";
|
||||
item.Enabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item = new ToolStripMenuItem(externalToolFile.GetName().Name);
|
||||
item.ToolTipText = "BizHawkExternalTool attribute hasn't been found";
|
||||
item.Enabled = false;
|
||||
}
|
||||
}
|
||||
catch (BadImageFormatException)
|
||||
{
|
||||
item = new ToolStripMenuItem(fileName);
|
||||
item.ToolTipText = "This is not an assembly";
|
||||
item.Enabled = false;
|
||||
}
|
||||
|
||||
#if DEBUG //I added special debug stuff to get additionnal informations. Don(t think it can be usefull for released versions
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
foreach (Exception e in ex.LoaderExceptions)
|
||||
{
|
||||
Debug.WriteLine(e.Message);
|
||||
}
|
||||
item.ToolTipText = "Something goes wrong while trying to load";
|
||||
item.Enabled = false;
|
||||
}
|
||||
#else
|
||||
catch (ReflectionTypeLoadException)
|
||||
{
|
||||
item.ToolTipText = "Something goes wrong while trying to load";
|
||||
item.Enabled = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event is raised when we add a dll file into
|
||||
/// the external tools path.
|
||||
/// It will automatically load the assembly and add it into the list
|
||||
/// </summary>
|
||||
/// <param name="sender">Object that raised the event</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private static void DirectoryMonitor_Created(object sender, FileSystemEventArgs e)
|
||||
{
|
||||
menuItems.Add(GenerateToolTipFromFileName(e.FullPath));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a prebuild <see cref="ToolStripMenuItem"/>
|
||||
/// This list auto-updated by the <see cref="ExternalToolManager"/> itself
|
||||
/// </summary>
|
||||
public static IEnumerable<ToolStripMenuItem> ToolStripMenu
|
||||
{
|
||||
get
|
||||
{
|
||||
return menuItems;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,77 +1,77 @@
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Paint.NET
|
||||
// Copyright (C) Rick Brewster, Chris Crosetto, Dennis Dietrich, Tom Jackson,
|
||||
// Michael Kelsey, Brandon Ortiz, Craig Taylor, Chris Trevino,
|
||||
// and Luke Walker
|
||||
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.
|
||||
// See src/setup/License.rtf for complete licensing and attribution information.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Copied for Paint.NET PCX Plugin
|
||||
// Copyright (C) Joshua Bell
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Paint.NET
|
||||
// Copyright (C) Rick Brewster, Chris Crosetto, Dennis Dietrich, Tom Jackson,
|
||||
// Michael Kelsey, Brandon Ortiz, Craig Taylor, Chris Trevino,
|
||||
// and Luke Walker
|
||||
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.
|
||||
// See src/setup/License.rtf for complete licensing and attribution information.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Bizhawk says: adapted from https://github.com/inexorabletash/PcxFileType/blob/master/Quantize
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Copied for Paint.NET PCX Plugin
|
||||
// Copyright (C) Joshua Bell
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//Bizhawk says: adapted from https://github.com/inexorabletash/PcxFileType/blob/master/Quantize
|
||||
|
||||
using System.Drawing;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public sealed class PaletteTable
|
||||
{
|
||||
private Color[] palette;
|
||||
|
||||
public Color this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.palette[index];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.palette[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetDistanceSquared(Color a, Color b)
|
||||
{
|
||||
int dsq = 0; // delta squared
|
||||
int v;
|
||||
|
||||
v = a.B - b.B;
|
||||
dsq += v * v;
|
||||
v = a.G - b.G;
|
||||
dsq += v * v;
|
||||
v = a.R - b.R;
|
||||
dsq += v * v;
|
||||
|
||||
return dsq;
|
||||
}
|
||||
|
||||
public int FindClosestPaletteIndex(Color pixel)
|
||||
{
|
||||
int dsqBest = int.MaxValue;
|
||||
int ret = 0;
|
||||
|
||||
for (int i = 0; i < this.palette.Length; ++i)
|
||||
{
|
||||
int dsq = GetDistanceSquared(this.palette[i], pixel);
|
||||
|
||||
if (dsq < dsqBest)
|
||||
{
|
||||
dsqBest = dsq;
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public PaletteTable(Color[] palette)
|
||||
{
|
||||
this.palette = (Color[])palette.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public sealed class PaletteTable
|
||||
{
|
||||
private Color[] palette;
|
||||
|
||||
public Color this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.palette[index];
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.palette[index] = value;
|
||||
}
|
||||
}
|
||||
|
||||
private int GetDistanceSquared(Color a, Color b)
|
||||
{
|
||||
int dsq = 0; // delta squared
|
||||
int v;
|
||||
|
||||
v = a.B - b.B;
|
||||
dsq += v * v;
|
||||
v = a.G - b.G;
|
||||
dsq += v * v;
|
||||
v = a.R - b.R;
|
||||
dsq += v * v;
|
||||
|
||||
return dsq;
|
||||
}
|
||||
|
||||
public int FindClosestPaletteIndex(Color pixel)
|
||||
{
|
||||
int dsqBest = int.MaxValue;
|
||||
int ret = 0;
|
||||
|
||||
for (int i = 0; i < this.palette.Length; ++i)
|
||||
{
|
||||
int dsq = GetDistanceSquared(this.palette[i], pixel);
|
||||
|
||||
if (dsq < dsqBest)
|
||||
{
|
||||
dsqBest = dsq;
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public PaletteTable(Color[] palette)
|
||||
{
|
||||
this.palette = (Color[])palette.Clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,186 +1,186 @@
|
|||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Paint.NET
|
||||
// Copyright (C) Rick Brewster, Chris Crosetto, Dennis Dietrich, Tom Jackson,
|
||||
// Michael Kelsey, Brandon Ortiz, Craig Taylor, Chris Trevino,
|
||||
// and Luke Walker
|
||||
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.
|
||||
// See src/setup/License.rtf for complete licensing and attribution information.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Copied for Paint.NET PCX Plugin
|
||||
// Copyright (C) Joshua Bell
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Paint.NET
|
||||
// Copyright (C) Rick Brewster, Chris Crosetto, Dennis Dietrich, Tom Jackson,
|
||||
// Michael Kelsey, Brandon Ortiz, Craig Taylor, Chris Trevino,
|
||||
// and Luke Walker
|
||||
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.
|
||||
// See src/setup/License.rtf for complete licensing and attribution information.
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// Copied for Paint.NET PCX Plugin
|
||||
// Copyright (C) Joshua Bell
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Based on: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/colorquant.asp
|
||||
|
||||
//Bizhawk says: adapted from https://github.com/inexorabletash/PcxFileType/blob/master/Quantize
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
//Bizhawk says: adapted from https://github.com/inexorabletash/PcxFileType/blob/master/Quantize
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Class1.
|
||||
/// </summary>
|
||||
internal unsafe abstract class Quantizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Flag used to indicate whether a single pass or two passes are needed for quantization.
|
||||
/// </summary>
|
||||
private bool _singlePass;
|
||||
|
||||
protected bool highquality;
|
||||
public bool HighQuality
|
||||
{
|
||||
get
|
||||
{
|
||||
return highquality;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
highquality = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected int ditherLevel;
|
||||
public int DitherLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ditherLevel;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.ditherLevel = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct the quantizer
|
||||
/// </summary>
|
||||
/// <param name="singlePass">If true, the quantization only needs to loop through the source pixels once</param>
|
||||
/// <remarks>
|
||||
/// If you construct this class with a true value for singlePass, then the code will, when quantizing your image,
|
||||
/// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage'
|
||||
/// and then 'QuantizeImage'.
|
||||
/// </remarks>
|
||||
public Quantizer(bool singlePass)
|
||||
{
|
||||
_singlePass = singlePass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quantize an image and return the resulting output bitmap
|
||||
/// </summary>
|
||||
/// <param name="source">The image to quantize</param>
|
||||
/// <returns>A quantized version of the image</returns>
|
||||
public Bitmap Quantize(Image source)
|
||||
{
|
||||
// Get the size of the source image
|
||||
int height = source.Height;
|
||||
int width = source.Width;
|
||||
|
||||
// And construct a rectangle from these dimensions
|
||||
Rectangle bounds = new Rectangle(0, 0, width, height);
|
||||
|
||||
// First off take a 32bpp copy of the image
|
||||
Bitmap copy;
|
||||
|
||||
if (source is Bitmap && source.PixelFormat == PixelFormat.Format32bppArgb)
|
||||
{
|
||||
copy = (Bitmap)source;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
|
||||
|
||||
// Now lock the bitmap into memory
|
||||
using (Graphics g = Graphics.FromImage(copy))
|
||||
{
|
||||
g.PageUnit = GraphicsUnit.Pixel;
|
||||
|
||||
// Draw the source image onto the copy bitmap,
|
||||
// which will effect a widening as appropriate.
|
||||
g.DrawImage(source, 0, 0, bounds.Width, bounds.Height);
|
||||
}
|
||||
}
|
||||
|
||||
// And construct an 8bpp version
|
||||
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
|
||||
|
||||
// Define a pointer to the bitmap data
|
||||
BitmapData sourceData = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Get the source image bits and lock into memory
|
||||
sourceData = copy.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
// Call the FirstPass function if not a single pass algorithm.
|
||||
// For something like an octree quantizer, this will run through
|
||||
// all image pixels, build a data structure, and create a palette.
|
||||
if (!_singlePass)
|
||||
{
|
||||
FirstPass(sourceData, width, height);
|
||||
}
|
||||
|
||||
// Then set the color palette on the output bitmap. I'm passing in the current palette
|
||||
// as there's no way to construct a new, empty palette.
|
||||
output.Palette = this.GetPalette(output.Palette);
|
||||
|
||||
// Then call the second pass which actually does the conversion
|
||||
SecondPass(sourceData, output, width, height, bounds);
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
// Ensure that the bits are unlocked
|
||||
copy.UnlockBits(sourceData);
|
||||
}
|
||||
|
||||
if (copy != source)
|
||||
{
|
||||
copy.Dispose();
|
||||
}
|
||||
|
||||
// Last but not least, return the output bitmap
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the first pass through the pixels in the image
|
||||
/// </summary>
|
||||
/// <param name="sourceData">The source data</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
protected virtual void FirstPass(BitmapData sourceData, int width, int height)
|
||||
{
|
||||
// Define the source data pointers. The source row is a byte to
|
||||
// keep addition of the stride value easier (as this is in bytes)
|
||||
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
|
||||
int* pSourcePixel;
|
||||
|
||||
// Loop through each row
|
||||
for (int row = 0; row < height; row++)
|
||||
{
|
||||
// Set the source pixel to the first pixel in this row
|
||||
pSourcePixel = (Int32*)pSourceRow;
|
||||
|
||||
// And loop through each column
|
||||
for (int col = 0; col < width; col++, pSourcePixel++)
|
||||
{
|
||||
InitialQuantizePixel(*pSourcePixel);
|
||||
}
|
||||
|
||||
// Add the stride to the source row
|
||||
pSourceRow += sourceData.Stride;
|
||||
|
||||
}
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for Class1.
|
||||
/// </summary>
|
||||
internal unsafe abstract class Quantizer
|
||||
{
|
||||
/// <summary>
|
||||
/// Flag used to indicate whether a single pass or two passes are needed for quantization.
|
||||
/// </summary>
|
||||
private bool _singlePass;
|
||||
|
||||
protected bool highquality;
|
||||
public bool HighQuality
|
||||
{
|
||||
get
|
||||
{
|
||||
return highquality;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
highquality = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected int ditherLevel;
|
||||
public int DitherLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ditherLevel;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.ditherLevel = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct the quantizer
|
||||
/// </summary>
|
||||
/// <param name="singlePass">If true, the quantization only needs to loop through the source pixels once</param>
|
||||
/// <remarks>
|
||||
/// If you construct this class with a true value for singlePass, then the code will, when quantizing your image,
|
||||
/// only call the 'QuantizeImage' function. If two passes are required, the code will call 'InitialQuantizeImage'
|
||||
/// and then 'QuantizeImage'.
|
||||
/// </remarks>
|
||||
public Quantizer(bool singlePass)
|
||||
{
|
||||
_singlePass = singlePass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quantize an image and return the resulting output bitmap
|
||||
/// </summary>
|
||||
/// <param name="source">The image to quantize</param>
|
||||
/// <returns>A quantized version of the image</returns>
|
||||
public Bitmap Quantize(Image source)
|
||||
{
|
||||
// Get the size of the source image
|
||||
int height = source.Height;
|
||||
int width = source.Width;
|
||||
|
||||
// And construct a rectangle from these dimensions
|
||||
Rectangle bounds = new Rectangle(0, 0, width, height);
|
||||
|
||||
// First off take a 32bpp copy of the image
|
||||
Bitmap copy;
|
||||
|
||||
if (source is Bitmap && source.PixelFormat == PixelFormat.Format32bppArgb)
|
||||
{
|
||||
copy = (Bitmap)source;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy = new Bitmap(width, height, PixelFormat.Format32bppArgb);
|
||||
|
||||
// Now lock the bitmap into memory
|
||||
using (Graphics g = Graphics.FromImage(copy))
|
||||
{
|
||||
g.PageUnit = GraphicsUnit.Pixel;
|
||||
|
||||
// Draw the source image onto the copy bitmap,
|
||||
// which will effect a widening as appropriate.
|
||||
g.DrawImage(source, 0, 0, bounds.Width, bounds.Height);
|
||||
}
|
||||
}
|
||||
|
||||
// And construct an 8bpp version
|
||||
Bitmap output = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
|
||||
|
||||
// Define a pointer to the bitmap data
|
||||
BitmapData sourceData = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Get the source image bits and lock into memory
|
||||
sourceData = copy.LockBits(bounds, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
// Call the FirstPass function if not a single pass algorithm.
|
||||
// For something like an octree quantizer, this will run through
|
||||
// all image pixels, build a data structure, and create a palette.
|
||||
if (!_singlePass)
|
||||
{
|
||||
FirstPass(sourceData, width, height);
|
||||
}
|
||||
|
||||
// Then set the color palette on the output bitmap. I'm passing in the current palette
|
||||
// as there's no way to construct a new, empty palette.
|
||||
output.Palette = this.GetPalette(output.Palette);
|
||||
|
||||
// Then call the second pass which actually does the conversion
|
||||
SecondPass(sourceData, output, width, height, bounds);
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
// Ensure that the bits are unlocked
|
||||
copy.UnlockBits(sourceData);
|
||||
}
|
||||
|
||||
if (copy != source)
|
||||
{
|
||||
copy.Dispose();
|
||||
}
|
||||
|
||||
// Last but not least, return the output bitmap
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the first pass through the pixels in the image
|
||||
/// </summary>
|
||||
/// <param name="sourceData">The source data</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
protected virtual void FirstPass(BitmapData sourceData, int width, int height)
|
||||
{
|
||||
// Define the source data pointers. The source row is a byte to
|
||||
// keep addition of the stride value easier (as this is in bytes)
|
||||
byte* pSourceRow = (byte*)sourceData.Scan0.ToPointer();
|
||||
int* pSourcePixel;
|
||||
|
||||
// Loop through each row
|
||||
for (int row = 0; row < height; row++)
|
||||
{
|
||||
// Set the source pixel to the first pixel in this row
|
||||
pSourcePixel = (Int32*)pSourceRow;
|
||||
|
||||
// And loop through each column
|
||||
for (int col = 0; col < width; col++, pSourcePixel++)
|
||||
{
|
||||
InitialQuantizePixel(*pSourcePixel);
|
||||
}
|
||||
|
||||
// Add the stride to the source row
|
||||
pSourceRow += sourceData.Stride;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int ClampToByte(int val)
|
||||
|
@ -188,80 +188,80 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (val < 0) return 0;
|
||||
else if (val > 255) return 255;
|
||||
else return val;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a second pass through the bitmap
|
||||
/// </summary>
|
||||
/// <param name="sourceData">The source bitmap, locked into memory</param>
|
||||
/// <param name="output">The output bitmap</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="bounds">The bounding rectangle</param>
|
||||
protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds)
|
||||
{
|
||||
BitmapData outputData = null;
|
||||
Color[] pallete = output.Palette.Entries;
|
||||
int weight = ditherLevel;
|
||||
|
||||
try
|
||||
{
|
||||
// Lock the output bitmap into memory
|
||||
outputData = output.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
|
||||
|
||||
// Define the source data pointers. The source row is a byte to
|
||||
// keep addition of the stride value easier (as this is in bytes)
|
||||
byte* pSourceRow = (byte *)sourceData.Scan0.ToPointer();
|
||||
Int32* pSourcePixel = (Int32 *)pSourceRow;
|
||||
|
||||
// Now define the destination data pointers
|
||||
byte* pDestinationRow = (byte *)outputData.Scan0.ToPointer();
|
||||
byte* pDestinationPixel = pDestinationRow;
|
||||
|
||||
int[] errorThisRowR = new int[width + 1];
|
||||
int[] errorThisRowG = new int[width + 1];
|
||||
int[] errorThisRowB = new int[width + 1];
|
||||
|
||||
for (int row = 0; row < height; row++)
|
||||
{
|
||||
int[] errorNextRowR = new int[width + 1];
|
||||
int[] errorNextRowG = new int[width + 1];
|
||||
int[] errorNextRowB = new int[width + 1];
|
||||
|
||||
int ptrInc;
|
||||
|
||||
if ((row & 1) == 0)
|
||||
{
|
||||
pSourcePixel = (Int32*)pSourceRow;
|
||||
pDestinationPixel = pDestinationRow;
|
||||
ptrInc = +1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSourcePixel = (Int32*)pSourceRow + width - 1;
|
||||
pDestinationPixel = pDestinationRow + width - 1;
|
||||
ptrInc = -1;
|
||||
}
|
||||
|
||||
// Loop through each pixel on this scan line
|
||||
for (int col = 0; col < width; ++col)
|
||||
{
|
||||
// Quantize the pixel
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a second pass through the bitmap
|
||||
/// </summary>
|
||||
/// <param name="sourceData">The source bitmap, locked into memory</param>
|
||||
/// <param name="output">The output bitmap</param>
|
||||
/// <param name="width">The width in pixels of the image</param>
|
||||
/// <param name="height">The height in pixels of the image</param>
|
||||
/// <param name="bounds">The bounding rectangle</param>
|
||||
protected virtual void SecondPass(BitmapData sourceData, Bitmap output, int width, int height, Rectangle bounds)
|
||||
{
|
||||
BitmapData outputData = null;
|
||||
Color[] pallete = output.Palette.Entries;
|
||||
int weight = ditherLevel;
|
||||
|
||||
try
|
||||
{
|
||||
// Lock the output bitmap into memory
|
||||
outputData = output.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
|
||||
|
||||
// Define the source data pointers. The source row is a byte to
|
||||
// keep addition of the stride value easier (as this is in bytes)
|
||||
byte* pSourceRow = (byte *)sourceData.Scan0.ToPointer();
|
||||
Int32* pSourcePixel = (Int32 *)pSourceRow;
|
||||
|
||||
// Now define the destination data pointers
|
||||
byte* pDestinationRow = (byte *)outputData.Scan0.ToPointer();
|
||||
byte* pDestinationPixel = pDestinationRow;
|
||||
|
||||
int[] errorThisRowR = new int[width + 1];
|
||||
int[] errorThisRowG = new int[width + 1];
|
||||
int[] errorThisRowB = new int[width + 1];
|
||||
|
||||
for (int row = 0; row < height; row++)
|
||||
{
|
||||
int[] errorNextRowR = new int[width + 1];
|
||||
int[] errorNextRowG = new int[width + 1];
|
||||
int[] errorNextRowB = new int[width + 1];
|
||||
|
||||
int ptrInc;
|
||||
|
||||
if ((row & 1) == 0)
|
||||
{
|
||||
pSourcePixel = (Int32*)pSourceRow;
|
||||
pDestinationPixel = pDestinationRow;
|
||||
ptrInc = +1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSourcePixel = (Int32*)pSourceRow + width - 1;
|
||||
pDestinationPixel = pDestinationRow + width - 1;
|
||||
ptrInc = -1;
|
||||
}
|
||||
|
||||
// Loop through each pixel on this scan line
|
||||
for (int col = 0; col < width; ++col)
|
||||
{
|
||||
// Quantize the pixel
|
||||
int srcPixel = *pSourcePixel;
|
||||
|
||||
int srcR = srcPixel & 0xFF; //not
|
||||
int srcG = (srcPixel>>8) & 0xFF; //a
|
||||
int srcB = (srcPixel>>16) & 0xFF; //mistake
|
||||
int srcA = (srcPixel >> 24) & 0xFF;
|
||||
|
||||
int targetB = ClampToByte(srcB - ((errorThisRowB[col] * weight) / 8));
|
||||
int targetG = ClampToByte(srcG - ((errorThisRowG[col] * weight) / 8));
|
||||
int targetR = ClampToByte(srcR - ((errorThisRowR[col] * weight) / 8));
|
||||
int targetA = srcA;
|
||||
|
||||
int target = (targetA<<24)|(targetB<<16)|(targetG<<8)|targetR;
|
||||
|
||||
byte pixelValue = QuantizePixel(target);
|
||||
int srcA = (srcPixel >> 24) & 0xFF;
|
||||
|
||||
int targetB = ClampToByte(srcB - ((errorThisRowB[col] * weight) / 8));
|
||||
int targetG = ClampToByte(srcG - ((errorThisRowG[col] * weight) / 8));
|
||||
int targetR = ClampToByte(srcR - ((errorThisRowR[col] * weight) / 8));
|
||||
int targetA = srcA;
|
||||
|
||||
int target = (targetA<<24)|(targetB<<16)|(targetG<<8)|targetR;
|
||||
|
||||
byte pixelValue = QuantizePixel(target);
|
||||
*pDestinationPixel = pixelValue;
|
||||
|
||||
int actual = pallete[pixelValue].ToArgb();
|
||||
|
@ -269,104 +269,104 @@ namespace BizHawk.Client.EmuHawk
|
|||
int actualR = actual & 0xFF;
|
||||
int actualG = (actual >> 8) & 0xFF;
|
||||
int actualB = (actual >> 16) & 0xFF;
|
||||
int errorR = actualR - targetR;
|
||||
int errorG = actualG - targetG;
|
||||
int errorB = actualB - targetB;
|
||||
|
||||
// Floyd-Steinberg Error Diffusion:
|
||||
// a) 7/16 error goes to x+1
|
||||
// b) 5/16 error goes to y+1
|
||||
// c) 3/16 error goes to x-1,y+1
|
||||
// d) 1/16 error goes to x+1,y+1
|
||||
|
||||
const int a = 7;
|
||||
const int b = 5;
|
||||
const int c = 3;
|
||||
|
||||
int errorRa = (errorR * a) / 16;
|
||||
int errorRb = (errorR * b) / 16;
|
||||
int errorRc = (errorR * c) / 16;
|
||||
int errorRd = errorR - errorRa - errorRb - errorRc;
|
||||
|
||||
int errorGa = (errorG * a) / 16;
|
||||
int errorGb = (errorG * b) / 16;
|
||||
int errorGc = (errorG * c) / 16;
|
||||
int errorGd = errorG - errorGa - errorGb - errorGc;
|
||||
|
||||
int errorBa = (errorB * a) / 16;
|
||||
int errorBb = (errorB * b) / 16;
|
||||
int errorBc = (errorB * c) / 16;
|
||||
int errorBd = errorB - errorBa - errorBb - errorBc;
|
||||
|
||||
errorThisRowR[col + 1] += errorRa;
|
||||
errorThisRowG[col + 1] += errorGa;
|
||||
errorThisRowB[col + 1] += errorBa;
|
||||
|
||||
errorNextRowR[width - col] += errorRb;
|
||||
errorNextRowG[width - col] += errorGb;
|
||||
errorNextRowB[width - col] += errorBb;
|
||||
|
||||
if (col != 0)
|
||||
{
|
||||
errorNextRowR[width - (col - 1)] += errorRc;
|
||||
errorNextRowG[width - (col - 1)] += errorGc;
|
||||
errorNextRowB[width - (col - 1)] += errorBc;
|
||||
}
|
||||
|
||||
errorNextRowR[width - (col + 1)] += errorRd;
|
||||
errorNextRowG[width - (col + 1)] += errorGd;
|
||||
errorNextRowB[width - (col + 1)] += errorBd;
|
||||
|
||||
unchecked
|
||||
{
|
||||
pSourcePixel += ptrInc;
|
||||
pDestinationPixel += ptrInc;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the stride to the source row
|
||||
pSourceRow += sourceData.Stride;
|
||||
|
||||
// And to the destination row
|
||||
pDestinationRow += outputData.Stride;
|
||||
|
||||
errorThisRowB = errorNextRowB;
|
||||
errorThisRowG = errorNextRowG;
|
||||
errorThisRowR = errorNextRowR;
|
||||
}
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
// Ensure that I unlock the output bits
|
||||
output.UnlockBits(outputData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to process the pixel in the first pass of the algorithm
|
||||
/// </summary>
|
||||
/// <param name="pixel">The pixel to quantize</param>
|
||||
/// <remarks>
|
||||
/// This function need only be overridden if your quantize algorithm needs two passes,
|
||||
/// such as an Octree quantizer.
|
||||
/// </remarks>
|
||||
protected virtual void InitialQuantizePixel(int pixel)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to process the pixel in the second pass of the algorithm
|
||||
/// </summary>
|
||||
/// <param name="pixel">The pixel to quantize</param>
|
||||
/// <returns>The quantized value</returns>
|
||||
protected abstract byte QuantizePixel(int pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the palette for the quantized image
|
||||
/// </summary>
|
||||
/// <param name="original">Any old palette, this is overrwritten</param>
|
||||
/// <returns>The new color palette</returns>
|
||||
protected abstract ColorPalette GetPalette(ColorPalette original);
|
||||
}
|
||||
}
|
||||
int errorR = actualR - targetR;
|
||||
int errorG = actualG - targetG;
|
||||
int errorB = actualB - targetB;
|
||||
|
||||
// Floyd-Steinberg Error Diffusion:
|
||||
// a) 7/16 error goes to x+1
|
||||
// b) 5/16 error goes to y+1
|
||||
// c) 3/16 error goes to x-1,y+1
|
||||
// d) 1/16 error goes to x+1,y+1
|
||||
|
||||
const int a = 7;
|
||||
const int b = 5;
|
||||
const int c = 3;
|
||||
|
||||
int errorRa = (errorR * a) / 16;
|
||||
int errorRb = (errorR * b) / 16;
|
||||
int errorRc = (errorR * c) / 16;
|
||||
int errorRd = errorR - errorRa - errorRb - errorRc;
|
||||
|
||||
int errorGa = (errorG * a) / 16;
|
||||
int errorGb = (errorG * b) / 16;
|
||||
int errorGc = (errorG * c) / 16;
|
||||
int errorGd = errorG - errorGa - errorGb - errorGc;
|
||||
|
||||
int errorBa = (errorB * a) / 16;
|
||||
int errorBb = (errorB * b) / 16;
|
||||
int errorBc = (errorB * c) / 16;
|
||||
int errorBd = errorB - errorBa - errorBb - errorBc;
|
||||
|
||||
errorThisRowR[col + 1] += errorRa;
|
||||
errorThisRowG[col + 1] += errorGa;
|
||||
errorThisRowB[col + 1] += errorBa;
|
||||
|
||||
errorNextRowR[width - col] += errorRb;
|
||||
errorNextRowG[width - col] += errorGb;
|
||||
errorNextRowB[width - col] += errorBb;
|
||||
|
||||
if (col != 0)
|
||||
{
|
||||
errorNextRowR[width - (col - 1)] += errorRc;
|
||||
errorNextRowG[width - (col - 1)] += errorGc;
|
||||
errorNextRowB[width - (col - 1)] += errorBc;
|
||||
}
|
||||
|
||||
errorNextRowR[width - (col + 1)] += errorRd;
|
||||
errorNextRowG[width - (col + 1)] += errorGd;
|
||||
errorNextRowB[width - (col + 1)] += errorBd;
|
||||
|
||||
unchecked
|
||||
{
|
||||
pSourcePixel += ptrInc;
|
||||
pDestinationPixel += ptrInc;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the stride to the source row
|
||||
pSourceRow += sourceData.Stride;
|
||||
|
||||
// And to the destination row
|
||||
pDestinationRow += outputData.Stride;
|
||||
|
||||
errorThisRowB = errorNextRowB;
|
||||
errorThisRowG = errorNextRowG;
|
||||
errorThisRowR = errorNextRowR;
|
||||
}
|
||||
}
|
||||
|
||||
finally
|
||||
{
|
||||
// Ensure that I unlock the output bits
|
||||
output.UnlockBits(outputData);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to process the pixel in the first pass of the algorithm
|
||||
/// </summary>
|
||||
/// <param name="pixel">The pixel to quantize</param>
|
||||
/// <remarks>
|
||||
/// This function need only be overridden if your quantize algorithm needs two passes,
|
||||
/// such as an Octree quantizer.
|
||||
/// </remarks>
|
||||
protected virtual void InitialQuantizePixel(int pixel)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override this to process the pixel in the second pass of the algorithm
|
||||
/// </summary>
|
||||
/// <param name="pixel">The pixel to quantize</param>
|
||||
/// <returns>The quantized value</returns>
|
||||
protected abstract byte QuantizePixel(int pixel);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the palette for the quantized image
|
||||
/// </summary>
|
||||
/// <param name="original">Any old palette, this is overrwritten</param>
|
||||
/// <returns>The new color palette</returns>
|
||||
protected abstract ColorPalette GetPalette(ColorPalette original);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
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;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class ExceptionBox : Form
|
||||
{
|
||||
public ExceptionBox(Exception ex)
|
||||
{
|
||||
InitializeComponent();
|
||||
txtException.Text = ex.ToString();
|
||||
timer1.Start();
|
||||
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;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class ExceptionBox : Form
|
||||
{
|
||||
public ExceptionBox(Exception ex)
|
||||
{
|
||||
InitializeComponent();
|
||||
txtException.Text = ex.ToString();
|
||||
timer1.Start();
|
||||
}
|
||||
|
||||
public ExceptionBox(string str)
|
||||
|
@ -23,70 +23,70 @@ namespace BizHawk.Client.EmuHawk
|
|||
InitializeComponent();
|
||||
txtException.Text = str;
|
||||
timer1.Start();
|
||||
}
|
||||
|
||||
private void btnCopy_Click(object sender, EventArgs e)
|
||||
{
|
||||
DoCopy();
|
||||
}
|
||||
|
||||
void DoCopy()
|
||||
{
|
||||
string txt = txtException.Text;
|
||||
Clipboard.SetText(txt);
|
||||
try
|
||||
{
|
||||
if (Clipboard.GetText() == txt)
|
||||
{
|
||||
lblDone.Text = "Done!";
|
||||
lblDone.ForeColor = SystemColors.ControlText;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
lblDone.Text = "ERROR!";
|
||||
lblDone.ForeColor = SystemColors.ControlText;
|
||||
}
|
||||
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||
{
|
||||
if (keyData == (Keys.C | Keys.Control))
|
||||
{
|
||||
DoCopy();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void btnOK_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void timer1_Tick(object sender, EventArgs e)
|
||||
{
|
||||
int a = lblDone.ForeColor.A - 16;
|
||||
if (a < 0) a = 0;
|
||||
lblDone.ForeColor = Color.FromArgb(a, lblDone.ForeColor);
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/2636065/alpha-in-forecolor
|
||||
class MyLabel : Label
|
||||
{
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
Rectangle rc = this.ClientRectangle;
|
||||
StringFormat fmt = new StringFormat(StringFormat.GenericTypographic);
|
||||
using (var br = new SolidBrush(this.ForeColor))
|
||||
{
|
||||
e.Graphics.DrawString(this.Text, this.Font, br, rc, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void btnCopy_Click(object sender, EventArgs e)
|
||||
{
|
||||
DoCopy();
|
||||
}
|
||||
|
||||
void DoCopy()
|
||||
{
|
||||
string txt = txtException.Text;
|
||||
Clipboard.SetText(txt);
|
||||
try
|
||||
{
|
||||
if (Clipboard.GetText() == txt)
|
||||
{
|
||||
lblDone.Text = "Done!";
|
||||
lblDone.ForeColor = SystemColors.ControlText;
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
lblDone.Text = "ERROR!";
|
||||
lblDone.ForeColor = SystemColors.ControlText;
|
||||
}
|
||||
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
|
||||
{
|
||||
if (keyData == (Keys.C | Keys.Control))
|
||||
{
|
||||
DoCopy();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void btnOK_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void timer1_Tick(object sender, EventArgs e)
|
||||
{
|
||||
int a = lblDone.ForeColor.A - 16;
|
||||
if (a < 0) a = 0;
|
||||
lblDone.ForeColor = Color.FromArgb(a, lblDone.ForeColor);
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/2636065/alpha-in-forecolor
|
||||
class MyLabel : Label
|
||||
{
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
{
|
||||
Rectangle rc = this.ClientRectangle;
|
||||
StringFormat fmt = new StringFormat(StringFormat.GenericTypographic);
|
||||
using (var br = new SolidBrush(this.ForeColor))
|
||||
{
|
||||
e.Graphics.DrawString(this.Text, this.Font, br, rc, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,351 +1,351 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
using BizHawk.Emulation.Cores.Calculators;
|
||||
using BizHawk.Emulation.Cores.ColecoVision;
|
||||
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
|
||||
using BizHawk.Emulation.Cores.Nintendo.NES;
|
||||
using BizHawk.Emulation.Cores.Nintendo.N64;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
using BizHawk.Emulation.Cores.PCEngine;
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
using BizHawk.Client.EmuHawk.CustomControls;
|
||||
using BizHawk.Client.EmuHawk.WinFormExtensions;
|
||||
using BizHawk.Client.EmuHawk.ToolExtensions;
|
||||
using BizHawk.Emulation.Cores.Computers.AppleII;
|
||||
using BizHawk.Client.ApiHawk;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
private enum LoadOrdering
|
||||
{
|
||||
ROM,
|
||||
STATE,
|
||||
WATCH,
|
||||
CDLFILE,
|
||||
LUASESSION,
|
||||
LUASCRIPT,
|
||||
CHEAT,
|
||||
MOVIEFILE,
|
||||
LEGACYMOVIEFILE
|
||||
}
|
||||
|
||||
public struct FileInformation
|
||||
{
|
||||
public string directoryName;
|
||||
public string fileName;
|
||||
public string archiveName;
|
||||
|
||||
public FileInformation(string directory, string file, string archive)
|
||||
{
|
||||
directoryName = directory;
|
||||
fileName = file;
|
||||
archiveName = archive;
|
||||
}
|
||||
}
|
||||
|
||||
// This is the list from MainForm->RomFilter()'s non-developer build. It needs to be kept up-to-date when new cores are added.
|
||||
readonly string[] knownROMExtensions = { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF" };
|
||||
readonly string[] nonArchive = { ".ISO", ".CUE", ".CCD" };
|
||||
|
||||
#region Loaders
|
||||
|
||||
// According to the documentation (http://tasvideos.org/Bizhawk/CodeDataLogger.html),
|
||||
// Currently supported for: PCE, GB/GBC, SMS/GG, Genesis, SNES
|
||||
// Perhaps the 'is PCEngine' requirement needs to be expanded.
|
||||
private void _LoadCDL(string filename, string archive = null)
|
||||
{
|
||||
if (!(Global.Emulator is PCEngine))
|
||||
return;
|
||||
|
||||
GlobalWin.Tools.Load<CDL>();
|
||||
(GlobalWin.Tools.Get<CDL>() as CDL).LoadFile(filename);
|
||||
}
|
||||
|
||||
private void _LoadCheats(string filename, string archive = null)
|
||||
{
|
||||
Global.CheatList.Load(filename, false);
|
||||
GlobalWin.Tools.Load<Cheats>();
|
||||
}
|
||||
|
||||
private void _LoadLegacyMovie(string filename, string archive = null)
|
||||
{
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
OpenRom();
|
||||
}
|
||||
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// tries to open a legacy movie format by importing it
|
||||
string errorMsg;
|
||||
string warningMsg;
|
||||
var movie = MovieImport.ImportFile(filename, out errorMsg, out warningMsg);
|
||||
if (!string.IsNullOrEmpty(errorMsg))
|
||||
{
|
||||
MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fix movie extension to something palatable for these purposes.
|
||||
// for instance, something which doesnt clobber movies you already may have had.
|
||||
// i'm evenly torn between this, and a file in %TEMP%, but since we dont really have a way to clean up this tempfile, i choose this:
|
||||
StartNewMovie(movie, false);
|
||||
}
|
||||
|
||||
GlobalWin.OSD.AddMessage(warningMsg);
|
||||
}
|
||||
|
||||
private void _LoadLuaFile(string filename, string archive = null)
|
||||
{
|
||||
OpenLuaConsole();
|
||||
if (GlobalWin.Tools.Has<LuaConsole>())
|
||||
{
|
||||
GlobalWin.Tools.LuaConsole.LoadLuaFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
private void _LoadLuaSession(string filename, string archive = null)
|
||||
{
|
||||
OpenLuaConsole();
|
||||
if (GlobalWin.Tools.Has<LuaConsole>())
|
||||
{
|
||||
GlobalWin.Tools.LuaConsole.LoadLuaSession(filename);
|
||||
}
|
||||
}
|
||||
|
||||
private void _LoadMovie(string filename, string archive = null)
|
||||
{
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
OpenRom();
|
||||
}
|
||||
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StartNewMovie(MovieService.Get(filename), false);
|
||||
}
|
||||
|
||||
private void _LoadRom(string filename, string archive = null)
|
||||
{
|
||||
var args = new LoadRomArgs();
|
||||
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filename };
|
||||
LoadRom(filename, args);
|
||||
}
|
||||
|
||||
private void _LoadState(string filename, string archive = null)
|
||||
{
|
||||
LoadState(filename, Path.GetFileName(filename));
|
||||
}
|
||||
|
||||
private void _LoadWatch(string filename, string archive = null)
|
||||
{
|
||||
GlobalWin.Tools.LoadRamWatch(true);
|
||||
(GlobalWin.Tools.Get<RamWatch>() as RamWatch).LoadWatchFile(new FileInfo(filename), false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void ProcessFileList(IEnumerable<string> fileList, ref Dictionary<LoadOrdering, List<FileInformation>> sortedFiles, string archive = null)
|
||||
{
|
||||
foreach (string file in fileList)
|
||||
{
|
||||
var ext = Path.GetExtension(file).ToUpper() ?? String.Empty;
|
||||
FileInformation fileInformation = new FileInformation(Path.GetDirectoryName(file), Path.GetFileName(file), archive);
|
||||
|
||||
switch (ext)
|
||||
{
|
||||
case ".LUA":
|
||||
sortedFiles[LoadOrdering.LUASCRIPT].Add(fileInformation);
|
||||
break;
|
||||
case ".LUASES":
|
||||
sortedFiles[LoadOrdering.LUASESSION].Add(fileInformation);
|
||||
break;
|
||||
case ".STATE":
|
||||
sortedFiles[LoadOrdering.STATE].Add(fileInformation);
|
||||
break;
|
||||
case ".CHT":
|
||||
sortedFiles[LoadOrdering.CHEAT].Add(fileInformation);
|
||||
break;
|
||||
case ".WCH":
|
||||
sortedFiles[LoadOrdering.WATCH].Add(fileInformation);
|
||||
break;
|
||||
case ".CDL":
|
||||
sortedFiles[LoadOrdering.CDLFILE].Add(fileInformation);
|
||||
break;
|
||||
default:
|
||||
if (MovieService.IsValidMovieExtension(ext))
|
||||
sortedFiles[LoadOrdering.MOVIEFILE].Add(fileInformation);
|
||||
else if (MovieImport.IsValidMovieExtension(ext))
|
||||
sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Add(fileInformation);
|
||||
else if (knownROMExtensions.Contains(ext))
|
||||
{
|
||||
if (String.IsNullOrEmpty(archive) || !nonArchive.Contains(ext))
|
||||
sortedFiles[LoadOrdering.ROM].Add(fileInformation);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Because the existing behaviour for archives is to try loading
|
||||
* ROMs out of them, that is exactly what we are going to continue
|
||||
* to do at present. Ideally, the archive should be scanned and
|
||||
* relevant files should be extracted, but see the note below for
|
||||
* further details.
|
||||
*/
|
||||
int offset = 0;
|
||||
bool executable = false;
|
||||
var archiveHandler = new SevenZipSharpArchiveHandler();
|
||||
|
||||
if (String.IsNullOrEmpty(archive) && archiveHandler.CheckSignature(file, out offset, out executable))
|
||||
sortedFiles[LoadOrdering.ROM].Add(fileInformation);
|
||||
|
||||
/*
|
||||
* This is where handling archives would go.
|
||||
* Right now, that's going to be a HUGE hassle, because of the problem with
|
||||
* saving things into the archive (no) and with everything requiring filenames
|
||||
* and not streams (also no), so for the purposes of making drag/drop more robust,
|
||||
* I am not building this out just yet.
|
||||
* -- Adam Michaud (Invariel)
|
||||
|
||||
int offset = 0;
|
||||
bool executable = false;
|
||||
var archiveHandler = new SevenZipSharpArchiveHandler();
|
||||
|
||||
// Not going to process nested archives at the moment.
|
||||
if (String.IsNullOrEmpty (archive) && archiveHandler.CheckSignature(file, out offset, out executable))
|
||||
{
|
||||
List<string> fileNames = new List<string>();
|
||||
var openedArchive = archiveHandler.Construct (file);
|
||||
|
||||
foreach (BizHawk.Common.HawkFileArchiveItem item in openedArchive.Scan ())
|
||||
fileNames.Add(item.Name);
|
||||
|
||||
ProcessFileList(fileNames.ToArray(), ref sortedFiles, file);
|
||||
|
||||
openedArchive.Dispose();
|
||||
}
|
||||
archiveHandler.Dispose();
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _FormDragDrop_internal(object sender, DragEventArgs e)
|
||||
{
|
||||
/*
|
||||
* Refactor, moving the loading of particular files into separate functions that can
|
||||
* then be used by this code, and loading individual files through the file dialogue.
|
||||
*
|
||||
* Step 1:
|
||||
* Build a dictionary of relevant files from everything that was dragged and dropped.
|
||||
* This includes peeking into all relevant archives and using their files.
|
||||
*
|
||||
* Step 2:
|
||||
* Perhaps ask the user which of a particular file type they want to use.
|
||||
* Example: rom1.nes, rom2.smc, rom3.cue are drag-dropped, ask the user which they want to use.
|
||||
*
|
||||
* Step 3:
|
||||
* Load all of the relevant files, in priority order:
|
||||
* 1) The ROM
|
||||
* 2) State
|
||||
* 3) Watch files
|
||||
* 4) Code Data Logger (CDL)
|
||||
* 5) LUA sessions
|
||||
* 6) LUA scripts
|
||||
* 7) Cheat files
|
||||
* 8) Movie Playback Files
|
||||
*
|
||||
* Bonus:
|
||||
* Make that order easy to change in the code, heavily suggesting ROM and playback as first and last respectively.
|
||||
*/
|
||||
|
||||
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
Dictionary<LoadOrdering, List<FileInformation>> sortedFiles = new Dictionary<LoadOrdering, List<FileInformation>>();
|
||||
|
||||
// Initialize the dictionary's lists.
|
||||
foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
|
||||
{
|
||||
sortedFiles.Add(value, new List<FileInformation>());
|
||||
}
|
||||
|
||||
ProcessFileList(HawkFile.Util_ResolveLinks(filePaths), ref sortedFiles, null);
|
||||
|
||||
// For each of the different types of item, if there are no items of that type, skip them.
|
||||
// If there is exactly one of that type of item, load it.
|
||||
// If there is more than one, ask.
|
||||
|
||||
foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
|
||||
{
|
||||
switch (sortedFiles[value].Count)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
FileInformation fileInformation = sortedFiles[value].First<FileInformation>();
|
||||
string filename = Path.Combine(new string[] { fileInformation.directoryName, fileInformation.fileName });
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case LoadOrdering.ROM:
|
||||
_LoadRom(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.STATE:
|
||||
_LoadState(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.WATCH:
|
||||
_LoadWatch(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.CDLFILE:
|
||||
_LoadCDL(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.LUASESSION:
|
||||
_LoadLuaSession(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.LUASCRIPT:
|
||||
_LoadLuaFile(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.CHEAT:
|
||||
_LoadCheats(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.MOVIEFILE:
|
||||
case LoadOrdering.LEGACYMOVIEFILE:
|
||||
// I don't really like this hack, but for now, we only want to load one movie file.
|
||||
if (sortedFiles[LoadOrdering.MOVIEFILE].Count + sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Count > 1)
|
||||
break;
|
||||
|
||||
if (value == LoadOrdering.MOVIEFILE)
|
||||
_LoadMovie(filename, fileInformation.archiveName);
|
||||
else
|
||||
_LoadLegacyMovie(filename, fileInformation.archiveName);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using BizHawk.Common;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
using BizHawk.Emulation.Cores.Calculators;
|
||||
using BizHawk.Emulation.Cores.ColecoVision;
|
||||
using BizHawk.Emulation.Cores.Nintendo.Gameboy;
|
||||
using BizHawk.Emulation.Cores.Nintendo.NES;
|
||||
using BizHawk.Emulation.Cores.Nintendo.N64;
|
||||
using BizHawk.Emulation.Cores.Nintendo.SNES;
|
||||
using BizHawk.Emulation.Cores.PCEngine;
|
||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
||||
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
|
||||
using BizHawk.Client.EmuHawk.CustomControls;
|
||||
using BizHawk.Client.EmuHawk.WinFormExtensions;
|
||||
using BizHawk.Client.EmuHawk.ToolExtensions;
|
||||
using BizHawk.Emulation.Cores.Computers.AppleII;
|
||||
using BizHawk.Client.ApiHawk;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
partial class MainForm
|
||||
{
|
||||
private enum LoadOrdering
|
||||
{
|
||||
ROM,
|
||||
STATE,
|
||||
WATCH,
|
||||
CDLFILE,
|
||||
LUASESSION,
|
||||
LUASCRIPT,
|
||||
CHEAT,
|
||||
MOVIEFILE,
|
||||
LEGACYMOVIEFILE
|
||||
}
|
||||
|
||||
public struct FileInformation
|
||||
{
|
||||
public string directoryName;
|
||||
public string fileName;
|
||||
public string archiveName;
|
||||
|
||||
public FileInformation(string directory, string file, string archive)
|
||||
{
|
||||
directoryName = directory;
|
||||
fileName = file;
|
||||
archiveName = archive;
|
||||
}
|
||||
}
|
||||
|
||||
// This is the list from MainForm->RomFilter()'s non-developer build. It needs to be kept up-to-date when new cores are added.
|
||||
readonly string[] knownROMExtensions = { ".NES", ".FDS", ".UNF", ".SMS", ".GG", ".SG", ".GB", ".GBC", ".GBA", ".PCE", ".SGX", ".BIN", ".SMD", ".GEN", ".MD", ".SMC", ".SFC", ".A26", ".A78", ".LNX", ".COL", ".ROM", ".M3U", ".CUE", ".CCD", ".SGB", ".Z64", ".V64", ".N64", ".WS", ".WSC", ".XML", ".DSK", ".DO", ".PO", ".PSF", ".MINIPSF", ".NSF" };
|
||||
readonly string[] nonArchive = { ".ISO", ".CUE", ".CCD" };
|
||||
|
||||
#region Loaders
|
||||
|
||||
// According to the documentation (http://tasvideos.org/Bizhawk/CodeDataLogger.html),
|
||||
// Currently supported for: PCE, GB/GBC, SMS/GG, Genesis, SNES
|
||||
// Perhaps the 'is PCEngine' requirement needs to be expanded.
|
||||
private void _LoadCDL(string filename, string archive = null)
|
||||
{
|
||||
if (!(Global.Emulator is PCEngine))
|
||||
return;
|
||||
|
||||
GlobalWin.Tools.Load<CDL>();
|
||||
(GlobalWin.Tools.Get<CDL>() as CDL).LoadFile(filename);
|
||||
}
|
||||
|
||||
private void _LoadCheats(string filename, string archive = null)
|
||||
{
|
||||
Global.CheatList.Load(filename, false);
|
||||
GlobalWin.Tools.Load<Cheats>();
|
||||
}
|
||||
|
||||
private void _LoadLegacyMovie(string filename, string archive = null)
|
||||
{
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
OpenRom();
|
||||
}
|
||||
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// tries to open a legacy movie format by importing it
|
||||
string errorMsg;
|
||||
string warningMsg;
|
||||
var movie = MovieImport.ImportFile(filename, out errorMsg, out warningMsg);
|
||||
if (!string.IsNullOrEmpty(errorMsg))
|
||||
{
|
||||
MessageBox.Show(errorMsg, "Conversion error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
else
|
||||
{
|
||||
// fix movie extension to something palatable for these purposes.
|
||||
// for instance, something which doesnt clobber movies you already may have had.
|
||||
// i'm evenly torn between this, and a file in %TEMP%, but since we dont really have a way to clean up this tempfile, i choose this:
|
||||
StartNewMovie(movie, false);
|
||||
}
|
||||
|
||||
GlobalWin.OSD.AddMessage(warningMsg);
|
||||
}
|
||||
|
||||
private void _LoadLuaFile(string filename, string archive = null)
|
||||
{
|
||||
OpenLuaConsole();
|
||||
if (GlobalWin.Tools.Has<LuaConsole>())
|
||||
{
|
||||
GlobalWin.Tools.LuaConsole.LoadLuaFile(filename);
|
||||
}
|
||||
}
|
||||
|
||||
private void _LoadLuaSession(string filename, string archive = null)
|
||||
{
|
||||
OpenLuaConsole();
|
||||
if (GlobalWin.Tools.Has<LuaConsole>())
|
||||
{
|
||||
GlobalWin.Tools.LuaConsole.LoadLuaSession(filename);
|
||||
}
|
||||
}
|
||||
|
||||
private void _LoadMovie(string filename, string archive = null)
|
||||
{
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
OpenRom();
|
||||
}
|
||||
|
||||
if (Global.Emulator.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
StartNewMovie(MovieService.Get(filename), false);
|
||||
}
|
||||
|
||||
private void _LoadRom(string filename, string archive = null)
|
||||
{
|
||||
var args = new LoadRomArgs();
|
||||
args.OpenAdvanced = new OpenAdvanced_OpenRom { Path = filename };
|
||||
LoadRom(filename, args);
|
||||
}
|
||||
|
||||
private void _LoadState(string filename, string archive = null)
|
||||
{
|
||||
LoadState(filename, Path.GetFileName(filename));
|
||||
}
|
||||
|
||||
private void _LoadWatch(string filename, string archive = null)
|
||||
{
|
||||
GlobalWin.Tools.LoadRamWatch(true);
|
||||
(GlobalWin.Tools.Get<RamWatch>() as RamWatch).LoadWatchFile(new FileInfo(filename), false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void ProcessFileList(IEnumerable<string> fileList, ref Dictionary<LoadOrdering, List<FileInformation>> sortedFiles, string archive = null)
|
||||
{
|
||||
foreach (string file in fileList)
|
||||
{
|
||||
var ext = Path.GetExtension(file).ToUpper() ?? String.Empty;
|
||||
FileInformation fileInformation = new FileInformation(Path.GetDirectoryName(file), Path.GetFileName(file), archive);
|
||||
|
||||
switch (ext)
|
||||
{
|
||||
case ".LUA":
|
||||
sortedFiles[LoadOrdering.LUASCRIPT].Add(fileInformation);
|
||||
break;
|
||||
case ".LUASES":
|
||||
sortedFiles[LoadOrdering.LUASESSION].Add(fileInformation);
|
||||
break;
|
||||
case ".STATE":
|
||||
sortedFiles[LoadOrdering.STATE].Add(fileInformation);
|
||||
break;
|
||||
case ".CHT":
|
||||
sortedFiles[LoadOrdering.CHEAT].Add(fileInformation);
|
||||
break;
|
||||
case ".WCH":
|
||||
sortedFiles[LoadOrdering.WATCH].Add(fileInformation);
|
||||
break;
|
||||
case ".CDL":
|
||||
sortedFiles[LoadOrdering.CDLFILE].Add(fileInformation);
|
||||
break;
|
||||
default:
|
||||
if (MovieService.IsValidMovieExtension(ext))
|
||||
sortedFiles[LoadOrdering.MOVIEFILE].Add(fileInformation);
|
||||
else if (MovieImport.IsValidMovieExtension(ext))
|
||||
sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Add(fileInformation);
|
||||
else if (knownROMExtensions.Contains(ext))
|
||||
{
|
||||
if (String.IsNullOrEmpty(archive) || !nonArchive.Contains(ext))
|
||||
sortedFiles[LoadOrdering.ROM].Add(fileInformation);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Because the existing behaviour for archives is to try loading
|
||||
* ROMs out of them, that is exactly what we are going to continue
|
||||
* to do at present. Ideally, the archive should be scanned and
|
||||
* relevant files should be extracted, but see the note below for
|
||||
* further details.
|
||||
*/
|
||||
int offset = 0;
|
||||
bool executable = false;
|
||||
var archiveHandler = new SevenZipSharpArchiveHandler();
|
||||
|
||||
if (String.IsNullOrEmpty(archive) && archiveHandler.CheckSignature(file, out offset, out executable))
|
||||
sortedFiles[LoadOrdering.ROM].Add(fileInformation);
|
||||
|
||||
/*
|
||||
* This is where handling archives would go.
|
||||
* Right now, that's going to be a HUGE hassle, because of the problem with
|
||||
* saving things into the archive (no) and with everything requiring filenames
|
||||
* and not streams (also no), so for the purposes of making drag/drop more robust,
|
||||
* I am not building this out just yet.
|
||||
* -- Adam Michaud (Invariel)
|
||||
|
||||
int offset = 0;
|
||||
bool executable = false;
|
||||
var archiveHandler = new SevenZipSharpArchiveHandler();
|
||||
|
||||
// Not going to process nested archives at the moment.
|
||||
if (String.IsNullOrEmpty (archive) && archiveHandler.CheckSignature(file, out offset, out executable))
|
||||
{
|
||||
List<string> fileNames = new List<string>();
|
||||
var openedArchive = archiveHandler.Construct (file);
|
||||
|
||||
foreach (BizHawk.Common.HawkFileArchiveItem item in openedArchive.Scan ())
|
||||
fileNames.Add(item.Name);
|
||||
|
||||
ProcessFileList(fileNames.ToArray(), ref sortedFiles, file);
|
||||
|
||||
openedArchive.Dispose();
|
||||
}
|
||||
archiveHandler.Dispose();
|
||||
*/
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void _FormDragDrop_internal(object sender, DragEventArgs e)
|
||||
{
|
||||
/*
|
||||
* Refactor, moving the loading of particular files into separate functions that can
|
||||
* then be used by this code, and loading individual files through the file dialogue.
|
||||
*
|
||||
* Step 1:
|
||||
* Build a dictionary of relevant files from everything that was dragged and dropped.
|
||||
* This includes peeking into all relevant archives and using their files.
|
||||
*
|
||||
* Step 2:
|
||||
* Perhaps ask the user which of a particular file type they want to use.
|
||||
* Example: rom1.nes, rom2.smc, rom3.cue are drag-dropped, ask the user which they want to use.
|
||||
*
|
||||
* Step 3:
|
||||
* Load all of the relevant files, in priority order:
|
||||
* 1) The ROM
|
||||
* 2) State
|
||||
* 3) Watch files
|
||||
* 4) Code Data Logger (CDL)
|
||||
* 5) LUA sessions
|
||||
* 6) LUA scripts
|
||||
* 7) Cheat files
|
||||
* 8) Movie Playback Files
|
||||
*
|
||||
* Bonus:
|
||||
* Make that order easy to change in the code, heavily suggesting ROM and playback as first and last respectively.
|
||||
*/
|
||||
|
||||
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
Dictionary<LoadOrdering, List<FileInformation>> sortedFiles = new Dictionary<LoadOrdering, List<FileInformation>>();
|
||||
|
||||
// Initialize the dictionary's lists.
|
||||
foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
|
||||
{
|
||||
sortedFiles.Add(value, new List<FileInformation>());
|
||||
}
|
||||
|
||||
ProcessFileList(HawkFile.Util_ResolveLinks(filePaths), ref sortedFiles, null);
|
||||
|
||||
// For each of the different types of item, if there are no items of that type, skip them.
|
||||
// If there is exactly one of that type of item, load it.
|
||||
// If there is more than one, ask.
|
||||
|
||||
foreach (LoadOrdering value in Enum.GetValues(typeof(LoadOrdering)))
|
||||
{
|
||||
switch (sortedFiles[value].Count)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
FileInformation fileInformation = sortedFiles[value].First<FileInformation>();
|
||||
string filename = Path.Combine(new string[] { fileInformation.directoryName, fileInformation.fileName });
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case LoadOrdering.ROM:
|
||||
_LoadRom(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.STATE:
|
||||
_LoadState(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.WATCH:
|
||||
_LoadWatch(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.CDLFILE:
|
||||
_LoadCDL(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.LUASESSION:
|
||||
_LoadLuaSession(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.LUASCRIPT:
|
||||
_LoadLuaFile(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.CHEAT:
|
||||
_LoadCheats(filename, fileInformation.archiveName);
|
||||
break;
|
||||
case LoadOrdering.MOVIEFILE:
|
||||
case LoadOrdering.LEGACYMOVIEFILE:
|
||||
// I don't really like this hack, but for now, we only want to load one movie file.
|
||||
if (sortedFiles[LoadOrdering.MOVIEFILE].Count + sortedFiles[LoadOrdering.LEGACYMOVIEFILE].Count > 1)
|
||||
break;
|
||||
|
||||
if (value == LoadOrdering.MOVIEFILE)
|
||||
_LoadMovie(filename, fileInformation.archiveName);
|
||||
else
|
||||
_LoadLegacyMovie(filename, fileInformation.archiveName);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
using System;
|
||||
using BizHawk.Bizware.BizwareGL;
|
||||
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// This singleton class manages OpenGL contexts, in an effort to minimize context changes.
|
||||
/// </summary>
|
||||
public class GLManager : IDisposable
|
||||
{
|
||||
private GLManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
using System;
|
||||
using BizHawk.Bizware.BizwareGL;
|
||||
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
/// <summary>
|
||||
/// This singleton class manages OpenGL contexts, in an effort to minimize context changes.
|
||||
/// </summary>
|
||||
public class GLManager : IDisposable
|
||||
{
|
||||
private GLManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public static GLManager Instance { get; private set; }
|
||||
|
||||
Bizware.BizwareGL.Drivers.OpenTK.IGL_TK MainContext;
|
||||
|
||||
public static void CreateInstance(Bizware.BizwareGL.Drivers.OpenTK.IGL_TK mainContext)
|
||||
{
|
||||
if (Instance != null) throw new InvalidOperationException("Attempt to create more than one GLManager");
|
||||
Bizware.BizwareGL.Drivers.OpenTK.IGL_TK MainContext;
|
||||
|
||||
public static void CreateInstance(Bizware.BizwareGL.Drivers.OpenTK.IGL_TK mainContext)
|
||||
{
|
||||
if (Instance != null) throw new InvalidOperationException("Attempt to create more than one GLManager");
|
||||
Instance = new GLManager();
|
||||
Instance.MainContext = mainContext;
|
||||
Instance.MainContext = mainContext;
|
||||
}
|
||||
|
||||
public void ReleaseGLContext(object o)
|
||||
|
@ -38,77 +38,77 @@ namespace BizHawk.Client.EmuHawk
|
|||
//[System.Runtime.InteropServices.DllImport("opengl32.dll")]
|
||||
//bool wglShareLists(IntPtr hglrc1, IntPtr hglrc2);
|
||||
|
||||
public ContextRef CreateGLContext(int major_version, int minor_version, bool forward_compatible)
|
||||
public ContextRef CreateGLContext(int major_version, int minor_version, bool forward_compatible)
|
||||
{
|
||||
var gl = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK(major_version, minor_version, forward_compatible);
|
||||
var ret = new ContextRef { gl = gl };
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ContextRef GetContextForGraphicsControl(GraphicsControl gc)
|
||||
{
|
||||
return new ContextRef
|
||||
{
|
||||
gc = gc,
|
||||
gl = gc.IGL
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This might not be a GL implementation. If it isnt GL, then setting it as active context is just NOP
|
||||
/// </summary>
|
||||
public ContextRef GetContextForIGL(IGL gl)
|
||||
{
|
||||
return new ContextRef
|
||||
{
|
||||
gl = gl
|
||||
};
|
||||
}
|
||||
|
||||
ContextRef ActiveContext;
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
ActiveContext = null;
|
||||
}
|
||||
|
||||
public void Activate(ContextRef cr)
|
||||
{
|
||||
bool begun = false;
|
||||
|
||||
//this needs a begin signal to set the swap chain to the next backbuffer
|
||||
if (cr.gl is BizHawk.Bizware.BizwareGL.Drivers.SlimDX.IGL_SlimDX9)
|
||||
{
|
||||
cr.gc.Begin();
|
||||
begun = true;
|
||||
}
|
||||
|
||||
if (cr == ActiveContext)
|
||||
return;
|
||||
|
||||
ActiveContext = cr;
|
||||
if (cr.gc != null)
|
||||
{
|
||||
//TODO - this is checking the current context inside to avoid an extra NOP context change. make this optional or remove it, since we're tracking it here
|
||||
if(!begun)
|
||||
cr.gc.Begin();
|
||||
}
|
||||
else if (cr.gl != null)
|
||||
{
|
||||
if(cr.gl is BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK)
|
||||
((BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK)cr.gl).MakeDefaultCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
//this is here for future use and tracking purposes.. however.. instead of relying on this, we should just make sure we always activate what we need before we use it
|
||||
}
|
||||
|
||||
public class ContextRef
|
||||
{
|
||||
public IGL gl;
|
||||
public GraphicsControl gc;
|
||||
}
|
||||
}
|
||||
var gl = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK(major_version, minor_version, forward_compatible);
|
||||
var ret = new ContextRef { gl = gl };
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ContextRef GetContextForGraphicsControl(GraphicsControl gc)
|
||||
{
|
||||
return new ContextRef
|
||||
{
|
||||
gc = gc,
|
||||
gl = gc.IGL
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This might not be a GL implementation. If it isnt GL, then setting it as active context is just NOP
|
||||
/// </summary>
|
||||
public ContextRef GetContextForIGL(IGL gl)
|
||||
{
|
||||
return new ContextRef
|
||||
{
|
||||
gl = gl
|
||||
};
|
||||
}
|
||||
|
||||
ContextRef ActiveContext;
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
ActiveContext = null;
|
||||
}
|
||||
|
||||
public void Activate(ContextRef cr)
|
||||
{
|
||||
bool begun = false;
|
||||
|
||||
//this needs a begin signal to set the swap chain to the next backbuffer
|
||||
if (cr.gl is BizHawk.Bizware.BizwareGL.Drivers.SlimDX.IGL_SlimDX9)
|
||||
{
|
||||
cr.gc.Begin();
|
||||
begun = true;
|
||||
}
|
||||
|
||||
if (cr == ActiveContext)
|
||||
return;
|
||||
|
||||
ActiveContext = cr;
|
||||
if (cr.gc != null)
|
||||
{
|
||||
//TODO - this is checking the current context inside to avoid an extra NOP context change. make this optional or remove it, since we're tracking it here
|
||||
if(!begun)
|
||||
cr.gc.Begin();
|
||||
}
|
||||
else if (cr.gl != null)
|
||||
{
|
||||
if(cr.gl is BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK)
|
||||
((BizHawk.Bizware.BizwareGL.Drivers.OpenTK.IGL_TK)cr.gl).MakeDefaultCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
public void Deactivate()
|
||||
{
|
||||
//this is here for future use and tracking purposes.. however.. instead of relying on this, we should just make sure we always activate what we need before we use it
|
||||
}
|
||||
|
||||
public class ContextRef
|
||||
{
|
||||
public IGL gl;
|
||||
public GraphicsControl gc;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +1,43 @@
|
|||
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.Common;
|
||||
using BizHawk.Emulation.Cores.Sony.PSX;
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Client.EmuHawk.WinFormExtensions;
|
||||
using BizHawk.Common.ReflectionExtensions;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class PSXControllerConfigNew : Form
|
||||
{
|
||||
public PSXControllerConfigNew()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PSXControllerConfigNew_Load(object sender, EventArgs e)
|
||||
{
|
||||
//populate combo boxes
|
||||
foreach(var combo in new[]{combo_1_1,combo_1_2,combo_1_3,combo_1_4,combo_2_1,combo_2_2,combo_2_3,combo_2_4})
|
||||
{
|
||||
combo.Items.Add("-Nothing-");
|
||||
combo.Items.Add("Gamepad");
|
||||
combo.Items.Add("Dual Shock");
|
||||
combo.Items.Add("Dual Analog");
|
||||
combo.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
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.Common;
|
||||
using BizHawk.Emulation.Cores.Sony.PSX;
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Client.EmuHawk.WinFormExtensions;
|
||||
using BizHawk.Common.ReflectionExtensions;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class PSXControllerConfigNew : Form
|
||||
{
|
||||
public PSXControllerConfigNew()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void PSXControllerConfigNew_Load(object sender, EventArgs e)
|
||||
{
|
||||
//populate combo boxes
|
||||
foreach(var combo in new[]{combo_1_1,combo_1_2,combo_1_3,combo_1_4,combo_2_1,combo_2_2,combo_2_3,combo_2_4})
|
||||
{
|
||||
combo.Items.Add("-Nothing-");
|
||||
combo.Items.Add("Gamepad");
|
||||
combo.Items.Add("Dual Shock");
|
||||
combo.Items.Add("Dual Analog");
|
||||
combo.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
var psxSettings = ((Octoshock)Global.Emulator).GetSyncSettings();
|
||||
GuiFromUserConfig(psxSettings.FIOConfig);
|
||||
|
||||
RefreshLabels();
|
||||
GuiFromUserConfig(psxSettings.FIOConfig);
|
||||
|
||||
RefreshLabels();
|
||||
}
|
||||
|
||||
void GuiFromUserConfig(OctoshockFIOConfigUser user)
|
||||
|
@ -56,7 +56,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (user.Devices8[i] == OctoshockDll.ePeripheralType.DualShock) combo.SelectedIndex = 2;
|
||||
if (user.Devices8[i] == OctoshockDll.ePeripheralType.DualAnalog) combo.SelectedIndex = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OctoshockFIOConfigUser UserConfigFromGui()
|
||||
{
|
||||
|
@ -79,60 +79,60 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
|
||||
return uc;
|
||||
}
|
||||
|
||||
void RefreshLabels()
|
||||
}
|
||||
|
||||
void RefreshLabels()
|
||||
{
|
||||
var uc = UserConfigFromGui();
|
||||
|
||||
bool b1 = uc.Multitaps[0];
|
||||
lbl_1_1.Visible = b1;
|
||||
lbl_1_2.Visible = b1;
|
||||
lbl_1_3.Visible = b1;
|
||||
lbl_1_4.Visible = b1;
|
||||
combo_1_2.Enabled = b1;
|
||||
combo_1_3.Enabled = b1;
|
||||
combo_1_4.Enabled = b1;
|
||||
lbl_p_1_2.Visible = b1;
|
||||
lbl_p_1_3.Visible = b1;
|
||||
var uc = UserConfigFromGui();
|
||||
|
||||
bool b1 = uc.Multitaps[0];
|
||||
lbl_1_1.Visible = b1;
|
||||
lbl_1_2.Visible = b1;
|
||||
lbl_1_3.Visible = b1;
|
||||
lbl_1_4.Visible = b1;
|
||||
combo_1_2.Enabled = b1;
|
||||
combo_1_3.Enabled = b1;
|
||||
combo_1_4.Enabled = b1;
|
||||
lbl_p_1_2.Visible = b1;
|
||||
lbl_p_1_3.Visible = b1;
|
||||
lbl_p_1_4.Visible = b1;
|
||||
|
||||
bool b2 = uc.Multitaps[1];
|
||||
lbl_2_1.Visible = b2;
|
||||
lbl_2_2.Visible = b2;
|
||||
lbl_2_3.Visible = b2;
|
||||
lbl_2_4.Visible = b2;
|
||||
combo_2_2.Enabled = b2;
|
||||
combo_2_3.Enabled = b2;
|
||||
combo_2_4.Enabled = b2;
|
||||
lbl_p_2_2.Visible = b2;
|
||||
lbl_p_2_3.Visible = b2;
|
||||
bool b2 = uc.Multitaps[1];
|
||||
lbl_2_1.Visible = b2;
|
||||
lbl_2_2.Visible = b2;
|
||||
lbl_2_3.Visible = b2;
|
||||
lbl_2_4.Visible = b2;
|
||||
combo_2_2.Enabled = b2;
|
||||
combo_2_3.Enabled = b2;
|
||||
combo_2_4.Enabled = b2;
|
||||
lbl_p_2_2.Visible = b2;
|
||||
lbl_p_2_3.Visible = b2;
|
||||
lbl_p_2_4.Visible = b2;
|
||||
|
||||
var LC = uc.ToLogical();
|
||||
|
||||
var p_labels = new[] { lbl_p_1_1,lbl_p_1_2,lbl_p_1_3,lbl_p_1_4,lbl_p_2_1,lbl_p_2_2,lbl_p_2_3,lbl_p_2_4};
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
var lbl = p_labels[i];
|
||||
if (LC.PlayerAssignments[i] == -1)
|
||||
lbl.Visible = false;
|
||||
else
|
||||
{
|
||||
lbl.Text = "P" + LC.PlayerAssignments[i];
|
||||
lbl.Visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cb_changed(object sender, EventArgs e)
|
||||
{
|
||||
RefreshLabels();
|
||||
}
|
||||
|
||||
private void combo_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
RefreshLabels();
|
||||
var LC = uc.ToLogical();
|
||||
|
||||
var p_labels = new[] { lbl_p_1_1,lbl_p_1_2,lbl_p_1_3,lbl_p_1_4,lbl_p_2_1,lbl_p_2_2,lbl_p_2_3,lbl_p_2_4};
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
var lbl = p_labels[i];
|
||||
if (LC.PlayerAssignments[i] == -1)
|
||||
lbl.Visible = false;
|
||||
else
|
||||
{
|
||||
lbl.Text = "P" + LC.PlayerAssignments[i];
|
||||
lbl.Visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cb_changed(object sender, EventArgs e)
|
||||
{
|
||||
RefreshLabels();
|
||||
}
|
||||
|
||||
private void combo_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
RefreshLabels();
|
||||
}
|
||||
|
||||
private void btnOK_Click(object sender, EventArgs e)
|
||||
|
@ -145,6 +145,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
DialogResult = DialogResult.OK;
|
||||
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,188 +1,188 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Client.EmuHawk.ToolExtensions;
|
||||
|
||||
//TODO - select which memorydomains go out to the CDL file. will this cause a problem when re-importing it?
|
||||
//perhaps missing domains shouldnt fail a check
|
||||
//OR - just add a contextmenu option to the listview item that selects it for export.
|
||||
//TODO - add a contextmenu option which warps to the hexeditor with the provided domain selected for visualizing on the hex editor.
|
||||
//TODO - consider setting colors for columns in CDL
|
||||
//TODO - option to print domain name in caption instead of 0x01 etc.
|
||||
//TODO - context menu should have copy option too
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class CDL : ToolFormBase, IToolFormAutoConfig
|
||||
{
|
||||
private RecentFiles _recent_fld = new RecentFiles();
|
||||
|
||||
[ConfigPersist]
|
||||
private RecentFiles _recent
|
||||
{
|
||||
get
|
||||
{ return _recent_fld; }
|
||||
set
|
||||
{
|
||||
_recent_fld = value;
|
||||
if (_recent_fld.AutoLoad)
|
||||
{
|
||||
LoadFile(_recent.MostRecent);
|
||||
SetCurrentFilename(_recent.MostRecent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetCurrentFilename(string fname)
|
||||
{
|
||||
_currentFilename = fname;
|
||||
if (_currentFilename == null)
|
||||
Text = "Code Data Logger";
|
||||
else Text = string.Format("Code Data Logger - {0}", fname);
|
||||
}
|
||||
|
||||
[RequiredService]
|
||||
private IMemoryDomains MemoryDomains { get; set; }
|
||||
|
||||
[RequiredService]
|
||||
private ICodeDataLogger CodeDataLogger { get; set; }
|
||||
|
||||
private string _currentFilename = null;
|
||||
private CodeDataLog _cdl;
|
||||
|
||||
public CDL()
|
||||
{
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
InitializeComponent();
|
||||
|
||||
tsbViewStyle.SelectedIndex = 0;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
using BizHawk.Client.Common;
|
||||
using BizHawk.Client.EmuHawk.ToolExtensions;
|
||||
|
||||
//TODO - select which memorydomains go out to the CDL file. will this cause a problem when re-importing it?
|
||||
//perhaps missing domains shouldnt fail a check
|
||||
//OR - just add a contextmenu option to the listview item that selects it for export.
|
||||
//TODO - add a contextmenu option which warps to the hexeditor with the provided domain selected for visualizing on the hex editor.
|
||||
//TODO - consider setting colors for columns in CDL
|
||||
//TODO - option to print domain name in caption instead of 0x01 etc.
|
||||
//TODO - context menu should have copy option too
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class CDL : ToolFormBase, IToolFormAutoConfig
|
||||
{
|
||||
private RecentFiles _recent_fld = new RecentFiles();
|
||||
|
||||
[ConfigPersist]
|
||||
private RecentFiles _recent
|
||||
{
|
||||
get
|
||||
{ return _recent_fld; }
|
||||
set
|
||||
{
|
||||
_recent_fld = value;
|
||||
if (_recent_fld.AutoLoad)
|
||||
{
|
||||
LoadFile(_recent.MostRecent);
|
||||
SetCurrentFilename(_recent.MostRecent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void NewUpdate(ToolFormUpdateType type) { }
|
||||
|
||||
public void UpdateValues()
|
||||
{
|
||||
UpdateDisplay(false);
|
||||
}
|
||||
|
||||
public void FastUpdate()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
//don't try to recover the current CDL!
|
||||
//even though it seems like it might be nice, it might get mixed up between games. even if we use CheckCDL. Switching games with the same memory map will be bad.
|
||||
_cdl = null;
|
||||
SetCurrentFilename(null);
|
||||
SetLoggingActiveCheck(false);
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
void SetLoggingActiveCheck(bool value)
|
||||
{
|
||||
tsbLoggingActive.Checked = value;
|
||||
}
|
||||
|
||||
string[][] listContents = new string[0][];
|
||||
|
||||
private void UpdateDisplay(bool force)
|
||||
{
|
||||
if (!tsbViewUpdate.Checked && !force)
|
||||
return;
|
||||
|
||||
|
||||
if (_cdl == null)
|
||||
{
|
||||
lvCDL.BeginUpdate();
|
||||
lvCDL.Items.Clear();
|
||||
lvCDL.EndUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
lvCDL.BeginUpdate();
|
||||
|
||||
listContents = new string[_cdl.Count][];
|
||||
|
||||
int idx = 0;
|
||||
foreach (var kvp in _cdl)
|
||||
{
|
||||
int[] totals = new int[8];
|
||||
int total = 0;
|
||||
unsafe
|
||||
{
|
||||
int* map = stackalloc int[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
map[i] = 0;
|
||||
|
||||
fixed (byte* data = kvp.Value)
|
||||
{
|
||||
byte* src = data;
|
||||
byte* end = data + kvp.Value.Length;
|
||||
while (src < end)
|
||||
{
|
||||
byte s = *src++;
|
||||
map[s]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
if(i!=0) total += map[i];
|
||||
if ((i & 0x01) != 0) totals[0] += map[i];
|
||||
if ((i & 0x02) != 0) totals[1] += map[i];
|
||||
if ((i & 0x04) != 0) totals[2] += map[i];
|
||||
if ((i & 0x08) != 0) totals[3] += map[i];
|
||||
if ((i & 0x10) != 0) totals[4] += map[i];
|
||||
if ((i & 0x20) != 0) totals[5] += map[i];
|
||||
if ((i & 0x40) != 0) totals[6] += map[i];
|
||||
if ((i & 0x80) != 0) totals[7] += map[i];
|
||||
}
|
||||
}
|
||||
|
||||
var bm = _cdl.GetBlockMap();
|
||||
long addr = bm[kvp.Key];
|
||||
|
||||
var lvi = listContents[idx++] = new string[13];
|
||||
lvi[0] = string.Format("{0:X8}", addr);
|
||||
lvi[1] = kvp.Key;
|
||||
lvi[2] = string.Format("{0:0.00}%", total / (float)kvp.Value.Length * 100f);
|
||||
if (tsbViewStyle.SelectedIndex == 2)
|
||||
lvi[3] = string.Format("{0:0.00}", total / 1024.0f);
|
||||
else
|
||||
lvi[3] = string.Format("{0}", total);
|
||||
if (tsbViewStyle.SelectedIndex == 2)
|
||||
{
|
||||
int n = (int)(kvp.Value.Length / 1024.0f);
|
||||
float ncheck = kvp.Value.Length / 1024.0f;
|
||||
lvi[4] = string.Format("of {0}{1} KBytes", n == ncheck ? "" : "~", n);
|
||||
}
|
||||
else
|
||||
lvi[4] = string.Format("of {0} Bytes", kvp.Value.Length);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (tsbViewStyle.SelectedIndex == 0)
|
||||
lvi[5 + i] = string.Format("{0:0.00}%", totals[i] / (float)kvp.Value.Length * 100f);
|
||||
if (tsbViewStyle.SelectedIndex == 1)
|
||||
lvi[5 + i] = string.Format("{0}", totals[i]);
|
||||
if (tsbViewStyle.SelectedIndex == 2)
|
||||
lvi[5 + i] = string.Format("{0:0.00}", totals[i] / 1024.0f);
|
||||
}
|
||||
|
||||
}
|
||||
lvCDL.VirtualListSize = _cdl.Count;
|
||||
lvCDL.EndUpdate();
|
||||
}
|
||||
|
||||
public bool AskSaveChanges()
|
||||
void SetCurrentFilename(string fname)
|
||||
{
|
||||
_currentFilename = fname;
|
||||
if (_currentFilename == null)
|
||||
Text = "Code Data Logger";
|
||||
else Text = string.Format("Code Data Logger - {0}", fname);
|
||||
}
|
||||
|
||||
[RequiredService]
|
||||
private IMemoryDomains MemoryDomains { get; set; }
|
||||
|
||||
[RequiredService]
|
||||
private ICodeDataLogger CodeDataLogger { get; set; }
|
||||
|
||||
private string _currentFilename = null;
|
||||
private CodeDataLog _cdl;
|
||||
|
||||
public CDL()
|
||||
{
|
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
InitializeComponent();
|
||||
|
||||
tsbViewStyle.SelectedIndex = 0;
|
||||
}
|
||||
|
||||
public void NewUpdate(ToolFormUpdateType type) { }
|
||||
|
||||
public void UpdateValues()
|
||||
{
|
||||
UpdateDisplay(false);
|
||||
}
|
||||
|
||||
public void FastUpdate()
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
//don't try to recover the current CDL!
|
||||
//even though it seems like it might be nice, it might get mixed up between games. even if we use CheckCDL. Switching games with the same memory map will be bad.
|
||||
_cdl = null;
|
||||
SetCurrentFilename(null);
|
||||
SetLoggingActiveCheck(false);
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
void SetLoggingActiveCheck(bool value)
|
||||
{
|
||||
tsbLoggingActive.Checked = value;
|
||||
}
|
||||
|
||||
string[][] listContents = new string[0][];
|
||||
|
||||
private void UpdateDisplay(bool force)
|
||||
{
|
||||
if (!tsbViewUpdate.Checked && !force)
|
||||
return;
|
||||
|
||||
|
||||
if (_cdl == null)
|
||||
{
|
||||
lvCDL.BeginUpdate();
|
||||
lvCDL.Items.Clear();
|
||||
lvCDL.EndUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
lvCDL.BeginUpdate();
|
||||
|
||||
listContents = new string[_cdl.Count][];
|
||||
|
||||
int idx = 0;
|
||||
foreach (var kvp in _cdl)
|
||||
{
|
||||
int[] totals = new int[8];
|
||||
int total = 0;
|
||||
unsafe
|
||||
{
|
||||
int* map = stackalloc int[256];
|
||||
for (int i = 0; i < 256; i++)
|
||||
map[i] = 0;
|
||||
|
||||
fixed (byte* data = kvp.Value)
|
||||
{
|
||||
byte* src = data;
|
||||
byte* end = data + kvp.Value.Length;
|
||||
while (src < end)
|
||||
{
|
||||
byte s = *src++;
|
||||
map[s]++;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
if(i!=0) total += map[i];
|
||||
if ((i & 0x01) != 0) totals[0] += map[i];
|
||||
if ((i & 0x02) != 0) totals[1] += map[i];
|
||||
if ((i & 0x04) != 0) totals[2] += map[i];
|
||||
if ((i & 0x08) != 0) totals[3] += map[i];
|
||||
if ((i & 0x10) != 0) totals[4] += map[i];
|
||||
if ((i & 0x20) != 0) totals[5] += map[i];
|
||||
if ((i & 0x40) != 0) totals[6] += map[i];
|
||||
if ((i & 0x80) != 0) totals[7] += map[i];
|
||||
}
|
||||
}
|
||||
|
||||
var bm = _cdl.GetBlockMap();
|
||||
long addr = bm[kvp.Key];
|
||||
|
||||
var lvi = listContents[idx++] = new string[13];
|
||||
lvi[0] = string.Format("{0:X8}", addr);
|
||||
lvi[1] = kvp.Key;
|
||||
lvi[2] = string.Format("{0:0.00}%", total / (float)kvp.Value.Length * 100f);
|
||||
if (tsbViewStyle.SelectedIndex == 2)
|
||||
lvi[3] = string.Format("{0:0.00}", total / 1024.0f);
|
||||
else
|
||||
lvi[3] = string.Format("{0}", total);
|
||||
if (tsbViewStyle.SelectedIndex == 2)
|
||||
{
|
||||
int n = (int)(kvp.Value.Length / 1024.0f);
|
||||
float ncheck = kvp.Value.Length / 1024.0f;
|
||||
lvi[4] = string.Format("of {0}{1} KBytes", n == ncheck ? "" : "~", n);
|
||||
}
|
||||
else
|
||||
lvi[4] = string.Format("of {0} Bytes", kvp.Value.Length);
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (tsbViewStyle.SelectedIndex == 0)
|
||||
lvi[5 + i] = string.Format("{0:0.00}%", totals[i] / (float)kvp.Value.Length * 100f);
|
||||
if (tsbViewStyle.SelectedIndex == 1)
|
||||
lvi[5 + i] = string.Format("{0}", totals[i]);
|
||||
if (tsbViewStyle.SelectedIndex == 2)
|
||||
lvi[5 + i] = string.Format("{0:0.00}", totals[i] / 1024.0f);
|
||||
}
|
||||
|
||||
}
|
||||
lvCDL.VirtualListSize = _cdl.Count;
|
||||
lvCDL.EndUpdate();
|
||||
}
|
||||
|
||||
public bool AskSaveChanges()
|
||||
{
|
||||
//nothing to fear:
|
||||
if (_cdl == null)
|
||||
|
@ -208,108 +208,108 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateBefore
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void LoadFile(string path)
|
||||
{
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
var newCDL = new CodeDataLog();
|
||||
newCDL.Load(fs);
|
||||
|
||||
//have the core create a CodeDataLog to check mapping information against
|
||||
var testCDL = new CodeDataLog();
|
||||
CodeDataLogger.NewCDL(testCDL);
|
||||
if (!newCDL.Check(testCDL))
|
||||
{
|
||||
MessageBox.Show(this, "CDL file does not match emulator's current memory map!");
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, it's all good:
|
||||
_cdl = newCDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UpdateBefore
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public void LoadFile(string path)
|
||||
{
|
||||
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
var newCDL = new CodeDataLog();
|
||||
newCDL.Load(fs);
|
||||
|
||||
//have the core create a CodeDataLog to check mapping information against
|
||||
var testCDL = new CodeDataLog();
|
||||
CodeDataLogger.NewCDL(testCDL);
|
||||
if (!newCDL.Check(testCDL))
|
||||
{
|
||||
MessageBox.Show(this, "CDL file does not match emulator's current memory map!");
|
||||
return;
|
||||
}
|
||||
|
||||
//ok, it's all good:
|
||||
_cdl = newCDL;
|
||||
CodeDataLogger.SetCDL(null);
|
||||
if (tsbLoggingActive.Checked || Global.Config.CDLAutoStart)
|
||||
CodeDataLogger.SetCDL(_cdl);
|
||||
|
||||
SetCurrentFilename(path);
|
||||
}
|
||||
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
private void FileSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
SaveMenuItem.Enabled = _currentFilename != null;
|
||||
SaveAsMenuItem.Enabled =
|
||||
AppendMenuItem.Enabled =
|
||||
ClearMenuItem.Enabled =
|
||||
DisassembleMenuItem.Enabled =
|
||||
if (tsbLoggingActive.Checked || Global.Config.CDLAutoStart)
|
||||
CodeDataLogger.SetCDL(_cdl);
|
||||
|
||||
SetCurrentFilename(path);
|
||||
}
|
||||
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
private void FileSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
SaveMenuItem.Enabled = _currentFilename != null;
|
||||
SaveAsMenuItem.Enabled =
|
||||
AppendMenuItem.Enabled =
|
||||
ClearMenuItem.Enabled =
|
||||
DisassembleMenuItem.Enabled =
|
||||
_cdl != null;
|
||||
|
||||
miAutoSave.Checked = Global.Config.CDLAutoSave;
|
||||
miAutoStart.Checked = Global.Config.CDLAutoStart;
|
||||
}
|
||||
|
||||
private void RecentSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
RecentSubMenu.DropDownItems.Clear();
|
||||
RecentSubMenu.DropDownItems.AddRange(_recent.RecentMenu(LoadFile, true));
|
||||
miAutoStart.Checked = Global.Config.CDLAutoStart;
|
||||
}
|
||||
|
||||
void NewFileLogic()
|
||||
{
|
||||
_cdl = new CodeDataLog();
|
||||
CodeDataLogger.NewCDL(_cdl);
|
||||
|
||||
if (tsbLoggingActive.Checked || Global.Config.CDLAutoStart)
|
||||
CodeDataLogger.SetCDL(_cdl);
|
||||
else CodeDataLogger.SetCDL(null);
|
||||
|
||||
SetCurrentFilename(null);
|
||||
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
private void NewMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
//take care not to clobber an existing CDL
|
||||
if (_cdl != null)
|
||||
{
|
||||
var result = MessageBox.Show(this, "OK to create new CDL?", "Query", MessageBoxButtons.YesNo);
|
||||
if (result != DialogResult.Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
NewFileLogic();
|
||||
}
|
||||
|
||||
private void OpenMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var file = OpenFileDialog(
|
||||
_currentFilename,
|
||||
PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null),
|
||||
"Code Data Logger Files",
|
||||
"cdl");
|
||||
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
//take care not to clobber an existing CDL
|
||||
if (_cdl != null)
|
||||
{
|
||||
var result = MessageBox.Show(this, "OK to load new CDL?", "Query", MessageBoxButtons.YesNo);
|
||||
if (result != DialogResult.Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
LoadFile(file.FullName);
|
||||
private void RecentSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
RecentSubMenu.DropDownItems.Clear();
|
||||
RecentSubMenu.DropDownItems.AddRange(_recent.RecentMenu(LoadFile, true));
|
||||
}
|
||||
|
||||
void NewFileLogic()
|
||||
{
|
||||
_cdl = new CodeDataLog();
|
||||
CodeDataLogger.NewCDL(_cdl);
|
||||
|
||||
if (tsbLoggingActive.Checked || Global.Config.CDLAutoStart)
|
||||
CodeDataLogger.SetCDL(_cdl);
|
||||
else CodeDataLogger.SetCDL(null);
|
||||
|
||||
SetCurrentFilename(null);
|
||||
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
private void NewMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
//take care not to clobber an existing CDL
|
||||
if (_cdl != null)
|
||||
{
|
||||
var result = MessageBox.Show(this, "OK to create new CDL?", "Query", MessageBoxButtons.YesNo);
|
||||
if (result != DialogResult.Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
NewFileLogic();
|
||||
}
|
||||
|
||||
private void OpenMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
var file = OpenFileDialog(
|
||||
_currentFilename,
|
||||
PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null),
|
||||
"Code Data Logger Files",
|
||||
"cdl");
|
||||
|
||||
if (file == null)
|
||||
return;
|
||||
|
||||
//take care not to clobber an existing CDL
|
||||
if (_cdl != null)
|
||||
{
|
||||
var result = MessageBox.Show(this, "OK to load new CDL?", "Query", MessageBoxButtons.YesNo);
|
||||
if (result != DialogResult.Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
LoadFile(file.FullName);
|
||||
}
|
||||
|
||||
void RunSave()
|
||||
|
@ -319,120 +319,120 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
_cdl.Save(fs);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveMenuItem_Click(object sender, EventArgs e)
|
||||
}
|
||||
|
||||
private void SaveMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot save with no CDL loaded!", "Alert");
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_currentFilename))
|
||||
{
|
||||
RunSaveAs();
|
||||
return;
|
||||
}
|
||||
|
||||
RunSave();
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(_currentFilename))
|
||||
{
|
||||
RunSaveAs();
|
||||
return;
|
||||
}
|
||||
|
||||
RunSave();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// returns false if the operation was canceled
|
||||
/// </summary>
|
||||
bool RunSaveAs()
|
||||
{
|
||||
var file = SaveFileDialog(
|
||||
_currentFilename,
|
||||
PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null),
|
||||
"Code Data Logger Files",
|
||||
bool RunSaveAs()
|
||||
{
|
||||
var file = SaveFileDialog(
|
||||
_currentFilename,
|
||||
PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null),
|
||||
"Code Data Logger Files",
|
||||
"cdl");
|
||||
|
||||
if (file == null)
|
||||
return false;
|
||||
return false;
|
||||
|
||||
SetCurrentFilename(file.FullName);
|
||||
RunSave();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SaveAsMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
RunSaveAs();
|
||||
}
|
||||
|
||||
private void AppendMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot append with no CDL loaded!", "Alert");
|
||||
}
|
||||
else
|
||||
{
|
||||
var file = ToolFormBase.OpenFileDialog(
|
||||
_currentFilename,
|
||||
PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null),
|
||||
"Code Data Logger Files",
|
||||
"cdl");
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
var newCDL = new CodeDataLog();
|
||||
newCDL.Load(fs);
|
||||
if (!_cdl.Check(newCDL))
|
||||
{
|
||||
MessageBox.Show(this, "CDL file does not match emulator's current memory map!");
|
||||
return;
|
||||
}
|
||||
_cdl.LogicalOrFrom(newCDL);
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot clear with no CDL loaded!", "Alert");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = MessageBox.Show(this, "OK to clear CDL?", "Query", MessageBoxButtons.YesNo);
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
_cdl.ClearData();
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DisassembleMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot disassemble with no CDL loaded!", "Alert");
|
||||
return;
|
||||
}
|
||||
|
||||
var sfd = new SaveFileDialog();
|
||||
var result = sfd.ShowDialog(this);
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
using (var fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
CodeDataLogger.DisassembleCDL(fs, _cdl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExitMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
RunSave();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SaveAsMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
RunSaveAs();
|
||||
}
|
||||
|
||||
private void AppendMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot append with no CDL loaded!", "Alert");
|
||||
}
|
||||
else
|
||||
{
|
||||
var file = ToolFormBase.OpenFileDialog(
|
||||
_currentFilename,
|
||||
PathManager.MakeAbsolutePath(Global.Config.PathEntries.LogPathFragment, null),
|
||||
"Code Data Logger Files",
|
||||
"cdl");
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
var newCDL = new CodeDataLog();
|
||||
newCDL.Load(fs);
|
||||
if (!_cdl.Check(newCDL))
|
||||
{
|
||||
MessageBox.Show(this, "CDL file does not match emulator's current memory map!");
|
||||
return;
|
||||
}
|
||||
_cdl.LogicalOrFrom(newCDL);
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot clear with no CDL loaded!", "Alert");
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = MessageBox.Show(this, "OK to clear CDL?", "Query", MessageBoxButtons.YesNo);
|
||||
if (result == DialogResult.Yes)
|
||||
{
|
||||
_cdl.ClearData();
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DisassembleMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
if (_cdl == null)
|
||||
{
|
||||
MessageBox.Show(this, "Cannot disassemble with no CDL loaded!", "Alert");
|
||||
return;
|
||||
}
|
||||
|
||||
var sfd = new SaveFileDialog();
|
||||
var result = sfd.ShowDialog(this);
|
||||
if (result == DialogResult.OK)
|
||||
{
|
||||
using (var fs = new FileStream(sfd.FileName, FileMode.Create, FileAccess.Write))
|
||||
{
|
||||
CodeDataLogger.DisassembleCDL(fs, _cdl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ExitMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
|
||||
|
@ -447,69 +447,69 @@ namespace BizHawk.Client.EmuHawk
|
|||
if (Global.Config.CDLAutoStart)
|
||||
NewFileLogic();
|
||||
base.OnShown(e);
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
//deactivate logger
|
||||
if (CodeDataLogger != null) //just in case...
|
||||
CodeDataLogger.SetCDL(null);
|
||||
}
|
||||
|
||||
private void PCECDL_Load(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void PCECDL_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
|
||||
}
|
||||
|
||||
private void PCECDL_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
if (Path.GetExtension(filePaths[0]) == ".cdl")
|
||||
{
|
||||
LoadFile(filePaths[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void tsbViewStyle_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
private void tsbLoggingActive_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (tsbLoggingActive.Checked && _cdl == null)
|
||||
{
|
||||
//implicitly create a new file
|
||||
NewFileLogic();
|
||||
}
|
||||
|
||||
if (_cdl != null && tsbLoggingActive.Checked)
|
||||
CodeDataLogger.SetCDL(_cdl);
|
||||
else
|
||||
CodeDataLogger.SetCDL(null);
|
||||
}
|
||||
|
||||
private void lvCDL_QueryItemText(int item, int subItem, out string text)
|
||||
{
|
||||
text = listContents[item][subItem];
|
||||
}
|
||||
|
||||
private void tsbExportText_Click(object sender, EventArgs e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
foreach(var line in listContents)
|
||||
{
|
||||
foreach (var entry in line)
|
||||
sw.Write("{0} |", entry);
|
||||
sw.WriteLine();
|
||||
}
|
||||
Clipboard.SetText(sw.ToString());
|
||||
//deactivate logger
|
||||
if (CodeDataLogger != null) //just in case...
|
||||
CodeDataLogger.SetCDL(null);
|
||||
}
|
||||
|
||||
private void PCECDL_Load(object sender, EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void PCECDL_DragEnter(object sender, DragEventArgs e)
|
||||
{
|
||||
e.Effect = e.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
|
||||
}
|
||||
|
||||
private void PCECDL_DragDrop(object sender, DragEventArgs e)
|
||||
{
|
||||
var filePaths = (string[])e.Data.GetData(DataFormats.FileDrop);
|
||||
if (Path.GetExtension(filePaths[0]) == ".cdl")
|
||||
{
|
||||
LoadFile(filePaths[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void tsbViewStyle_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
UpdateDisplay(true);
|
||||
}
|
||||
|
||||
private void tsbLoggingActive_CheckedChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (tsbLoggingActive.Checked && _cdl == null)
|
||||
{
|
||||
//implicitly create a new file
|
||||
NewFileLogic();
|
||||
}
|
||||
|
||||
if (_cdl != null && tsbLoggingActive.Checked)
|
||||
CodeDataLogger.SetCDL(_cdl);
|
||||
else
|
||||
CodeDataLogger.SetCDL(null);
|
||||
}
|
||||
|
||||
private void lvCDL_QueryItemText(int item, int subItem, out string text)
|
||||
{
|
||||
text = listContents[item][subItem];
|
||||
}
|
||||
|
||||
private void tsbExportText_Click(object sender, EventArgs e)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
foreach(var line in listContents)
|
||||
{
|
||||
foreach (var entry in line)
|
||||
sw.Write("{0} |", entry);
|
||||
sw.WriteLine();
|
||||
}
|
||||
Clipboard.SetText(sw.ToString());
|
||||
}
|
||||
|
||||
private void miAutoSave_Click(object sender, EventArgs e)
|
||||
|
@ -522,6 +522,6 @@ namespace BizHawk.Client.EmuHawk
|
|||
Global.Config.CDLAutoStart ^= true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,105 +1,105 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class NewHexEditor : Form, IToolFormAutoConfig
|
||||
{
|
||||
#region Initialize and Dependencies
|
||||
|
||||
[RequiredService]
|
||||
private IMemoryDomains MemoryDomains { get; set; }
|
||||
|
||||
[RequiredService]
|
||||
private IEmulator Emulator { get; set; }
|
||||
|
||||
public NewHexEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Closing += (o, e) => SaveConfigSettings();
|
||||
|
||||
HexViewControl.QueryIndexValue += HexView_QueryIndexValue;
|
||||
HexViewControl.QueryIndexForeColor += HexView_QueryIndexForeColor;
|
||||
HexViewControl.QueryIndexBgColor += HexView_QueryIndexForeColor;
|
||||
}
|
||||
|
||||
private void NewHexEditor_Load(object sender, EventArgs e)
|
||||
{
|
||||
HexViewControl.ArrayLength = MemoryDomains.MainMemory.Size;
|
||||
}
|
||||
|
||||
private void SaveConfigSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Client.EmuHawk
|
||||
{
|
||||
public partial class NewHexEditor : Form, IToolFormAutoConfig
|
||||
{
|
||||
#region Initialize and Dependencies
|
||||
|
||||
[RequiredService]
|
||||
private IMemoryDomains MemoryDomains { get; set; }
|
||||
|
||||
[RequiredService]
|
||||
private IEmulator Emulator { get; set; }
|
||||
|
||||
public NewHexEditor()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Closing += (o, e) => SaveConfigSettings();
|
||||
|
||||
HexViewControl.QueryIndexValue += HexView_QueryIndexValue;
|
||||
HexViewControl.QueryIndexForeColor += HexView_QueryIndexForeColor;
|
||||
HexViewControl.QueryIndexBgColor += HexView_QueryIndexForeColor;
|
||||
}
|
||||
|
||||
private void NewHexEditor_Load(object sender, EventArgs e)
|
||||
{
|
||||
HexViewControl.ArrayLength = MemoryDomains.MainMemory.Size;
|
||||
}
|
||||
|
||||
private void SaveConfigSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IToolForm implementation
|
||||
|
||||
public void NewUpdate(ToolFormUpdateType type) { }
|
||||
|
||||
public void UpdateValues()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void FastUpdate()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public bool AskSaveChanges()
|
||||
{
|
||||
return true; // TODO
|
||||
}
|
||||
|
||||
public bool UpdateBefore { get { return false; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region HexView Callbacks
|
||||
|
||||
private void HexView_QueryIndexValue(int index, out long value)
|
||||
{
|
||||
value = MemoryDomains.MainMemory.PeekByte(index);
|
||||
}
|
||||
|
||||
private void HexView_QueryIndexBgColor(int index, ref Color color)
|
||||
{
|
||||
color = Color.White;
|
||||
}
|
||||
|
||||
private void HexView_QueryIndexForeColor(int index, ref Color color)
|
||||
{
|
||||
color = Color.Black;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Menu Items
|
||||
|
||||
private void FileSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void ExitMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
public void NewUpdate(ToolFormUpdateType type) { }
|
||||
|
||||
public void UpdateValues()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void FastUpdate()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void Restart()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
public bool AskSaveChanges()
|
||||
{
|
||||
return true; // TODO
|
||||
}
|
||||
|
||||
public bool UpdateBefore { get { return false; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region HexView Callbacks
|
||||
|
||||
private void HexView_QueryIndexValue(int index, out long value)
|
||||
{
|
||||
value = MemoryDomains.MainMemory.PeekByte(index);
|
||||
}
|
||||
|
||||
private void HexView_QueryIndexBgColor(int index, ref Color color)
|
||||
{
|
||||
color = Color.White;
|
||||
}
|
||||
|
||||
private void HexView_QueryIndexForeColor(int index, ref Color color)
|
||||
{
|
||||
color = Color.Black;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Menu Items
|
||||
|
||||
private void FileSubMenu_DropDownOpened(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void ExitMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of ITraceable that is implementation using only methods
|
||||
|
@ -16,42 +16,42 @@ namespace BizHawk.Emulation.Common
|
|||
/// <seealso cref="IDebuggable"/>
|
||||
/// <seealso cref="IMemoryDomains"/>
|
||||
/// <seealso cref="IDisassemblable"/>
|
||||
public abstract class CallbackBasedTraceBuffer : ITraceable
|
||||
{
|
||||
public CallbackBasedTraceBuffer(IDebuggable debuggableCore, IMemoryDomains memoryDomains, IDisassemblable disassembler)
|
||||
{
|
||||
if (!debuggableCore.MemoryCallbacksAvailable())
|
||||
{
|
||||
throw new InvalidOperationException("Memory callbacks are required");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
debuggableCore.GetCpuFlagsAndRegisters();
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
throw new InvalidOperationException("GetCpuFlagsAndRegisters is required");
|
||||
}
|
||||
|
||||
Header = "Instructions";
|
||||
DebuggableCore = debuggableCore;
|
||||
MemoryDomains = memoryDomains;
|
||||
Disassembler = disassembler;
|
||||
}
|
||||
|
||||
protected readonly IMemoryDomains MemoryDomains;
|
||||
protected readonly IDisassemblable Disassembler;
|
||||
protected readonly IDebuggable DebuggableCore;
|
||||
|
||||
protected readonly List<TraceInfo> Buffer = new List<TraceInfo>();
|
||||
|
||||
public abstract class CallbackBasedTraceBuffer : ITraceable
|
||||
{
|
||||
public CallbackBasedTraceBuffer(IDebuggable debuggableCore, IMemoryDomains memoryDomains, IDisassemblable disassembler)
|
||||
{
|
||||
if (!debuggableCore.MemoryCallbacksAvailable())
|
||||
{
|
||||
throw new InvalidOperationException("Memory callbacks are required");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
debuggableCore.GetCpuFlagsAndRegisters();
|
||||
}
|
||||
catch (NotImplementedException)
|
||||
{
|
||||
throw new InvalidOperationException("GetCpuFlagsAndRegisters is required");
|
||||
}
|
||||
|
||||
Header = "Instructions";
|
||||
DebuggableCore = debuggableCore;
|
||||
MemoryDomains = memoryDomains;
|
||||
Disassembler = disassembler;
|
||||
}
|
||||
|
||||
protected readonly IMemoryDomains MemoryDomains;
|
||||
protected readonly IDisassemblable Disassembler;
|
||||
protected readonly IDebuggable DebuggableCore;
|
||||
|
||||
protected readonly List<TraceInfo> Buffer = new List<TraceInfo>();
|
||||
|
||||
public abstract void TraceFromCallback();
|
||||
|
||||
private ITraceSink _sink;
|
||||
|
||||
public bool Enabled => Sink != null;
|
||||
|
||||
public bool Enabled => Sink != null;
|
||||
|
||||
public void Put(TraceInfo info)
|
||||
{
|
||||
Sink.Put(info);
|
||||
|
@ -73,26 +73,26 @@ namespace BizHawk.Emulation.Common
|
|||
DebuggableCore.MemoryCallbacks.Add(new TracingMemoryCallback(TraceFromCallback));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Header { get; set; }
|
||||
|
||||
public class TracingMemoryCallback : IMemoryCallback
|
||||
{
|
||||
public TracingMemoryCallback(Action callback)
|
||||
{
|
||||
Callback = callback;
|
||||
}
|
||||
|
||||
public MemoryCallbackType Type => MemoryCallbackType.Execute;
|
||||
|
||||
public string Name => "Trace Logging";
|
||||
|
||||
public Action Callback { get; }
|
||||
|
||||
public uint? Address => null;
|
||||
|
||||
public uint? AddressMask => null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string Header { get; set; }
|
||||
|
||||
public class TracingMemoryCallback : IMemoryCallback
|
||||
{
|
||||
public TracingMemoryCallback(Action callback)
|
||||
{
|
||||
Callback = callback;
|
||||
}
|
||||
|
||||
public MemoryCallbackType Type => MemoryCallbackType.Execute;
|
||||
|
||||
public string Name => "Trace Logging";
|
||||
|
||||
public Action Callback { get; }
|
||||
|
||||
public uint? Address => null;
|
||||
|
||||
public uint? AddressMask => null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,120 +1,120 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||
{
|
||||
public sealed partial class Drive1541
|
||||
{
|
||||
[SaveState.DoNotSave]
|
||||
private const long LEHMER_RNG_PRIME = 48271;
|
||||
[SaveState.SaveWithName("DiskDensityCounter")]
|
||||
private int _diskDensityCounter; // density .. 16
|
||||
[SaveState.SaveWithName("DiskSupplementaryCounter")]
|
||||
private int _diskSupplementaryCounter; // 0 .. 16
|
||||
[SaveState.SaveWithName("DiskFluxReversalDetected")]
|
||||
private bool _diskFluxReversalDetected;
|
||||
[SaveState.SaveWithName("DiskBitsRemainingInDataEntry")]
|
||||
private int _diskBitsLeft;
|
||||
[SaveState.SaveWithName("DiskDataEntryIndex")]
|
||||
private int _diskByteOffset;
|
||||
[SaveState.SaveWithName("DiskDataEntry")]
|
||||
private int _diskBits;
|
||||
[SaveState.SaveWithName("DiskCurrentCycle")]
|
||||
private int _diskCycle;
|
||||
[SaveState.SaveWithName("DiskDensityConfig")]
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
||||
{
|
||||
public sealed partial class Drive1541
|
||||
{
|
||||
[SaveState.DoNotSave]
|
||||
private const long LEHMER_RNG_PRIME = 48271;
|
||||
[SaveState.SaveWithName("DiskDensityCounter")]
|
||||
private int _diskDensityCounter; // density .. 16
|
||||
[SaveState.SaveWithName("DiskSupplementaryCounter")]
|
||||
private int _diskSupplementaryCounter; // 0 .. 16
|
||||
[SaveState.SaveWithName("DiskFluxReversalDetected")]
|
||||
private bool _diskFluxReversalDetected;
|
||||
[SaveState.SaveWithName("DiskBitsRemainingInDataEntry")]
|
||||
private int _diskBitsLeft;
|
||||
[SaveState.SaveWithName("DiskDataEntryIndex")]
|
||||
private int _diskByteOffset;
|
||||
[SaveState.SaveWithName("DiskDataEntry")]
|
||||
private int _diskBits;
|
||||
[SaveState.SaveWithName("DiskCurrentCycle")]
|
||||
private int _diskCycle;
|
||||
[SaveState.SaveWithName("DiskDensityConfig")]
|
||||
private int _diskDensity;
|
||||
[SaveState.SaveWithName("PreviousCA1")]
|
||||
private bool _previousCa1;
|
||||
[SaveState.SaveWithName("CountsBeforeRandomTransition")]
|
||||
private int _countsBeforeRandomTransition;
|
||||
[SaveState.SaveWithName("CurrentRNG")]
|
||||
private int _rngCurrent;
|
||||
[SaveState.SaveWithName("Clocks")]
|
||||
private int _clocks;
|
||||
[SaveState.SaveWithName("CpuClocks")]
|
||||
private int _cpuClocks;
|
||||
|
||||
// Lehmer RNG
|
||||
private void AdvanceRng()
|
||||
{
|
||||
if (_rngCurrent == 0)
|
||||
_rngCurrent = 1;
|
||||
_rngCurrent = (int)(_rngCurrent * LEHMER_RNG_PRIME % int.MaxValue);
|
||||
}
|
||||
|
||||
private void ExecuteFlux()
|
||||
[SaveState.SaveWithName("PreviousCA1")]
|
||||
private bool _previousCa1;
|
||||
[SaveState.SaveWithName("CountsBeforeRandomTransition")]
|
||||
private int _countsBeforeRandomTransition;
|
||||
[SaveState.SaveWithName("CurrentRNG")]
|
||||
private int _rngCurrent;
|
||||
[SaveState.SaveWithName("Clocks")]
|
||||
private int _clocks;
|
||||
[SaveState.SaveWithName("CpuClocks")]
|
||||
private int _cpuClocks;
|
||||
|
||||
// Lehmer RNG
|
||||
private void AdvanceRng()
|
||||
{
|
||||
if (_rngCurrent == 0)
|
||||
_rngCurrent = 1;
|
||||
_rngCurrent = (int)(_rngCurrent * LEHMER_RNG_PRIME % int.MaxValue);
|
||||
}
|
||||
|
||||
private void ExecuteFlux()
|
||||
{
|
||||
// This actually executes the main 16mhz clock
|
||||
while (_clocks > 0)
|
||||
{
|
||||
_clocks--;
|
||||
|
||||
// rotate disk
|
||||
while (_clocks > 0)
|
||||
{
|
||||
_clocks--;
|
||||
|
||||
// rotate disk
|
||||
if (_motorEnabled)
|
||||
{
|
||||
if (_disk == null)
|
||||
{
|
||||
_diskBitsLeft = 1;
|
||||
_diskBits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_diskBitsLeft <= 0)
|
||||
{
|
||||
_diskByteOffset++;
|
||||
if (_diskByteOffset == Disk.FluxEntriesPerTrack)
|
||||
{
|
||||
_diskByteOffset = 0;
|
||||
}
|
||||
_diskBits = _trackImageData[_diskByteOffset];
|
||||
_diskBitsLeft = Disk.FluxBitsPerEntry;
|
||||
}
|
||||
}
|
||||
if ((_diskBits & 1) != 0)
|
||||
{
|
||||
_countsBeforeRandomTransition = 0;
|
||||
_diskFluxReversalDetected = true;
|
||||
}
|
||||
_diskBits >>= 1;
|
||||
_diskBitsLeft--;
|
||||
}
|
||||
|
||||
// random flux transition readings for unformatted data
|
||||
if (_countsBeforeRandomTransition > 0)
|
||||
{
|
||||
_countsBeforeRandomTransition--;
|
||||
if (_countsBeforeRandomTransition == 0)
|
||||
{
|
||||
_diskFluxReversalDetected = true;
|
||||
AdvanceRng();
|
||||
// This constant is what VICE uses. TODO: Determine accuracy.
|
||||
_countsBeforeRandomTransition = (_rngCurrent % 367) + 33;
|
||||
}
|
||||
}
|
||||
|
||||
// flux transition circuitry
|
||||
if (_diskFluxReversalDetected)
|
||||
{
|
||||
_diskDensityCounter = _diskDensity;
|
||||
_diskSupplementaryCounter = 0;
|
||||
_diskFluxReversalDetected = false;
|
||||
if (_countsBeforeRandomTransition == 0)
|
||||
{
|
||||
if (_disk == null)
|
||||
{
|
||||
AdvanceRng();
|
||||
// This constant is what VICE uses. TODO: Determine accuracy.
|
||||
_countsBeforeRandomTransition = (_rngCurrent & 0x1F) + 289;
|
||||
}
|
||||
}
|
||||
|
||||
// counter circuitry
|
||||
if (_diskDensityCounter >= 16)
|
||||
{
|
||||
_diskDensityCounter = _diskDensity;
|
||||
_diskBitsLeft = 1;
|
||||
_diskBits = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_diskBitsLeft <= 0)
|
||||
{
|
||||
_diskByteOffset++;
|
||||
if (_diskByteOffset == Disk.FluxEntriesPerTrack)
|
||||
{
|
||||
_diskByteOffset = 0;
|
||||
}
|
||||
_diskBits = _trackImageData[_diskByteOffset];
|
||||
_diskBitsLeft = Disk.FluxBitsPerEntry;
|
||||
}
|
||||
}
|
||||
if ((_diskBits & 1) != 0)
|
||||
{
|
||||
_countsBeforeRandomTransition = 0;
|
||||
_diskFluxReversalDetected = true;
|
||||
}
|
||||
_diskBits >>= 1;
|
||||
_diskBitsLeft--;
|
||||
}
|
||||
|
||||
// random flux transition readings for unformatted data
|
||||
if (_countsBeforeRandomTransition > 0)
|
||||
{
|
||||
_countsBeforeRandomTransition--;
|
||||
if (_countsBeforeRandomTransition == 0)
|
||||
{
|
||||
_diskFluxReversalDetected = true;
|
||||
AdvanceRng();
|
||||
// This constant is what VICE uses. TODO: Determine accuracy.
|
||||
_countsBeforeRandomTransition = (_rngCurrent % 367) + 33;
|
||||
}
|
||||
}
|
||||
|
||||
// flux transition circuitry
|
||||
if (_diskFluxReversalDetected)
|
||||
{
|
||||
_diskDensityCounter = _diskDensity;
|
||||
_diskSupplementaryCounter = 0;
|
||||
_diskFluxReversalDetected = false;
|
||||
if (_countsBeforeRandomTransition == 0)
|
||||
{
|
||||
AdvanceRng();
|
||||
// This constant is what VICE uses. TODO: Determine accuracy.
|
||||
_countsBeforeRandomTransition = (_rngCurrent & 0x1F) + 289;
|
||||
}
|
||||
}
|
||||
|
||||
// counter circuitry
|
||||
if (_diskDensityCounter >= 16)
|
||||
{
|
||||
_diskDensityCounter = _diskDensity;
|
||||
_diskSupplementaryCounter++;
|
||||
if ((_diskSupplementaryCounter & 0x3) == 0x2)
|
||||
if ((_diskSupplementaryCounter & 0x3) == 0x2)
|
||||
{
|
||||
_bitsRemainingInLatchedByte--;
|
||||
_byteReady = false;
|
||||
|
@ -144,23 +144,23 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
|
|||
_overflowFlagDelaySr |= _diskCycle > 6 ? 4 : 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_diskSupplementaryCounter >= 16)
|
||||
{
|
||||
_diskSupplementaryCounter = 0;
|
||||
}
|
||||
|
||||
_cpuClocks--;
|
||||
if (_cpuClocks <= 0)
|
||||
{
|
||||
ExecuteSystem();
|
||||
_cpuClocks = 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (_diskSupplementaryCounter >= 16)
|
||||
{
|
||||
_diskSupplementaryCounter = 0;
|
||||
}
|
||||
|
||||
_cpuClocks--;
|
||||
if (_cpuClocks <= 0)
|
||||
{
|
||||
ExecuteSystem();
|
||||
_cpuClocks = 16;
|
||||
}
|
||||
|
||||
_diskDensityCounter++;
|
||||
_diskCycle = (_diskCycle + 1) & 0xF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_diskCycle = (_diskCycle + 1) & 0xF;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.User
|
||||
using System;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Computers.Commodore64.User
|
||||
{
|
||||
public sealed class UserPort
|
||||
{
|
||||
|
@ -9,67 +9,67 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.User
|
|||
public Func<bool> ReadCounter2;
|
||||
public Func<bool> ReadHandshake;
|
||||
public Func<bool> ReadSerial1;
|
||||
public Func<bool> ReadSerial2;
|
||||
|
||||
private bool _connected;
|
||||
private UserPortDevice _device;
|
||||
|
||||
public void Connect(UserPortDevice device)
|
||||
{
|
||||
_device = device;
|
||||
_connected = _device != null;
|
||||
if (_device != null)
|
||||
{
|
||||
_device.ReadCounter1 = () => ReadCounter1();
|
||||
_device.ReadCounter2 = () => ReadCounter2();
|
||||
_device.ReadHandshake = () => ReadHandshake();
|
||||
_device.ReadSerial1 = () => ReadSerial1();
|
||||
_device.ReadSerial2 = () => ReadSerial2();
|
||||
}
|
||||
}
|
||||
|
||||
public void Disconnect()
|
||||
{
|
||||
_connected = false;
|
||||
_device = null;
|
||||
}
|
||||
public Func<bool> ReadSerial2;
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
if (_connected)
|
||||
{
|
||||
_device.HardReset();
|
||||
private bool _connected;
|
||||
private UserPortDevice _device;
|
||||
|
||||
public void Connect(UserPortDevice device)
|
||||
{
|
||||
_device = device;
|
||||
_connected = _device != null;
|
||||
if (_device != null)
|
||||
{
|
||||
_device.ReadCounter1 = () => ReadCounter1();
|
||||
_device.ReadCounter2 = () => ReadCounter2();
|
||||
_device.ReadHandshake = () => ReadHandshake();
|
||||
_device.ReadSerial1 = () => ReadSerial1();
|
||||
_device.ReadSerial2 = () => ReadSerial2();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReadAtn()
|
||||
{
|
||||
return !_connected || _device.ReadAtn();
|
||||
public void Disconnect()
|
||||
{
|
||||
_connected = false;
|
||||
_device = null;
|
||||
}
|
||||
|
||||
public void HardReset()
|
||||
{
|
||||
if (_connected)
|
||||
{
|
||||
_device.HardReset();
|
||||
}
|
||||
}
|
||||
|
||||
public bool ReadAtn()
|
||||
{
|
||||
return !_connected || _device.ReadAtn();
|
||||
}
|
||||
|
||||
public int ReadData()
|
||||
{
|
||||
return !_connected ? 0xFF : _device.ReadData();
|
||||
return !_connected ? 0xFF : _device.ReadData();
|
||||
}
|
||||
|
||||
public bool ReadFlag2()
|
||||
{
|
||||
return !_connected || _device.ReadFlag2();
|
||||
return !_connected || _device.ReadFlag2();
|
||||
}
|
||||
|
||||
public bool ReadPa2()
|
||||
{
|
||||
return !_connected || _device.ReadPa2();
|
||||
return !_connected || _device.ReadPa2();
|
||||
}
|
||||
|
||||
public bool ReadReset()
|
||||
{
|
||||
return !_connected || _device.ReadReset();
|
||||
return !_connected || _device.ReadReset();
|
||||
}
|
||||
|
||||
public void SyncState(Serializer ser)
|
||||
{
|
||||
SaveState.SyncObject(ser, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,133 +1,133 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Intellivision
|
||||
{
|
||||
public sealed partial class Intellivision
|
||||
{
|
||||
internal IMemoryDomains MemoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
// TODO: is 8bit for byte arrays and 16bit for ushort correct here?
|
||||
// If ushort is correct, how about little endian?
|
||||
var domains = new List<MemoryDomain>
|
||||
{
|
||||
new MemoryDomainDelegate(
|
||||
"Main RAM",
|
||||
ScratchpadRam.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => ScratchpadRam[addr],
|
||||
(addr, value) => ScratchpadRam[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"Graphics RAM",
|
||||
GraphicsRam.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => GraphicsRam[addr],
|
||||
(addr, value) => GraphicsRam[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"Graphics ROM",
|
||||
GraphicsRom.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => GraphicsRom[addr],
|
||||
(addr, value) => GraphicsRom[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"System Ram",
|
||||
SystemRam.Length * 2,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => ReadByteFromShortArray(addr, SystemRam),
|
||||
(addr, value) => WriteByteToShortArray(addr, value, SystemRam),
|
||||
1
|
||||
),
|
||||
new MemoryDomainDelegate(
|
||||
"Executive Rom",
|
||||
ExecutiveRom.Length * 2,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => ReadByteFromShortArray(addr, ExecutiveRom),
|
||||
(addr, value) => WriteByteToShortArray(addr, value, ExecutiveRom),
|
||||
1
|
||||
),
|
||||
new MemoryDomainDelegate(
|
||||
"System Bus",
|
||||
0X20000,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => PeekSystemBus(addr),
|
||||
(addr, value) => PokeSystemBus(addr, value),
|
||||
1
|
||||
)
|
||||
};
|
||||
|
||||
MemoryDomains = new MemoryDomainList(domains);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
|
||||
}
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Intellivision
|
||||
{
|
||||
public sealed partial class Intellivision
|
||||
{
|
||||
internal IMemoryDomains MemoryDomains;
|
||||
|
||||
private void SetupMemoryDomains()
|
||||
{
|
||||
// TODO: is 8bit for byte arrays and 16bit for ushort correct here?
|
||||
// If ushort is correct, how about little endian?
|
||||
var domains = new List<MemoryDomain>
|
||||
{
|
||||
new MemoryDomainDelegate(
|
||||
"Main RAM",
|
||||
ScratchpadRam.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => ScratchpadRam[addr],
|
||||
(addr, value) => ScratchpadRam[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"Graphics RAM",
|
||||
GraphicsRam.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => GraphicsRam[addr],
|
||||
(addr, value) => GraphicsRam[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"Graphics ROM",
|
||||
GraphicsRom.Length,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => GraphicsRom[addr],
|
||||
(addr, value) => GraphicsRom[addr] = value,
|
||||
1),
|
||||
new MemoryDomainDelegate(
|
||||
"System Ram",
|
||||
SystemRam.Length * 2,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => ReadByteFromShortArray(addr, SystemRam),
|
||||
(addr, value) => WriteByteToShortArray(addr, value, SystemRam),
|
||||
1
|
||||
),
|
||||
new MemoryDomainDelegate(
|
||||
"Executive Rom",
|
||||
ExecutiveRom.Length * 2,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => ReadByteFromShortArray(addr, ExecutiveRom),
|
||||
(addr, value) => WriteByteToShortArray(addr, value, ExecutiveRom),
|
||||
1
|
||||
),
|
||||
new MemoryDomainDelegate(
|
||||
"System Bus",
|
||||
0X20000,
|
||||
MemoryDomain.Endian.Little,
|
||||
addr => PeekSystemBus(addr),
|
||||
(addr, value) => PokeSystemBus(addr, value),
|
||||
1
|
||||
)
|
||||
};
|
||||
|
||||
MemoryDomains = new MemoryDomainList(domains);
|
||||
(ServiceProvider as BasicServiceProvider).Register<IMemoryDomains>(MemoryDomains);
|
||||
}
|
||||
|
||||
private byte PeekSystemBus(long addr)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
long index = addr / 2;
|
||||
return (byte)(ReadMemory((ushort)index, true) >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
return (byte)(ReadMemory((ushort)index, true) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
return (byte)(ReadMemory((ushort)index, true) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
private void PokeSystemBus(long addr, byte value)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
long index = addr / 2;
|
||||
int temp = (ReadMemory((ushort)index, true) >> 8);
|
||||
WriteMemory((ushort)index, (ushort)(temp & (value << 8)), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
int temp = ((ReadMemory((ushort)index, true) & 0xFF)<<8);
|
||||
WriteMemory((ushort)index, (ushort)(temp & value), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
int temp = ((ReadMemory((ushort)index, true) & 0xFF)<<8);
|
||||
WriteMemory((ushort)index, (ushort)(temp & value), true);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move these to a common library and maybe add an endian parameter
|
||||
// Little endian
|
||||
private byte ReadByteFromShortArray(long addr, ushort[] array)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
long index = addr / 2;
|
||||
return (byte)(array[index] >> 8);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
return (byte)(array[index] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteByteToShortArray(long addr, byte value, ushort[] array)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
ushort val = (ushort)((value << 8) + (array[index] & 0xFF));
|
||||
array[index] = val;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = addr / 2;
|
||||
ushort val = (ushort)((((array[index] >> 8) & 0xFF) << 8) + value);
|
||||
array[index] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private byte ReadByteFromShortArray(long addr, ushort[] array)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
long index = addr / 2;
|
||||
return (byte)(array[index] >> 8);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
return (byte)(array[index] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteByteToShortArray(long addr, byte value, ushort[] array)
|
||||
{
|
||||
if (addr % 2 == 0)
|
||||
{
|
||||
long index = (addr - 1) / 2;
|
||||
ushort val = (ushort)((value << 8) + (array[index] & 0xFF));
|
||||
array[index] = val;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
long index = addr / 2;
|
||||
ushort val = (ushort)((((array[index] >> 8) & 0xFF) << 8) + value);
|
||||
array[index] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,60 +1,60 @@
|
|||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
// Adapted from Nestopia src
|
||||
public sealed class Mapper121 : MMC3Board_Base
|
||||
{
|
||||
private ByteBuffer exRegs = new ByteBuffer(3);
|
||||
|
||||
private readonly byte[] lut = { 0x00, 0x83, 0x42, 0x00 };
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER121":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
return true;
|
||||
}
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
// Adapted from Nestopia src
|
||||
public sealed class Mapper121 : MMC3Board_Base
|
||||
{
|
||||
private ByteBuffer exRegs = new ByteBuffer(3);
|
||||
|
||||
private readonly byte[] lut = { 0x00, 0x83, 0x42, 0x00 };
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER121":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
exRegs.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
base.SyncState(ser);
|
||||
ser.Sync("exRegs", ref exRegs);
|
||||
}
|
||||
|
||||
public override byte ReadEXP(int addr)
|
||||
{
|
||||
if (addr >= 0x1000)
|
||||
{
|
||||
return exRegs[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ReadEXP(addr);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteEXP(int addr, byte value)
|
||||
{
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
base.SyncState(ser);
|
||||
ser.Sync("exRegs", ref exRegs);
|
||||
}
|
||||
|
||||
public override byte ReadEXP(int addr)
|
||||
{
|
||||
if (addr >= 0x1000)
|
||||
{
|
||||
return exRegs[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ReadEXP(addr);
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteEXP(int addr, byte value)
|
||||
{
|
||||
if (addr >= 0x1000) // 0x5000-0x5FFF
|
||||
{
|
||||
exRegs[2] = lut[value & 0x3];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
exRegs[2] = lut[value & 0x3];
|
||||
}
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
int bank_8k = addr >> 13;
|
||||
|
@ -73,38 +73,38 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
bank_8k &= prg_mask;
|
||||
addr = (bank_8k << 13) | (addr & 0x1FFF);
|
||||
return ROM[addr];
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
{
|
||||
if ((addr & 3) == 3)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 0x28: exRegs[0] = 0x0C; break;
|
||||
case 0x26: exRegs[1] = 0x08; break;
|
||||
case 0xAB: exRegs[1] = 0x07; break;
|
||||
case 0xEC: exRegs[1] = 0x0D; break;
|
||||
case 0xEF: exRegs[1] = 0x0D; break;
|
||||
case 0xFF: exRegs[1] = 0x09; break;
|
||||
|
||||
case 0x20: exRegs[1] = 0x13; break;
|
||||
case 0x29: exRegs[1] = 0x1B; break;
|
||||
|
||||
default: exRegs[0] = 0x0; exRegs[1] = 0x0; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
{
|
||||
if ((addr & 3) == 3)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case 0x28: exRegs[0] = 0x0C; break;
|
||||
case 0x26: exRegs[1] = 0x08; break;
|
||||
case 0xAB: exRegs[1] = 0x07; break;
|
||||
case 0xEC: exRegs[1] = 0x0D; break;
|
||||
case 0xEF: exRegs[1] = 0x0D; break;
|
||||
case 0xFF: exRegs[1] = 0x09; break;
|
||||
|
||||
case 0x20: exRegs[1] = 0x13; break;
|
||||
case 0x29: exRegs[1] = 0x1B; break;
|
||||
|
||||
default: exRegs[0] = 0x0; exRegs[1] = 0x0; break;
|
||||
}
|
||||
}
|
||||
else if ((addr & 1)>0)
|
||||
base.WritePRG(addr, value);
|
||||
else //if (addr==0)
|
||||
base.WritePRG(0, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.WritePRG(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
base.WritePRG(addr, value);
|
||||
else //if (addr==0)
|
||||
base.WritePRG(0, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
base.WritePRG(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public sealed class Mapper219 : MMC3Board_Base
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public sealed class Mapper219 : MMC3Board_Base
|
||||
{
|
||||
public byte[] exregs = new byte[3];
|
||||
public byte[] prgregs = new byte[4];
|
||||
|
@ -8,22 +8,22 @@
|
|||
|
||||
public byte bits_rev, reg_value;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER219":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
|
||||
prgregs[1] = 1;
|
||||
prgregs[2] = 2;
|
||||
prgregs[3] = 3;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER219":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
|
||||
prgregs[1] = 1;
|
||||
prgregs[2] = 2;
|
||||
prgregs[3] = 3;
|
||||
|
||||
byte r0_0 = (byte)(0 & ~1);
|
||||
byte r0_1 = (byte)(0 | 1);
|
||||
byte r1_0 = (byte)(2 & ~1);
|
||||
|
@ -46,11 +46,11 @@
|
|||
chr_regs_1k[4] = regs[2];
|
||||
chr_regs_1k[5] = regs[3];
|
||||
chr_regs_1k[6] = regs[4];
|
||||
chr_regs_1k[7] = regs[5];*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
chr_regs_1k[7] = regs[5];*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
if (addr<0x2000)
|
||||
|
@ -103,8 +103,8 @@
|
|||
}
|
||||
else
|
||||
base.WritePRG(addr, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
int bank_prg = addr >> 13;
|
||||
|
@ -122,8 +122,8 @@
|
|||
}
|
||||
else
|
||||
return base.ReadPPU(addr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void WritePPU(int addr, byte value)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
|
@ -134,6 +134,6 @@
|
|||
}
|
||||
else
|
||||
base.WritePPU(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
// TODO
|
||||
public sealed class Mapper223 : MMC3Board_Base
|
||||
{
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER223":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
// TODO
|
||||
public sealed class Mapper223 : MMC3Board_Base
|
||||
{
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER223":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
BaseSetup();
|
||||
|
||||
mmc3.wram_enable = true;
|
||||
mmc3.wram_write_protect = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
mmc3.wram_write_protect = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void WriteEXP(int addr, byte value)
|
||||
{
|
||||
if (addr>0x1000)
|
||||
|
@ -30,8 +30,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
else
|
||||
base.WriteEXP(addr, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override byte ReadEXP(int addr)
|
||||
{
|
||||
if (addr > 0x1000)
|
||||
|
@ -40,6 +40,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
}
|
||||
else
|
||||
return base.ReadEXP(addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,72 +1,72 @@
|
|||
using BizHawk.Common;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public sealed class Mapper125 : NES.NESBoardBase
|
||||
{
|
||||
private byte reg;
|
||||
private int prg_bank_mask_8k;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER125":
|
||||
case "UNIF_UNL-LH32":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
SetMirrorType(Cart.pad_h, Cart.pad_v);
|
||||
|
||||
prg_bank_mask_8k = Cart.prg_size / 8 - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
ser.Sync("reg", ref reg);
|
||||
base.SyncState(ser);
|
||||
}
|
||||
|
||||
public override void WriteWRAM(int addr, byte value)
|
||||
{
|
||||
if (addr == 0)
|
||||
{
|
||||
reg = value;
|
||||
}
|
||||
}
|
||||
|
||||
using BizHawk.Common;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public sealed class Mapper125 : NES.NESBoardBase
|
||||
{
|
||||
private byte reg;
|
||||
private int prg_bank_mask_8k;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER125":
|
||||
case "UNIF_UNL-LH32":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
SetMirrorType(Cart.pad_h, Cart.pad_v);
|
||||
|
||||
prg_bank_mask_8k = Cart.prg_size / 8 - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
ser.Sync("reg", ref reg);
|
||||
base.SyncState(ser);
|
||||
}
|
||||
|
||||
public override void WriteWRAM(int addr, byte value)
|
||||
{
|
||||
if (addr == 0)
|
||||
{
|
||||
reg = value;
|
||||
}
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
if ((addr >= 0x4000) && (addr < 0x6000))
|
||||
WRAM[addr - 0x4000] = value;
|
||||
else
|
||||
base.WritePRG(addr, value);
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
int bank = 0;
|
||||
if (addr < 0x2000) { bank = prg_bank_mask_8k - 3; }
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
int bank = 0;
|
||||
if (addr < 0x2000) { bank = prg_bank_mask_8k - 3; }
|
||||
else if (addr < 0x4000) { bank = prg_bank_mask_8k - 2; }
|
||||
// for some reason WRAM is mapped to here.
|
||||
else if (addr < 0x6000)
|
||||
{
|
||||
return WRAM[addr - 0x4000];
|
||||
}
|
||||
else { bank = prg_bank_mask_8k; }
|
||||
|
||||
bank &= prg_bank_mask_8k;
|
||||
return ROM[(bank << 13) + (addr & 0x1FFF)];
|
||||
}
|
||||
|
||||
public override byte ReadWRAM(int addr)
|
||||
{
|
||||
return ROM[((reg & prg_bank_mask_8k) << 13) + addr];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { bank = prg_bank_mask_8k; }
|
||||
|
||||
bank &= prg_bank_mask_8k;
|
||||
return ROM[(bank << 13) + (addr & 0x1FFF)];
|
||||
}
|
||||
|
||||
public override byte ReadWRAM(int addr)
|
||||
{
|
||||
return ROM[((reg & prg_bank_mask_8k) << 13) + addr];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,128 +1,128 @@
|
|||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public sealed class Mapper142 : NES.NESBoardBase
|
||||
{
|
||||
private ByteBuffer reg = new ByteBuffer(8);
|
||||
private byte cmd;
|
||||
private int lastBank;
|
||||
|
||||
private bool isirqused = false;
|
||||
private byte IRQa = 0;
|
||||
private int IRQCount = 0;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER142":
|
||||
case "UNIF_UNL-KS7032":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
SetMirrorType(EMirrorType.Horizontal);
|
||||
lastBank = Cart.prg_size / 8 - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public sealed class Mapper142 : NES.NESBoardBase
|
||||
{
|
||||
private ByteBuffer reg = new ByteBuffer(8);
|
||||
private byte cmd;
|
||||
private int lastBank;
|
||||
|
||||
private bool isirqused = false;
|
||||
private byte IRQa = 0;
|
||||
private int IRQCount = 0;
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER142":
|
||||
case "UNIF_UNL-KS7032":
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
SetMirrorType(EMirrorType.Horizontal);
|
||||
lastBank = Cart.prg_size / 8 - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
reg.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public override byte ReadWRAM(int addr)
|
||||
}
|
||||
|
||||
public override byte ReadWRAM(int addr)
|
||||
{
|
||||
return ROM[(reg[4] << 13) + (addr & 0x1FFF)];
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
return ROM[(reg[4] << 13) + (addr & 0x1FFF)];
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
|
||||
if (addr < 0x2000) { return ROM[(reg[1] << 13) + (addr & 0x1FFF)]; }
|
||||
if (addr < 0x4000) { return ROM[(reg[2] << 13) + (addr & 0x1FFF)]; }
|
||||
if (addr < 0x6000) { return ROM[(reg[3] << 13) + (addr & 0x1FFF)]; }
|
||||
|
||||
return ROM[(lastBank << 13) + (addr & 0x1FFF)];
|
||||
}
|
||||
|
||||
public override void WriteEXP(int addr, byte value)
|
||||
{
|
||||
Write(addr + 0x4000, value);
|
||||
}
|
||||
|
||||
public override void WriteWRAM(int addr, byte value)
|
||||
{
|
||||
Write(addr + 0x6000, value);
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
Write(addr + 0x8000, value);
|
||||
}
|
||||
|
||||
private void IRQHook(int a)
|
||||
{
|
||||
if (IRQa > 0)
|
||||
{
|
||||
IRQCount += a;
|
||||
if (IRQCount >= 0xFFFF)
|
||||
{
|
||||
IRQa = 0;
|
||||
IRQCount = 0;
|
||||
|
||||
IRQSignal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClockPPU()
|
||||
{
|
||||
IRQHook(1);
|
||||
}
|
||||
|
||||
private void Write(int addr, byte value)
|
||||
{
|
||||
switch (addr & 0xF000)
|
||||
{
|
||||
case 0x8000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0x000F) | (value & 0x0F);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0x9000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0x00F0) | ((value & 0x0F) << 4);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0xA000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0x0F00) | ((value & 0x0F) << 8);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0xB000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0xF000) | (value << 12);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0xC000:
|
||||
if (isirqused)
|
||||
{
|
||||
IRQSignal = false;
|
||||
IRQa = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE000:
|
||||
cmd = (byte)(value & 7);
|
||||
break;
|
||||
case 0xF000:
|
||||
reg[cmd] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ROM[(lastBank << 13) + (addr & 0x1FFF)];
|
||||
}
|
||||
|
||||
public override void WriteEXP(int addr, byte value)
|
||||
{
|
||||
Write(addr + 0x4000, value);
|
||||
}
|
||||
|
||||
public override void WriteWRAM(int addr, byte value)
|
||||
{
|
||||
Write(addr + 0x6000, value);
|
||||
}
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
Write(addr + 0x8000, value);
|
||||
}
|
||||
|
||||
private void IRQHook(int a)
|
||||
{
|
||||
if (IRQa > 0)
|
||||
{
|
||||
IRQCount += a;
|
||||
if (IRQCount >= 0xFFFF)
|
||||
{
|
||||
IRQa = 0;
|
||||
IRQCount = 0;
|
||||
|
||||
IRQSignal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void ClockPPU()
|
||||
{
|
||||
IRQHook(1);
|
||||
}
|
||||
|
||||
private void Write(int addr, byte value)
|
||||
{
|
||||
switch (addr & 0xF000)
|
||||
{
|
||||
case 0x8000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0x000F) | (value & 0x0F);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0x9000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0x00F0) | ((value & 0x0F) << 4);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0xA000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0x0F00) | ((value & 0x0F) << 8);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0xB000:
|
||||
IRQSignal = false;
|
||||
IRQCount = (IRQCount & 0xF000) | (value << 12);
|
||||
isirqused = true;
|
||||
break;
|
||||
case 0xC000:
|
||||
if (isirqused)
|
||||
{
|
||||
IRQSignal = false;
|
||||
IRQa = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xE000:
|
||||
cmd = (byte)(value & 7);
|
||||
break;
|
||||
case 0xF000:
|
||||
reg[cmd] = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES
|
|||
static readonly float[] hi_levels = { 0.40f, 0.68f, 1.00f, 1.00f };
|
||||
static readonly byte[] tints = { 0, 6, 10, 8, 2, 4, 0, 0 };
|
||||
|
||||
static readonly float[] phases =
|
||||
{
|
||||
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||
1.0f, 0.866025f, 0.5f, 0.0f, -0.5f, -0.866025f,
|
||||
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||
1.0f
|
||||
static readonly float[] phases =
|
||||
{
|
||||
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||
1.0f, 0.866025f, 0.5f, 0.0f, -0.5f, -0.866025f,
|
||||
-1.0f, -0.866025f, -0.5f, 0.0f, 0.5f, 0.866025f,
|
||||
1.0f
|
||||
};
|
||||
|
||||
public static void Emphasis(byte[] inp, byte[] outp, int entrynum)
|
||||
|
|
|
@ -1,278 +1,278 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
||||
{
|
||||
public partial class GPGX : ISettable<GPGX.GPGXSettings, GPGX.GPGXSyncSettings>
|
||||
{
|
||||
public GPGXSettings GetSettings()
|
||||
{
|
||||
return _settings.Clone();
|
||||
}
|
||||
|
||||
public GPGXSyncSettings GetSyncSettings()
|
||||
{
|
||||
return _syncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(GPGXSettings o)
|
||||
{
|
||||
bool ret = GPGXSettings.NeedsReboot(_settings, o);
|
||||
_settings = o;
|
||||
LibGPGX.gpgx_set_draw_mask(_settings.GetDrawMask());
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(GPGXSyncSettings o)
|
||||
{
|
||||
bool ret = GPGXSyncSettings.NeedsReboot(_syncSettings, o);
|
||||
_syncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private class UintToHexConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string) && value.GetType() == typeof(uint))
|
||||
{
|
||||
return string.Format("0x{0:x8}", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value.GetType() == typeof(string))
|
||||
{
|
||||
string input = (string)value;
|
||||
if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
input = input.Substring(2);
|
||||
}
|
||||
return uint.Parse(input, NumberStyles.HexNumber, culture);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GPGXSyncSettings _syncSettings;
|
||||
private GPGXSettings _settings;
|
||||
|
||||
public class GPGXSettings
|
||||
{
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawBGA;
|
||||
|
||||
[DisplayName("Background Layer A")]
|
||||
[Description("True to draw BG layer A")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawBGA { get { return _DrawBGA; } set { _DrawBGA = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawBGB;
|
||||
|
||||
[DisplayName("Background Layer B")]
|
||||
[Description("True to draw BG layer B")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawBGB { get { return _DrawBGB; } set { _DrawBGB = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawBGW;
|
||||
|
||||
[DisplayName("Background Layer W")]
|
||||
[Description("True to draw BG layer W")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawBGW { get { return _DrawBGW; } set { _DrawBGW = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawObj;
|
||||
|
||||
[DisplayName("Sprite Layer")]
|
||||
[Description("True to draw sprite layer")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawObj { get { return _DrawObj; } set { _DrawObj = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
||||
{
|
||||
public partial class GPGX : ISettable<GPGX.GPGXSettings, GPGX.GPGXSyncSettings>
|
||||
{
|
||||
public GPGXSettings GetSettings()
|
||||
{
|
||||
return _settings.Clone();
|
||||
}
|
||||
|
||||
public GPGXSyncSettings GetSyncSettings()
|
||||
{
|
||||
return _syncSettings.Clone();
|
||||
}
|
||||
|
||||
public bool PutSettings(GPGXSettings o)
|
||||
{
|
||||
bool ret = GPGXSettings.NeedsReboot(_settings, o);
|
||||
_settings = o;
|
||||
LibGPGX.gpgx_set_draw_mask(_settings.GetDrawMask());
|
||||
return ret;
|
||||
}
|
||||
|
||||
public bool PutSyncSettings(GPGXSyncSettings o)
|
||||
{
|
||||
bool ret = GPGXSyncSettings.NeedsReboot(_syncSettings, o);
|
||||
_syncSettings = o;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private class UintToHexConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(string) && value.GetType() == typeof(uint))
|
||||
{
|
||||
return string.Format("0x{0:x8}", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value.GetType() == typeof(string))
|
||||
{
|
||||
string input = (string)value;
|
||||
if (input.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
input = input.Substring(2);
|
||||
}
|
||||
return uint.Parse(input, NumberStyles.HexNumber, culture);
|
||||
}
|
||||
else
|
||||
{
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GPGXSyncSettings _syncSettings;
|
||||
private GPGXSettings _settings;
|
||||
|
||||
public class GPGXSettings
|
||||
{
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawBGA;
|
||||
|
||||
[DisplayName("Background Layer A")]
|
||||
[Description("True to draw BG layer A")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawBGA { get { return _DrawBGA; } set { _DrawBGA = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawBGB;
|
||||
|
||||
[DisplayName("Background Layer B")]
|
||||
[Description("True to draw BG layer B")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawBGB { get { return _DrawBGB; } set { _DrawBGB = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawBGW;
|
||||
|
||||
[DisplayName("Background Layer W")]
|
||||
[Description("True to draw BG layer W")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawBGW { get { return _DrawBGW; } set { _DrawBGW = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _DrawObj;
|
||||
|
||||
[DisplayName("Sprite Layer")]
|
||||
[Description("True to draw sprite layer")]
|
||||
[DefaultValue(true)]
|
||||
public bool DrawObj { get { return _DrawObj; } set { _DrawObj = value; } }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _PadScreen320;
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _AlwaysDoubleSize;
|
||||
|
||||
[DisplayName("Pad screen to 320")]
|
||||
[Description("Set to True to pad the screen out to be 320 when in 256 wide video modes")]
|
||||
[DefaultValue(false)]
|
||||
private bool _AlwaysDoubleSize;
|
||||
|
||||
[DisplayName("Pad screen to 320")]
|
||||
[Description("Set to True to pad the screen out to be 320 when in 256 wide video modes")]
|
||||
[DefaultValue(false)]
|
||||
public bool PadScreen320 { get { return _PadScreen320; } set { _PadScreen320 = value; } }
|
||||
|
||||
[DisplayName("Always double-size")]
|
||||
[Description("Set to True to convert the video to high-resolution mode even when it's low resolution so that the window doesn't change size between game modes")]
|
||||
[DefaultValue(false)]
|
||||
public bool AlwaysDoubleSize { get { return _AlwaysDoubleSize; } set { _AlwaysDoubleSize = value; } }
|
||||
|
||||
[DisplayName("Audio Filter")]
|
||||
[DefaultValue(LibGPGX.InitSettings.FilterType.LowPass)]
|
||||
public LibGPGX.InitSettings.FilterType Filter { get; set; }
|
||||
|
||||
[DisplayName("Low Pass Range")]
|
||||
[Description("Only active when filter type is lowpass")]
|
||||
[DefaultValue((ushort)39321)]
|
||||
public ushort LowPassRange { get; set; }
|
||||
|
||||
[DisplayName("Three band low cutoff")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)880)]
|
||||
public short LowFreq { get; set; }
|
||||
|
||||
[DisplayName("Three band high cutoff")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)5000)]
|
||||
public short HighFreq { get; set; }
|
||||
|
||||
[DisplayName("Three band low gain")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)1)]
|
||||
public short LowGain { get; set; }
|
||||
|
||||
[DisplayName("Three band mid gain")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)1)]
|
||||
public short MidGain { get; set; }
|
||||
|
||||
[DisplayName("Three band high gain")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)1)]
|
||||
public short HighGain { get; set; }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _Backdrop;
|
||||
|
||||
[DisplayName("Use custom backdrop color")]
|
||||
[Description("Filler when layers are off")]
|
||||
[DefaultValue((bool)false)]
|
||||
public bool Backdrop { get { return _Backdrop; } set { _Backdrop = value; } }
|
||||
|
||||
[DisplayName("Custom backdrop color")]
|
||||
[Description("Magic pink by default. Requires core reboot")]
|
||||
[TypeConverter(typeof(UintToHexConverter))]
|
||||
[DefaultValue((uint)0xffff00ff)]
|
||||
public uint BackdropColor { get; set; }
|
||||
|
||||
public GPGXSettings()
|
||||
{
|
||||
SettingsUtil.SetDefaultValues(this);
|
||||
}
|
||||
|
||||
public GPGXSettings Clone()
|
||||
{
|
||||
return (GPGXSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public LibGPGX.DrawMask GetDrawMask()
|
||||
{
|
||||
LibGPGX.DrawMask ret = 0;
|
||||
if (DrawBGA) ret |= LibGPGX.DrawMask.BGA;
|
||||
if (DrawBGB) ret |= LibGPGX.DrawMask.BGB;
|
||||
if (DrawBGW) ret |= LibGPGX.DrawMask.BGW;
|
||||
if (DrawObj) ret |= LibGPGX.DrawMask.Obj;
|
||||
if (Backdrop) ret |= LibGPGX.DrawMask.Backdrop;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(GPGXSettings x, GPGXSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
|
||||
public LibGPGX.InitSettings GetNativeSettings()
|
||||
{
|
||||
return new LibGPGX.InitSettings
|
||||
{
|
||||
Filter = Filter,
|
||||
LowPassRange = LowPassRange,
|
||||
LowFreq = LowFreq,
|
||||
HighFreq = HighFreq,
|
||||
LowGain = LowGain,
|
||||
MidGain = MidGain,
|
||||
HighGain = HighGain,
|
||||
BackdropColor = BackdropColor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class GPGXSyncSettings
|
||||
{
|
||||
[DisplayName("Use Six Button Controllers")]
|
||||
[Description("Controls the type of any attached normal controllers; six button controllers are used if true, otherwise three button controllers. Some games don't work correctly with six button controllers. Not relevant if other controller types are connected.")]
|
||||
[DefaultValue(true)]
|
||||
public bool UseSixButton { get; set; }
|
||||
|
||||
[DisplayName("Control Type")]
|
||||
[Description("Sets the type of controls that are plugged into the console. Some games will automatically load with a different control type.")]
|
||||
[DefaultValue(ControlType.Normal)]
|
||||
public ControlType ControlType { get; set; }
|
||||
|
||||
[DisplayName("Autodetect Region")]
|
||||
[Description("Sets the region of the emulated console. Many games can run on multiple regions and will behave differently on different ones. Some games may require a particular region.")]
|
||||
[DefaultValue(LibGPGX.Region.Autodetect)]
|
||||
public LibGPGX.Region Region { get; set; }
|
||||
|
||||
public GPGXSyncSettings()
|
||||
{
|
||||
SettingsUtil.SetDefaultValues(this);
|
||||
}
|
||||
|
||||
public GPGXSyncSettings Clone()
|
||||
{
|
||||
return (GPGXSyncSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(GPGXSyncSettings x, GPGXSyncSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool AlwaysDoubleSize { get { return _AlwaysDoubleSize; } set { _AlwaysDoubleSize = value; } }
|
||||
|
||||
[DisplayName("Audio Filter")]
|
||||
[DefaultValue(LibGPGX.InitSettings.FilterType.LowPass)]
|
||||
public LibGPGX.InitSettings.FilterType Filter { get; set; }
|
||||
|
||||
[DisplayName("Low Pass Range")]
|
||||
[Description("Only active when filter type is lowpass")]
|
||||
[DefaultValue((ushort)39321)]
|
||||
public ushort LowPassRange { get; set; }
|
||||
|
||||
[DisplayName("Three band low cutoff")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)880)]
|
||||
public short LowFreq { get; set; }
|
||||
|
||||
[DisplayName("Three band high cutoff")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)5000)]
|
||||
public short HighFreq { get; set; }
|
||||
|
||||
[DisplayName("Three band low gain")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)1)]
|
||||
public short LowGain { get; set; }
|
||||
|
||||
[DisplayName("Three band mid gain")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)1)]
|
||||
public short MidGain { get; set; }
|
||||
|
||||
[DisplayName("Three band high gain")]
|
||||
[Description("Only active when filter type is three band")]
|
||||
[DefaultValue((short)1)]
|
||||
public short HighGain { get; set; }
|
||||
|
||||
[DeepEqualsIgnore]
|
||||
[JsonIgnore]
|
||||
private bool _Backdrop;
|
||||
|
||||
[DisplayName("Use custom backdrop color")]
|
||||
[Description("Filler when layers are off")]
|
||||
[DefaultValue((bool)false)]
|
||||
public bool Backdrop { get { return _Backdrop; } set { _Backdrop = value; } }
|
||||
|
||||
[DisplayName("Custom backdrop color")]
|
||||
[Description("Magic pink by default. Requires core reboot")]
|
||||
[TypeConverter(typeof(UintToHexConverter))]
|
||||
[DefaultValue((uint)0xffff00ff)]
|
||||
public uint BackdropColor { get; set; }
|
||||
|
||||
public GPGXSettings()
|
||||
{
|
||||
SettingsUtil.SetDefaultValues(this);
|
||||
}
|
||||
|
||||
public GPGXSettings Clone()
|
||||
{
|
||||
return (GPGXSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public LibGPGX.DrawMask GetDrawMask()
|
||||
{
|
||||
LibGPGX.DrawMask ret = 0;
|
||||
if (DrawBGA) ret |= LibGPGX.DrawMask.BGA;
|
||||
if (DrawBGB) ret |= LibGPGX.DrawMask.BGB;
|
||||
if (DrawBGW) ret |= LibGPGX.DrawMask.BGW;
|
||||
if (DrawObj) ret |= LibGPGX.DrawMask.Obj;
|
||||
if (Backdrop) ret |= LibGPGX.DrawMask.Backdrop;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(GPGXSettings x, GPGXSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
|
||||
public LibGPGX.InitSettings GetNativeSettings()
|
||||
{
|
||||
return new LibGPGX.InitSettings
|
||||
{
|
||||
Filter = Filter,
|
||||
LowPassRange = LowPassRange,
|
||||
LowFreq = LowFreq,
|
||||
HighFreq = HighFreq,
|
||||
LowGain = LowGain,
|
||||
MidGain = MidGain,
|
||||
HighGain = HighGain,
|
||||
BackdropColor = BackdropColor
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class GPGXSyncSettings
|
||||
{
|
||||
[DisplayName("Use Six Button Controllers")]
|
||||
[Description("Controls the type of any attached normal controllers; six button controllers are used if true, otherwise three button controllers. Some games don't work correctly with six button controllers. Not relevant if other controller types are connected.")]
|
||||
[DefaultValue(true)]
|
||||
public bool UseSixButton { get; set; }
|
||||
|
||||
[DisplayName("Control Type")]
|
||||
[Description("Sets the type of controls that are plugged into the console. Some games will automatically load with a different control type.")]
|
||||
[DefaultValue(ControlType.Normal)]
|
||||
public ControlType ControlType { get; set; }
|
||||
|
||||
[DisplayName("Autodetect Region")]
|
||||
[Description("Sets the region of the emulated console. Many games can run on multiple regions and will behave differently on different ones. Some games may require a particular region.")]
|
||||
[DefaultValue(LibGPGX.Region.Autodetect)]
|
||||
public LibGPGX.Region Region { get; set; }
|
||||
|
||||
public GPGXSyncSettings()
|
||||
{
|
||||
SettingsUtil.SetDefaultValues(this);
|
||||
}
|
||||
|
||||
public GPGXSyncSettings Clone()
|
||||
{
|
||||
return (GPGXSyncSettings)MemberwiseClone();
|
||||
}
|
||||
|
||||
public static bool NeedsReboot(GPGXSyncSettings x, GPGXSyncSettings y)
|
||||
{
|
||||
return !DeepEquality.DeepEquals(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,54 +1,54 @@
|
|||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
||||
{
|
||||
public partial class GPGX : IVideoProvider
|
||||
{
|
||||
public int[] GetVideoBuffer() { return vidbuff; }
|
||||
|
||||
public int VirtualWidth { get { return 320; } }
|
||||
|
||||
public int VirtualHeight { get { return 224; } }
|
||||
|
||||
public int BufferWidth { get { return vwidth; } }
|
||||
|
||||
public int BufferHeight { get { return vheight; } }
|
||||
|
||||
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
||||
|
||||
private int[] vidbuff = new int[0];
|
||||
private int vwidth;
|
||||
private int vheight;
|
||||
|
||||
private void UpdateVideoInitial()
|
||||
{
|
||||
// hack: you should call update_video() here, but that gives you 256x192 on frame 0
|
||||
// and we know that we only use GPGX to emulate genesis games that will always be 320x224 immediately afterwards
|
||||
|
||||
// so instead, just assume a 320x224 size now; if that happens to be wrong, it'll be fixed soon enough.
|
||||
|
||||
vwidth = 320;
|
||||
vheight = 224;
|
||||
vidbuff = new int[vwidth * vheight];
|
||||
for (int i = 0; i < vidbuff.Length; i++)
|
||||
vidbuff[i] = unchecked((int)0xff000000);
|
||||
}
|
||||
|
||||
private unsafe void UpdateVideo()
|
||||
{
|
||||
int gppitch, gpwidth, gpheight;
|
||||
IntPtr src = IntPtr.Zero;
|
||||
|
||||
LibGPGX.gpgx_get_video(out gpwidth, out gpheight, out gppitch, ref src);
|
||||
|
||||
//in case we're receiving high vertical resolution video, we shall double the horizontal resolution to keep the same proportions
|
||||
//(concept pioneered for snes)
|
||||
|
||||
using System;
|
||||
using BizHawk.Emulation.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
||||
{
|
||||
public partial class GPGX : IVideoProvider
|
||||
{
|
||||
public int[] GetVideoBuffer() { return vidbuff; }
|
||||
|
||||
public int VirtualWidth { get { return 320; } }
|
||||
|
||||
public int VirtualHeight { get { return 224; } }
|
||||
|
||||
public int BufferWidth { get { return vwidth; } }
|
||||
|
||||
public int BufferHeight { get { return vheight; } }
|
||||
|
||||
public int BackgroundColor { get { return unchecked((int)0xff000000); } }
|
||||
|
||||
private int[] vidbuff = new int[0];
|
||||
private int vwidth;
|
||||
private int vheight;
|
||||
|
||||
private void UpdateVideoInitial()
|
||||
{
|
||||
// hack: you should call update_video() here, but that gives you 256x192 on frame 0
|
||||
// and we know that we only use GPGX to emulate genesis games that will always be 320x224 immediately afterwards
|
||||
|
||||
// so instead, just assume a 320x224 size now; if that happens to be wrong, it'll be fixed soon enough.
|
||||
|
||||
vwidth = 320;
|
||||
vheight = 224;
|
||||
vidbuff = new int[vwidth * vheight];
|
||||
for (int i = 0; i < vidbuff.Length; i++)
|
||||
vidbuff[i] = unchecked((int)0xff000000);
|
||||
}
|
||||
|
||||
private unsafe void UpdateVideo()
|
||||
{
|
||||
int gppitch, gpwidth, gpheight;
|
||||
IntPtr src = IntPtr.Zero;
|
||||
|
||||
LibGPGX.gpgx_get_video(out gpwidth, out gpheight, out gppitch, ref src);
|
||||
|
||||
//in case we're receiving high vertical resolution video, we shall double the horizontal resolution to keep the same proportions
|
||||
//(concept pioneered for snes)
|
||||
|
||||
bool dotDouble = (gpheight == 448); //todo: pal?
|
||||
bool lineDouble = false;
|
||||
|
||||
vwidth = gpwidth;
|
||||
vwidth = gpwidth;
|
||||
vheight = gpheight;
|
||||
|
||||
if (_settings.AlwaysDoubleSize)
|
||||
|
@ -61,15 +61,15 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
}
|
||||
}
|
||||
|
||||
if (_settings.PadScreen320 && vwidth == 256)
|
||||
if (_settings.PadScreen320 && vwidth == 256)
|
||||
vwidth = 320;
|
||||
|
||||
int xpad = (vwidth - gpwidth) / 2;
|
||||
int xpad = (vwidth - gpwidth) / 2;
|
||||
int xpad2 = vwidth - gpwidth - xpad;
|
||||
|
||||
if (dotDouble) vwidth *= 2;
|
||||
|
||||
if (vidbuff.Length < vwidth * vheight)
|
||||
|
||||
if (vidbuff.Length < vwidth * vheight)
|
||||
vidbuff = new int[vwidth * vheight];
|
||||
|
||||
int xskip = 1;
|
||||
|
@ -112,8 +112,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx
|
|||
psrc += rinc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,48 +1,48 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sony.PSX
|
||||
{
|
||||
public partial class Octoshock
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Common.NumberExtensions;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Sony.PSX
|
||||
{
|
||||
public partial class Octoshock
|
||||
{
|
||||
public TraceBuffer Tracer { get; private set; }
|
||||
|
||||
public static string TraceHeader = "R3000A: PC, machine code, mnemonic, operands, registers (GPRs, lo, hi, sr, cause, epc)";
|
||||
|
||||
OctoshockDll.ShockCallback_Trace trace_cb;
|
||||
|
||||
public void ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis)
|
||||
{
|
||||
var regs = GetCpuFlagsAndRegisters();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
foreach (var r in regs)
|
||||
{
|
||||
if (r.Key != "pc")
|
||||
sb.Append(
|
||||
string.Format("{0}:{1} ",
|
||||
r.Key,
|
||||
r.Value.Value.ToHexString(r.Value.BitSize / 4)));
|
||||
|
||||
public void ShockTraceCallback(IntPtr opaque, uint PC, uint inst, string dis)
|
||||
{
|
||||
var regs = GetCpuFlagsAndRegisters();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
foreach (var r in regs)
|
||||
{
|
||||
if (r.Key != "pc")
|
||||
sb.Append(
|
||||
string.Format("{0}:{1} ",
|
||||
r.Key,
|
||||
r.Value.Value.ToHexString(r.Value.BitSize / 4)));
|
||||
}
|
||||
|
||||
Tracer.Put(new TraceInfo
|
||||
{
|
||||
Disassembly = string.Format("{0:X8}: {1:X8} {2}", PC, inst, dis.PadRight(30)),
|
||||
RegisterInfo = sb.ToString().Trim()
|
||||
});
|
||||
}
|
||||
|
||||
Tracer.Put(new TraceInfo
|
||||
{
|
||||
Disassembly = string.Format("{0:X8}: {1:X8} {2}", PC, inst, dis.PadRight(30)),
|
||||
RegisterInfo = sb.ToString().Trim()
|
||||
});
|
||||
}
|
||||
|
||||
private void ConnectTracer()
|
||||
{
|
||||
trace_cb = new OctoshockDll.ShockCallback_Trace(ShockTraceCallback);
|
||||
Tracer = new TraceBuffer() { Header = TraceHeader };
|
||||
ServiceProvider = new BasicServiceProvider(this);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
|
||||
}
|
||||
}
|
||||
}
|
||||
trace_cb = new OctoshockDll.ShockCallback_Trace(ShockTraceCallback);
|
||||
Tracer = new TraceBuffer() { Header = TraceHeader };
|
||||
ServiceProvider = new BasicServiceProvider(this);
|
||||
(ServiceProvider as BasicServiceProvider).Register<ITraceable>(Tracer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,114 +1,114 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
//todo - be able to run out of PATH too
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL
|
||||
{
|
||||
public class CGC
|
||||
{
|
||||
public CGC()
|
||||
{
|
||||
}
|
||||
|
||||
public static string CGCBinPath;
|
||||
|
||||
private static string[] Escape(IEnumerable<string> args)
|
||||
{
|
||||
return args.Select(s => s.Contains(" ") ? string.Format("\"{0}\"", s) : s).ToArray();
|
||||
}
|
||||
|
||||
public class Results
|
||||
{
|
||||
public bool Succeeded;
|
||||
public string Code, Errors;
|
||||
public Dictionary<string, string> MapCodeToNative = new Dictionary<string, string>();
|
||||
public Dictionary<string, string> MapNativeToCode = new Dictionary<string, string>();
|
||||
using System.Threading;
|
||||
using System.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
//todo - be able to run out of PATH too
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL
|
||||
{
|
||||
public class CGC
|
||||
{
|
||||
public CGC()
|
||||
{
|
||||
}
|
||||
|
||||
Regex rxHlslSamplerCrashWorkaround = new Regex(@"\((.*?)(in sampler2D)(.*?)\)", RegexOptions.Multiline | RegexOptions.IgnoreCase);
|
||||
|
||||
public Results Run(string code, string entry, string profile, bool hlslHacks)
|
||||
{
|
||||
//version=110; GLSL generates old fashioned semantic attributes and not generic attributes
|
||||
string[] args = new[]{"-profile", profile, "-entry", entry, "-po", "version=110"};
|
||||
|
||||
args = Escape(args);
|
||||
StringBuilder sbCmdline = new StringBuilder();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
sbCmdline.Append(args[i]);
|
||||
if (i != args.Length - 1) sbCmdline.Append(' ');
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why
|
||||
using (Process proc = new Process())
|
||||
{
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc.StartInfo.CreateNoWindow = true;
|
||||
proc.StartInfo.RedirectStandardInput = true;
|
||||
proc.StartInfo.RedirectStandardOutput = true;
|
||||
proc.StartInfo.RedirectStandardError = true;
|
||||
proc.StartInfo.Arguments = sbCmdline.ToString();
|
||||
proc.StartInfo.FileName = CGCBinPath;
|
||||
|
||||
StringBuilder output = new StringBuilder(), error = new StringBuilder();
|
||||
|
||||
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
|
||||
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
|
||||
{
|
||||
proc.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
if (e.Data == null) outputWaitHandle.Set();
|
||||
else output.AppendLine(e.Data);
|
||||
};
|
||||
proc.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (e.Data == null) errorWaitHandle.Set();
|
||||
else error.AppendLine(e.Data);
|
||||
};
|
||||
|
||||
|
||||
proc.Start();
|
||||
new Thread(() =>
|
||||
{
|
||||
proc.StandardInput.AutoFlush = true;
|
||||
proc.StandardInput.Write(code);
|
||||
proc.StandardInput.Flush();
|
||||
proc.StandardInput.Close();
|
||||
}).Start();
|
||||
|
||||
proc.BeginOutputReadLine();
|
||||
proc.BeginErrorReadLine();
|
||||
proc.WaitForExit();
|
||||
outputWaitHandle.WaitOne();
|
||||
errorWaitHandle.WaitOne();
|
||||
}
|
||||
|
||||
bool ok = (proc.ExitCode == 0);
|
||||
|
||||
var ret = new Results()
|
||||
{
|
||||
Succeeded = ok,
|
||||
Code = output.ToString(),
|
||||
Errors = error.ToString()
|
||||
public static string CGCBinPath;
|
||||
|
||||
private static string[] Escape(IEnumerable<string> args)
|
||||
{
|
||||
return args.Select(s => s.Contains(" ") ? string.Format("\"{0}\"", s) : s).ToArray();
|
||||
}
|
||||
|
||||
public class Results
|
||||
{
|
||||
public bool Succeeded;
|
||||
public string Code, Errors;
|
||||
public Dictionary<string, string> MapCodeToNative = new Dictionary<string, string>();
|
||||
public Dictionary<string, string> MapNativeToCode = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
Regex rxHlslSamplerCrashWorkaround = new Regex(@"\((.*?)(in sampler2D)(.*?)\)", RegexOptions.Multiline | RegexOptions.IgnoreCase);
|
||||
|
||||
public Results Run(string code, string entry, string profile, bool hlslHacks)
|
||||
{
|
||||
//version=110; GLSL generates old fashioned semantic attributes and not generic attributes
|
||||
string[] args = new[]{"-profile", profile, "-entry", entry, "-po", "version=110"};
|
||||
|
||||
args = Escape(args);
|
||||
StringBuilder sbCmdline = new StringBuilder();
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
{
|
||||
sbCmdline.Append(args[i]);
|
||||
if (i != args.Length - 1) sbCmdline.Append(' ');
|
||||
}
|
||||
|
||||
//http://stackoverflow.com/questions/139593/processstartinfo-hanging-on-waitforexit-why
|
||||
using (Process proc = new Process())
|
||||
{
|
||||
proc.StartInfo.UseShellExecute = false;
|
||||
proc.StartInfo.CreateNoWindow = true;
|
||||
proc.StartInfo.RedirectStandardInput = true;
|
||||
proc.StartInfo.RedirectStandardOutput = true;
|
||||
proc.StartInfo.RedirectStandardError = true;
|
||||
proc.StartInfo.Arguments = sbCmdline.ToString();
|
||||
proc.StartInfo.FileName = CGCBinPath;
|
||||
|
||||
StringBuilder output = new StringBuilder(), error = new StringBuilder();
|
||||
|
||||
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
|
||||
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
|
||||
{
|
||||
proc.OutputDataReceived += (sender, e) =>
|
||||
{
|
||||
if (e.Data == null) outputWaitHandle.Set();
|
||||
else output.AppendLine(e.Data);
|
||||
};
|
||||
proc.ErrorDataReceived += (sender, e) =>
|
||||
{
|
||||
if (e.Data == null) errorWaitHandle.Set();
|
||||
else error.AppendLine(e.Data);
|
||||
};
|
||||
|
||||
|
||||
proc.Start();
|
||||
new Thread(() =>
|
||||
{
|
||||
proc.StandardInput.AutoFlush = true;
|
||||
proc.StandardInput.Write(code);
|
||||
proc.StandardInput.Flush();
|
||||
proc.StandardInput.Close();
|
||||
}).Start();
|
||||
|
||||
proc.BeginOutputReadLine();
|
||||
proc.BeginErrorReadLine();
|
||||
proc.WaitForExit();
|
||||
outputWaitHandle.WaitOne();
|
||||
errorWaitHandle.WaitOne();
|
||||
}
|
||||
|
||||
bool ok = (proc.ExitCode == 0);
|
||||
|
||||
var ret = new Results()
|
||||
{
|
||||
Succeeded = ok,
|
||||
Code = output.ToString(),
|
||||
Errors = error.ToString()
|
||||
};
|
||||
|
||||
if (!ok)
|
||||
Console.WriteLine(ret.Errors);
|
||||
|
||||
Console.WriteLine(ret.Errors);
|
||||
|
||||
if (hlslHacks)
|
||||
{
|
||||
ret.Code = rxHlslSamplerCrashWorkaround.Replace(ret.Code, m => string.Format("({0}uniform sampler2D{1})", m.Groups[1].Value, m.Groups[3].Value));
|
||||
}
|
||||
|
||||
//make variable name map
|
||||
}
|
||||
|
||||
//make variable name map
|
||||
//loop until the first line that doesnt start with a comment
|
||||
var reader = new StringReader(ret.Code);
|
||||
for(;;)
|
||||
|
@ -131,10 +131,10 @@ namespace BizHawk.Bizware.BizwareGL
|
|||
ret.MapCodeToNative[code_name] = native_name;
|
||||
ret.MapNativeToCode[native_name] = code_name;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,46 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles RetroArch's GLSL shader pass format
|
||||
/// </summary>
|
||||
public class RetroShader : IDisposable
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace BizHawk.Bizware.BizwareGL
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles RetroArch's GLSL shader pass format
|
||||
/// </summary>
|
||||
public class RetroShader : IDisposable
|
||||
{
|
||||
//NOTE: we may need to overhaul uniform-setting infrastructure later.
|
||||
//maybe samplers will need to be set by index and not by name (I think the specs dont dictate what the sampler must be named)
|
||||
|
||||
public RetroShader(IGL owner, string source, bool debug = false)
|
||||
{
|
||||
Owner = owner;
|
||||
|
||||
//maybe samplers will need to be set by index and not by name (I think the specs dont dictate what the sampler must be named)
|
||||
|
||||
public RetroShader(IGL owner, string source, bool debug = false)
|
||||
{
|
||||
Owner = owner;
|
||||
|
||||
VertexLayout = owner.CreateVertexLayout();
|
||||
VertexLayout.DefineVertexAttribute("position", 0, 4, VertexAttribPointerType.Float, AttributeUsage.Position, false, 40, 0);
|
||||
VertexLayout.DefineVertexAttribute("color", 1, 4, VertexAttribPointerType.Float, AttributeUsage.Color0, false, 40, 16); //just dead weight, i have no idea why this is here. but some old HLSL compilers (used in bizhawk for various reasons) will want it to exist here since it exists in the vertex shader
|
||||
VertexLayout.DefineVertexAttribute("texCoord1", 2, 2, VertexAttribPointerType.Float, AttributeUsage.Texcoord0, false, 40, 32);
|
||||
VertexLayout.Close();
|
||||
|
||||
string defines = "#define TEXCOORD TEXCOORD0\r\n"; //maybe not safe..
|
||||
string vsSource = "#define VERTEX\r\n" + defines + source;
|
||||
string psSource = "#define FRAGMENT\r\n" + defines + source;
|
||||
var vs = owner.CreateVertexShader(true, vsSource, "main_vertex", debug);
|
||||
var ps = owner.CreateFragmentShader(true, psSource, "main_fragment", debug);
|
||||
VertexLayout.Close();
|
||||
|
||||
string defines = "#define TEXCOORD TEXCOORD0\r\n"; //maybe not safe..
|
||||
string vsSource = "#define VERTEX\r\n" + defines + source;
|
||||
string psSource = "#define FRAGMENT\r\n" + defines + source;
|
||||
var vs = owner.CreateVertexShader(true, vsSource, "main_vertex", debug);
|
||||
var ps = owner.CreateFragmentShader(true, psSource, "main_fragment", debug);
|
||||
Pipeline = Owner.CreatePipeline(VertexLayout, vs, ps, debug, "retro");
|
||||
|
||||
if (!Pipeline.Available)
|
||||
{
|
||||
Available = false;
|
||||
return;
|
||||
}
|
||||
|
||||
//retroarch shaders will sometimes not have the right sampler name
|
||||
//it's unclear whether we should bind to s_p or sampler0
|
||||
//lets bind to sampler0 in case we dont have s_p
|
||||
}
|
||||
|
||||
//retroarch shaders will sometimes not have the right sampler name
|
||||
//it's unclear whether we should bind to s_p or sampler0
|
||||
//lets bind to sampler0 in case we dont have s_p
|
||||
sampler0 = Pipeline.TryGetUniform("s_p");
|
||||
if (sampler0 == null)
|
||||
{
|
||||
|
@ -58,80 +58,80 @@ namespace BizHawk.Bizware.BizwareGL
|
|||
if (sampler0 == null)
|
||||
return;
|
||||
|
||||
Available = true;
|
||||
Available = true;
|
||||
}
|
||||
|
||||
public bool Available { get; private set; }
|
||||
public string Errors { get { return Pipeline.Errors; } }
|
||||
|
||||
PipelineUniform sampler0;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Pipeline.Dispose();
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
//lame...
|
||||
Owner.BindPipeline(Pipeline);
|
||||
}
|
||||
|
||||
public unsafe void Run(Texture2d tex, Size InputSize, Size OutputSize, bool flip)
|
||||
{
|
||||
flip = false;
|
||||
//test
|
||||
|
||||
//ack! make sure to set the pipeline before setting uniforms
|
||||
Bind();
|
||||
|
||||
PipelineUniform sampler0;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Pipeline.Dispose();
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
//lame...
|
||||
Owner.BindPipeline(Pipeline);
|
||||
}
|
||||
|
||||
public unsafe void Run(Texture2d tex, Size InputSize, Size OutputSize, bool flip)
|
||||
{
|
||||
flip = false;
|
||||
//test
|
||||
|
||||
//ack! make sure to set the pipeline before setting uniforms
|
||||
Bind();
|
||||
|
||||
Pipeline["IN.video_size"].Set(new Vector2(InputSize.Width, InputSize.Height));
|
||||
Pipeline["IN.texture_size"].Set(new Vector2(tex.Width, tex.Height));
|
||||
Pipeline["IN.output_size"].Set(new Vector2(OutputSize.Width, OutputSize.Height));
|
||||
Pipeline["IN.frame_count"].Set(1); //todo
|
||||
Pipeline["IN.frame_direction"].Set(1); //todo
|
||||
|
||||
|
||||
var Projection = Owner.CreateGuiProjectionMatrix(OutputSize);
|
||||
Pipeline["IN.texture_size"].Set(new Vector2(tex.Width, tex.Height));
|
||||
Pipeline["IN.output_size"].Set(new Vector2(OutputSize.Width, OutputSize.Height));
|
||||
Pipeline["IN.frame_count"].Set(1); //todo
|
||||
Pipeline["IN.frame_direction"].Set(1); //todo
|
||||
|
||||
|
||||
var Projection = Owner.CreateGuiProjectionMatrix(OutputSize);
|
||||
var Modelview = Owner.CreateGuiViewMatrix(OutputSize);
|
||||
var mat = Modelview * Projection;
|
||||
mat.Transpose();
|
||||
Pipeline["modelViewProj"].Set(mat, true);
|
||||
|
||||
Pipeline["modelViewProj"].Set(mat, true);
|
||||
|
||||
Owner.SetTextureWrapMode(tex, true);
|
||||
|
||||
sampler0.Set(tex);
|
||||
Owner.SetViewport(OutputSize);
|
||||
|
||||
sampler0.Set(tex);
|
||||
Owner.SetViewport(OutputSize);
|
||||
|
||||
int w = OutputSize.Width;
|
||||
int h = OutputSize.Height;
|
||||
float v0,v1;
|
||||
if (flip) { v0 = 1; v1 = 0; }
|
||||
else { v0 = 0; v1 = 1; }
|
||||
float* pData = stackalloc float[10*4];
|
||||
int i=0;
|
||||
int h = OutputSize.Height;
|
||||
float v0,v1;
|
||||
if (flip) { v0 = 1; v1 = 0; }
|
||||
else { v0 = 0; v1 = 1; }
|
||||
float* pData = stackalloc float[10*4];
|
||||
int i=0;
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topleft vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color
|
||||
pData[i++] = 0; pData[i++] = v0;
|
||||
pData[i++] = 0; pData[i++] = v0;
|
||||
pData[i++] = w; pData[i++] = 0; pData[i++] = 0; pData[i++] = 1; //topright vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color
|
||||
pData[i++] = 1; pData[i++] = v0;
|
||||
pData[i++] = 1; pData[i++] = v0;
|
||||
pData[i++] = 0; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomleft vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color
|
||||
pData[i++] = 0; pData[i++] = v1;
|
||||
pData[i++] = 0; pData[i++] = v1;
|
||||
pData[i++] = w; pData[i++] = h; pData[i++] = 0; pData[i++] = 1; //bottomright vert
|
||||
pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; pData[i++] = 0; //useless color
|
||||
pData[i++] = 1; pData[i++] = v1;
|
||||
|
||||
Owner.SetBlendState(Owner.BlendNoneCopy);
|
||||
Owner.BindArrayData(pData);
|
||||
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
public IGL Owner { get; private set; }
|
||||
|
||||
VertexLayout VertexLayout;
|
||||
public Pipeline Pipeline;
|
||||
}
|
||||
pData[i++] = 1; pData[i++] = v1;
|
||||
|
||||
Owner.SetBlendState(Owner.BlendNoneCopy);
|
||||
Owner.BindArrayData(pData);
|
||||
Owner.DrawArrays(PrimitiveType.TriangleStrip, 0, 4);
|
||||
}
|
||||
|
||||
|
||||
public IGL Owner { get; private set; }
|
||||
|
||||
VertexLayout VertexLayout;
|
||||
public Pipeline Pipeline;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue