misc code cleanups in BizHawk.Emulation.Common

This commit is contained in:
adelikat 2017-04-14 12:28:23 -05:00
parent 8eda3dfe16
commit 7ab8455e84
28 changed files with 543 additions and 517 deletions

View File

@ -22,9 +22,7 @@ namespace BizHawk.Emulation.Common
// this removes the possibility of automagically picking up a service in a nested class, (find the type, then
// find the field), but we're going to keep such logic out of the basic provider. anything the passed
// core doesn't implement directly needs to be added with Register()
// this also fully allows services that are not IEmulatorService
Type coreType = core.GetType();
var services = coreType.GetInterfaces()

View File

@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Common
/// <seealso cref="ITraceable"/>
/// <seealso cref="IDebuggable"/>
/// <seealso cref="IMemoryDomains"/>
/// /// <seealso cref="IDisassemblable"/>
/// <seealso cref="IDisassemblable"/>
public abstract class CallbackBasedTraceBuffer : ITraceable
{
public CallbackBasedTraceBuffer(IDebuggable debuggableCore, IMemoryDomains memoryDomains, IDisassemblable disassembler)
@ -50,12 +50,9 @@ namespace BizHawk.Emulation.Common
private ITraceSink _sink;
public bool Enabled
{
get { return Sink != null; }
}
public void Put(TraceInfo info)
public bool Enabled => Sink != null;
public void Put(TraceInfo info)
{
Sink.Put(info);
}
@ -87,27 +84,15 @@ namespace BizHawk.Emulation.Common
Callback = callback;
}
public MemoryCallbackType Type
{
get { return MemoryCallbackType.Execute; }
}
public MemoryCallbackType Type => MemoryCallbackType.Execute;
public string Name
{
get { return "Trace Logging"; }
}
public string Name => "Trace Logging";
public Action Callback { get; private set; }
public Action Callback { get; }
public uint? Address
{
get { return null; }
}
public uint? Address => null;
public uint? AddressMask
{
get { return null; }
}
public uint? AddressMask => null;
}
}
}

View File

@ -65,12 +65,18 @@ namespace BizHawk.Emulation.Common
public void ApplyAxisConstraints(string constraintClass, IDictionary<string, float> floatButtons)
{
if (AxisConstraints == null) return;
if (AxisConstraints == null)
{
return;
}
foreach (var constraint in AxisConstraints)
{
if (constraint.Class != constraintClass)
{
continue;
}
switch (constraint.Type)
{
case AxisConstraintType.Circular:

View File

@ -62,10 +62,7 @@ namespace BizHawk.Emulation.Common
{
if ((hadAny && !hasAny) || (!hadAny && hasAny))
{
if (ActiveChanged != null)
{
ActiveChanged();
}
ActiveChanged?.Invoke();
}
}
}

View File

@ -66,7 +66,9 @@ namespace BizHawk.Emulation.Common
for (int i = 0; i < cbs.Count; i++)
{
if (!cbs[i].Address.HasValue || cbs[i].Address == (addr & cbs[i].AddressMask))
{
cbs[i].Callback();
}
}
}
@ -94,22 +96,13 @@ namespace BizHawk.Emulation.Common
}
}
public bool HasReads
{
get { return _hasReads; }
}
public bool HasReads => _hasReads;
public bool HasWrites
{
get { return _hasWrites; }
}
public bool HasWrites => _hasWrites;
public bool HasExecutes
{
get { return _hasExecutes; }
}
public bool HasExecutes => _hasExecutes;
private void UpdateHasVariables()
private void UpdateHasVariables()
{
_hasReads = Reads.Count > 0;
_hasWrites = Writes.Count > 0;
@ -122,14 +115,20 @@ namespace BizHawk.Emulation.Common
var writesToRemove = Writes.Where(imc => imc.Callback == action).ToList();
var execsToRemove = Execs.Where(imc => imc.Callback == action).ToList();
foreach(var read in readsToRemove)
foreach (var read in readsToRemove)
{
Reads.Remove(read);
}
foreach(var write in writesToRemove)
foreach (var write in writesToRemove)
{
Writes.Remove(write);
}
foreach(var exec in execsToRemove)
foreach (var exec in execsToRemove)
{
Execs.Remove(exec);
}
UpdateHasVariables();
@ -142,7 +141,10 @@ namespace BizHawk.Emulation.Common
{
bool newEmpty = !HasReads && !HasWrites && !HasExecutes;
if (newEmpty != _empty)
{
Changes();
}
_empty = newEmpty;
}
}
@ -154,11 +156,15 @@ namespace BizHawk.Emulation.Common
{
changed |= RemoveInternal(action) > 0;
}
if (changed)
{
bool newEmpty = !HasReads && !HasWrites && !HasExecutes;
if (newEmpty != _empty)
{
Changes();
}
_empty = newEmpty;
}
@ -168,17 +174,26 @@ namespace BizHawk.Emulation.Common
public void Clear()
{
// Remove one-by-one to avoid NotifyCollectionChangedAction.Reset events.
for(int i = (Reads.Count - 1); i >= 0; i--)
for (int i = Reads.Count - 1; i >= 0; i--)
{
Reads.RemoveAt(i);
}
for(int i = (Reads.Count - 1); i >= 0; i--)
for (int i = Reads.Count - 1; i >= 0; i--)
{
Writes.RemoveAt(i);
}
for(int i = (Reads.Count - 1); i >= 0; i--)
for (int i = Reads.Count - 1; i >= 0; i--)
{
Execs.RemoveAt(i);
}
if (!_empty)
{
Changes();
}
_empty = true;
UpdateHasVariables();
@ -195,10 +210,7 @@ namespace BizHawk.Emulation.Common
private void Changes()
{
if (ActiveChanged != null)
{
ActiveChanged();
}
ActiveChanged?.Invoke();
}
public void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
@ -208,19 +220,13 @@ namespace BizHawk.Emulation.Common
case NotifyCollectionChangedAction.Add:
foreach(IMemoryCallback callback in args.NewItems)
{
if(CallbackAdded != null)
{
CallbackAdded(callback);
}
CallbackAdded?.Invoke(callback);
}
break;
case NotifyCollectionChangedAction.Remove:
foreach(IMemoryCallback callback in args.OldItems)
{
if(CallbackRemoved != null)
{
CallbackRemoved(callback);
}
CallbackRemoved?.Invoke(callback);
}
break;
}
@ -276,13 +282,13 @@ namespace BizHawk.Emulation.Common
Name = name;
Callback = callback;
Address = address;
AddressMask = (mask.HasValue ? mask : 0xFFFFFFFF);
AddressMask = mask ?? 0xFFFFFFFF;
}
public MemoryCallbackType Type { get; private set; }
public string Name { get; private set; }
public Action Callback { get; private set; }
public uint? Address { get; private set; }
public uint? AddressMask { get; private set; }
public MemoryCallbackType Type { get; }
public string Name { get; }
public Action Callback { get; }
public uint? Address { get; }
public uint? AddressMask { get; }
}
}

