more misc cleanups

This commit is contained in:
adelikat 2017-04-24 07:41:55 -05:00
parent b488529a7b
commit 76b9367378
25 changed files with 413 additions and 274 deletions

View File

@ -14,7 +14,7 @@ namespace BizHawk.Emulation.Common
/// <seealso cref="IEmulatorServiceProvider"/> /// <seealso cref="IEmulatorServiceProvider"/>
public class BasicServiceProvider : IEmulatorServiceProvider public class BasicServiceProvider : IEmulatorServiceProvider
{ {
private Dictionary<Type, object> Services = new Dictionary<Type, object>(); private readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
public BasicServiceProvider(IEmulator core) public BasicServiceProvider(IEmulator core)
{ {

View File

@ -63,6 +63,7 @@ namespace BizHawk.Emulation.Common
{ {
return _sink; return _sink;
} }
set set
{ {
_sink = value; _sink = value;

View File

@ -31,37 +31,37 @@ namespace BizHawk.Emulation.Common
} }
/// <summary> /// <summary>
/// The name of the controller definition /// Gets or sets the name of the controller definition
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// A list of all button types that have a boolean (on/off) value /// Gets or sets a list of all button types that have a boolean (on/off) value
/// </summary> /// </summary>
public List<string> BoolButtons { get; set; } public List<string> BoolButtons { get; set; }
/// <summary> /// <summary>
/// A list of all non-boolean types, that can be represented by a numerical value (such as analog controls, stylus coordinates, etc /// Gets a list of all non-boolean types, that can be represented by a numerical value (such as analog controls, stylus coordinates, etc
/// </summary> /// </summary>
public List<string> FloatControls { get; private set; } public List<string> FloatControls { get; }
/// <summary> /// <summary>
/// A list of all float ranges for each float control (must be one to one with FloatControls) /// Gets a list of all float ranges for each float control (must be one to one with FloatControls)
/// FloatRanges include the min/max/default values /// FloatRanges include the min/max/default values
/// </summary> /// </summary>
public List<FloatRange> FloatRanges { get; private set; } public List<FloatRange> FloatRanges { get; }
/// <summary> /// <summary>
/// Axis contraints apply artificial contraints to float values /// Gets the axis constraints that apply artificial constraints to float values
/// For instance, a N64 controller's analog range is actually larger than the amount allowed by the plastic that artificially contrains it to lower values /// For instance, a N64 controller's analog range is actually larger than the amount allowed by the plastic that artificially constrains it to lower values
/// Axis contraints provide a way to technically allow the full range but have a user option to contrain down to typical values that a real control would have /// Axis constraints provide a way to technically allow the full range but have a user option to constrain down to typical values that a real control would have
/// </summary> /// </summary>
public List<AxisConstraint> AxisConstraints { get; private set; } public List<AxisConstraint> AxisConstraints { get; }
/// <summary> /// <summary>
/// A means of categorizing controls in various controller display and config screens /// Gets the category labels. These labels provide a means of categorizing controls in various controller display and config screens
/// </summary> /// </summary>
public Dictionary<string, string> CategoryLabels { get; private set; } public Dictionary<string, string> CategoryLabels { get; }
public void ApplyAxisConstraints(string constraintClass, IDictionary<string, float> floatButtons) public void ApplyAxisConstraints(string constraintClass, IDictionary<string, float> floatButtons)
{ {
@ -93,6 +93,7 @@ namespace BizHawk.Emulation.Common
xval *= ratio; xval *= ratio;
yval *= ratio; yval *= ratio;
} }
floatButtons[xaxis] = (float)xval; floatButtons[xaxis] = (float)xval;
floatButtons[yaxis] = (float)yval; floatButtons[yaxis] = (float)yval;
break; break;
@ -214,5 +215,4 @@ namespace BizHawk.Emulation.Common
return BoolButtons.Any() || FloatControls.Any(); return BoolButtons.Any() || FloatControls.Any();
} }
} }
} }

View File

@ -33,7 +33,7 @@ namespace BizHawk.Emulation.Common
private bool _hasWrites; private bool _hasWrites;
private bool _hasExecutes; private bool _hasExecutes;
public bool ExecuteCallbacksAvailable { get; set; } public bool ExecuteCallbacksAvailable { get; }
public void Add(IMemoryCallback callback) public void Add(IMemoryCallback callback)
{ {
@ -222,12 +222,14 @@ namespace BizHawk.Emulation.Common
{ {
CallbackAdded?.Invoke(callback); CallbackAdded?.Invoke(callback);
} }
break; break;
case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Remove:
foreach (IMemoryCallback callback in args.OldItems) foreach (IMemoryCallback callback in args.OldItems)
{ {
CallbackRemoved?.Invoke(callback); CallbackRemoved?.Invoke(callback);
} }
break; break;
} }
} }

View File

@ -41,7 +41,7 @@ namespace BizHawk.Emulation.Common
/// <param name="data">must remain valid as long as the MemoryDomain exists!</param> /// <param name="data">must remain valid as long as the MemoryDomain exists!</param>
/// <param name="writable">if false, writes will be ignored</param> /// <param name="writable">if false, writes will be ignored</param>
[Obsolete] [Obsolete]
public unsafe static MemoryDomain FromIntPtr(string name, long size, Endian endian, IntPtr data, bool writable = true, int wordSize = 1) public static unsafe MemoryDomain FromIntPtr(string name, long size, Endian endian, IntPtr data, bool writable = true, int wordSize = 1)
{ {
return new MemoryDomainIntPtr(name, endian, data, size, writable, wordSize); return new MemoryDomainIntPtr(name, endian, data, size, writable, wordSize);
} }
@ -52,7 +52,7 @@ namespace BizHawk.Emulation.Common
/// <param name="data">must remain valid as long as the MemoryDomain exists!</param> /// <param name="data">must remain valid as long as the MemoryDomain exists!</param>
/// <param name="writable">if false, writes will be ignored</param> /// <param name="writable">if false, writes will be ignored</param>
[Obsolete] [Obsolete]
public unsafe static MemoryDomain FromIntPtrSwap16(string name, long size, Endian endian, IntPtr data, bool writable = true) public static unsafe MemoryDomain FromIntPtrSwap16(string name, long size, Endian endian, IntPtr data, bool writable = true)
{ {
return new MemoryDomainIntPtrSwap16(name, endian, data, size, writable); return new MemoryDomainIntPtrSwap16(name, endian, data, size, writable);
} }
@ -69,9 +69,9 @@ namespace BizHawk.Emulation.Common
{ {
default: default:
case Endian.Big: case Endian.Big:
return (ushort)((PeekByte(addr) << 8) | (PeekByte(addr + 1))); return (ushort)((PeekByte(addr) << 8) | PeekByte(addr + 1));
case Endian.Little: case Endian.Little:
return (ushort)((PeekByte(addr)) | (PeekByte(addr + 1) << 8)); return (ushort)(PeekByte(addr) | (PeekByte(addr + 1) << 8));
} }
} }
@ -102,10 +102,10 @@ namespace BizHawk.Emulation.Common
default: default:
case Endian.Big: case Endian.Big:
PokeByte(addr + 0, (byte)(val >> 8)); PokeByte(addr + 0, (byte)(val >> 8));
PokeByte(addr + 1, (byte)(val)); PokeByte(addr + 1, (byte)val);
break; break;
case Endian.Little: case Endian.Little:
PokeByte(addr + 0, (byte)(val)); PokeByte(addr + 0, (byte)val);
PokeByte(addr + 1, (byte)(val >> 8)); PokeByte(addr + 1, (byte)(val >> 8));
break; break;
} }
@ -121,10 +121,10 @@ namespace BizHawk.Emulation.Common
PokeByte(addr + 0, (byte)(val >> 24)); PokeByte(addr + 0, (byte)(val >> 24));
PokeByte(addr + 1, (byte)(val >> 16)); PokeByte(addr + 1, (byte)(val >> 16));
PokeByte(addr + 2, (byte)(val >> 8)); PokeByte(addr + 2, (byte)(val >> 8));
PokeByte(addr + 3, (byte)(val)); PokeByte(addr + 3, (byte)val);
break; break;
case Endian.Little: case Endian.Little:
PokeByte(addr + 0, (byte)(val)); PokeByte(addr + 0, (byte)val);
PokeByte(addr + 1, (byte)(val >> 8)); PokeByte(addr + 1, (byte)(val >> 8));
PokeByte(addr + 2, (byte)(val >> 16)); PokeByte(addr + 2, (byte)(val >> 16));
PokeByte(addr + 3, (byte)(val >> 24)); PokeByte(addr + 3, (byte)(val >> 24));

View File

@ -24,6 +24,6 @@
return 0f; return 0f;
} }
public static NullController Instance = new NullController(); public static readonly NullController Instance = new NullController();
} }
} }

View File

