misc code cleanups in BizHawk.Emulation.Common
This commit is contained in:
parent
8eda3dfe16
commit
7ab8455e84
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -62,10 +62,7 @@ namespace BizHawk.Emulation.Common
|
|||
{
|
||||
if ((hadAny && !hasAny) || (!hadAny && hasAny))
|
||||
{
|
||||
if (ActiveChanged != null)
|
||||
{
|
||||
ActiveChanged();
|
||||
}
|
||||
ActiveChanged?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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..
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ using System.IO;
|
|||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
|
||||
namespace BizHawk.Emulation.Common
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
Loading…
Reference in New Issue