View File

@ -1,135 +1,176 @@
using System;
namespace BizHawk.Emulation.Common
{
public class MemoryDomainDelegate : MemoryDomain
{
private Func<long, byte> _peek;
private Action<long, byte> _poke;
public Func<long, byte> Peek { get { return _peek; } set { _peek = value; } }
public Action<long, byte> Poke { get { return _poke; } set { _poke = value; Writable = value != null; } }
public override byte PeekByte(long addr)
{
return _peek(addr);
}
public override void PokeByte(long addr, byte val)
{
if (_poke != null)
_poke(addr, val);
}
public MemoryDomainDelegate(string name, long size, Endian endian, Func<long, byte> peek, Action<long, byte> poke, int wordSize)
{
Name = name;
EndianType = endian;
Size = size;
_peek = peek;
_poke = poke;
Writable = poke != null;
WordSize = wordSize;
}
}
public class MemoryDomainByteArray : MemoryDomain
{
private byte[] _data;
public byte[] Data { get { return _data; } set { _data = value; Size = _data.LongLength; } }
public override byte PeekByte(long addr)
{
return Data[addr];
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
Data[addr] = val;
}
public MemoryDomainByteArray(string name, Endian endian, byte[] data, bool writable, int wordSize)
{
Name = name;
EndianType = endian;
Data = data;
Writable = writable;
WordSize = wordSize;
}
}
public unsafe class MemoryDomainIntPtr : MemoryDomain
{
public IntPtr Data { get; set; }
public override byte PeekByte(long addr)
using System;
namespace BizHawk.Emulation.Common
{
public class MemoryDomainDelegate : MemoryDomain
{
private Func<long, byte> _peek;
private Action<long, byte> _poke;
public Func<long, byte> Peek
{
if ((ulong)addr < (ulong)Size)
return ((byte*)Data)[addr];
else
throw new ArgumentOutOfRangeException(nameof(addr));
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
{
if ((ulong)addr < (ulong)Size)
((byte*)Data)[addr] = val;
else
throw new ArgumentOutOfRangeException(nameof(addr));
}
get { return _peek; } set { _peek = value; }
}
public Action<long, byte> Poke
{
get
{
return _poke;
}
set
{
_poke = value;
Writable = value != null;
}
}
public override byte PeekByte(long addr)
{
return _peek(addr);
}
public override void PokeByte(long addr, byte val)
{
_poke?.Invoke(addr, val);
}
public MemoryDomainDelegate(string name, long size, Endian endian, Func<long, byte> peek, Action<long, byte> poke, int wordSize)
{
Name = name;
EndianType = endian;
Size = size;
_peek = peek;
_poke = poke;
Writable = poke != null;
WordSize = wordSize;
}
}
public class MemoryDomainByteArray : MemoryDomain
{
private byte[] _data;
public byte[] Data
{
get
{
return _data;
}
set
{
_data = value;
Size = _data.LongLength;
}
}
public override byte PeekByte(long addr)
{
return Data[addr];
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
{
Data[addr] = val;
}
}
public MemoryDomainByteArray(string name, Endian endian, byte[] data, bool writable, int wordSize)
{
Name = name;
EndianType = endian;
Data = data;
Writable = writable;
WordSize = wordSize;
}
}
public unsafe class MemoryDomainIntPtr : MemoryDomain
{
public IntPtr Data { get; set; }
public override byte PeekByte(long addr)
{
if ((ulong)addr < (ulong)Size)
{
return ((byte*)Data)[addr];
}
throw new ArgumentOutOfRangeException(nameof(addr));
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
{
if ((ulong)addr < (ulong)Size)
{
((byte*)Data)[addr] = val;
}
else
{
throw new ArgumentOutOfRangeException(nameof(addr));
}
}
}
public void SetSize(long size)
{
Size = size;
}
public MemoryDomainIntPtr(string name, Endian endian, IntPtr data, long size, bool writable, int wordSize)
{
Name = name;
EndianType = endian;
Data = data;
Size = size;
Writable = writable;
WordSize = wordSize;
}
}
public unsafe class MemoryDomainIntPtrSwap16 : MemoryDomain
{
public IntPtr Data { get; set; }
public override byte PeekByte(long addr)
{
if ((ulong)addr < (ulong)Size)
return ((byte*)Data)[addr ^ 1];
else
throw new ArgumentOutOfRangeException(nameof(addr));
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
}
public MemoryDomainIntPtr(string name, Endian endian, IntPtr data, long size, bool writable, int wordSize)
{
Name = name;
EndianType = endian;
Data = data;
Size = size;
Writable = writable;
WordSize = wordSize;
}
}
public unsafe class MemoryDomainIntPtrSwap16 : MemoryDomain
{
public IntPtr Data { get; set; }
public override byte PeekByte(long addr)
{
if ((ulong)addr < (ulong)Size)
{
if ((ulong)addr < (ulong)Size)
((byte*)Data)[addr ^ 1] = val;
else
throw new ArgumentOutOfRangeException(nameof(addr));
}
}
public MemoryDomainIntPtrSwap16(string name, Endian endian, IntPtr data, long size, bool writable)
{
Name = name;
EndianType = endian;
Data = data;
Size = size;
Writable = writable;
WordSize = 2;
}
}
}
return ((byte*)Data)[addr ^ 1];
}
throw new ArgumentOutOfRangeException(nameof(addr));
}
public override void PokeByte(long addr, byte val)
{
if (Writable)
{
if ((ulong)addr < (ulong)Size)
{
((byte*)Data)[addr ^ 1] = val;
}
else
{
throw new ArgumentOutOfRangeException(nameof(addr));
}
}
}
public MemoryDomainIntPtrSwap16(string name, Endian endian, IntPtr data, long size, bool writable)
{
Name = name;
EndianType = endian;
Data = data;
Size = size;
Writable = writable;
WordSize = 2;
}
}
}