@ -201,7 +201,7 @@ namespace BizHawk.Emulation.Common
private bool _frameBufferClear = true; private bool _frameBufferClear = true;
private bool _xmas; private bool _xmas;
private Pleg _pleg; private readonly Pleg _pleg;
private NullEmulatorSettings _settings; private NullEmulatorSettings _settings;
@ -356,9 +356,7 @@ namespace BizHawk.Emulation.Common
return; return;
} }
var s = new SinMan(1500, n); var s = new SinMan(1500, n) { c = c, n = n };
s.c = c;
s.n = n;
SinMen.Add(s); SinMen.Add(s);
} }
@ -378,6 +376,7 @@ namespace BizHawk.Emulation.Common
ret += s.Next(); ret += s.Next();
} }
} }
if (ret > 32767) ret = 32767; if (ret > 32767) ret = 32767;
if (ret < -32767) ret = -32767; if (ret < -32767) ret = -32767;
return (short)ret; return (short)ret;
@ -432,10 +431,7 @@ namespace BizHawk.Emulation.Common
public bool fading = false; public bool fading = false;
public bool Done public bool Done => amp < 2.0;
{
get { return amp < 2.0; }
}
static double GetFreq(int note) static double GetFreq(int note)
{ {
@ -447,9 +443,15 @@ namespace BizHawk.Emulation.Common
short result = (short)(Math.Sin(theta) * amp); short result = (short)(Math.Sin(theta) * amp);
theta += freq * Math.PI / 22050.0; theta += freq * Math.PI / 22050.0;
if (theta >= Math.PI * 2.0) if (theta >= Math.PI * 2.0)
{
theta -= Math.PI * 2.0; theta -= Math.PI * 2.0;
}
if (fading) if (fading)
{
amp *= 0.87; amp *= 0.87;
}
return result; return result;
} }

View File

@ -12,6 +12,8 @@
return new int[BufferWidth * BufferHeight]; return new int[BufferWidth * BufferHeight];
} }
public static NullVideo Instance { get; } = new NullVideo();
public int VirtualWidth => 256; public int VirtualWidth => 256;
public int VirtualHeight => 192; public int VirtualHeight => 192;
@ -21,9 +23,5 @@
public int BufferHeight => 192; public int BufferHeight => 192;
public int BackgroundColor => 0; public int BackgroundColor => 0;
private static readonly NullVideo _nullVideo = new NullVideo();
public static NullVideo Instance => _nullVideo;
} }
} }

View File

@ -23,13 +23,18 @@ namespace BizHawk.Emulation.Common
{ {
var caller = e as MethodCallExpression; var caller = e as MethodCallExpression;
if (caller == null) if (caller == null)
{
throw new ArgumentException("Expression must be a method call"); throw new ArgumentException("Expression must be a method call");
}
return caller.Method; return caller.Method;
} }
private static MethodInfo Method(Expression<Action> f) private static MethodInfo Method(Expression<Action> f)
{ {
return FromExpression(f.Body); return FromExpression(f.Body);
} }
private static MethodInfo Method<T>(Expression<Action<T>> f) private static MethodInfo Method<T>(Expression<Action<T>> f)
{ {
return FromExpression(f.Body); return FromExpression(f.Body);
@ -39,14 +44,17 @@ namespace BizHawk.Emulation.Common
#region read and write handlers for individual fields #region read and write handlers for individual fields
private static Dictionary<Type, MethodInfo> readhandlers = new Dictionary<Type, MethodInfo>(); private static readonly Dictionary<Type, MethodInfo> readhandlers = new Dictionary<Type, MethodInfo>();
private static Dictionary<Type, MethodInfo> writehandlers = new Dictionary<Type, MethodInfo>(); private static readonly Dictionary<Type, MethodInfo> writehandlers = new Dictionary<Type, MethodInfo>();
private static void AddR<T>(Expression<Action<BinaryReader>> f) private static void AddR<T>(Expression<Action<BinaryReader>> f)
{ {
var method = Method(f); var method = Method(f);
if (!typeof(T).IsAssignableFrom(method.ReturnType)) if (!typeof(T).IsAssignableFrom(method.ReturnType))
{
throw new InvalidOperationException("Type mismatch"); throw new InvalidOperationException("Type mismatch");
}
readhandlers.Add(typeof(T), method); readhandlers.Add(typeof(T), method);
} }
@ -54,7 +62,10 @@ namespace BizHawk.Emulation.Common
{ {
var method = Method(f); var method = Method(f);
if (!method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(T))) if (!method.GetParameters()[0].ParameterType.IsAssignableFrom(typeof(T)))
{
throw new InvalidOperationException("Type mismatch"); throw new InvalidOperationException("Type mismatch");
}
writehandlers.Add(typeof(T), Method(f)); writehandlers.Add(typeof(T), Method(f));
} }
@ -125,12 +136,17 @@ namespace BizHawk.Emulation.Common
il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_1);
MethodInfo m; MethodInfo m;
if (!readhandlers.TryGetValue(field.FieldType, out m)) if (!readhandlers.TryGetValue(field.FieldType, out m))
{
throw new InvalidOperationException("(R) Can't handle nested type " + field.FieldType); throw new InvalidOperationException("(R) Can't handle nested type " + field.FieldType);
}
il.Emit(OpCodes.Callvirt, m); il.Emit(OpCodes.Callvirt, m);
il.Emit(OpCodes.Stfld, field); il.Emit(OpCodes.Stfld, field);
} }
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
{ {
var il = wmeth.GetILGenerator(); var il = wmeth.GetILGenerator();
var target = il.DeclareLocal(t); var target = il.DeclareLocal(t);
@ -145,9 +161,13 @@ namespace BizHawk.Emulation.Common
il.Emit(OpCodes.Ldfld, field); il.Emit(OpCodes.Ldfld, field);
MethodInfo m; MethodInfo m;
if (!writehandlers.TryGetValue(field.FieldType, out m)) if (!writehandlers.TryGetValue(field.FieldType, out m))
{
throw new InvalidOperationException("(W) Can't handle nested type " + field.FieldType); throw new InvalidOperationException("(W) Can't handle nested type " + field.FieldType);
}
il.Emit(OpCodes.Callvirt, m); il.Emit(OpCodes.Callvirt, m);
} }
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
@ -161,7 +181,7 @@ namespace BizHawk.Emulation.Common
#endregion #endregion
private static IDictionary<Type, SerializationFactory> serializers = private static readonly IDictionary<Type, SerializationFactory> serializers =
new ConcurrentDictionary<Type, SerializationFactory>(); new ConcurrentDictionary<Type, SerializationFactory>();
private static SerializationFactory GetFactory(Type t) private static SerializationFactory GetFactory(Type t)
@ -172,6 +192,7 @@ namespace BizHawk.Emulation.Common
f = CreateFactory(t); f = CreateFactory(t);
serializers[t] = f; serializers[t] = f;
} }
return f; return f;
} }

View File

@ -36,7 +36,7 @@ namespace BizHawk.Emulation.Common.BizInvoke
/// <summary> /// <summary>
/// dictionary of all generated proxy implementations and their basetypes /// dictionary of all generated proxy implementations and their basetypes
/// </summary> /// </summary>
private static IDictionary<Type, InvokerImpl> Impls = new Dictionary<Type, InvokerImpl>(); private static readonly IDictionary<Type, InvokerImpl> Impls = new Dictionary<Type, InvokerImpl>();
/// <summary> /// <summary>
/// the assembly that all proxies are placed in /// the assembly that all proxies are placed in
@ -138,14 +138,18 @@ namespace BizHawk.Emulation.Common.BizInvoke
{ {
var uo = baseMethods.FirstOrDefault(a => !a.Info.IsVirtual || a.Info.IsFinal); var uo = baseMethods.FirstOrDefault(a => !a.Info.IsVirtual || a.Info.IsFinal);
if (uo != null) if (uo != null)
{
throw new InvalidOperationException("Method " + uo.Info.Name + " cannot be overriden!"); throw new InvalidOperationException("Method " + uo.Info.Name + " cannot be overriden!");
}
// there's no technical reason to disallow this, but we wouldn't be doing anything // there's no technical reason to disallow this, but we wouldn't be doing anything
// with the base implementation, so it's probably a user error // with the base implementation, so it's probably a user error
var na = baseMethods.FirstOrDefault(a => !a.Info.IsAbstract); var na = baseMethods.FirstOrDefault(a => !a.Info.IsAbstract);
if (na != null) if (na != null)
{
throw new InvalidOperationException("Method " + na.Info.Name + " is not abstract!"); throw new InvalidOperationException("Method " + na.Info.Name + " is not abstract!");
} }
}
// hooks that will be run on the created proxy object // hooks that will be run on the created proxy object
var postCreateHooks = new List<Action<object, IImportResolver>>(); var postCreateHooks = new List<Action<object, IImportResolver>>();
@ -171,7 +175,9 @@ namespace BizHawk.Emulation.Common.BizInvoke
ImplType = type.CreateType() ImplType = type.CreateType()
}; };
if (monitor) if (monitor)
{
ret.ConnectMonitor = (o, m) => o.GetType().GetField(monitorField.Name).SetValue(o, m); ret.ConnectMonitor = (o, m) => o.GetType().GetField(monitorField.Name).SetValue(o, m);
}
return ret; return ret;
} }
@ -234,7 +240,9 @@ namespace BizHawk.Emulation.Common.BizInvoke
il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, field); il.Emit(OpCodes.Ldfld, field);
for (int i = 0; i < paramTypes.Length; i++) for (int i = 0; i < paramTypes.Length; i++)
{
il.Emit(OpCodes.Ldarg, (short)(i + 1)); il.Emit(OpCodes.Ldarg, (short)(i + 1));
}
il.Emit(OpCodes.Callvirt, delegateInvoke); il.Emit(OpCodes.Callvirt, delegateInvoke);
@ -354,11 +362,18 @@ namespace BizHawk.Emulation.Common.BizInvoke
private static void LoadConstant(ILGenerator il, IntPtr p) private static void LoadConstant(ILGenerator il, IntPtr p)
{ {
if (p == IntPtr.Zero) if (p == IntPtr.Zero)
{
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
}
else if (IntPtr.Size == 4) else if (IntPtr.Size == 4)
{
il.Emit(OpCodes.Ldc_I4, (int)p); il.Emit(OpCodes.Ldc_I4, (int)p);
}
else else
{
il.Emit(OpCodes.Ldc_I8, (long)p); il.Emit(OpCodes.Ldc_I8, (long)p);
}
il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Conv_I);
} }
@ -368,11 +383,18 @@ namespace BizHawk.Emulation.Common.BizInvoke
private static void LoadConstant(ILGenerator il, UIntPtr p) private static void LoadConstant(ILGenerator il, UIntPtr p)
{ {
if (p == UIntPtr.Zero) if (p == UIntPtr.Zero)
{
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
}
else if (UIntPtr.Size == 4) else if (UIntPtr.Size == 4)
{
il.Emit(OpCodes.Ldc_I4, (int)p); il.Emit(OpCodes.Ldc_I4, (int)p);
}
else else
{
il.Emit(OpCodes.Ldc_I8, (long)p); il.Emit(OpCodes.Ldc_I8, (long)p);
}
il.Emit(OpCodes.Conv_U); il.Emit(OpCodes.Conv_U);
} }
@ -382,12 +404,18 @@ namespace BizHawk.Emulation.Common.BizInvoke
private static Type EmitParamterLoad(ILGenerator il, int idx, Type type) private static Type EmitParamterLoad(ILGenerator il, int idx, Type type)
{ {
if (type.IsGenericType) if (type.IsGenericType)
{
throw new InvalidOperationException("Generic types not supported"); throw new InvalidOperationException("Generic types not supported");
}
if (type.IsByRef) if (type.IsByRef)
{ {
var et = type.GetElementType(); var et = type.GetElementType();
if (!et.IsPrimitive && !et.IsEnum) if (!et.IsPrimitive && !et.IsEnum)
{
throw new InvalidOperationException("Only refs of primitive or enum types are supported!"); throw new InvalidOperationException("Only refs of primitive or enum types are supported!");
}
var loc = il.DeclareLocal(type, true); var loc = il.DeclareLocal(type, true);
il.Emit(OpCodes.Ldarg, (short)idx); il.Emit(OpCodes.Ldarg, (short)idx);
il.Emit(OpCodes.Dup); il.Emit(OpCodes.Dup);
@ -395,17 +423,24 @@ namespace BizHawk.Emulation.Common.BizInvoke
il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Conv_I);
return typeof(IntPtr); return typeof(IntPtr);
} }
else if (type.IsArray)
if (type.IsArray)
{ {
var et = type.GetElementType(); var et = type.GetElementType();
if (!et.IsPrimitive && !et.IsEnum) if (!et.IsPrimitive && !et.IsEnum)
{
throw new InvalidOperationException("Only arrays of primitive or enum types are supported!"); throw new InvalidOperationException("Only arrays of primitive or enum types are supported!");
}
// these two cases aren't too hard to add // these two cases aren't too hard to add
if (type.GetArrayRank() > 1) if (type.GetArrayRank() > 1)
{
throw new InvalidOperationException("Multidimensional arrays are not supported!"); throw new InvalidOperationException("Multidimensional arrays are not supported!");
}
if (type.Name.Contains('*')) if (type.Name.Contains('*'))
{
throw new InvalidOperationException("Only 0-based 1-dimensional arrays are supported!"); throw new InvalidOperationException("Only 0-based 1-dimensional arrays are supported!");
}
var loc = il.DeclareLocal(type, true); var loc = il.DeclareLocal(type, true);
var end = il.DefineLabel(); var end = il.DefineLabel();
@ -428,7 +463,8 @@ namespace BizHawk.Emulation.Common.BizInvoke
return typeof(IntPtr); return typeof(IntPtr);
} }
else if (typeof(Delegate).IsAssignableFrom(type))
if (typeof(Delegate).IsAssignableFrom(type))
{ {
var mi = typeof(Marshal).GetMethod("GetFunctionPointerForDelegate", new[] { typeof(Delegate) }); var mi = typeof(Marshal).GetMethod("GetFunctionPointerForDelegate", new[] { typeof(Delegate) });
var end = il.DefineLabel(); var end = il.DefineLabel();
@ -446,23 +482,25 @@ namespace BizHawk.Emulation.Common.BizInvoke
il.MarkLabel(end); il.MarkLabel(end);
return typeof(IntPtr); return typeof(IntPtr);
} }
else if (type.IsPrimitive || type.IsEnum)
if (type.IsPrimitive || type.IsEnum)
{ {
il.Emit(OpCodes.Ldarg, (short)idx); il.Emit(OpCodes.Ldarg, (short)idx);
return type; return type;
} }
else
{
throw new InvalidOperationException("Unrecognized parameter type!"); throw new InvalidOperationException("Unrecognized parameter type!");
} }
}
private static CustomAttributeBuilder GetAttributeBuilder(object o) private static CustomAttributeBuilder GetAttributeBuilder(object o)
{ {
// anything more clever we can do here? // anything more clever we can do here?
var t = o.GetType(); var t = o.GetType();
if (t == typeof(OutAttribute) || t == typeof(InAttribute)) if (t == typeof(OutAttribute) || t == typeof(InAttribute))
{
return new CustomAttributeBuilder(t.GetConstructor(Type.EmptyTypes), new object[0]); return new CustomAttributeBuilder(t.GetConstructor(Type.EmptyTypes), new object[0]);
}
throw new InvalidOperationException("Unknown parameter attribute " + t.Name); throw new InvalidOperationException("Unknown parameter attribute " + t.Name);
} }
} }

View File