View File

@ -1,122 +1,124 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace BizHawk.Emulation.Common
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace BizHawk.Emulation.Common
{
/// <summary>
/// A generic implementation of IMemoryDomain that can be used by any core
/// </summary>
/// <seealso cref="IMemoryDomains" />
public class MemoryDomainList : ReadOnlyCollection<MemoryDomain>, IMemoryDomains
{
private MemoryDomain _mainMemory;
private MemoryDomain _systemBus;
public bool Has(string name)
{
return this.FirstOrDefault((md) => md.Name == name) != null;
}
public MemoryDomainList(IList<MemoryDomain> domains)
: base(domains)
{
}
public MemoryDomain this[string name]
{
get
{
return this.FirstOrDefault(x => x.Name == name);
}
}
public MemoryDomain MainMemory
{
get
{
if (_mainMemory != null)
{
return _mainMemory;
}
return this.First();
}
set
{
_mainMemory = value;
}
}
public bool HasSystemBus
{
get
{
if (_systemBus != null)
{
return true;
}
return this.Any(x => x.Name == "System Bus");
}
}
public MemoryDomain SystemBus
{
get
{
if (_systemBus != null)
{
return _systemBus;
}
var bus = this.FirstOrDefault(x => x.Name == "System Bus");
if (bus != null)
{
return bus;
}
return MainMemory;
}
set
{
_systemBus = value;
}
}
/// <summary>
/// for core use only
/// </summary>
public void MergeList(MemoryDomainList other)
{
var domains = this.ToDictionary(m => m.Name);
foreach (var src in other)
{
MemoryDomain dst;
if (domains.TryGetValue(src.Name, out dst))
{
TryMerge<MemoryDomainByteArray>(dst, src, (d, s) => d.Data = s.Data);
TryMerge<MemoryDomainIntPtr>(dst, src, (d, s) => d.Data = s.Data);
TryMerge<MemoryDomainIntPtrSwap16>(dst, src, (d, s) => d.Data = s.Data);
TryMerge<MemoryDomainDelegate>(dst, src, (d, s) => { d.Peek = s.Peek; d.Poke = s.Poke; });
}
}
}
/// <summary>
/// big hacks
/// </summary>
private static void TryMerge<T>(MemoryDomain dest, MemoryDomain src, Action<T, T> func)
where T : MemoryDomain
{
var d1 = dest as T;
var s1 = src as T;
if (d1 != null && s1 != null)
func(d1, s1);
}
}
}
public class MemoryDomainList : ReadOnlyCollection<MemoryDomain>, IMemoryDomains
{
private MemoryDomain _mainMemory;
private MemoryDomain _systemBus;
public bool Has(string name)
{
return this.FirstOrDefault((md) => md.Name == name) != null;
}
public MemoryDomainList(IList<MemoryDomain> domains)
: base(domains)
{
}
public MemoryDomain this[string name]
{
get
{
return this.FirstOrDefault(x => x.Name == name);
}
}
public MemoryDomain MainMemory
{
get
{
if (_mainMemory != null)
{
return _mainMemory;
}
return this.First();
}
set
{
_mainMemory = value;
}
}
public bool HasSystemBus
{
get
{
if (_systemBus != null)
{
return true;
}
return this.Any(x => x.Name == "System Bus");
}
}
public MemoryDomain SystemBus
{
get
{
if (_systemBus != null)
{
return _systemBus;
}
var bus = this.FirstOrDefault(x => x.Name == "System Bus");
if (bus != null)
{
return bus;
}
return MainMemory;
}
set
{
_systemBus = value;
}
}
/// <summary>
/// for core use only
/// </summary>
public void MergeList(MemoryDomainList other)
{
var domains = this.ToDictionary(m => m.Name);
foreach (var src in other)
{
MemoryDomain dst;
if (domains.TryGetValue(src.Name, out dst))
{
TryMerge<MemoryDomainByteArray>(dst, src, (d, s) => d.Data = s.Data);
TryMerge<MemoryDomainIntPtr>(dst, src, (d, s) => d.Data = s.Data);
TryMerge<MemoryDomainIntPtrSwap16>(dst, src, (d, s) => d.Data = s.Data);
TryMerge<MemoryDomainDelegate>(dst, src, (d, s) => { d.Peek = s.Peek; d.Poke = s.Poke; });
}
}
}
/// <summary>
/// big hacks
/// </summary>
private static void TryMerge<T>(MemoryDomain dest, MemoryDomain src, Action<T, T> func)
where T : MemoryDomain
{
var d1 = dest as T;
var s1 = src as T;
if (d1 != null && s1 != null)
{
func(d1, s1);
}
}
}
}