@ -1,14 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
// the idea here is that various connected peripherals have their controls all merged // the idea here is that various connected peripherals have their controls all merged
// into one definition, including logic to unmerge the data back so each one can work // into one definition, including logic to unmerge the data back so each one can work
// with it without knowing what else is connected // with it without knowing what else is connected
public static class ControllerDefinitionMerger public static class ControllerDefinitionMerger
{ {
private static string Allocate(string input, ref int plr, ref int plrnext) private static string Allocate(string input, ref int plr, ref int plrnext)
@ -16,22 +13,24 @@ namespace BizHawk.Emulation.Common
int offset = int.Parse(input.Substring(0, 1)); int offset = int.Parse(input.Substring(0, 1));
int currplr = plr + offset; int currplr = plr + offset;
if (currplr >= plrnext) if (currplr >= plrnext)
{
plrnext = currplr + 1; plrnext = currplr + 1;
return string.Format("P{0} {1}", currplr, input.Substring(1)); }
return $"P{currplr} {input.Substring(1)}";
} }
/// <summary> /// <summary>
/// merge some controller definitions for different ports, and such. i promise to fully document this tomorrow /// merge some controller definitions for different ports, and such. i promise to fully document this tomorrow
/// </summary> /// </summary>
/// <param name="Controllers"></param>
/// <returns></returns> /// <returns></returns>
public static ControllerDefinition GetMerged(IEnumerable<ControllerDefinition> Controllers, out List<ControlDefUnMerger> Unmergers) public static ControllerDefinition GetMerged(IEnumerable<ControllerDefinition> controllers, out List<ControlDefUnMerger> unmergers)
{ {
ControllerDefinition ret = new ControllerDefinition(); ControllerDefinition ret = new ControllerDefinition();
Unmergers = new List<ControlDefUnMerger>(); unmergers = new List<ControlDefUnMerger>();
int plr = 1; int plr = 1;
int plrnext = 1; int plrnext = 1;
foreach (var def in Controllers) foreach (var def in controllers)
{ {
Dictionary<string, string> remaps = new Dictionary<string, string>(); Dictionary<string, string> remaps = new Dictionary<string, string>();
@ -41,33 +40,37 @@ namespace BizHawk.Emulation.Common
ret.BoolButtons.Add(r); ret.BoolButtons.Add(r);
remaps[s] = r; remaps[s] = r;
} }
foreach (string s in def.FloatControls) foreach (string s in def.FloatControls)
{ {
string r = Allocate(s, ref plr, ref plrnext); string r = Allocate(s, ref plr, ref plrnext);
ret.FloatControls.Add(r); ret.FloatControls.Add(r);
remaps[s] = r; remaps[s] = r;
} }
ret.FloatRanges.AddRange(def.FloatRanges); ret.FloatRanges.AddRange(def.FloatRanges);
plr = plrnext; plr = plrnext;
Unmergers.Add(new ControlDefUnMerger(remaps)); unmergers.Add(new ControlDefUnMerger(remaps));
} }
return ret; return ret;
} }
} }
public class ControlDefUnMerger public class ControlDefUnMerger
{ {
Dictionary<string, string> Remaps; private readonly Dictionary<string, string> Remaps;
public ControlDefUnMerger(Dictionary<string, string> Remaps) public ControlDefUnMerger(Dictionary<string, string> remaps)
{ {
this.Remaps = Remaps; Remaps = remaps;
} }
private class DummyController : IController private class DummyController : IController
{ {
IController src; private readonly IController src;
Dictionary<string, string> remaps; private readonly Dictionary<string, string> remaps;
public DummyController(IController src, Dictionary<string, string> remaps) public DummyController(IController src, Dictionary<string, string> remaps)
{ {
this.src = src; this.src = src;
@ -76,7 +79,7 @@ namespace BizHawk.Emulation.Common
public ControllerDefinition Definition { get { throw new NotImplementedException(); } } public ControllerDefinition Definition { get { throw new NotImplementedException(); } }
public bool this[string button] { get { return IsPressed(button); } } public bool this[string button] => IsPressed(button);
public bool IsPressed(string button) public bool IsPressed(string button)
{ {
@ -93,6 +96,5 @@ namespace BizHawk.Emulation.Common
{ {
return new DummyController(c, Remaps); return new DummyController(c, Remaps);
} }
} }
} }

View File

@ -11,10 +11,10 @@ namespace BizHawk.Emulation.Common
/// <seealso cref="IEmulator" /> /// <seealso cref="IEmulator" />
public class CoreComm public class CoreComm
{ {
public CoreComm(Action<string> showMessage, Action<string> NotifyMessage) public CoreComm(Action<string> showMessage, Action<string> notifyMessage)
{ {
ShowMessage = showMessage; ShowMessage = showMessage;
Notify = NotifyMessage; Notify = notifyMessage;
} }
public ICoreFileProvider CoreFileProvider; public ICoreFileProvider CoreFileProvider;

View File

@ -1,6 +1,5 @@
// we could get a little list of crcs from here and make it clear which crc this class was for, and expose others // we could get a little list of crcs from here and make it clear which crc this class was for, and expose others
// http://www.ross.net/crc/download/crc_v3.txt // http://www.ross.net/crc/download/crc_v3.txt
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
// TODO - why am I here? put me alongside hash_md5 and such in a non-emulation-related class // TODO - why am I here? put me alongside hash_md5 and such in a non-emulation-related class
@ -18,10 +17,14 @@ namespace BizHawk.Emulation.Common
for (int j = 8; j > 0; --j) for (int j = 8; j > 0; --j)
{ {
if ((crc & 1) == 1) if ((crc & 1) == 1)
crc = ((crc >> 1) ^ 0xEDB88320); {
crc = (crc >> 1) ^ 0xEDB88320;
}
else else
{
crc >>= 1; crc >>= 1;
} }
}
CRC32Table[i] = crc; CRC32Table[i] = crc;
} }
@ -29,11 +32,13 @@ namespace BizHawk.Emulation.Common
public static int Calculate(byte[] data) public static int Calculate(byte[] data)
{ {
uint Result = 0xFFFFFFFF; uint result = 0xFFFFFFFF;
foreach (var b in data) foreach (var b in data)
Result = (((Result) >> 8) ^ CRC32Table[b ^ ((Result) & 0xFF)]); {
result = (result >> 8) ^ CRC32Table[b ^ (result & 0xFF)];
}
return (int) ~Result; return (int)~result;
} }
} }
} }

View File

@ -212,7 +212,7 @@ namespace BizHawk.Emulation.Common
public static GameInfo GetGameInfo(byte[] romData, string fileName) public static GameInfo GetGameInfo(byte[] romData, string fileName)
{ {
CompactGameInfo cgi; CompactGameInfo cgi;
var hash = string.Format("{0:X8}", CRC32.Calculate(romData)); var hash = $"{CRC32.Calculate(romData):X8}";
if (db.TryGetValue(hash, out cgi)) if (db.TryGetValue(hash, out cgi))
{ {
return new GameInfo(cgi); return new GameInfo(cgi);

View File

@ -168,12 +168,12 @@ namespace BizHawk.Emulation.Common
Option("PSX", "U", ps_30a); Option("PSX", "U", ps_30a);
Option("PSX", "J", ps_30j); Option("PSX", "J", ps_30j);
Option("PSX", "E", ps_30e); Option("PSX", "E", ps_30e);
// in general, alternates arent allowed.. their quality isnt known. // in general, alternates arent allowed.. their quality isnt known.
// we have this comment from fobby.net: "SCPH7502 works fine for European games" (TBD) // we have this comment from fobby.net: "SCPH7502 works fine for European games" (TBD)
// however, we're sticking with the 3.0 series. // however, we're sticking with the 3.0 series.
// please note: 2.1 or 2.2 would be a better choice, as the dates are the same and the bioses are more likely to matching in terms of entrypoints and such. // please note: 2.1 or 2.2 would be a better choice, as the dates are the same and the bioses are more likely to matching in terms of entrypoints and such.
// but 3.0 is what mednafen used // but 3.0 is what mednafen used
Option("PSX", "J", ps_10j, FirmwareOptionStatus.Unacceptable); Option("PSX", "J", ps_10j, FirmwareOptionStatus.Unacceptable);
Option("PSX", "J", ps_11j, FirmwareOptionStatus.Unacceptable); Option("PSX", "J", ps_11j, FirmwareOptionStatus.Unacceptable);
Option("PSX", "U", ps_20a, FirmwareOptionStatus.Unacceptable); Option("PSX", "U", ps_20a, FirmwareOptionStatus.Unacceptable);
@ -205,7 +205,7 @@ namespace BizHawk.Emulation.Common
} }
// adds a defined firmware ID to the database // adds a defined firmware ID to the database
static void Firmware(string systemId, string id, string descr) private static void Firmware(string systemId, string id, string descr)
{ {
var fr = new FirmwareRecord var fr = new FirmwareRecord
{ {
@ -218,7 +218,7 @@ namespace BizHawk.Emulation.Common
} }
// adds an acceptable option for a firmware ID to the database // adds an acceptable option for a firmware ID to the database
static FirmwareOption Option(string hash, long size, string systemId, string id, FirmwareOptionStatus status = FirmwareOptionStatus.Acceptable) private static FirmwareOption Option(string hash, long size, string systemId, string id, FirmwareOptionStatus status = FirmwareOptionStatus.Acceptable)
{ {
var fo = new FirmwareOption var fo = new FirmwareOption
{ {
@ -233,22 +233,29 @@ namespace BizHawk.Emulation.Common
// first option is automatically ideal // first option is automatically ideal
if (FirmwareOptions.Count == 1 && fo.status == FirmwareOptionStatus.Acceptable) if (FirmwareOptions.Count == 1 && fo.status == FirmwareOptionStatus.Acceptable)
{
fo.status = FirmwareOptionStatus.Ideal; fo.status = FirmwareOptionStatus.Ideal;
}
return fo; return fo;
} }
// adds an acceptable option for a firmware ID to the database // adds an acceptable option for a firmware ID to the database
static FirmwareOption Option(string systemId, string id, FirmwareFile ff, FirmwareOptionStatus status = FirmwareOptionStatus.Acceptable) private static FirmwareOption Option(string systemId, string id, FirmwareFile ff, FirmwareOptionStatus status = FirmwareOptionStatus.Acceptable)
{ {
var fo = Option(ff.hash, ff.size, systemId, id, status); var fo = Option(ff.hash, ff.size, systemId, id, status);
// make sure this goes in as bad // make sure this goes in as bad
if(ff.bad) fo.status = FirmwareOptionStatus.Bad; if (ff.bad)
{
fo.status = FirmwareOptionStatus.Bad;
}
return fo; return fo;
} }
// defines a firmware file // defines a firmware file
static FirmwareFile File(string hash, long size, string recommendedName, string descr, string additionalInfo = "") private static FirmwareFile File(string hash, long size, string recommendedName, string descr, string additionalInfo = "")
{ {
string hashfix = hash.ToUpperInvariant(); string hashfix = hash.ToUpperInvariant();
@ -266,7 +273,7 @@ namespace BizHawk.Emulation.Common
} }
// adds a defined firmware ID and one file and option // adds a defined firmware ID and one file and option
static void FirmwareAndOption(string hash, long size, string systemId, string id, string name, string descr) private static void FirmwareAndOption(string hash, long size, string systemId, string id, string name, string descr)
{ {
Firmware(systemId, id, descr); Firmware(systemId, id, descr);
File(hash, size, name, descr, ""); File(hash, size, name, descr, "");
@ -274,9 +281,9 @@ namespace BizHawk.Emulation.Common
} }
public static List<FirmwareRecord> FirmwareRecords = new List<FirmwareRecord>(); public static readonly List<FirmwareRecord> FirmwareRecords = new List<FirmwareRecord>();
public static List<FirmwareOption> FirmwareOptions = new List<FirmwareOption>(); public static readonly List<FirmwareOption> FirmwareOptions = new List<FirmwareOption>();
public static List<FirmwareFile> FirmwareFiles = new List<FirmwareFile>(); public static readonly List<FirmwareFile> FirmwareFiles = new List<FirmwareFile>();
public static Dictionary<string, FirmwareFile> FirmwareFilesByHash = new Dictionary<string, FirmwareFile>(); public static Dictionary<string, FirmwareFile> FirmwareFilesByHash = new Dictionary<string, FirmwareFile>();
@ -295,7 +302,7 @@ namespace BizHawk.Emulation.Common
public string systemId; public string systemId;
public string firmwareId; public string firmwareId;
public string descr; public string descr;
public string ConfigKey { get { return string.Format("{0}+{1}", systemId, firmwareId); } } public string ConfigKey => $"{systemId}+{firmwareId}";
} }
public enum FirmwareOptionStatus public enum FirmwareOptionStatus
@ -311,7 +318,7 @@ namespace BizHawk.Emulation.Common
public long size; public long size;
public FirmwareOptionStatus status; public FirmwareOptionStatus status;
public bool IsAcceptableOrIdeal { get { return status == FirmwareOptionStatus.Ideal || status == FirmwareOptionStatus.Acceptable; } } public bool IsAcceptableOrIdeal { get { return status == FirmwareOptionStatus.Ideal || status == FirmwareOptionStatus.Acceptable; } }
public string ConfigKey { get { return string.Format("{0}+{1}", systemId, firmwareId); } } public string ConfigKey => $"{systemId}+{firmwareId}";
} }
@ -325,6 +332,5 @@ namespace BizHawk.Emulation.Common
return found.FirstOrDefault(); return found.FirstOrDefault();
} }
} // static class FirmwareDatabase } // static class FirmwareDatabase
} }

View File

@ -13,18 +13,20 @@ namespace BizHawk.Emulation.Common
return Status == RomStatus.BadDump || Status == RomStatus.Overdump; return Status == RomStatus.BadDump || Status == RomStatus.Overdump;
} }
public string Name; public string Name { get; set; }
public string System; public string System { get; set; }
public string Hash; public string Hash { get; set; }
public string Region; public string Region { get; set; }
public RomStatus Status = RomStatus.NotInDatabase; public RomStatus Status { get; set; } = RomStatus.NotInDatabase;
public bool NotInDatabase = true; public bool NotInDatabase { get; set; } = true;
public string FirmwareHash; public string FirmwareHash { get; set; }
public string ForcedCore; public string ForcedCore { get; private set; }
Dictionary<string, string> Options = new Dictionary<string, string>(); private Dictionary<string, string> Options { get; set; } = new Dictionary<string, string>();
public GameInfo() { } public GameInfo()
{
}
public GameInfo Clone() public GameInfo Clone()
{ {
@ -33,27 +35,18 @@ namespace BizHawk.Emulation.Common
return ret; return ret;
} }
public static GameInfo NullInstance public static GameInfo NullInstance => new GameInfo
{
get
{
return new GameInfo
{ {
Name = "Null", Name = "Null",
System = "NULL", System = "NULL",
Hash = "", Hash = string.Empty,
Region = "", Region = string.Empty,
Status = RomStatus.GoodDump, Status = RomStatus.GoodDump,
ForcedCore = "", ForcedCore = string.Empty,
NotInDatabase = false NotInDatabase = false
}; };
}
}
public bool IsNullInstance public bool IsNullInstance => System == "NULL";
{
get { return System == "NULL"; }
}
internal GameInfo(CompactGameInfo cgi) internal GameInfo(CompactGameInfo cgi)
{ {
@ -82,10 +75,7 @@ namespace BizHawk.Emulation.Common
Options.Remove(option); Options.Remove(option);
} }
public bool this[string option] public bool this[string option] => Options.ContainsKey(option);
{
get { return Options.ContainsKey(option); }
}
public bool OptionPresent(string option) public bool OptionPresent(string option)
{ {
@ -95,7 +85,10 @@ namespace BizHawk.Emulation.Common
public string OptionValue(string option) public string OptionValue(string option)
{ {
if (Options.ContainsKey(option)) if (Options.ContainsKey(option))
{
return Options[option]; return Options[option];
}
return null; return null;
} }
@ -114,25 +107,37 @@ namespace BizHawk.Emulation.Common
return int.Parse(Options[option], NumberStyles.HexNumber); return int.Parse(Options[option], NumberStyles.HexNumber);
} }
/// <summary>
/// /// Gets a boolean value from the database
/// </summary>
/// <param name="parameter">The option to look up</param> /// <param name="parameter">The option to look up</param>
/// <param name="defaultVal">The value to return if the option is invalid or doesn't exist</param> /// <param name="defaultVal">The value to return if the option is invalid or doesn't exist</param>
/// <returns> The bool value from the database if present, otherwise the given default value</returns> /// <returns> The boolean value from the database if present, otherwise the given default value</returns>
public bool GetBool(string parameter, bool defaultVal) public bool GetBool(string parameter, bool defaultVal)
{ {
if (OptionPresent(parameter) && OptionValue(parameter) == "true") if (OptionPresent(parameter) && OptionValue(parameter) == "true")
{
return true; return true;
else if (OptionPresent(parameter) && OptionValue(parameter) == "false") }
if (OptionPresent(parameter) && OptionValue(parameter) == "false")
{
return false; return false;
else }
return defaultVal; return defaultVal;
} }
/// <summary>
/// /// Gets an integer value from the database
/// </summary>
/// <param name="parameter">The option to look up</param> /// <param name="parameter">The option to look up</param>
/// <param name="defaultVal">The value to return if the option is invalid or doesn't exist</param> /// <param name="defaultVal">The value to return if the option is invalid or doesn't exist</param>
/// <returns> The int value from the database if present, otherwise the given default value</returns> /// <returns> The integer value from the database if present, otherwise the given default value</returns>
public int GetInt(string parameter, int defaultVal) public int GetInt(string parameter, int defaultVal)
{ {
if (OptionPresent(parameter)) if (OptionPresent(parameter))
{
try try
{ {
return int.Parse(OptionValue(parameter)); return int.Parse(OptionValue(parameter));
@ -141,24 +146,27 @@ namespace BizHawk.Emulation.Common
{ {
return defaultVal; return defaultVal;
} }
else }
return defaultVal; return defaultVal;
} }
public ICollection<string> GetOptions() public ICollection<string> GetOptions()
{ {
return Options.Keys; return Options.Keys;
} }
public IDictionary<string, string> GetOptionsDict() public IDictionary<string, string> GetOptionsDict()
{ {
return new ReadOnlyDictionary<string, string>(Options); return new ReadOnlyDictionary<string, string>(Options);
} }
void ParseOptionsDictionary(string metaData) private void ParseOptionsDictionary(string metaData)
{ {
if (string.IsNullOrEmpty(metaData)) if (string.IsNullOrEmpty(metaData))
{
return; return;
}
var options = metaData.Split(';').Where(opt => string.IsNullOrEmpty(opt) == false).ToArray(); var options = metaData.Split(';').Where(opt => string.IsNullOrEmpty(opt) == false).ToArray();
@ -166,7 +174,7 @@ namespace BizHawk.Emulation.Common
{ {
var parts = opt.Split('='); var parts = opt.Split('=');
var key = parts[0]; var key = parts[0];
var value = parts.Length > 1 ? parts[1] : ""; var value = parts.Length > 1 ? parts[1] : string.Empty;
Options[key] = value; Options[key] = value;
} }
} }

View File

@ -1,6 +1,6 @@
namespace BizHawk.Emulation.Common namespace BizHawk.Emulation.Common
{ {
public enum SyncSoundMode { Sync, Async }; public enum SyncSoundMode { Sync, Async }
/// <summary> /// <summary>
/// This service provides the ability to output sound from the client, /// This service provides the ability to output sound from the client,

View File

@ -1,6 +1,4 @@
using System.Collections.Generic; namespace BizHawk.Emulation.Common
namespace BizHawk.Emulation.Common
{ {
public interface ITraceSink public interface ITraceSink
{ {

View File

@ -6,30 +6,31 @@ namespace BizHawk.Emulation.Common
{ {
public sealed class Equalizer public sealed class Equalizer
{ {
double lowFilter; private double lowFilter;
double lowFilterPole0; private double lowFilterPole0;
double lowFilterPole1; private double lowFilterPole1;
double lowFilterPole2; private double lowFilterPole2;
double lowFilterPole3; private double lowFilterPole3;
double highFilter; private double highFilter;
double highFilterPole0; private double highFilterPole0;
double highFilterPole1; private double highFilterPole1;
double highFilterPole2; private double highFilterPole2;
double highFilterPole3; private double highFilterPole3;
double sampleDataMinus1; private double sampleDataMinus1;
double sampleDataMinus2; private double sampleDataMinus2;
double sampleDataMinus3; private double sampleDataMinus3;
double lowGain; private double lowGain;
double midGain; private double midGain;
double highGain; private double highGain;
const double sampleRate = 44100.0; private const double sampleRate = 44100.0;
const double verySmallAmount = (1.0 / 4294967295.0); private const double verySmallAmount = 1.0 / 4294967295.0;
private double lowfreq;
double lowfreq;
public double LowFreqCutoff public double LowFreqCutoff
{ {
get { return lowfreq; } get { return lowfreq; }
@ -40,7 +41,7 @@ namespace BizHawk.Emulation.Common
} }
} }
double highfreq; private double highfreq;
public double HighFreqCutoff public double HighFreqCutoff
{ {
get { return highfreq; } get { return highfreq; }
@ -89,7 +90,9 @@ namespace BizHawk.Emulation.Common
public void Equalize(short[] samples) public void Equalize(short[] samples)
{ {
for (int i = 0; i < samples.Length; i++) for (int i = 0; i < samples.Length; i++)
{
samples[i] = EqualizeSample(samples[i]); samples[i] = EqualizeSample(samples[i]);
} }
} }
} }
}

View File

@ -64,7 +64,7 @@ namespace BizHawk.Emulation.Common
// is to provide exact amounts of output samples, // is to provide exact amounts of output samples,
// even when the input provided varies.... // even when the input provided varies....
int output_samples(short[] buf, int samples_requested); int output_samples(short[] buf, int samples_requested);
}; }
public enum ESynchMethod public enum ESynchMethod
{ {
@ -72,7 +72,7 @@ namespace BizHawk.Emulation.Common
ESynchMethod_Z, // zero's ESynchMethod_Z, // zero's
//ESynchMethod_P, //PCSX2 spu2-x //ohno! not available yet in c# //ESynchMethod_P, //PCSX2 spu2-x //ohno! not available yet in c#
ESynchMethod_V // vecna ESynchMethod_V // vecna
}; }
public static class Metaspu public static class Metaspu
{ {
@ -136,8 +136,10 @@ namespace BizHawk.Emulation.Common
if (!mixqueue_go) if (!mixqueue_go)
{ {
if (adjustobuf.size > 200) if (adjustobuf.size > 200)
{
mixqueue_go = true; mixqueue_go = true;
} }
}
else else
{ {
for (int i = 0; i < samples_requested; i++) for (int i = 0; i < samples_requested; i++)
@ -147,6 +149,7 @@ namespace BizHawk.Emulation.Common
mixqueue_go = false; mixqueue_go = false;
break; break;
} }
done++; done++;
short left, right; short left, right;
adjustobuf.dequeue(out left, out right); adjustobuf.dequeue(out left, out right);
@ -159,7 +162,8 @@ namespace BizHawk.Emulation.Common
} }
private readonly Adjustobuf adjustobuf; private readonly Adjustobuf adjustobuf;
class Adjustobuf
private class Adjustobuf
{ {
public Adjustobuf(int _minLatency, int _maxLatency) public Adjustobuf(int _minLatency, int _maxLatency)
{ {
@ -168,12 +172,12 @@ namespace BizHawk.Emulation.Common
clear(); clear();
} }
float rate, cursor; private float rate, cursor;
int minLatency, targetLatency, maxLatency; private int minLatency, targetLatency, maxLatency;
Queue<short> buffer = new Queue<short>(); private readonly Queue<short> buffer = new Queue<short>();
Queue<int> statsHistory = new Queue<int>(); private readonly Queue<int> statsHistory = new Queue<int>();
public int size = 0; public int size = 0;
short[] curr = new short[2]; private readonly short[] curr = new short[2];
public void clear() public void clear()
{ {
@ -195,11 +199,11 @@ namespace BizHawk.Emulation.Common
size++; size++;
} }
long rollingTotalSize; private long rollingTotalSize;
uint kAverageSize; private uint kAverageSize;
void addStatistic() private void addStatistic()
{ {
statsHistory.Enqueue(size); statsHistory.Enqueue(size);
rollingTotalSize += size; rollingTotalSize += size;
@ -227,15 +231,17 @@ namespace BizHawk.Emulation.Common
} }
} }
} }
public void dequeue(out short left, out short right) public void dequeue(out short left, out short right)
{ {
left = right = 0; left = right = 0;
addStatistic(); addStatistic();
if (size == 0) { return; } if (size == 0)
{
return;
}
cursor += rate; cursor += rate;
while (cursor > 1.0f) while (cursor > 1.0f)
{ {
@ -254,22 +260,29 @@ namespace BizHawk.Emulation.Common
} }
} }
class NitsujaSynchronizer : ISynchronizingAudioBuffer internal class NitsujaSynchronizer : ISynchronizingAudioBuffer
{ {
struct ssamp private struct ssamp
{ {
public short l, r; public short l, r;
public ssamp(short ll, short rr) { l = ll; r = rr; }
};
readonly List<ssamp> sampleQueue = new List<ssamp>(); public ssamp(short ll, short rr)
{
l = ll; r = rr;
}
}
private readonly List<ssamp> sampleQueue = new List<ssamp>();
// returns values going between 0 and y-1 in a saw wave pattern, based on x // returns values going between 0 and y-1 in a saw wave pattern, based on x
static int pingpong(int x, int y) private static int pingpong(int x, int y)
{ {
x %= 2 * y; x %= 2 * y;
if (x >= y) if (x >= y)
x = 2 * y - x - 1; {
x = (2 * y) - x - 1;
}
return x; return x;
// in case we want to switch to odd buffer sizes for more sharpness // in case we want to switch to odd buffer sizes for more sharpness
@ -279,12 +292,17 @@ namespace BizHawk.Emulation.Common
//return x; //return x;
} }
static ssamp crossfade(ssamp lhs, ssamp rhs, int cur, int start, int end) private static ssamp crossfade(ssamp lhs, ssamp rhs, int cur, int start, int end)
{ {
if (cur <= start) if (cur <= start)
{
return lhs; return lhs;
}
if (cur >= end) if (cur >= end)
{
return rhs; return rhs;
}
// in case we want sine wave interpolation instead of linear here // in case we want sine wave interpolation instead of linear here
//float ang = 3.14159f * (float)(cur - start) / (float)(end - start); //float ang = 3.14159f * (float)(cur - start) / (float)(end - start);
@ -305,28 +323,38 @@ namespace BizHawk.Emulation.Common
sampleQueue.Clear(); sampleQueue.Clear();
} }
static void emit_sample(short[] outbuf, ref int cursor, ssamp sample) private static void emit_sample(short[] outbuf, ref int cursor, ssamp sample)
{ {
outbuf[cursor++] = sample.l; outbuf[cursor++] = sample.l;
outbuf[cursor++] = sample.r; outbuf[cursor++] = sample.r;
} }
static void emit_samples(short[] outbuf, ref int outcursor, ssamp[] samplebuf, int incursor, int samples) private static void emit_samples(short[] outbuf, ref int outcursor, ssamp[] samplebuf, int incursor, int samples)
{ {
for (int i = 0; i < samples; i++) for (int i = 0; i < samples; i++)
{
emit_sample(outbuf, ref outcursor, samplebuf[i + incursor]); emit_sample(outbuf, ref outcursor, samplebuf[i + incursor]);
} }
static short abs(short value)
{
if (value < 0) return (short)-value;
else return value;
} }
static int abs(int value) private static short abs(short value)
{ {
if (value < 0) return -value; if (value < 0)
else return value; {
return (short)-value;
}
return value;
}
private static int abs(int value)
{
if (value < 0)
{
return -value;
}
return value;
} }
public void enqueue_samples(short[] buf, int samples_provided) public void enqueue_samples(short[] buf, int samples_provided)
@ -420,6 +448,7 @@ namespace BizHawk.Emulation.Common
beststart = i; beststart = i;
} }
} }
for (int i = queued - 3; i > queued - 3 - 128; i -= 2) for (int i = queued - 3; i > queued - 3 - 128; i -= 2)
{ {
int diff = abs(sampleQueue[i].l - sampleQueue[i + 1].l) + abs(sampleQueue[i].r - sampleQueue[i + 1].r); int diff = abs(sampleQueue[i].l - sampleQueue[i + 1].l) + abs(sampleQueue[i].r - sampleQueue[i + 1].r);
@ -435,13 +464,17 @@ namespace BizHawk.Emulation.Common
int oksize = queued; int oksize = queued;
while (oksize + queued * 2 + beststart + extraAtEnd <= samples_requested) while (oksize + queued * 2 + beststart + extraAtEnd <= samples_requested)
{
oksize += queued * 2; oksize += queued * 2;
}
audiosize = oksize; audiosize = oksize;
for (int x = 0; x < beststart; x++) for (int x = 0; x < beststart; x++)
{ {
emit_sample(buf, ref bufcursor, sampleQueue[x]); emit_sample(buf, ref bufcursor, sampleQueue[x]);
} }
// sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart); // sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + beststart);
sampleQueue.RemoveRange(0, beststart); sampleQueue.RemoveRange(0, beststart);
// zero 08-nov-2010: did i do this right? // zero 08-nov-2010: did i do this right?
@ -456,7 +489,6 @@ namespace BizHawk.Emulation.Common
// midpointXOffset = min(something,somethingElse); // midpointXOffset = min(something,somethingElse);
// but it's a little difficult to work it out exactly // but it's a little difficult to work it out exactly
// so here's a stupid search for the value for now: // so here's a stupid search for the value for now:
int prevA = 999999; int prevA = 999999;
int midpointXOffset = queued / 2; int midpointXOffset = queued / 2;
while (true) while (true)
@ -494,9 +526,14 @@ namespace BizHawk.Emulation.Common
int dyMidLeft = (leftMidpointY < midpointY) ? 1 : -1; int dyMidLeft = (leftMidpointY < midpointY) ? 1 : -1;
int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1; int dyMidRight = (rightMidpointY > midpointY) ? 1 : -1;
for (int x = leftMidpointX; x < midpointX; x++, y += dyMidLeft) for (int x = leftMidpointX; x < midpointX; x++, y += dyMidLeft)
{
emit_sample(buf, ref bufcursor, sampleQueue[y]); emit_sample(buf, ref bufcursor, sampleQueue[y]);
}
for (int x = midpointX; x < rightMidpointX; x++, y += dyMidRight) for (int x = midpointX; x < rightMidpointX; x++, y += dyMidRight)
{
emit_sample(buf, ref bufcursor, sampleQueue[y]); emit_sample(buf, ref bufcursor, sampleQueue[y]);
}
// output the end of the queued sound (section "C") // output the end of the queued sound (section "C")
for (int x = rightMidpointX; x < audiosize; x++) for (int x = rightMidpointX; x < audiosize; x++)
@ -510,12 +547,14 @@ namespace BizHawk.Emulation.Common
int i = queued + x; int i = queued + x;
emit_sample(buf, ref bufcursor, sampleQueue[i]); emit_sample(buf, ref bufcursor, sampleQueue[i]);
} }
queued += extraAtEnd; queued += extraAtEnd;
audiosize += beststart + extraAtEnd; audiosize += beststart + extraAtEnd;
} // end else } // end else
// sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); // sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
sampleQueue.RemoveRange(0, queued); sampleQueue.RemoveRange(0, queued);
// zero 08-nov-2010: did i do this right? // zero 08-nov-2010: did i do this right?
return audiosize; return audiosize;
} }
@ -529,20 +568,23 @@ namespace BizHawk.Emulation.Common
// and entering the "slow motion speed" branch above. // and entering the "slow motion speed" branch above.
// but that's ok! because all of these branches sound similar enough that we can get away with it. // but that's ok! because all of these branches sound similar enough that we can get away with it.
// so the two cases actually complement each other. // so the two cases actually complement each other.
if (audiosize >= queued) if (audiosize >= queued)
{ {
emit_samples(buf, ref bufcursor, sampleQueue.ToArray(), 0, queued); emit_samples(buf, ref bufcursor, sampleQueue.ToArray(), 0, queued);
// sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued); // sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin() + queued);
sampleQueue.RemoveRange(0, queued); sampleQueue.RemoveRange(0, queued);
// zero 08-nov-2010: did i do this right? // zero 08-nov-2010: did i do this right?
return queued; return queued;
} }
else else
{ {
emit_samples(buf, ref bufcursor, sampleQueue.ToArray(), 0, audiosize); emit_samples(buf, ref bufcursor, sampleQueue.ToArray(), 0, audiosize);
// sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize); // sampleQueue.erase(sampleQueue.begin(), sampleQueue.begin()+audiosize);
sampleQueue.RemoveRange(0, audiosize); sampleQueue.RemoveRange(0, audiosize);
// zero 08-nov-2010: did i do this right? // zero 08-nov-2010: did i do this right?
return audiosize; return audiosize;
} }
@ -554,13 +596,10 @@ namespace BizHawk.Emulation.Common
{ {
return 0; return 0;
} }
} // output_samples } // output_samples
} // NitsujaSynchronizer
internal class VecnaSynchronizer : ISynchronizingAudioBuffer
}; //NitsujaSynchronizer
class VecnaSynchronizer : ISynchronizingAudioBuffer
{ {
// vecna's attempt at a fully synchronous sound provider. // vecna's attempt at a fully synchronous sound provider.
// It's similar in philosophy to my "BufferedAsync" provider, but BufferedAsync is not // It's similar in philosophy to my "BufferedAsync" provider, but BufferedAsync is not
@ -580,7 +619,7 @@ namespace BizHawk.Emulation.Common
// Since it has done this, it will go ahead and generate some excess silence in order // Since it has done this, it will go ahead and generate some excess silence in order
// to restock its excess buffer. // to restock its excess buffer.
struct Sample private struct Sample
{ {
public short left, right; public short left, right;
public Sample(short l, short r) public Sample(short l, short r)
@ -590,11 +629,11 @@ namespace BizHawk.Emulation.Common
} }
} }
Queue<Sample> buffer; private Queue<Sample> buffer;
Sample[] resampleBuffer; private Sample[] resampleBuffer;
const int SamplesInOneFrame = 735; private const int SamplesInOneFrame = 735;
const int MaxExcessSamples = 2048; private const int MaxExcessSamples = 2048;
public VecnaSynchronizer() public VecnaSynchronizer()
{ {
@ -603,8 +642,10 @@ namespace BizHawk.Emulation.Common
// Give us a little buffer wiggle-room // Give us a little buffer wiggle-room
for (int i = 0; i < 367; i++) for (int i = 0; i < 367; i++)
{
buffer.Enqueue(new Sample(0, 0)); buffer.Enqueue(new Sample(0, 0));
} }
}
public void enqueue_samples(short[] buf, int samples_provided) public void enqueue_samples(short[] buf, int samples_provided)
{ {
@ -624,6 +665,7 @@ namespace BizHawk.Emulation.Common
// if buffer is overfull, dequeue old samples to make room for new samples. // if buffer is overfull, dequeue old samples to make room for new samples.
buffer.Dequeue(); buffer.Dequeue();
} }
buffer.Enqueue(new Sample(left, right)); buffer.Enqueue(new Sample(left, right));
} }
@ -641,7 +683,6 @@ namespace BizHawk.Emulation.Common
{ {
// if we're within 75% of target, then I guess we suck it up and resample. // if we're within 75% of target, then I guess we suck it up and resample.
// we sample in a goofy way, we could probably do it a bit smarter, if we cared more. // we sample in a goofy way, we could probably do it a bit smarter, if we cared more.
int samples_available = buffer.Count; int samples_available = buffer.Count;
for (int i = 0; buffer.Count > 0; i++) for (int i = 0; buffer.Count > 0; i++)
resampleBuffer[i] = buffer.Dequeue(); resampleBuffer[i] = buffer.Dequeue();
@ -672,6 +713,7 @@ namespace BizHawk.Emulation.Common
buf[index++] += sample.right; buf[index++] += sample.right;
} }
} }
return samples_requested; return samples_requested;
} }
} }

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Common
/// </summary> /// </summary>
public class SpeexResampler : IDisposable, ISoundProvider public class SpeexResampler : IDisposable, ISoundProvider
{ {
static class LibSpeexDSP private static class LibSpeexDSP
{ {
public const int QUALITY_MAX = 10; public const int QUALITY_MAX = 10;
public const int QUALITY_MIN = 0; public const int QUALITY_MIN = 0;
@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Common
INVALID_ARG = 3, INVALID_ARG = 3,
PTR_OVERLAP = 4, PTR_OVERLAP = 4,
MAX_ERROR MAX_ERROR
}; }
/// <summary> /// <summary>
/// Create a new resampler with integer input and output rates. /// Create a new resampler with integer input and output rates.
@ -281,7 +281,7 @@ namespace BizHawk.Emulation.Common
/// throw an exception based on error state /// throw an exception based on error state
/// </summary> /// </summary>
/// <param name="e"></param> /// <param name="e"></param>
static void CheckError(LibSpeexDSP.RESAMPLER_ERR e) private static void CheckError(LibSpeexDSP.RESAMPLER_ERR e)
{ {
switch (e) switch (e)
{ {
@ -299,7 +299,6 @@ namespace BizHawk.Emulation.Common
} }
/// <summary> /// <summary>
///
/// </summary> /// </summary>
/// <param name="quality">0 to 10</param> /// <param name="quality">0 to 10</param>
/// <param name="rationum">numerator of srate change ratio (inrate / outrate)</param> /// <param name="rationum">numerator of srate change ratio (inrate / outrate)</param>
@ -311,13 +310,17 @@ namespace BizHawk.Emulation.Common
public SpeexResampler(int quality, uint rationum, uint ratioden, uint sratein, uint srateout, Action<short[], int> drainer = null, ISoundProvider input = null) public SpeexResampler(int quality, uint rationum, uint ratioden, uint sratein, uint srateout, Action<short[], int> drainer = null, ISoundProvider input = null)
{ {
if (drainer != null && input != null) if (drainer != null && input != null)
{
throw new ArgumentException("Can't autofetch without being an ISyncSoundProvider?"); throw new ArgumentException("Can't autofetch without being an ISyncSoundProvider?");
}
LibSpeexDSP.RESAMPLER_ERR err = LibSpeexDSP.RESAMPLER_ERR.SUCCESS; LibSpeexDSP.RESAMPLER_ERR err = LibSpeexDSP.RESAMPLER_ERR.SUCCESS;
st = LibSpeexDSP.speex_resampler_init_frac(2, rationum, ratioden, sratein, srateout, quality, ref err); st = LibSpeexDSP.speex_resampler_init_frac(2, rationum, ratioden, sratein, srateout, quality, ref err);
if (st == IntPtr.Zero) if (st == IntPtr.Zero)
{
throw new Exception("LibSpeexDSP returned null!"); throw new Exception("LibSpeexDSP returned null!");
}
CheckError(err); CheckError(err);
@ -349,8 +352,10 @@ namespace BizHawk.Emulation.Common
inbuf[inbufpos++] = right; inbuf[inbufpos++] = right;
if (inbufpos == inbuf.Length) if (inbufpos == inbuf.Length)
{
Flush(); Flush();
} }
}
/// <summary> /// <summary>
/// add multiple samples to the queue /// add multiple samples to the queue
@ -369,9 +374,11 @@ namespace BizHawk.Emulation.Common
numused += shortstocopy / 2; numused += shortstocopy / 2;
if (inbufpos == inbuf.Length) if (inbufpos == inbuf.Length)
{
Flush(); Flush();
} }
} }
}
/// <summary> /// <summary>
@ -386,9 +393,11 @@ namespace BizHawk.Emulation.Common
LibSpeexDSP.speex_resampler_process_interleaved_int(st, inbuf, ref inal, outbuf, ref outal); LibSpeexDSP.speex_resampler_process_interleaved_int(st, inbuf, ref inal, outbuf, ref outal);
// reset inbuf // reset inbuf
if (inal != inbufpos / 2) if (inal != inbufpos / 2)
{
throw new Exception("Speexresampler didn't eat the whole array?"); throw new Exception("Speexresampler didn't eat the whole array?");
}
inbufpos = 0; inbufpos = 0;
//Buffer.BlockCopy(inbuf, (int)inal * 2 * sizeof(short), inbuf, 0, inbufpos - (int)inal * 2); //Buffer.BlockCopy(inbuf, (int)inal * 2 * sizeof(short), inbuf, 0, inbufpos - (int)inal * 2);
@ -413,7 +422,7 @@ namespace BizHawk.Emulation.Common
Dispose(); Dispose();
} }
void InternalDrain(short[] buf, int nsamp) private void InternalDrain(short[] buf, int nsamp)
{ {
if (outbuf2pos + nsamp * 2 > outbuf2.Length) if (outbuf2pos + nsamp * 2 > outbuf2.Length)
{ {
@ -421,6 +430,7 @@ namespace BizHawk.Emulation.Common
Buffer.BlockCopy(outbuf2, 0, newbuf, 0, outbuf2pos * sizeof(short)); Buffer.BlockCopy(outbuf2, 0, newbuf, 0, outbuf2pos * sizeof(short));
outbuf2 = newbuf; outbuf2 = newbuf;
} }
Buffer.BlockCopy(buf, 0, outbuf2, outbuf2pos * sizeof(short), nsamp * 2 * sizeof(short)); Buffer.BlockCopy(buf, 0, outbuf2, outbuf2pos * sizeof(short), nsamp * 2 * sizeof(short));
outbuf2pos += nsamp * 2; outbuf2pos += nsamp * 2;
} }
@ -434,6 +444,7 @@ namespace BizHawk.Emulation.Common
input.GetSamplesSync(out sampin, out nsampin); input.GetSamplesSync(out sampin, out nsampin);
EnqueueSamples(sampin, nsampin); EnqueueSamples(sampin, nsampin);
} }
Flush(); Flush();
nsamp = outbuf2pos / 2; nsamp = outbuf2pos / 2;
samples = outbuf2; samples = outbuf2;
@ -445,15 +456,9 @@ namespace BizHawk.Emulation.Common
outbuf2pos = 0; outbuf2pos = 0;
} }
public bool CanProvideAsync public bool CanProvideAsync => false;
{
get { return false; }
}
public SyncSoundMode SyncMode public SyncSoundMode SyncMode => SyncSoundMode.Sync;
{
get { return SyncSoundMode.Sync; }
}
public void GetSamplesAsync(short[] samples) public void GetSamplesAsync(short[] samples)
{ {

View File

@ -29,8 +29,10 @@
{ {
int r = rnd.Next(); int r = rnd.Next();
if ((r & 1) > 0) if ((r & 1) > 0)
{
NoiseWave[i] = short.MaxValue; NoiseWave[i] = short.MaxValue;
} }
}
/*TriangleWave = new short[512]; /*TriangleWave = new short[512];
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)

View File

@ -18,8 +18,8 @@ namespace BizHawk.Emulation.Common
public class Node public class Node
{ {
public Dictionary<string, byte[]> Data = new Dictionary<string, byte[]>(); public readonly Dictionary<string, byte[]> Data = new Dictionary<string, byte[]>();
public Dictionary<string, Node> Objects = new Dictionary<string, Node>(); public readonly Dictionary<string, Node> Objects = new Dictionary<string, Node>();
// methods named "ShouldSerialize*" are detected and dynamically invoked by JSON.NET // methods named "ShouldSerialize*" are detected and dynamically invoked by JSON.NET
// if they return false during serialization, the field/prop is omitted from the created json // if they return false during serialization, the field/prop is omitted from the created json
@ -34,13 +34,13 @@ namespace BizHawk.Emulation.Common
} }
} }
public Node Root = new Node(); public readonly Node Root = new Node();
[JsonIgnore] [JsonIgnore]
Stack<Node> Nodes; Stack<Node> Nodes;
[JsonIgnore] [JsonIgnore]
Node Current { get { return Nodes.Peek(); } } private Node Current => Nodes.Peek();
public void Prepare() public void Prepare()
{ {
@ -59,7 +59,10 @@ namespace BizHawk.Emulation.Common
{ {
byte[] d = Current.Data[name]; byte[] d = Current.Data[name];
if (length != d.Length) if (length != d.Length)
{
throw new InvalidOperationException(); throw new InvalidOperationException();
}
Marshal.Copy(d, 0, data, length); Marshal.Copy(d, 0, data, length);
} }
@ -87,6 +90,7 @@ namespace BizHawk.Emulation.Common
next = new Node(); next = new Node();
Current.Objects.Add(name, next); Current.Objects.Add(name, next);
} }
Nodes.Push(next); Nodes.Push(next);
} }
@ -94,8 +98,10 @@ namespace BizHawk.Emulation.Common
{ {
Node last = Nodes.Pop(); Node last = Nodes.Pop();
if (Current.Objects[name] != last) if (Current.Objects[name] != last)
{
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
}
// other data besides the core // other data besides the core
public T ExtraData; public T ExtraData;

View File

@ -1,4 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantCaseLabel/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1101/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1101/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1108/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1108/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1126/@EntryIndexedValue">DO_NOT_SHOW</s:String> <s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1126/@EntryIndexedValue">DO_NOT_SHOW</s:String>

View File

@ -1,4 +1,3 @@
using System;
using System.IO; using System.IO;
static class VersionInfo static class VersionInfo