View File

@ -29,21 +29,26 @@ namespace BizHawk.Emulation.Common
#region IEmulator
public IEmulatorServiceProvider ServiceProvider { get; private set; }
public IEmulatorServiceProvider ServiceProvider { get; }
public ControllerDefinition ControllerDefinition
{
get { return NullController.Instance.Definition; }
}
public ControllerDefinition ControllerDefinition => NullController.Instance.Definition;
public IController Controller { get; set; }
public IController Controller { get; set; }
public void FrameAdvance(bool render, bool rendersound)
{
if (render == false) return;
if (render == false)
{
return;
}
if (!_settings.SnowyDisplay)
{
if (_frameBufferClear) return;
if (_frameBufferClear)
{
return;
}
_frameBufferClear = true;
Array.Clear(FrameBuffer, 0, 256 * 192);
return;
@ -69,22 +74,24 @@ namespace BizHawk.Emulation.Common
Frame++;
}
public int Frame { get; set; }
public int Frame { get; private set; }
public string SystemId { get { return "NULL"; } }
public string SystemId => "NULL";
public bool DeterministicEmulation { get { return true; } }
public bool DeterministicEmulation => true;
public void ResetCounters()
public void ResetCounters()
{
Frame = 0;
}
public string BoardName { get { return null; } }
public string BoardName => null;
public CoreComm CoreComm { get; private set; }
public CoreComm CoreComm { get; }
public void Dispose() { }
public void Dispose()
{
}
#endregion
@ -95,32 +102,17 @@ namespace BizHawk.Emulation.Common
return FrameBuffer;
}
public int VirtualWidth
{
get { return 256; }
}
public int VirtualWidth => 256;
public int VirtualHeight
{
get { return 192; }
}
public int VirtualHeight => 192;
public int BufferWidth
{
get { return 256; }
}
public int BufferWidth => 256;
public int BufferHeight
{
get { return 192; }
}
public int BufferHeight => 192;
public int BackgroundColor
{
get { return 0; }
}
public int BackgroundColor => 0;
#endregion
#endregion
#region ISoundProvider
@ -166,12 +158,9 @@ namespace BizHawk.Emulation.Common
}
}
public bool CanProvideAsync
{
get { return true; }
}
public bool CanProvideAsync => true;
public SyncSoundMode SyncMode { get; private set; }
public SyncSoundMode SyncMode { get; private set; }
public void SetSyncMode(SyncSoundMode mode)
{

View File

@ -22,7 +22,6 @@ namespace BizHawk.Emulation.Common
/// <summary>
/// create a NullSound that provides an exact number of audio samples per call when in sync mode
/// </summary>
/// <param name="spf"></param>
public NullSound(int spf)
: this()
{
@ -33,41 +32,38 @@ namespace BizHawk.Emulation.Common
/// <summary>
/// create a NullSound that exactly matches a given framerate when in sync mode
/// </summary>
/// <param name="fpsNum"></param>
/// <param name="fpsDen"></param>
public NullSound(long fpsNum, long fpsDen)
{
_spfNumerator = fpsDen * 44100;
_spfDenominator = fpsNum;
}
public bool CanProvideAsync
{
get { return true; }
}
public bool CanProvideAsync => true;
public SyncSoundMode SyncMode
{
get;
private set;
}
public SyncSoundMode SyncMode { get; private set; }
public void GetSamplesSync(out short[] samples, out int nsamp)
{
if (SyncMode != SyncSoundMode.Sync)
{
throw new InvalidOperationException("Wrong sound mode");
}
int s = (int)((_spfNumerator + _remainder) / _spfDenominator);
_remainder = (_spfNumerator + _remainder) % _spfDenominator;
if (_buff.Length < s * 2)
{
_buff = new short[s * 2];
}
samples = _buff;
nsamp = s;
}
public void DiscardSamples() { }
public void DiscardSamples()
{
}
public void SetSyncMode(SyncSoundMode mode)
{
@ -77,7 +73,10 @@ namespace BizHawk.Emulation.Common
public void GetSamplesAsync(short[] samples)
{
if (SyncMode != SyncSoundMode.Async)
{
throw new InvalidOperationException("Wrong sound mode");
}
Array.Clear(samples, 0, samples.Length);
}
}

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Common.Base_Implementations
{
@ -13,23 +10,19 @@ namespace BizHawk.Emulation.Common.Base_Implementations
private short[] _buffer = new short[0];
private int _nsamp = 0;
public bool CanProvideAsync
{
get { return false; }
}
public bool CanProvideAsync => false;
public void SetSyncMode(SyncSoundMode mode)
public void SetSyncMode(SyncSoundMode mode)
{
if (mode != SyncSoundMode.Sync)
{
throw new ArgumentException("Only supports Sync mode");
}
}
public SyncSoundMode SyncMode
{
get { return SyncSoundMode.Sync; }
}
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
/// <summary>
/// <summary>
/// Add samples to be output. no queueing; must be drained every frame
/// </summary>
/// <param name="samples"></param>
@ -37,10 +30,15 @@ namespace BizHawk.Emulation.Common.Base_Implementations
public void PutSamples(short[] samples, int nsamp)
{
if (_nsamp != 0)
{
Console.WriteLine("Warning: Samples disappeared from SimpleSyncSoundProvider");
}
if (_buffer.Length < nsamp * 2)
{
_buffer = new short[nsamp * 2];
}
Array.Copy(samples, _buffer, nsamp * 2);
_nsamp = nsamp;
}

View File

@ -1,16 +1,15 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Linq.Expressions;
using System.IO;
using BizHawk.Common;
using BizHawk.Common.ReflectionExtensions;
using System.Collections.Concurrent;
using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Common
{
public class BinaryQuickSerializer

View File

@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using BizHawk.Common;
namespace BizHawk.Emulation.Common.BizInvoke
@ -24,9 +24,11 @@ namespace BizHawk.Emulation.Common.BizInvoke
{
var ret = Activator.CreateInstance(ImplType);
foreach (var f in Hooks)
{
f(ret, dll);
if (ConnectMonitor != null)
ConnectMonitor(ret, monitor);
}
ConnectMonitor?.Invoke(ret, monitor);
return ret;
}
}
@ -40,6 +42,7 @@ namespace BizHawk.Emulation.Common.BizInvoke
/// the assembly that all proxies are placed in
/// </summary>
private static readonly AssemblyBuilder ImplAssemblyBuilder;
/// <summary>
/// the module that all proxies are placed in
/// </summary>
@ -68,8 +71,12 @@ namespace BizHawk.Emulation.Common.BizInvoke
Impls.Add(baseType, impl);
}
}
if (impl.ConnectMonitor != null)
{
throw new InvalidOperationException("Class was previously proxied with a monitor!");
}
return (T)impl.Create(dll, null);
}
@ -86,22 +93,33 @@ namespace BizHawk.Emulation.Common.BizInvoke
Impls.Add(baseType, impl);
}
}
if (impl.ConnectMonitor == null)
{
throw new InvalidOperationException("Class was previously proxied without a monitor!");
}
return (T)impl.Create(dll, monitor);
}
private static InvokerImpl CreateProxy(Type baseType, bool monitor)
{
if (baseType.IsSealed)
{
throw new InvalidOperationException("Can't proxy a sealed type");
}
if (!baseType.IsPublic)
{
// the proxy type will be in a new assembly, so public is required here
throw new InvalidOperationException("Type must be public");
}
var baseConstructor = baseType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
if (baseConstructor == null)
{
throw new InvalidOperationException("Base type must have a zero arg constructor");
}
var baseMethods = baseType.GetMethods(BindingFlags.Instance | BindingFlags.Public)
.Select(m => new
@ -113,7 +131,9 @@ namespace BizHawk.Emulation.Common.BizInvoke
.ToList();
if (baseMethods.Count == 0)
{
throw new InvalidOperationException("Couldn't find any [BizImport] methods to proxy");
}
{
var uo = baseMethods.FirstOrDefault(a => !a.Info.IsVirtual || a.Info.IsFinal);
@ -288,6 +308,7 @@ namespace BizHawk.Emulation.Common.BizInvoke
// arg 0 is this, so + 1
nativeParamTypes.Add(EmitParamterLoad(il, i + 1, paramTypes[i]));
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, field);
il.EmitCalli(OpCodes.Calli, nativeCall, returnType, nativeParamTypes.ToArray());
@ -452,13 +473,9 @@ namespace BizHawk.Emulation.Common.BizInvoke
[AttributeUsage(AttributeTargets.Method)]
public class BizImportAttribute : Attribute
{
public CallingConvention CallingConvention
{
get { return _callingConvention; }
}
private readonly CallingConvention _callingConvention;
public CallingConvention CallingConvention { get; }
/// <summary>
/// <summary>
/// name of entry point; if not given, the method's name is used
/// </summary>
public string EntryPoint { get; set; }
@ -469,12 +486,11 @@ namespace BizHawk.Emulation.Common.BizInvoke
public bool Compatibility { get; set; }
/// <summary>
///
/// </summary>
/// <param name="c">unmanaged calling convention</param>
public BizImportAttribute(CallingConvention c)
{
_callingConvention = c;
CallingConvention = c;
}
}
}

View File

@ -19,18 +19,12 @@ namespace BizHawk.Emulation.Common
public ICoreFileProvider CoreFileProvider;
public double VsyncRate
{
get
{
return VsyncNum / (double)VsyncDen;
}
}
public double VsyncRate => VsyncNum / (double)VsyncDen;
public int VsyncNum = 60;
public int VsyncNum = 60;
public int VsyncDen = 1;
//a core should set these if you wish to provide rom status information yourself. otherwise it will be calculated by the frontend in a way you may not like, using RomGame-related concepts.
// a core should set these if you wish to provide rom status information yourself. otherwise it will be calculated by the frontend in a way you may not like, using RomGame-related concepts.
public string RomStatusAnnotation;
public string RomStatusDetails;
@ -40,7 +34,7 @@ namespace BizHawk.Emulation.Common
public int NominalWidth = 640;
public int NominalHeight = 480;
//I know we want to get rid of CoreComm, but while it's still here, I'll use it for this
// I know we want to get rid of CoreComm, but while it's still here, I'll use it for this
public string LaunchLibretroCore;
/// <summary>
@ -56,6 +50,6 @@ namespace BizHawk.Emulation.Common
public Func<int,int,bool,object> RequestGLContext;
public Action<object> ReleaseGLContext;
public Action<object> ActivateGLContext;
public Action DeactivateGLContext; //this shouldnt be necessary.. frontend should be changing context before it does anything.. but for now..
public Action DeactivateGLContext; // this shouldnt be necessary.. frontend should be changing context before it does anything.. but for now..
}
}

View File

@ -1,5 +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
//http://www.ross.net/crc/download/crc_v3.txt
// 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
namespace BizHawk.Emulation.Common
{
@ -22,6 +22,7 @@ namespace BizHawk.Emulation.Common
else
crc >>= 1;
}
CRC32Table[i] = crc;
}
}
@ -31,9 +32,8 @@ namespace BizHawk.Emulation.Common
uint Result = 0xFFFFFFFF;
foreach (var b in data)
Result = (((Result) >> 8) ^ CRC32Table[b ^ ((Result) & 0xFF)]);
return (int) ~Result;
}
}
}

View File

@ -4,7 +4,6 @@ using System.IO;
using System.Text;
using System.Threading;
using BizHawk.Common;
using BizHawk.Common.BufferExtensions;
namespace BizHawk.Emulation.Common

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Common
{
static FirmwareDatabase()
{
//FDS has two OK variants (http://tcrf.net/Family_Computer_Disk_System)
// FDS has two OK variants (http://tcrf.net/Family_Computer_Disk_System)
var fds_nintendo = File("57FE1BDEE955BB48D357E463CCBF129496930B62", 8192, "disksys-nintendo.rom", "Bios (Nintendo)");
var fds_twinfc = File("E4E41472C454F928E53EB10E0509BF7D1146ECC1", 8192, "disksys-nintendo.rom", "Bios (TwinFC)");
Firmware("NES", "Bios_FDS", "Bios");

View File

@ -6,7 +6,6 @@ namespace BizHawk.Emulation.Common
{
public MissingFirmwareException(string message) : base(message)
{
}
}
@ -18,7 +17,6 @@ namespace BizHawk.Emulation.Common
public UnsupportedGameException(string message)
: base(message)
{
}
}

View File

@ -1,7 +1,6 @@
using System;
using System.Linq;
using System.Reflection;
using BizHawk.Common.ReflectionExtensions;
using System.Runtime.CompilerServices;
namespace BizHawk.Emulation.Common.IEmulatorExtensions
@ -37,8 +36,6 @@ namespace BizHawk.Emulation.Common.IEmulatorExtensions
/// <summary>
/// Returns the core's VideoProvider, or a suitable dummy provider
/// </summary>
/// <param name="core"></param>
/// <returns></returns>
public static IVideoProvider AsVideoProviderOrDefault(this IEmulator core)
{
return core.ServiceProvider.GetService<IVideoProvider>()
@ -67,10 +64,8 @@ namespace BizHawk.Emulation.Common.IEmulatorExtensions
/// </summary>
public static ISoundProvider AsSoundProviderOrDefault(this IEmulator core)
{
var ret = core.ServiceProvider.GetService<ISoundProvider>();
if (ret == null)
ret = CachedNullSoundProviders.GetValue(core, e => new NullSound(e.CoreComm.VsyncNum, e.CoreComm.VsyncDen));
return ret;
return core.ServiceProvider.GetService<ISoundProvider>()
?? CachedNullSoundProviders.GetValue(core, e => new NullSound(e.CoreComm.VsyncNum, e.CoreComm.VsyncDen));
}
public static bool HasMemoryDomains(this IEmulator core)
@ -268,8 +263,7 @@ namespace BizHawk.Emulation.Common.IEmulatorExtensions
return false;
}
//once upon a time, we did a try { poke(peek) } here, but that was before Writable was added. the poke(peek) is not acceptable. If there are further problems, make sure Writable is correct.
// once upon a time, we did a try { poke(peek) } here, but that was before Writable was added. the poke(peek) is not acceptable. If there are further problems, make sure Writable is correct.
return true;
}

View File

@ -7,12 +7,12 @@
public interface IDriveLight : IEmulatorService
{
/// <summary>
/// Specifies whether there is currently a Drive light available
/// Gets a value indicating whether there is currently a Drive light available
/// </summary>
bool DriveLightEnabled { get; }
/// <summary>
/// Specifies whether the light is currently lit
/// Gets a value indicating whether the light is currently lit
/// </summary>
bool DriveLightOn { get; }
}

View File

@ -1,5 +1,5 @@
namespace BizHawk.Emulation.Common
{
namespace BizHawk.Emulation.Common
{
public enum SyncSoundMode { Sync, Async };
/// <summary>
@ -8,43 +8,43 @@
/// If unavailable the client will fallback to a default sound implementation
/// that generates empty samples (silence)
/// </summary>
public interface ISoundProvider : IEmulatorService
{
/// <summary>
/// Returns true if a core can provide Async sound
/// </summary>
bool CanProvideAsync { get; }
/// <summary>
/// Sets sync or async sound mode,
/// Sync should be the default mode if not set
/// All implementations must provide sync
/// If a core can not provide async sound and the mode is set to sync,
/// an NotSupportedException should be thrown
/// </summary>
void SetSyncMode(SyncSoundMode mode);
/// <summary>
/// Reports which mode the sound provider is currently in
/// </summary>
SyncSoundMode SyncMode { get; }
/// <summary>
/// Provides samples in syncmode
/// If the core is not in sync mode, this should throw an InvalidOperationException
/// </summary>
void GetSamplesSync(out short[] samples, out int nsamp);
/// <summary>
/// Provides samples in async mode
/// If the core is not in async mode, this shoudl throw an InvalidOperationException
/// </summary>
/// <param name="samples"></param>
void GetSamplesAsync(short[] samples);
/// <summary>
/// Discards stuff, is there anything more to say here?
/// </summary>
void DiscardSamples();
}
}
public interface ISoundProvider : IEmulatorService
{
/// <summary>
/// Returns true if a core can provide Async sound
/// </summary>
bool CanProvideAsync { get; }
/// <summary>
/// Sets sync or async sound mode,
/// Sync should be the default mode if not set
/// All implementations must provide sync
/// If a core can not provide async sound and the mode is set to sync,
/// an NotSupportedException should be thrown
/// </summary>
void SetSyncMode(SyncSoundMode mode);
/// <summary>
/// Reports which mode the sound provider is currently in
/// </summary>
SyncSoundMode SyncMode { get; }
/// <summary>
/// Provides samples in syncmode
/// If the core is not in sync mode, this should throw an InvalidOperationException
/// </summary>
void GetSamplesSync(out short[] samples, out int nsamp);
/// <summary>
/// Provides samples in async mode
/// If the core is not in async mode, this shoudl throw an InvalidOperationException
/// </summary>
/// <param name="samples"></param>
void GetSamplesAsync(short[] samples);
/// <summary>
/// Discards stuff, is there anything more to say here?
/// </summary>
void DiscardSamples();
}
}

View File

@ -11,7 +11,7 @@ namespace BizHawk.Emulation.Common
public interface IStatable : IEmulatorService
{
/// <summary>
/// true if the core would rather give a binary savestate than a text one. both must function regardless
/// Gets a value indicating whether the core would rather give a binary savestate than a text one. Both must function regardless
/// </summary>
bool BinarySaveStatesPreferred { get; }

View File

@ -9,7 +9,9 @@ namespace BizHawk.Emulation.Common
/// By Convention it should also throw a NotImplementedException
/// Any feature that does not have this attribute is assumed to be implemented
/// </summary>
public class FeatureNotImplemented : Attribute { }
public class FeatureNotImplemented : Attribute
{
}
/// <summary>
/// Should be added to any implementation of IEmulator to document any
@ -23,14 +25,7 @@ namespace BizHawk.Emulation.Common
{
public ServiceNotApplicable(params Type[] types)
{
if (types != null)
{
NotApplicableTypes = types.ToList();
}
else
{
NotApplicableTypes = new List<Type>();
}
NotApplicableTypes = types?.ToList() ?? new List<Type>();
}
public IEnumerable<Type> NotApplicableTypes { get; private set; }

View File

@ -39,7 +39,10 @@ namespace BizHawk.Emulation.Common
{
tmp[0] = source.GetService(propinfo.PropertyType);
if (tmp[0] == null)
{
return false;
}
propinfo.GetSetMethod(true).Invoke(target, tmp);
}
@ -48,6 +51,7 @@ namespace BizHawk.Emulation.Common
tmp[0] = source.GetService(propinfo.PropertyType);
propinfo.GetSetMethod(true).Invoke(target, tmp);
}
return true;
}
@ -59,7 +63,7 @@ namespace BizHawk.Emulation.Common
{
return targetType.GetPropertiesWithAttrib(typeof(RequiredService))
.Select(pi => pi.PropertyType)
.All(t => source.HasService(t));
.All(source.HasService);
}
}

View File

@ -5,17 +5,16 @@ namespace BizHawk.Emulation.Common
/// <summary>
/// implements a DC block filter on top of an ISoundProvider. rather simple.
/// </summary>
sealed public class DCFilter : ISoundProvider
public sealed class DCFilter : ISoundProvider
{
private ISoundProvider _soundProvider;
private int _latchL = 0;
private int _latchR = 0;
private int _accumL = 0;
private int _accumR = 0;
private readonly ISoundProvider _soundProvider;
private readonly int _depth;
private int _latchL;
private int _latchR;
private int _accumL;
private int _accumR;
private static int DepthFromFilterwidth(int filterwidth)
{
int ret = -2;
@ -24,6 +23,7 @@ namespace BizHawk.Emulation.Common
filterwidth >>= 1;
ret++;
}
return ret;
}
@ -82,19 +82,33 @@ namespace BizHawk.Emulation.Common
int bigL = _accumL >> 12;
int bigR = _accumR >> 12;
// check for clipping
if (bigL > 32767)
{
samplesout[i] = 32767;
}
else if (bigL < -32768)
{
samplesout[i] = -32768;
}
else
{
samplesout[i] = (short)bigL;
}
if (bigR > 32767)
{
samplesout[i + 1] = 32767;
}
else if (bigR < -32768)
{
samplesout[i + 1] = -32768;
}
else
{
samplesout[i + 1] = (short)bigR;
}
}
}
@ -122,17 +136,11 @@ namespace BizHawk.Emulation.Common
nsamp = nsampin;
}
public SyncSoundMode SyncMode
{
get { return _soundProvider.SyncMode; }
}
public SyncSoundMode SyncMode => _soundProvider.SyncMode;
public bool CanProvideAsync
{
get { return _soundProvider.CanProvideAsync; }
}
public bool CanProvideAsync => _soundProvider.CanProvideAsync;
public void SetSyncMode(SyncSoundMode mode)
public void SetSyncMode(SyncSoundMode mode)
{
_soundProvider.SetSyncMode(mode);
}

View File

@ -34,17 +34,11 @@ namespace BizHawk.Emulation.Common
buffer.clear();
}
public bool CanProvideAsync
{
get { return true; }
}
public bool CanProvideAsync => true;
public SyncSoundMode SyncMode
{
get { return SyncSoundMode.Async; }
}
public SyncSoundMode SyncMode => SyncSoundMode.Async;
public void SetSyncMode(SyncSoundMode mode)
public void SetSyncMode(SyncSoundMode mode)
{
if (mode != SyncSoundMode.Async)
{
@ -64,7 +58,7 @@ namespace BizHawk.Emulation.Common
void enqueue_sample(short left, short right);
void clear();
//returns the number of samples actually supplied, which may not match the number requested
// returns the number of samples actually supplied, which may not match the number requested
// ^^ what the hell is that supposed to mean.
// the entire point of an ISynchronzingAudioBuffer
// is to provide exact amounts of output samples,
@ -134,7 +128,7 @@ namespace BizHawk.Emulation.Common
}
}
//returns the number of samples actually supplied, which may not match the number requested
// returns the number of samples actually supplied, which may not match the number requested
public int output_samples(short[] buf, int samples_requested)
{
int ctr = 0;
@ -253,6 +247,7 @@ namespace BizHawk.Emulation.Common
size--;
}
}
left = curr[0];
right = curr[1];
}
@ -267,7 +262,7 @@ namespace BizHawk.Emulation.Common
public ssamp(short ll, short rr) { l = ll; r = rr; }
};
List<ssamp> sampleQueue = new List<ssamp>();
readonly List<ssamp> sampleQueue = new List<ssamp>();
// returns values going between 0 and y-1 in a saw wave pattern, based on x
static int pingpong(int x, int y)

View File

@ -1,8 +1,5 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace BizHawk.Emulation.Common
{

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Newtonsoft.Json;
@ -29,6 +27,7 @@ namespace BizHawk.Emulation.Common
{
return Data.Count > 0;
}
public bool ShouldSerializeObjects()
{
return Objects.Count > 0;
@ -39,6 +38,7 @@ namespace BizHawk.Emulation.Common
[JsonIgnore]
Stack<Node> Nodes;
[JsonIgnore]
Node Current { get { return Nodes.Peek(); } }
@ -54,6 +54,7 @@ namespace BizHawk.Emulation.Common
Marshal.Copy(data, d, 0, length);
Current.Data.Add(name, d); // will except for us if the key is already present
}
public void Load(IntPtr data, int length, string name)
{
byte[] d = Current.Data[name];
@ -61,17 +62,20 @@ namespace BizHawk.Emulation.Common
throw new InvalidOperationException();
Marshal.Copy(d, 0, data, length);
}
public void EnterSectionSave(string name)
{
Node next = new Node();
Current.Objects.Add(name, next);
Nodes.Push(next);
}
public void EnterSectionLoad(string name)
{
Node next = Current.Objects[name];
Nodes.Push(next);
}
public void EnterSection(string name)
{
// works for either save or load, but as a consequence cannot report intelligent
@ -85,6 +89,7 @@ namespace BizHawk.Emulation.Common
}
Nodes.Push(next);
}
public void ExitSection(string name)
{
Node last = Nodes.Pop();
@ -105,6 +110,7 @@ namespace BizHawk.Emulation.Common
ExitSection = new TextStateFPtrs.SectionFunction(ExitSection)
};
}
public TextStateFPtrs GetFunctionPointersLoad()
{
return new TextStateFPtrs
@ -116,6 +122,7 @@ namespace BizHawk.Emulation.Common
};
}
}
[StructLayout(LayoutKind.Sequential)]
public struct TextStateFPtrs
{
@ -129,6 +136,4 @@ namespace BizHawk.Emulation.Common
public SectionFunction EnterSection;
public SectionFunction ExitSection;
}
}

View File

@ -18,6 +18,7 @@
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=StyleCop_002ESA1210/@EntryIndexedValue">DO_NOT_SHOW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ARGB/@EntryIndexedValue">ARGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CDL/@EntryIndexedValue">CDL</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CGB/@EntryIndexedValue">CGB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DB/@EntryIndexedValue">DB</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IO/@EntryIndexedValue">IO</s:String></wpf:ResourceDictionary>