Merge pull request #1739 from TASVideos/lua-via-apihawk
Delegate Lua API to ApiHawk
This commit is contained in:
commit
9162c8d246
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||||
|
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class APISubsetContainer : IApiContainer
|
public class APISubsetContainer : IApiContainer
|
||||||
{
|
{
|
||||||
public Dictionary<Type, IExternalApi> Libraries { get; set; }
|
public Dictionary<Type, IExternalApi> Libraries { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,15 @@ namespace BizHawk.Client.Common
|
||||||
[Description("A library for interacting with the currently loaded emulator core")]
|
[Description("A library for interacting with the currently loaded emulator core")]
|
||||||
public sealed class EmuApi : IEmu
|
public sealed class EmuApi : IEmu
|
||||||
{
|
{
|
||||||
|
public EmuApi(Action<string> logCallback)
|
||||||
|
{
|
||||||
|
LogCallback = logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmuApi() : this(Console.WriteLine) {}
|
||||||
|
|
||||||
|
private readonly Action<string> LogCallback;
|
||||||
|
|
||||||
private static class EmuStatic
|
private static class EmuStatic
|
||||||
{
|
{
|
||||||
public static void DisplayVsync(bool enabled)
|
public static void DisplayVsync(bool enabled)
|
||||||
|
@ -37,8 +46,8 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
Global.Config.AutoMinimizeSkipping = enabled;
|
Global.Config.AutoMinimizeSkipping = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[RequiredService]
|
[RequiredService]
|
||||||
private IEmulator Emulator { get; set; }
|
private IEmulator Emulator { get; set; }
|
||||||
|
|
||||||
|
@ -100,7 +109,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()");
|
LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +130,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +153,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
||||||
}
|
}
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
|
@ -163,7 +172,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()");
|
LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +189,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()");
|
LogCallback($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -198,7 +207,7 @@ namespace BizHawk.Client.Common
|
||||||
return InputPollableCore.IsLagFrame;
|
return InputPollableCore.IsLagFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
LogCallback($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +219,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +230,7 @@ namespace BizHawk.Client.Common
|
||||||
return InputPollableCore.LagCount;
|
return InputPollableCore.LagCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
LogCallback($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +242,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
LogCallback($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,15 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class JoypadApi : IJoypad
|
public sealed class JoypadApi : IJoypad
|
||||||
{
|
{
|
||||||
|
public JoypadApi(Action<string> logCallback)
|
||||||
|
{
|
||||||
|
LogCallback = logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JoypadApi() : this(Console.WriteLine) {}
|
||||||
|
|
||||||
|
private readonly Action<string> LogCallback;
|
||||||
|
|
||||||
public Dictionary<string,dynamic> Get(int? controller = null)
|
public Dictionary<string,dynamic> Get(int? controller = null)
|
||||||
{
|
{
|
||||||
var buttons = new Dictionary<string, dynamic>();
|
var buttons = new Dictionary<string, dynamic>();
|
||||||
|
@ -42,7 +51,6 @@ namespace BizHawk.Client.Common
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: what about float controls?
|
|
||||||
public Dictionary<string, dynamic> GetImmediate()
|
public Dictionary<string, dynamic> GetImmediate()
|
||||||
{
|
{
|
||||||
var buttons = new Dictionary<string, dynamic>();
|
var buttons = new Dictionary<string, dynamic>();
|
||||||
|
@ -79,7 +87,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"invalid mnemonic string: {inputLogEntry}");
|
LogCallback($"invalid mnemonic string: {inputLogEntry}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,24 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
using BizHawk.Common.BufferExtensions;
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||||
using BizHawk.Common.BufferExtensions;
|
|
||||||
|
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class MemApi : MemApiBase, IMem
|
public sealed class MemApi : IMem
|
||||||
{
|
{
|
||||||
private MemoryDomain _currentMemoryDomain;
|
[RequiredService]
|
||||||
private bool _isBigEndian;
|
private IEmulator Emulator { get; set; }
|
||||||
public MemApi()
|
|
||||||
: base()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override MemoryDomain Domain
|
[OptionalService]
|
||||||
|
private IMemoryDomains MemoryDomainCore { get; set; }
|
||||||
|
|
||||||
|
private MemoryDomain _currentMemoryDomain;
|
||||||
|
|
||||||
|
private MemoryDomain Domain
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -33,11 +35,165 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
||||||
Console.WriteLine(error);
|
LogCallback(error);
|
||||||
throw new NotImplementedException(error);
|
throw new NotImplementedException(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _isBigEndian;
|
||||||
|
|
||||||
|
private IMemoryDomains DomainList
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (MemoryDomainCore != null)
|
||||||
|
{
|
||||||
|
return MemoryDomainCore;
|
||||||
|
}
|
||||||
|
|
||||||
|
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
||||||
|
LogCallback(error);
|
||||||
|
throw new NotImplementedException(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemApi(Action<string> logCallback)
|
||||||
|
{
|
||||||
|
LogCallback = logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemApi() : this(Console.WriteLine) {}
|
||||||
|
|
||||||
|
private readonly Action<string> LogCallback;
|
||||||
|
|
||||||
|
private string VerifyMemoryDomain(string domain)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (DomainList[domain] == null)
|
||||||
|
{
|
||||||
|
LogCallback($"Unable to find domain: {domain}, falling back to current");
|
||||||
|
return Domain.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
catch // Just in case
|
||||||
|
{
|
||||||
|
LogCallback($"Unable to find domain: {domain}, falling back to current");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Domain.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint ReadUnsignedByte(long addr, string domain = null)
|
||||||
|
{
|
||||||
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
return d.PeekByte(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogCallback($"Warning: attempted read of {addr} outside the memory size of {d.Size}");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteUnsignedByte(long addr, uint v, string domain = null)
|
||||||
|
{
|
||||||
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
if (d.CanPoke())
|
||||||
|
{
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
d.PokeByte(addr, (byte)v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogCallback($"Warning: attempted write to {addr} outside the memory size of {d.Size}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogCallback($"Error: the domain {d.Name} is not writable");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int U2S(uint u, int size)
|
||||||
|
{
|
||||||
|
var s = (int)u;
|
||||||
|
s <<= 8 * (4 - size);
|
||||||
|
s >>= 8 * (4 - size);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Endian Handling
|
||||||
|
|
||||||
|
private uint ReadUnsignedLittle(long addr, int size, string domain = null)
|
||||||
|
{
|
||||||
|
uint v = 0;
|
||||||
|
for (var i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
v |= ReadUnsignedByte(addr + i, domain) << (8 * i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint ReadUnsignedBig(long addr, int size, string domain = null)
|
||||||
|
{
|
||||||
|
uint v = 0;
|
||||||
|
for (var i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
v |= ReadUnsignedByte(addr + i, domain) << (8 * (size - 1 - i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteUnsignedLittle(long addr, uint v, int size, string domain = null)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
WriteUnsignedByte(addr + i, (v >> (8 * i)) & 0xFF, domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteUnsignedBig(long addr, uint v, int size, string domain = null)
|
||||||
|
{
|
||||||
|
for (var i = 0; i < size; ++i)
|
||||||
|
{
|
||||||
|
WriteUnsignedByte(addr + i, (v >> (8 * (size - 1 - i))) & 0xFF, domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int ReadSigned(long addr, int size, string domain = null)
|
||||||
|
{
|
||||||
|
return _isBigEndian
|
||||||
|
? U2S(ReadUnsignedBig(addr, size, domain), size)
|
||||||
|
: U2S(ReadUnsignedLittle(addr, size, domain), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private uint ReadUnsigned(long addr, int size, string domain = null)
|
||||||
|
{
|
||||||
|
return _isBigEndian
|
||||||
|
? ReadUnsignedBig(addr, size, domain)
|
||||||
|
: ReadUnsignedLittle(addr, size, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteSigned(long addr, int value, int size, string domain = null)
|
||||||
|
{
|
||||||
|
if (_isBigEndian) WriteUnsignedBig(addr, (uint)value, size, domain);
|
||||||
|
else WriteUnsignedLittle(addr, (uint)value, size, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteUnsigned(long addr, uint value, int size, string domain = null)
|
||||||
|
{
|
||||||
|
if (_isBigEndian) WriteUnsignedBig(addr, value, size, domain);
|
||||||
|
else WriteUnsignedLittle(addr, value, size, domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region Unique Library Methods
|
#region Unique Library Methods
|
||||||
|
|
||||||
public void SetBigEndian(bool enabled = true)
|
public void SetBigEndian(bool enabled = true)
|
||||||
|
@ -87,12 +243,12 @@ namespace BizHawk.Client.Common
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Console.WriteLine($"Unable to find domain: {domain}");
|
LogCallback($"Unable to find domain: {domain}");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
catch // Just in case
|
catch // Just in case
|
||||||
{
|
{
|
||||||
Console.WriteLine($"Unable to find domain: {domain}");
|
LogCallback($"Unable to find domain: {domain}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -106,13 +262,13 @@ namespace BizHawk.Client.Common
|
||||||
if (addr < 0 || addr >= d.Size)
|
if (addr < 0 || addr >= d.Size)
|
||||||
{
|
{
|
||||||
string error = $"Address {addr} is outside the bounds of domain {d.Name}";
|
string error = $"Address {addr} is outside the bounds of domain {d.Name}";
|
||||||
Console.WriteLine(error);
|
LogCallback(error);
|
||||||
throw new ArgumentOutOfRangeException(error);
|
throw new ArgumentOutOfRangeException(error);
|
||||||
}
|
}
|
||||||
if (addr + count > d.Size)
|
if (addr + count > d.Size)
|
||||||
{
|
{
|
||||||
string error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}";
|
string error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}";
|
||||||
Console.WriteLine(error);
|
LogCallback(error);
|
||||||
throw new ArgumentOutOfRangeException(error);
|
throw new ArgumentOutOfRangeException(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,42 +278,12 @@ namespace BizHawk.Client.Common
|
||||||
data[i] = d.PeekByte(addr + i);
|
data[i] = d.PeekByte(addr + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
using var hasher = System.Security.Cryptography.SHA256.Create();
|
using var hasher = SHA256.Create();
|
||||||
return hasher.ComputeHash(data).BytesToHexString();
|
return hasher.ComputeHash(data).BytesToHexString();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Endian Handling
|
|
||||||
|
|
||||||
private int ReadSigned(long addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
return _isBigEndian
|
|
||||||
? ReadSignedBig(addr, size, domain)
|
|
||||||
: ReadSignedLittle(addr, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
private uint ReadUnsigned(long addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
return _isBigEndian
|
|
||||||
? ReadUnsignedBig(addr, size, domain)
|
|
||||||
: ReadUnsignedLittle(addr, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteSigned(long addr, int value, int size, string domain = null)
|
|
||||||
{
|
|
||||||
if (_isBigEndian) WriteSignedBig(addr, value, size, domain);
|
|
||||||
else WriteSignedLittle(addr, value, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteUnsigned(long addr, uint value, int size, string domain = null)
|
|
||||||
{
|
|
||||||
if (_isBigEndian) WriteUnsignedBig(addr, value, size, domain);
|
|
||||||
else WriteUnsignedLittle(addr, value, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Common Special and Legacy Methods
|
#region Common Special and Legacy Methods
|
||||||
|
|
||||||
public uint ReadByte(long addr, string domain = null)
|
public uint ReadByte(long addr, string domain = null)
|
||||||
|
@ -170,24 +296,83 @@ namespace BizHawk.Client.Common
|
||||||
WriteUnsignedByte(addr, value, domain);
|
WriteUnsignedByte(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
public new List<byte> ReadByteRange(long addr, int length, string domain = null)
|
public List<byte> ReadByteRange(long addr, int length, string domain = null)
|
||||||
{
|
{
|
||||||
return base.ReadByteRange(addr, length, domain);
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
var lastAddr = length + addr;
|
||||||
|
var list = new List<byte>();
|
||||||
|
for (; addr <= lastAddr; addr++)
|
||||||
|
{
|
||||||
|
if (addr < d.Size)
|
||||||
|
list.Add(d.PeekByte(addr));
|
||||||
|
else {
|
||||||
|
LogCallback($"Warning: Attempted read {addr} outside memory domain size of {d.Size} in {nameof(ReadByteRange)}()");
|
||||||
|
list.Add(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void WriteByteRange(long addr, List<byte> memoryblock, string domain = null)
|
public void WriteByteRange(long addr, List<byte> memoryblock, string domain = null)
|
||||||
{
|
{
|
||||||
base.WriteByteRange(addr, memoryblock, domain);
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
if (d.CanPoke())
|
||||||
|
{
|
||||||
|
foreach (var m in memoryblock)
|
||||||
|
{
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
d.PokeByte(addr++, m);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogCallback($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in {nameof(WriteByteRange)}()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogCallback($"Error: the domain {d.Name} is not writable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public float ReadFloat(long addr, string domain = null)
|
public float ReadFloat(long addr, string domain = null)
|
||||||
{
|
{
|
||||||
return base.ReadFloat(addr, _isBigEndian, domain);
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
var val = d.PeekUint(addr, _isBigEndian);
|
||||||
|
var bytes = BitConverter.GetBytes(val);
|
||||||
|
return BitConverter.ToSingle(bytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogCallback($"Warning: Attempted read {addr} outside memory size of {d.Size}");
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteFloat(long addr, double value, string domain = null)
|
public void WriteFloat(long addr, double value, string domain = null)
|
||||||
{
|
{
|
||||||
base.WriteFloat(addr, value, _isBigEndian, domain);
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
if (d.CanPoke())
|
||||||
|
{
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
var dv = (float)value;
|
||||||
|
var bytes = BitConverter.GetBytes(dv);
|
||||||
|
var v = BitConverter.ToUInt32(bytes, 0);
|
||||||
|
d.PokeUint(addr, v, _isBigEndian);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogCallback($"Warning: Attempted write {addr} outside memory size of {d.Size}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LogCallback($"Error: the domain {Domain.Name} is not writable");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -217,6 +402,7 @@ namespace BizHawk.Client.Common
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 2 Byte
|
#region 2 Byte
|
||||||
|
|
||||||
public int ReadS16(long addr, string domain = null)
|
public int ReadS16(long addr, string domain = null)
|
||||||
{
|
{
|
||||||
return (short)ReadSigned(addr, 2, domain);
|
return (short)ReadSigned(addr, 2, domain);
|
||||||
|
@ -285,4 +471,4 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using BizHawk.Emulation.Common;
|
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
|
||||||
|
|
||||||
namespace BizHawk.Client.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for the Memory and MainMemory plugin libraries
|
|
||||||
/// </summary>
|
|
||||||
public abstract class MemApiBase : IExternalApi
|
|
||||||
{
|
|
||||||
[RequiredService]
|
|
||||||
protected IEmulator Emulator { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
protected IMemoryDomains MemoryDomainCore { get; set; }
|
|
||||||
|
|
||||||
protected abstract MemoryDomain Domain { get; }
|
|
||||||
|
|
||||||
protected MemApiBase()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
protected IMemoryDomains DomainList
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (MemoryDomainCore != null)
|
|
||||||
{
|
|
||||||
return MemoryDomainCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
|
||||||
Console.WriteLine(error);
|
|
||||||
throw new NotImplementedException(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string VerifyMemoryDomain(string domain)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DomainList[domain] == null)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Unable to find domain: {domain}, falling back to current");
|
|
||||||
return Domain.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return domain;
|
|
||||||
}
|
|
||||||
catch // Just in case
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Unable to find domain: {domain}, falling back to current");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Domain.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadUnsignedByte(long addr, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
return d.PeekByte(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"Warning: attempted read of {addr} outside the memory size of {d.Size}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteUnsignedByte(long addr, uint v, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (d.CanPoke())
|
|
||||||
{
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
d.PokeByte(addr, (byte)v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Warning: attempted write to {addr} outside the memory size of {d.Size}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error: the domain {d.Name} is not writable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static int U2S(uint u, int size)
|
|
||||||
{
|
|
||||||
var s = (int)u;
|
|
||||||
s <<= 8 * (4 - size);
|
|
||||||
s >>= 8 * (4 - size);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int ReadSignedLittle(long addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
return U2S(ReadUnsignedLittle(addr, size, domain), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadUnsignedLittle(long addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
uint v = 0;
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
v |= ReadUnsignedByte(addr + i, domain) << (8 * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int ReadSignedBig(long addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
return U2S(ReadUnsignedBig(addr, size, domain), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadUnsignedBig(long addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
uint v = 0;
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
v |= ReadUnsignedByte(addr + i, domain) << (8 * (size - 1 - i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteSignedLittle(long addr, int v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
WriteUnsignedLittle(addr, (uint)v, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteUnsignedLittle(long addr, uint v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr + i, (v >> (8 * i)) & 0xFF, domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteSignedBig(long addr, int v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
WriteUnsignedBig(addr, (uint)v, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteUnsignedBig(long addr, uint v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr + i, (v >> (8 * (size - 1 - i))) & 0xFF, domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region public Library implementations
|
|
||||||
|
|
||||||
protected List<byte> ReadByteRange(long addr, int length, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
var lastAddr = length + addr;
|
|
||||||
var list = new List<byte>();
|
|
||||||
for (; addr <= lastAddr; addr++)
|
|
||||||
{
|
|
||||||
if (addr < d.Size)
|
|
||||||
list.Add(d.PeekByte(addr));
|
|
||||||
else {
|
|
||||||
Console.WriteLine($"Warning: Attempted read {addr} outside memory domain size of {d.Size} in {nameof(ReadByteRange)}()");
|
|
||||||
list.Add(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteByteRange(long addr, List<byte> memoryblock, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (d.CanPoke())
|
|
||||||
{
|
|
||||||
foreach (var m in memoryblock)
|
|
||||||
{
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
d.PokeByte(addr++, m);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in {nameof(WriteByteRange)}()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error: the domain {d.Name} is not writable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float ReadFloat(long addr, bool bigEndian, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
var val = d.PeekUint(addr, bigEndian);
|
|
||||||
var bytes = BitConverter.GetBytes(val);
|
|
||||||
return BitConverter.ToSingle(bytes, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"Warning: Attempted read {addr} outside memory size of {d.Size}");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteFloat(long addr, double value, bool bigEndian, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (d.CanPoke())
|
|
||||||
{
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
var dv = (float)value;
|
|
||||||
var bytes = BitConverter.GetBytes(dv);
|
|
||||||
var v = BitConverter.ToUInt32(bytes, 0);
|
|
||||||
d.PokeUint(addr, v, bigEndian);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Warning: Attempted write {addr} outside memory size of {d.Size}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Error: the domain {Domain.Name} is not writable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,8 +8,14 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class MemorySaveStateApi : IMemorySaveState
|
public sealed class MemorySaveStateApi : IMemorySaveState
|
||||||
{
|
{
|
||||||
public MemorySaveStateApi()
|
public MemorySaveStateApi(Action<string> logCallback)
|
||||||
{ }
|
{
|
||||||
|
LogCallback = logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemorySaveStateApi() : this(Console.WriteLine) {}
|
||||||
|
|
||||||
|
private readonly Action<string> LogCallback;
|
||||||
|
|
||||||
[RequiredService]
|
[RequiredService]
|
||||||
private IStatable StatableCore { get; set; }
|
private IStatable StatableCore { get; set; }
|
||||||
|
@ -40,7 +46,7 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
Console.WriteLine("Unable to find the given savestate in memory");
|
LogCallback("Unable to find the given savestate in memory");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,15 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class MovieApi : IInputMovie
|
public sealed class MovieApi : IInputMovie
|
||||||
{
|
{
|
||||||
|
public MovieApi(Action<string> logCallback)
|
||||||
|
{
|
||||||
|
LogCallback = logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MovieApi() : this(Console.WriteLine) {}
|
||||||
|
|
||||||
|
private readonly Action<string> LogCallback;
|
||||||
|
|
||||||
private static class MoviePluginStatic
|
private static class MoviePluginStatic
|
||||||
{
|
{
|
||||||
public static string Filename()
|
public static string Filename()
|
||||||
|
@ -105,8 +114,6 @@ namespace BizHawk.Client.Common
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public MovieApi()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public bool StartsFromSavestate()
|
public bool StartsFromSavestate()
|
||||||
{
|
{
|
||||||
|
@ -122,7 +129,7 @@ namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
if (!Global.MovieSession.Movie.IsActive)
|
if (!Global.MovieSession.Movie.IsActive)
|
||||||
{
|
{
|
||||||
Console.WriteLine("No movie loaded");
|
LogCallback("No movie loaded");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +138,7 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
if (adapter == null)
|
if (adapter == null)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Can't get input of the last frame of the movie. Use the previous frame");
|
LogCallback("Can't get input of the last frame of the movie. Use the previous frame");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +180,7 @@ namespace BizHawk.Client.Common
|
||||||
var test = new FileInfo(filename);
|
var test = new FileInfo(filename);
|
||||||
if (test.Exists)
|
if (test.Exists)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"File {filename} already exists, will not overwrite");
|
LogCallback($"File {filename} already exists, will not overwrite");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
{
|
{
|
||||||
public interface ISaveState : IExternalApi
|
public interface ISaveState : IExternalApi
|
||||||
{
|
{
|
||||||
void Load(string path);
|
void Load(string path, bool suppressOSD = false);
|
||||||
void LoadSlot(int slotNum);
|
void LoadSlot(int slotNum, bool suppressOSD = false);
|
||||||
void Save(string path);
|
void Save(string path, bool suppressOSD = false);
|
||||||
void SaveSlot(int slotNum);
|
void SaveSlot(int slotNum, bool suppressOSD = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,6 @@
|
||||||
<Compile Include="Api\Classes\GameInfoApi.cs" />
|
<Compile Include="Api\Classes\GameInfoApi.cs" />
|
||||||
<Compile Include="Api\Classes\JoypadApi.cs" />
|
<Compile Include="Api\Classes\JoypadApi.cs" />
|
||||||
<Compile Include="Api\Classes\MemApi.cs" />
|
<Compile Include="Api\Classes\MemApi.cs" />
|
||||||
<Compile Include="Api\Classes\MemApiBase.cs" />
|
|
||||||
<Compile Include="Api\Classes\MemEventsApi.cs" />
|
<Compile Include="Api\Classes\MemEventsApi.cs" />
|
||||||
<Compile Include="Api\Classes\MemorySaveStateApi.cs" />
|
<Compile Include="Api\Classes\MemorySaveStateApi.cs" />
|
||||||
<Compile Include="Api\Classes\MovieApi.cs" />
|
<Compile Include="Api\Classes\MovieApi.cs" />
|
||||||
|
@ -171,7 +170,6 @@
|
||||||
<Compile Include="lua\LuaFunctionList.cs" />
|
<Compile Include="lua\LuaFunctionList.cs" />
|
||||||
<Compile Include="lua\LuaHelper.cs" />
|
<Compile Include="lua\LuaHelper.cs" />
|
||||||
<Compile Include="lua\LuaLibraryBase.cs" />
|
<Compile Include="lua\LuaLibraryBase.cs" />
|
||||||
<Compile Include="lua\LuaMemoryBase.cs" />
|
|
||||||
<Compile Include="lua\LuaSandbox.cs" />
|
<Compile Include="lua\LuaSandbox.cs" />
|
||||||
<Compile Include="lua\NamedLuaFunction.cs" />
|
<Compile Include="lua\NamedLuaFunction.cs" />
|
||||||
<Compile Include="miniz\LibMiniz.cs" />
|
<Compile Include="miniz\LibMiniz.cs" />
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
using BizHawk.Emulation.Common;
|
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
|
||||||
using BizHawk.Emulation.Cores.Nintendo.NES;
|
|
||||||
using BizHawk.Emulation.Cores.PCEngine;
|
|
||||||
using BizHawk.Emulation.Cores.Sega.MasterSystem;
|
|
||||||
using BizHawk.Emulation.Cores.WonderSwan;
|
|
||||||
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES;
|
|
||||||
|
|
||||||
using NLua;
|
using NLua;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
|
@ -16,29 +8,8 @@ using NLua;
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
[Description("A library for interacting with the currently loaded emulator core")]
|
[Description("A library for interacting with the currently loaded emulator core")]
|
||||||
public sealed class EmulatorLuaLibrary : LuaLibraryBase
|
public sealed class EmulatorLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
[RequiredService]
|
|
||||||
private IEmulator Emulator { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
private IDebuggable DebuggableCore { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
private IDisassemblable DisassemblableCore { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
private IMemoryDomains MemoryDomains { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
private IInputPollable InputPollableCore { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
private IRegionable RegionableCore { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
private IBoardInfo BoardInfo { get; set; }
|
|
||||||
|
|
||||||
public Action FrameAdvanceCallback { get; set; }
|
public Action FrameAdvanceCallback { get; set; }
|
||||||
public Action YieldCallback { get; set; }
|
public Action YieldCallback { get; set; }
|
||||||
|
|
||||||
|
@ -52,10 +23,7 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("emu.displayvsync( true );")]
|
[LuaMethodExample("emu.displayvsync( true );")]
|
||||||
[LuaMethod("displayvsync", "Sets the display vsync property of the emulator")]
|
[LuaMethod("displayvsync", "Sets the display vsync property of the emulator")]
|
||||||
public static void DisplayVsync(bool enabled)
|
public void DisplayVsync(bool enabled) => APIs.Emu.DisplayVsync(enabled);
|
||||||
{
|
|
||||||
Global.Config.VSync = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.frameadvance( );")]
|
[LuaMethodExample("emu.frameadvance( );")]
|
||||||
[LuaMethod("frameadvance", "Signals to the emulator to resume emulation. Necessary for any lua script while loop or else the emulator will freeze!")]
|
[LuaMethod("frameadvance", "Signals to the emulator to resume emulation. Necessary for any lua script while loop or else the emulator will freeze!")]
|
||||||
|
@ -66,269 +34,66 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local inemufra = emu.framecount( );")]
|
[LuaMethodExample("local inemufra = emu.framecount( );")]
|
||||||
[LuaMethod("framecount", "Returns the current frame count")]
|
[LuaMethod("framecount", "Returns the current frame count")]
|
||||||
public int FrameCount()
|
public int FrameCount() => APIs.Emu.FrameCount();
|
||||||
{
|
|
||||||
return Emulator.Frame;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local obemudis = emu.disassemble( 0x8000 );")]
|
[LuaMethodExample("local obemudis = emu.disassemble( 0x8000 );")]
|
||||||
[LuaMethod("disassemble", "Returns the disassembly object (disasm string and length int) for the given PC address. Uses System Bus domain if no domain name provided")]
|
[LuaMethod("disassemble", "Returns the disassembly object (disasm string and length int) for the given PC address. Uses System Bus domain if no domain name provided")]
|
||||||
public object Disassemble(uint pc, string name = "")
|
public object Disassemble(uint pc, string name = "") => APIs.Emu.Disassemble(pc, name);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DisassemblableCore == null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
int l;
|
|
||||||
MemoryDomain domain = MemoryDomains.SystemBus;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
domain = MemoryDomains[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
var d = DisassemblableCore.Disassemble(domain, pc, out l);
|
|
||||||
return new { disasm = d, length = l };
|
|
||||||
}
|
|
||||||
catch (NotImplementedException)
|
|
||||||
{
|
|
||||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDisassemblable.Disassemble)}()");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: what about 64 bit registers?
|
// TODO: what about 64 bit registers?
|
||||||
[LuaMethodExample("local inemuget = emu.getregister( emu.getregisters( )[ 0 ] );")]
|
[LuaMethodExample("local inemuget = emu.getregister( emu.getregisters( )[ 0 ] );")]
|
||||||
[LuaMethod("getregister", "returns the value of a cpu register or flag specified by name. For a complete list of possible registers or flags for a given core, use getregisters")]
|
[LuaMethod("getregister", "returns the value of a cpu register or flag specified by name. For a complete list of possible registers or flags for a given core, use getregisters")]
|
||||||
public int GetRegister(string name)
|
public int GetRegister(string name) => (int?) APIs.Emu.GetRegister(name) ?? 0;
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DebuggableCore == null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
var registers = DebuggableCore.GetCpuFlagsAndRegisters();
|
|
||||||
return registers.ContainsKey(name)
|
|
||||||
? (int)registers[name].Value
|
|
||||||
: 0;
|
|
||||||
}
|
|
||||||
catch (NotImplementedException)
|
|
||||||
{
|
|
||||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local nlemuget = emu.getregisters( );")]
|
[LuaMethodExample("local nlemuget = emu.getregisters( );")]
|
||||||
[LuaMethod("getregisters", "returns the complete set of available flags and registers for a given core")]
|
[LuaMethod("getregisters", "returns the complete set of available flags and registers for a given core")]
|
||||||
public LuaTable GetRegisters()
|
public LuaTable GetRegisters()
|
||||||
{
|
{
|
||||||
|
var result = APIs.Emu.GetRegisters();
|
||||||
var table = Lua.NewTable();
|
var table = Lua.NewTable();
|
||||||
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DebuggableCore == null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kvp in DebuggableCore.GetCpuFlagsAndRegisters())
|
|
||||||
{
|
|
||||||
table[kvp.Key] = kvp.Value.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (NotImplementedException)
|
|
||||||
{
|
|
||||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.GetCpuFlagsAndRegisters)}()");
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("emu.setregister( emu.getregisters( )[ 0 ], -1000 );")]
|
[LuaMethodExample("emu.setregister( emu.getregisters( )[ 0 ], -1000 );")]
|
||||||
[LuaMethod("setregister", "sets the given register name to the given value")]
|
[LuaMethod("setregister", "sets the given register name to the given value")]
|
||||||
public void SetRegister(string register, int value)
|
public void SetRegister(string register, int value) => APIs.Emu.SetRegister(register, value);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DebuggableCore == null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
DebuggableCore.SetCpuRegister(register, value);
|
|
||||||
}
|
|
||||||
catch (NotImplementedException)
|
|
||||||
{
|
|
||||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.SetCpuRegister)}()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local inemutot = emu.totalexecutedcycles( );")]
|
[LuaMethodExample("local inemutot = emu.totalexecutedcycles( );")]
|
||||||
[LuaMethod("totalexecutedcycles", "gets the total number of executed cpu cycles")]
|
[LuaMethod("totalexecutedcycles", "gets the total number of executed cpu cycles")]
|
||||||
public long TotalExecutedycles()
|
public long TotalExecutedycles() => APIs.Emu.TotalExecutedCycles();
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DebuggableCore == null)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return DebuggableCore.TotalExecutedCycles;
|
|
||||||
}
|
|
||||||
catch (NotImplementedException)
|
|
||||||
{
|
|
||||||
Log($"Error: {Emulator.Attributes().CoreName} does not yet implement {nameof(IDebuggable.TotalExecutedCycles)}()");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stemuget = emu.getsystemid( );")]
|
[LuaMethodExample("local stemuget = emu.getsystemid( );")]
|
||||||
[LuaMethod("getsystemid", "Returns the ID string of the current core loaded. Note: No ROM loaded will return the string NULL")]
|
[LuaMethod("getsystemid", "Returns the ID string of the current core loaded. Note: No ROM loaded will return the string NULL")]
|
||||||
public static string GetSystemId()
|
public string GetSystemId() => APIs.Emu.GetSystemId();
|
||||||
{
|
|
||||||
return Global.Game.System;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( emu.islagged( ) ) then\r\n\tconsole.log( \"Returns whether or not the current frame is a lag frame\" );\r\nend;")]
|
[LuaMethodExample("if ( emu.islagged( ) ) then\r\n\tconsole.log( \"Returns whether or not the current frame is a lag frame\" );\r\nend;")]
|
||||||
[LuaMethod("islagged", "Returns whether or not the current frame is a lag frame")]
|
[LuaMethod("islagged", "Returns whether or not the current frame is a lag frame")]
|
||||||
public bool IsLagged()
|
public bool IsLagged() => APIs.Emu.IsLagged();
|
||||||
{
|
|
||||||
if (InputPollableCore != null)
|
|
||||||
{
|
|
||||||
return InputPollableCore.IsLagFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.setislagged( true );")]
|
[LuaMethodExample("emu.setislagged( true );")]
|
||||||
[LuaMethod("setislagged", "Sets the lag flag for the current frame. If no value is provided, it will default to true")]
|
[LuaMethod("setislagged", "Sets the lag flag for the current frame. If no value is provided, it will default to true")]
|
||||||
public void SetIsLagged(bool value = true)
|
public void SetIsLagged(bool value = true) => APIs.Emu.SetIsLagged(value);
|
||||||
{
|
|
||||||
if (InputPollableCore != null)
|
|
||||||
{
|
|
||||||
InputPollableCore.IsLagFrame = value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local inemulag = emu.lagcount( );")]
|
[LuaMethodExample("local inemulag = emu.lagcount( );")]
|
||||||
[LuaMethod("lagcount", "Returns the current lag count")]
|
[LuaMethod("lagcount", "Returns the current lag count")]
|
||||||
public int LagCount()
|
public int LagCount() => APIs.Emu.LagCount();
|
||||||
{
|
|
||||||
if (InputPollableCore != null)
|
|
||||||
{
|
|
||||||
return InputPollableCore.LagCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Can not get lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.setlagcount( 50 );")]
|
[LuaMethodExample("emu.setlagcount( 50 );")]
|
||||||
[LuaMethod("setlagcount", "Sets the current lag count")]
|
[LuaMethod("setlagcount", "Sets the current lag count")]
|
||||||
public void SetLagCount(int count)
|
public void SetLagCount(int count) => APIs.Emu.SetLagCount(count);
|
||||||
{
|
|
||||||
if (InputPollableCore != null)
|
|
||||||
{
|
|
||||||
InputPollableCore.LagCount = count;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Can not set lag information, {Emulator.Attributes().CoreName} does not implement {nameof(IInputPollable)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.limitframerate( true );")]
|
[LuaMethodExample("emu.limitframerate( true );")]
|
||||||
[LuaMethod("limitframerate", "sets the limit framerate property of the emulator")]
|
[LuaMethod("limitframerate", "sets the limit framerate property of the emulator")]
|
||||||
public static void LimitFramerate(bool enabled)
|
public void LimitFramerate(bool enabled) => APIs.Emu.LimitFramerate(enabled);
|
||||||
{
|
|
||||||
Global.Config.ClockThrottle = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.minimizeframeskip( true );")]
|
[LuaMethodExample("emu.minimizeframeskip( true );")]
|
||||||
[LuaMethod("minimizeframeskip", "Sets the autominimizeframeskip value of the emulator")]
|
[LuaMethod("minimizeframeskip", "Sets the autominimizeframeskip value of the emulator")]
|
||||||
public static void MinimizeFrameskip(bool enabled)
|
public void MinimizeFrameskip(bool enabled) => APIs.Emu.MinimizeFrameskip(enabled);
|
||||||
{
|
|
||||||
Global.Config.AutoMinimizeSkipping = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.setrenderplanes( true, false );")]
|
[LuaMethodExample("emu.setrenderplanes( true, false );")]
|
||||||
[LuaMethod("setrenderplanes", "Toggles the drawing of sprites and background planes. Set to false or nil to disable a pane, anything else will draw them")]
|
[LuaMethod("setrenderplanes", "Toggles the drawing of sprites and background planes. Set to false or nil to disable a pane, anything else will draw them")]
|
||||||
public void SetRenderPlanes(params bool[] luaParam)
|
public void SetRenderPlanes(params bool[] luaParam) => APIs.Emu.SetRenderPlanes(luaParam);
|
||||||
{
|
|
||||||
if (Emulator is NES nes)
|
|
||||||
{
|
|
||||||
// in the future, we could do something more arbitrary here.
|
|
||||||
// but this isn't any worse than the old system
|
|
||||||
var s = nes.GetSettings();
|
|
||||||
s.DispSprites = luaParam[0];
|
|
||||||
s.DispBackground = luaParam[1];
|
|
||||||
nes.PutSettings(s);
|
|
||||||
}
|
|
||||||
else if (Emulator is QuickNES quicknes)
|
|
||||||
{
|
|
||||||
var s = quicknes.GetSettings();
|
|
||||||
|
|
||||||
// this core doesn't support disabling BG
|
|
||||||
bool showSp = GetSetting(0, luaParam);
|
|
||||||
if (showSp && s.NumSprites == 0)
|
|
||||||
{
|
|
||||||
s.NumSprites = 8;
|
|
||||||
}
|
|
||||||
else if (!showSp && s.NumSprites > 0)
|
|
||||||
{
|
|
||||||
s.NumSprites = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
quicknes.PutSettings(s);
|
|
||||||
}
|
|
||||||
else if (Emulator is PCEngine pce)
|
|
||||||
{
|
|
||||||
var s = pce.GetSettings();
|
|
||||||
s.ShowOBJ1 = GetSetting(0, luaParam);
|
|
||||||
s.ShowBG1 = GetSetting(1, luaParam);
|
|
||||||
if (luaParam.Length > 2)
|
|
||||||
{
|
|
||||||
s.ShowOBJ2 = GetSetting(2, luaParam);
|
|
||||||
s.ShowBG2 = GetSetting(3, luaParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
pce.PutSettings(s);
|
|
||||||
}
|
|
||||||
else if (Emulator is SMS sms)
|
|
||||||
{
|
|
||||||
var s = sms.GetSettings();
|
|
||||||
s.DispOBJ = GetSetting(0, luaParam);
|
|
||||||
s.DispBG = GetSetting(1, luaParam);
|
|
||||||
sms.PutSettings(s);
|
|
||||||
}
|
|
||||||
else if (Emulator is WonderSwan ws)
|
|
||||||
{
|
|
||||||
var s = ws.GetSettings();
|
|
||||||
s.EnableSprites = GetSetting(0, luaParam);
|
|
||||||
s.EnableFG = GetSetting(1, luaParam);
|
|
||||||
s.EnableBG = GetSetting(2, luaParam);
|
|
||||||
ws.PutSettings(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool GetSetting(int index, bool[] settings)
|
|
||||||
{
|
|
||||||
return index >= settings.Length || settings[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("emu.yield( );")]
|
[LuaMethodExample("emu.yield( );")]
|
||||||
[LuaMethod("yield", "allows a script to run while emulation is paused and interact with the gui/main window in realtime ")]
|
[LuaMethod("yield", "allows a script to run while emulation is paused and interact with the gui/main window in realtime ")]
|
||||||
|
@ -339,21 +104,11 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local stemuget = emu.getdisplaytype();")]
|
[LuaMethodExample("local stemuget = emu.getdisplaytype();")]
|
||||||
[LuaMethod("getdisplaytype", "returns the display type (PAL vs NTSC) that the emulator is currently running in")]
|
[LuaMethod("getdisplaytype", "returns the display type (PAL vs NTSC) that the emulator is currently running in")]
|
||||||
public string GetDisplayType()
|
public string GetDisplayType() => APIs.Emu.GetDisplayType();
|
||||||
{
|
|
||||||
return RegionableCore != null
|
|
||||||
? RegionableCore.Region.ToString()
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stemuget = emu.getboardname();")]
|
[LuaMethodExample("local stemuget = emu.getboardname();")]
|
||||||
[LuaMethod("getboardname", "returns (if available) the board name of the loaded ROM")]
|
[LuaMethod("getboardname", "returns (if available) the board name of the loaded ROM")]
|
||||||
public string GetBoardName()
|
public string GetBoardName() => APIs.Emu.GetBoardName();
|
||||||
{
|
|
||||||
return BoardInfo != null
|
|
||||||
? BoardInfo.BoardName
|
|
||||||
: "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethod("getluacore", "returns the name of the Lua core currently in use")]
|
[LuaMethod("getluacore", "returns the name of the Lua core currently in use")]
|
||||||
public string GetLuaBackend()
|
public string GetLuaBackend()
|
||||||
|
|
|
@ -7,11 +7,8 @@ using BizHawk.Emulation.Common;
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class GameInfoLuaLibrary : LuaLibraryBase
|
public sealed class GameInfoLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
[OptionalService]
|
|
||||||
private IBoardInfo BoardInfo { get; set; }
|
|
||||||
|
|
||||||
public GameInfoLuaLibrary(Lua lua)
|
public GameInfoLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
|
||||||
|
@ -22,66 +19,36 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local stgamget = gameinfo.getromname( );")]
|
[LuaMethodExample("local stgamget = gameinfo.getromname( );")]
|
||||||
[LuaMethod("getromname", "returns the name of the currently loaded rom, if a rom is loaded")]
|
[LuaMethod("getromname", "returns the name of the currently loaded rom, if a rom is loaded")]
|
||||||
public string GetRomName()
|
public string GetRomName() => APIs.GameInfo.GetRomName();
|
||||||
{
|
|
||||||
return Global.Game?.Name ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stgamget = gameinfo.getromhash( );")]
|
[LuaMethodExample("local stgamget = gameinfo.getromhash( );")]
|
||||||
[LuaMethod("getromhash", "returns the hash of the currently loaded rom, if a rom is loaded")]
|
[LuaMethod("getromhash", "returns the hash of the currently loaded rom, if a rom is loaded")]
|
||||||
public string GetRomHash()
|
public string GetRomHash() => APIs.GameInfo.GetRomHash();
|
||||||
{
|
|
||||||
return Global.Game?.Hash ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( gameinfo.indatabase( ) ) then\r\n\tconsole.log( \"returns whether or not the currently loaded rom is in the game database\" );\r\nend;")]
|
[LuaMethodExample("if ( gameinfo.indatabase( ) ) then\r\n\tconsole.log( \"returns whether or not the currently loaded rom is in the game database\" );\r\nend;")]
|
||||||
[LuaMethod("indatabase", "returns whether or not the currently loaded rom is in the game database")]
|
[LuaMethod("indatabase", "returns whether or not the currently loaded rom is in the game database")]
|
||||||
public bool InDatabase()
|
public bool InDatabase() => APIs.GameInfo.InDatabase();
|
||||||
{
|
|
||||||
if (Global.Game != null)
|
|
||||||
{
|
|
||||||
return !Global.Game.NotInDatabase;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stgamget = gameinfo.getstatus( );")]
|
[LuaMethodExample("local stgamget = gameinfo.getstatus( );")]
|
||||||
[LuaMethod("getstatus", "returns the game database status of the currently loaded rom. Statuses are for example: GoodDump, BadDump, Hack, Unknown, NotInDatabase")]
|
[LuaMethod("getstatus", "returns the game database status of the currently loaded rom. Statuses are for example: GoodDump, BadDump, Hack, Unknown, NotInDatabase")]
|
||||||
public string GetStatus()
|
public string GetStatus() => APIs.GameInfo.GetStatus();
|
||||||
{
|
|
||||||
return Global.Game?.Status.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( gameinfo.isstatusbad( ) ) then\r\n\tconsole.log( \"returns the currently loaded rom's game database status is considered 'bad'\" );\r\nend;")]
|
[LuaMethodExample("if ( gameinfo.isstatusbad( ) ) then\r\n\tconsole.log( \"returns the currently loaded rom's game database status is considered 'bad'\" );\r\nend;")]
|
||||||
[LuaMethod("isstatusbad", "returns the currently loaded rom's game database status is considered 'bad'")]
|
[LuaMethod("isstatusbad", "returns the currently loaded rom's game database status is considered 'bad'")]
|
||||||
public bool IsStatusBad()
|
public bool IsStatusBad() => APIs.GameInfo.IsStatusBad();
|
||||||
{
|
|
||||||
return Global.Game?.IsRomStatusBad() ?? true;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stgamget = gameinfo.getboardtype( );")]
|
[LuaMethodExample("local stgamget = gameinfo.getboardtype( );")]
|
||||||
[LuaMethod("getboardtype", "returns identifying information about the 'mapper' or similar capability used for this game. empty if no such useful distinction can be drawn")]
|
[LuaMethod("getboardtype", "returns identifying information about the 'mapper' or similar capability used for this game. empty if no such useful distinction can be drawn")]
|
||||||
public string GetBoardType()
|
public string GetBoardType() => APIs.GameInfo.GetBoardType();
|
||||||
{
|
|
||||||
return BoardInfo?.BoardName ?? "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local nlgamget = gameinfo.getoptions( );")]
|
[LuaMethodExample("local nlgamget = gameinfo.getoptions( );")]
|
||||||
[LuaMethod("getoptions", "returns the game options for the currently loaded rom. Options vary per platform")]
|
[LuaMethod("getoptions", "returns the game options for the currently loaded rom. Options vary per platform")]
|
||||||
public LuaTable GetOptions()
|
public LuaTable GetOptions()
|
||||||
{
|
{
|
||||||
var options = Lua.NewTable();
|
var dict = APIs.GameInfo.GetOptions();
|
||||||
|
var table = Lua.NewTable();
|
||||||
if (Global.Game != null)
|
foreach (var kvp in dict) table[kvp.Key] = kvp.Value;
|
||||||
{
|
return table;
|
||||||
foreach (var option in Global.Game.GetOptionsDict())
|
|
||||||
{
|
|
||||||
options[option.Key] = option.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using NLua;
|
using NLua;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class JoypadLuaLibrary : LuaLibraryBase
|
public sealed class JoypadLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
public JoypadLuaLibrary(Lua lua)
|
public JoypadLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -18,169 +20,42 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("get", "returns a lua table of the controller buttons pressed. If supplied, it will only return a table of buttons for the given controller")]
|
[LuaMethod("get", "returns a lua table of the controller buttons pressed. If supplied, it will only return a table of buttons for the given controller")]
|
||||||
public LuaTable Get(int? controller = null)
|
public LuaTable Get(int? controller = null)
|
||||||
{
|
{
|
||||||
var buttons = Lua.NewTable();
|
var result = APIs.Joypad.Get(controller);
|
||||||
var adapter = Global.AutofireStickyXORAdapter;
|
var table = Lua.NewTable();
|
||||||
foreach (var button in adapter.Source.Definition.BoolButtons)
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
{
|
return table;
|
||||||
if (!controller.HasValue)
|
|
||||||
{
|
|
||||||
buttons[button] = adapter.IsPressed(button);
|
|
||||||
}
|
|
||||||
else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}")
|
|
||||||
{
|
|
||||||
buttons[button.Substring(3)] = adapter.IsPressed($"P{controller} {button.Substring(3)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var button in adapter.Source.Definition.FloatControls)
|
|
||||||
{
|
|
||||||
if (controller == null)
|
|
||||||
{
|
|
||||||
buttons[button] = adapter.GetFloat(button);
|
|
||||||
}
|
|
||||||
else if (button.Length >= 3 && button.Substring(0, 2) == $"P{controller}")
|
|
||||||
{
|
|
||||||
buttons[button.Substring(3)] = adapter.GetFloat($"P{controller} {button.Substring(3)}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buttons["clear"] = null;
|
|
||||||
buttons["getluafunctionslist"] = null;
|
|
||||||
buttons["output"] = null;
|
|
||||||
|
|
||||||
return buttons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: what about float controls?
|
|
||||||
[LuaMethodExample("local nljoyget = joypad.getimmediate( );")]
|
[LuaMethodExample("local nljoyget = joypad.getimmediate( );")]
|
||||||
[LuaMethod("getimmediate", "returns a lua table of any controller buttons currently pressed by the user")]
|
[LuaMethod("getimmediate", "returns a lua table of any controller buttons currently pressed by the user")]
|
||||||
public LuaTable GetImmediate()
|
public LuaTable GetImmediate()
|
||||||
{
|
{
|
||||||
var buttons = Lua.NewTable();
|
var result = APIs.Joypad.GetImmediate();
|
||||||
foreach (var button in Global.ActiveController.Definition.BoolButtons)
|
var table = Lua.NewTable();
|
||||||
{
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
buttons[button] = Global.ActiveController.IsPressed(button);
|
return table;
|
||||||
}
|
|
||||||
|
|
||||||
return buttons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("joypad.setfrommnemonicstr( \"| 0, 0, 0, 100,...R..B....|\" );")]
|
[LuaMethodExample("joypad.setfrommnemonicstr( \"| 0, 0, 0, 100,...R..B....|\" );")]
|
||||||
[LuaMethod("setfrommnemonicstr", "sets the given buttons to their provided values for the current frame, string will be interpretted the same way an entry from a movie input log would be")]
|
[LuaMethod("setfrommnemonicstr", "sets the given buttons to their provided values for the current frame, string will be interpretted the same way an entry from a movie input log would be")]
|
||||||
public void SetFromMnemonicStr(string inputLogEntry)
|
public void SetFromMnemonicStr(string inputLogEntry) => APIs.Joypad.SetFromMnemonicStr(inputLogEntry);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var lg = Global.MovieSession.MovieControllerInstance();
|
|
||||||
lg.SetControllersAsMnemonic(inputLogEntry);
|
|
||||||
|
|
||||||
foreach (var button in lg.Definition.BoolButtons)
|
|
||||||
{
|
|
||||||
Global.LuaAndAdaptor.SetButton(button, lg.IsPressed(button));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var floatButton in lg.Definition.FloatControls)
|
|
||||||
{
|
|
||||||
Global.LuaAndAdaptor.SetFloat(floatButton, lg.GetFloat(floatButton));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
Log($"invalid mnemonic string: {inputLogEntry}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("joypad.set( { [\"Left\"] = true, [ \"A\" ] = true, [ \"B\" ] = true } );")]
|
[LuaMethodExample("joypad.set( { [\"Left\"] = true, [ \"A\" ] = true, [ \"B\" ] = true } );")]
|
||||||
[LuaMethod("set", "sets the given buttons to their provided values for the current frame")]
|
[LuaMethod("set", "sets the given buttons to their provided values for the current frame")]
|
||||||
public void Set(LuaTable buttons, int? controller = null)
|
public void Set(LuaTable buttons, int? controller = null)
|
||||||
{
|
{
|
||||||
try
|
var dict = new Dictionary<string, bool>();
|
||||||
{
|
foreach (var k in buttons.Keys) dict[k.ToString()] = (bool) buttons[k];
|
||||||
foreach (var button in buttons.Keys)
|
APIs.Joypad.Set(dict, controller);
|
||||||
{
|
|
||||||
var invert = false;
|
|
||||||
bool? theValue;
|
|
||||||
var theValueStr = buttons[button].ToString();
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(theValueStr))
|
|
||||||
{
|
|
||||||
if (theValueStr.ToLower() == "false")
|
|
||||||
{
|
|
||||||
theValue = false;
|
|
||||||
}
|
|
||||||
else if (theValueStr.ToLower() == "true")
|
|
||||||
{
|
|
||||||
theValue = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
invert = true;
|
|
||||||
theValue = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
theValue = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var toPress = button.ToString();
|
|
||||||
if (controller.HasValue)
|
|
||||||
{
|
|
||||||
toPress = $"P{controller} {button}";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!invert)
|
|
||||||
{
|
|
||||||
if (theValue.HasValue) // Force
|
|
||||||
{
|
|
||||||
Global.LuaAndAdaptor.SetButton(toPress, theValue.Value);
|
|
||||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
|
||||||
}
|
|
||||||
else // Unset
|
|
||||||
{
|
|
||||||
Global.LuaAndAdaptor.UnSet(toPress);
|
|
||||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Inverse
|
|
||||||
{
|
|
||||||
Global.LuaAndAdaptor.SetInverse(toPress);
|
|
||||||
Global.ActiveController.Overrides(Global.LuaAndAdaptor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
/*Eat it*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("joypad.setanalog( { [ \"Tilt X\" ] = true, [ \"Tilt Y\" ] = false } );")]
|
[LuaMethodExample("joypad.setanalog( { [ \"Tilt X\" ] = true, [ \"Tilt Y\" ] = false } );")]
|
||||||
[LuaMethod("setanalog", "sets the given analog controls to their provided values for the current frame. Note that unlike set() there is only the logic of overriding with the given value.")]
|
[LuaMethod("setanalog", "sets the given analog controls to their provided values for the current frame. Note that unlike set() there is only the logic of overriding with the given value.")]
|
||||||
public void SetAnalog(LuaTable controls, object controller = null)
|
public void SetAnalog(LuaTable controls, object controller = null)
|
||||||
{
|
{
|
||||||
try
|
var dict = new Dictionary<string, float>();
|
||||||
{
|
foreach (var k in controls.Keys) dict[k.ToString()] = (float) controls[k];
|
||||||
foreach (var name in controls.Keys)
|
APIs.Joypad.SetAnalog(dict, controller);
|
||||||
{
|
|
||||||
var theValueStr = controls[name].ToString();
|
|
||||||
float? theValue = null;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(theValueStr))
|
|
||||||
{
|
|
||||||
if (float.TryParse(theValueStr, out var f))
|
|
||||||
{
|
|
||||||
theValue = f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.StickyXORAdapter.SetFloat(controller == null ? name.ToString() : $"P{controller} {name}", theValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
/*Eat it*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,23 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
using NLua;
|
|
||||||
using BizHawk.Emulation.Common;
|
using BizHawk.Emulation.Common;
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||||
|
|
||||||
|
using NLua;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
[Description("Main memory library reads and writes from the Main memory domain (the default memory domain set by any given core)")]
|
[Description("Main memory library reads and writes from the Main memory domain (the default memory domain set by any given core)")]
|
||||||
public sealed class MainMemoryLuaLibrary : LuaMemoryBase
|
public sealed class MainMemoryLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
|
[RequiredService]
|
||||||
|
private IEmulator Emulator { get; set; }
|
||||||
|
|
||||||
|
[OptionalService]
|
||||||
|
private IMemoryDomains MemoryDomainCore { get; set; }
|
||||||
|
|
||||||
public MainMemoryLuaLibrary(Lua lua)
|
public MainMemoryLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
|
||||||
|
@ -19,7 +26,7 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
public override string Name => "mainmemory";
|
public override string Name => "mainmemory";
|
||||||
|
|
||||||
protected override MemoryDomain Domain
|
private MemoryDomain Domain
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
|
@ -58,44 +65,68 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.readbyte( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.readbyte( 0x100 );")]
|
||||||
[LuaMethod("readbyte", "gets the value from the given address as an unsigned byte")]
|
[LuaMethod("readbyte", "gets the value from the given address as an unsigned byte")]
|
||||||
public uint ReadByte(int addr)
|
public uint ReadByte(int addr) => APIs.Mem.ReadByte(addr, Domain.Name);
|
||||||
{
|
|
||||||
return ReadUnsignedByte(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.writebyte( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.writebyte( 0x100, 1000 );")]
|
||||||
[LuaMethod("writebyte", "Writes the given value to the given address as an unsigned byte")]
|
[LuaMethod("writebyte", "Writes the given value to the given address as an unsigned byte")]
|
||||||
public void WriteByte(int addr, uint value)
|
public void WriteByte(int addr, uint value) => APIs.Mem.WriteByte(addr, value, Domain.Name);
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local nlmairea = mainmemory.readbyterange( 0x100, 64 );")]
|
[LuaMethodExample("local nlmairea = mainmemory.readbyterange( 0x100, 64 );")]
|
||||||
[LuaMethod("readbyterange", "Reads the address range that starts from address, and is length long. Returns the result into a table of key value pairs (where the address is the key).")]
|
[LuaMethod("readbyterange", "Reads the address range that starts from address, and is length long. Returns the result into a table of key value pairs (where the address is the key).")]
|
||||||
public LuaTable ReadByteRange(int addr, int length)
|
public LuaTable ReadByteRange(int addr, int length)
|
||||||
{
|
{
|
||||||
return base.ReadByteRange(addr, length);
|
var result = APIs.Mem.ReadByteRange(addr, length, Domain.Name);
|
||||||
|
var table = Lua.NewTable();
|
||||||
|
var count = result.Count;
|
||||||
|
for (var i = 0; i != count; i++) table[i] = result[i];
|
||||||
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <remarks>TODO C# version requires a contiguous address range</remarks>
|
||||||
[LuaMethodExample("")]
|
[LuaMethodExample("")]
|
||||||
[LuaMethod("writebyterange", "Writes the given values to the given addresses as unsigned bytes")]
|
[LuaMethod("writebyterange", "Writes the given values to the given addresses as unsigned bytes")]
|
||||||
public void WriteByteRange(LuaTable memoryblock)
|
public void WriteByteRange(LuaTable memoryblock)
|
||||||
{
|
{
|
||||||
base.WriteByteRange(memoryblock);
|
#if true
|
||||||
|
foreach (var addr in memoryblock.Keys) APIs.Mem.WriteByte(LuaInt(addr), (uint) memoryblock[addr], Domain.Name);
|
||||||
|
#else
|
||||||
|
var d = Domain;
|
||||||
|
if (d.CanPoke())
|
||||||
|
{
|
||||||
|
foreach (var address in memoryblock.Keys)
|
||||||
|
{
|
||||||
|
var addr = LuaInt(address);
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
d.PokeByte(addr, (byte)LuaInt(memoryblock[address]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in writebyterange()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log($"Error: the domain {d.Name} is not writable");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local simairea = mainmemory.readfloat(0x100, false);")]
|
[LuaMethodExample("local simairea = mainmemory.readfloat(0x100, false);")]
|
||||||
[LuaMethod("readfloat", "Reads the given address as a 32-bit float value from the main memory domain with th e given endian")]
|
[LuaMethod("readfloat", "Reads the given address as a 32-bit float value from the main memory domain with th e given endian")]
|
||||||
public float ReadFloat(int addr, bool bigendian)
|
public float ReadFloat(int addr, bool bigendian)
|
||||||
{
|
{
|
||||||
return base.ReadFloat(addr, bigendian);
|
APIs.Mem.SetBigEndian(bigendian);
|
||||||
|
return APIs.Mem.ReadFloat(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.writefloat( 0x100, 10.0, false );")]
|
[LuaMethodExample("mainmemory.writefloat( 0x100, 10.0, false );")]
|
||||||
[LuaMethod("writefloat", "Writes the given 32-bit float value to the given address and endian")]
|
[LuaMethod("writefloat", "Writes the given 32-bit float value to the given address and endian")]
|
||||||
public void WriteFloat(int addr, double value, bool bigendian)
|
public void WriteFloat(int addr, double value, bool bigendian)
|
||||||
{
|
{
|
||||||
base.WriteFloat(addr, value, bigendian);
|
APIs.Mem.SetBigEndian(bigendian);
|
||||||
|
APIs.Mem.WriteFloat(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -104,31 +135,19 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local inmairea = mainmemory.read_s8( 0x100 );")]
|
[LuaMethodExample("local inmairea = mainmemory.read_s8( 0x100 );")]
|
||||||
[LuaMethod("read_s8", "read signed byte")]
|
[LuaMethod("read_s8", "read signed byte")]
|
||||||
public int ReadS8(int addr)
|
public int ReadS8(int addr) => APIs.Mem.ReadS8(addr, Domain.Name);
|
||||||
{
|
|
||||||
return (sbyte)ReadUnsignedByte(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s8( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_s8( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_s8", "write signed byte")]
|
[LuaMethod("write_s8", "write signed byte")]
|
||||||
public void WriteS8(int addr, uint value)
|
public void WriteS8(int addr, uint value) => APIs.Mem.WriteS8(addr, unchecked((int) value), Domain.Name);
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u8( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u8( 0x100 );")]
|
||||||
[LuaMethod("read_u8", "read unsigned byte")]
|
[LuaMethod("read_u8", "read unsigned byte")]
|
||||||
public uint ReadU8(int addr)
|
public uint ReadU8(int addr) => APIs.Mem.ReadU8(addr, Domain.Name);
|
||||||
{
|
|
||||||
return ReadUnsignedByte(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u8( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u8( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u8", "write unsigned byte")]
|
[LuaMethod("write_u8", "write unsigned byte")]
|
||||||
public void WriteU8(int addr, uint value)
|
public void WriteU8(int addr, uint value) => APIs.Mem.WriteU8(addr, value, Domain.Name);
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -138,56 +157,64 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("read_s16_le", "read signed 2 byte value, little endian")]
|
[LuaMethod("read_s16_le", "read signed 2 byte value, little endian")]
|
||||||
public int ReadS16Little(int addr)
|
public int ReadS16Little(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedLittleCore(addr, 2);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadS16(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s16_le( 0x100, -1000 );")]
|
[LuaMethodExample("mainmemory.write_s16_le( 0x100, -1000 );")]
|
||||||
[LuaMethod("write_s16_le", "write signed 2 byte value, little endian")]
|
[LuaMethod("write_s16_le", "write signed 2 byte value, little endian")]
|
||||||
public void WriteS16Little(int addr, int value)
|
public void WriteS16Little(int addr, int value)
|
||||||
{
|
{
|
||||||
WriteSignedLittle(addr, value, 2);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteS16(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local inmairea = mainmemory.read_s16_be( 0x100 );")]
|
[LuaMethodExample("local inmairea = mainmemory.read_s16_be( 0x100 );")]
|
||||||
[LuaMethod("read_s16_be", "read signed 2 byte value, big endian")]
|
[LuaMethod("read_s16_be", "read signed 2 byte value, big endian")]
|
||||||
public int ReadS16Big(int addr)
|
public int ReadS16Big(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedBig(addr, 2);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadS16(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s16_be( 0x100, -1000 );")]
|
[LuaMethodExample("mainmemory.write_s16_be( 0x100, -1000 );")]
|
||||||
[LuaMethod("write_s16_be", "write signed 2 byte value, big endian")]
|
[LuaMethod("write_s16_be", "write signed 2 byte value, big endian")]
|
||||||
public void WriteS16Big(int addr, int value)
|
public void WriteS16Big(int addr, int value)
|
||||||
{
|
{
|
||||||
WriteSignedBig(addr, value, 2);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteS16(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u16_le( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u16_le( 0x100 );")]
|
||||||
[LuaMethod("read_u16_le", "read unsigned 2 byte value, little endian")]
|
[LuaMethod("read_u16_le", "read unsigned 2 byte value, little endian")]
|
||||||
public uint ReadU16Little(int addr)
|
public uint ReadU16Little(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedLittle(addr, 2);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadU16(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u16_le( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u16_le( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u16_le", "write unsigned 2 byte value, little endian")]
|
[LuaMethod("write_u16_le", "write unsigned 2 byte value, little endian")]
|
||||||
public void WriteU16Little(int addr, uint value)
|
public void WriteU16Little(int addr, uint value)
|
||||||
{
|
{
|
||||||
WriteUnsignedLittle(addr, value, 2);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteU16(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u16_be( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u16_be( 0x100 );")]
|
||||||
[LuaMethod("read_u16_be", "read unsigned 2 byte value, big endian")]
|
[LuaMethod("read_u16_be", "read unsigned 2 byte value, big endian")]
|
||||||
public uint ReadU16Big(int addr)
|
public uint ReadU16Big(int addr)
|
||||||
{
|
{
|
||||||
return ReadUnsignedBig(addr, 2);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadU16(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u16_be( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u16_be( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u16_be", "write unsigned 2 byte value, big endian")]
|
[LuaMethod("write_u16_be", "write unsigned 2 byte value, big endian")]
|
||||||
public void WriteU16Big(int addr, uint value)
|
public void WriteU16Big(int addr, uint value)
|
||||||
{
|
{
|
||||||
WriteUnsignedBig(addr, value, 2);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteU16(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -198,56 +225,64 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("read_s24_le", "read signed 24 bit value, little endian")]
|
[LuaMethod("read_s24_le", "read signed 24 bit value, little endian")]
|
||||||
public int ReadS24Little(int addr)
|
public int ReadS24Little(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedLittleCore(addr, 3);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadS24(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s24_le( 0x100, -1000 );")]
|
[LuaMethodExample("mainmemory.write_s24_le( 0x100, -1000 );")]
|
||||||
[LuaMethod("write_s24_le", "write signed 24 bit value, little endian")]
|
[LuaMethod("write_s24_le", "write signed 24 bit value, little endian")]
|
||||||
public void WriteS24Little(int addr, int value)
|
public void WriteS24Little(int addr, int value)
|
||||||
{
|
{
|
||||||
WriteSignedLittle(addr, value, 3);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteS24(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local inmairea = mainmemory.read_s24_be( 0x100 );")]
|
[LuaMethodExample("local inmairea = mainmemory.read_s24_be( 0x100 );")]
|
||||||
[LuaMethod("read_s24_be", "read signed 24 bit value, big endian")]
|
[LuaMethod("read_s24_be", "read signed 24 bit value, big endian")]
|
||||||
public int ReadS24Big(int addr)
|
public int ReadS24Big(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedBig(addr, 3);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadS24(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s24_be( 0x100, -1000 );")]
|
[LuaMethodExample("mainmemory.write_s24_be( 0x100, -1000 );")]
|
||||||
[LuaMethod("write_s24_be", "write signed 24 bit value, big endian")]
|
[LuaMethod("write_s24_be", "write signed 24 bit value, big endian")]
|
||||||
public void WriteS24Big(int addr, int value)
|
public void WriteS24Big(int addr, int value)
|
||||||
{
|
{
|
||||||
WriteSignedBig(addr, value, 3);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteS24(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u24_le( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u24_le( 0x100 );")]
|
||||||
[LuaMethod("read_u24_le", "read unsigned 24 bit value, little endian")]
|
[LuaMethod("read_u24_le", "read unsigned 24 bit value, little endian")]
|
||||||
public uint ReadU24Little(int addr)
|
public uint ReadU24Little(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedLittle(addr, 3);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadU24(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u24_le( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u24_le( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u24_le", "write unsigned 24 bit value, little endian")]
|
[LuaMethod("write_u24_le", "write unsigned 24 bit value, little endian")]
|
||||||
public void WriteU24Little(int addr, uint value)
|
public void WriteU24Little(int addr, uint value)
|
||||||
{
|
{
|
||||||
WriteUnsignedLittle(addr, value, 3);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteU24(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u24_be( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u24_be( 0x100 );")]
|
||||||
[LuaMethod("read_u24_be", "read unsigned 24 bit value, big endian")]
|
[LuaMethod("read_u24_be", "read unsigned 24 bit value, big endian")]
|
||||||
public uint ReadU24Big(int addr)
|
public uint ReadU24Big(int addr)
|
||||||
{
|
{
|
||||||
return ReadUnsignedBig(addr, 3);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadU24(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u24_be( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u24_be( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u24_be", "write unsigned 24 bit value, big endian")]
|
[LuaMethod("write_u24_be", "write unsigned 24 bit value, big endian")]
|
||||||
public void WriteU24Big(int addr, uint value)
|
public void WriteU24Big(int addr, uint value)
|
||||||
{
|
{
|
||||||
WriteUnsignedBig(addr, value, 3);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteU24(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -258,56 +293,64 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("read_s32_le", "read signed 4 byte value, little endian")]
|
[LuaMethod("read_s32_le", "read signed 4 byte value, little endian")]
|
||||||
public int ReadS32Little(int addr)
|
public int ReadS32Little(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedLittleCore(addr, 4);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadS32(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s32_le( 0x100, -1000 );")]
|
[LuaMethodExample("mainmemory.write_s32_le( 0x100, -1000 );")]
|
||||||
[LuaMethod("write_s32_le", "write signed 4 byte value, little endian")]
|
[LuaMethod("write_s32_le", "write signed 4 byte value, little endian")]
|
||||||
public void WriteS32Little(int addr, int value)
|
public void WriteS32Little(int addr, int value)
|
||||||
{
|
{
|
||||||
WriteSignedLittle(addr, value, 4);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteS32(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local inmairea = mainmemory.read_s32_be( 0x100 );")]
|
[LuaMethodExample("local inmairea = mainmemory.read_s32_be( 0x100 );")]
|
||||||
[LuaMethod("read_s32_be", "read signed 4 byte value, big endian")]
|
[LuaMethod("read_s32_be", "read signed 4 byte value, big endian")]
|
||||||
public int ReadS32Big(int addr)
|
public int ReadS32Big(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedBig(addr, 4);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadS32(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_s32_be( 0x100, -1000 );")]
|
[LuaMethodExample("mainmemory.write_s32_be( 0x100, -1000 );")]
|
||||||
[LuaMethod("write_s32_be", "write signed 4 byte value, big endian")]
|
[LuaMethod("write_s32_be", "write signed 4 byte value, big endian")]
|
||||||
public void WriteS32Big(int addr, int value)
|
public void WriteS32Big(int addr, int value)
|
||||||
{
|
{
|
||||||
WriteSignedBig(addr, value, 4);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteS32(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u32_le( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u32_le( 0x100 );")]
|
||||||
[LuaMethod("read_u32_le", "read unsigned 4 byte value, little endian")]
|
[LuaMethod("read_u32_le", "read unsigned 4 byte value, little endian")]
|
||||||
public uint ReadU32Little(int addr)
|
public uint ReadU32Little(int addr)
|
||||||
{
|
{
|
||||||
return ReadSignedLittle(addr, 4);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadU32(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u32_le( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u32_le( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u32_le", "write unsigned 4 byte value, little endian")]
|
[LuaMethod("write_u32_le", "write unsigned 4 byte value, little endian")]
|
||||||
public void WriteU32Little(int addr, uint value)
|
public void WriteU32Little(int addr, uint value)
|
||||||
{
|
{
|
||||||
WriteUnsignedLittle(addr, value, 4);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteU32(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimairea = mainmemory.read_u32_be( 0x100 );")]
|
[LuaMethodExample("local uimairea = mainmemory.read_u32_be( 0x100 );")]
|
||||||
[LuaMethod("read_u32_be", "read unsigned 4 byte value, big endian")]
|
[LuaMethod("read_u32_be", "read unsigned 4 byte value, big endian")]
|
||||||
public uint ReadU32Big(int addr)
|
public uint ReadU32Big(int addr)
|
||||||
{
|
{
|
||||||
return ReadUnsignedBig(addr, 4);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadU32(addr, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("mainmemory.write_u32_be( 0x100, 1000 );")]
|
[LuaMethodExample("mainmemory.write_u32_be( 0x100, 1000 );")]
|
||||||
[LuaMethod("write_u32_be", "write unsigned 4 byte value, big endian")]
|
[LuaMethod("write_u32_be", "write unsigned 4 byte value, big endian")]
|
||||||
public void WriteU32Big(int addr, uint value)
|
public void WriteU32Big(int addr, uint value)
|
||||||
{
|
{
|
||||||
WriteUnsignedBig(addr, value, 4);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteU32(addr, value, Domain.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -2,18 +2,13 @@
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
using NLua;
|
using NLua;
|
||||||
using BizHawk.Emulation.Common;
|
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
|
||||||
using BizHawk.Common.BufferExtensions;
|
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
[Description("These functions behavior identically to the mainmemory functions but the user can set the memory domain to read and write from. The default domain is the system bus. Use getcurrentmemorydomain(), and usememorydomain() to control which domain is used. Each core has its own set of valid memory domains. Use getmemorydomainlist() to get a list of memory domains for the current core loaded.")]
|
[Description("These functions behavior identically to the mainmemory functions but the user can set the memory domain to read and write from. The default domain is the system bus. Use getcurrentmemorydomain(), and usememorydomain() to control which domain is used. Each core has its own set of valid memory domains. Use getmemorydomainlist() to get a list of memory domains for the current core loaded.")]
|
||||||
public sealed class MemoryLuaLibrary : LuaMemoryBase
|
public sealed class MemoryLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
private MemoryDomain _currentMemoryDomain;
|
|
||||||
|
|
||||||
public MemoryLuaLibrary(Lua lua)
|
public MemoryLuaLibrary(Lua lua)
|
||||||
: base(lua)
|
: base(lua)
|
||||||
{
|
{
|
||||||
|
@ -26,124 +21,38 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
public override string Name => "memory";
|
public override string Name => "memory";
|
||||||
|
|
||||||
protected override MemoryDomain Domain
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (MemoryDomainCore != null)
|
|
||||||
{
|
|
||||||
if (_currentMemoryDomain == null)
|
|
||||||
{
|
|
||||||
_currentMemoryDomain = MemoryDomainCore.HasSystemBus
|
|
||||||
? MemoryDomainCore.SystemBus
|
|
||||||
: MemoryDomainCore.MainMemory;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _currentMemoryDomain;
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
|
||||||
Log(error);
|
|
||||||
throw new NotImplementedException(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region Unique Library Methods
|
#region Unique Library Methods
|
||||||
|
|
||||||
[LuaMethodExample("local nlmemget = memory.getmemorydomainlist();")]
|
[LuaMethodExample("local nlmemget = memory.getmemorydomainlist();")]
|
||||||
[LuaMethod("getmemorydomainlist", "Returns a string of the memory domains for the loaded platform core. List will be a single string delimited by line feeds")]
|
[LuaMethod("getmemorydomainlist", "Returns a string of the memory domains for the loaded platform core. List will be a single string delimited by line feeds")]
|
||||||
public LuaTable GetMemoryDomainList()
|
public LuaTable GetMemoryDomainList()
|
||||||
{
|
{
|
||||||
|
var result = APIs.Mem.GetMemoryDomainList();
|
||||||
var table = Lua.NewTable();
|
var table = Lua.NewTable();
|
||||||
|
var count = result.Count;
|
||||||
int i = 0;
|
for (var i = 0; i != count; i++) table[i] = result[i];
|
||||||
foreach (var domain in DomainList)
|
|
||||||
{
|
|
||||||
table[i] = domain.Name;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemget = memory.getmemorydomainsize( mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemget = memory.getmemorydomainsize( mainmemory.getname( ) );")]
|
||||||
[LuaMethod("getmemorydomainsize", "Returns the number of bytes of the specified memory domain. If no domain is specified, or the specified domain doesn't exist, returns the current domain size")]
|
[LuaMethod("getmemorydomainsize", "Returns the number of bytes of the specified memory domain. If no domain is specified, or the specified domain doesn't exist, returns the current domain size")]
|
||||||
public uint GetMemoryDomainSize(string name = "")
|
public uint GetMemoryDomainSize(string name = "") => APIs.Mem.GetMemoryDomainSize(name);
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(name))
|
|
||||||
{
|
|
||||||
return (uint)Domain.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (uint)DomainList[VerifyMemoryDomain(name)].Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stmemget = memory.getcurrentmemorydomain( );")]
|
[LuaMethodExample("local stmemget = memory.getcurrentmemorydomain( );")]
|
||||||
[LuaMethod("getcurrentmemorydomain", "Returns a string name of the current memory domain selected by Lua. The default is Main memory")]
|
[LuaMethod("getcurrentmemorydomain", "Returns a string name of the current memory domain selected by Lua. The default is Main memory")]
|
||||||
public string GetCurrentMemoryDomain()
|
public string GetCurrentMemoryDomain() => APIs.Mem.GetCurrentMemoryDomain();
|
||||||
{
|
|
||||||
return Domain.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local uimemget = memory.getcurrentmemorydomainsize( );")]
|
[LuaMethodExample("local uimemget = memory.getcurrentmemorydomainsize( );")]
|
||||||
[LuaMethod("getcurrentmemorydomainsize", "Returns the number of bytes of the current memory domain selected by Lua. The default is Main memory")]
|
[LuaMethod("getcurrentmemorydomainsize", "Returns the number of bytes of the current memory domain selected by Lua. The default is Main memory")]
|
||||||
public uint GetCurrentMemoryDomainSize()
|
public uint GetCurrentMemoryDomainSize() => APIs.Mem.GetCurrentMemoryDomainSize();
|
||||||
{
|
|
||||||
return (uint)Domain.Size;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( memory.usememorydomain( mainmemory.getname( ) ) ) then\r\n\tconsole.log( \"Attempts to set the current memory domain to the given domain. If the name does not match a valid memory domain, the function returns false, else it returns true\" );\r\nend;")]
|
[LuaMethodExample("if ( memory.usememorydomain( mainmemory.getname( ) ) ) then\r\n\tconsole.log( \"Attempts to set the current memory domain to the given domain. If the name does not match a valid memory domain, the function returns false, else it returns true\" );\r\nend;")]
|
||||||
[LuaMethod("usememorydomain", "Attempts to set the current memory domain to the given domain. If the name does not match a valid memory domain, the function returns false, else it returns true")]
|
[LuaMethod("usememorydomain", "Attempts to set the current memory domain to the given domain. If the name does not match a valid memory domain, the function returns false, else it returns true")]
|
||||||
public bool UseMemoryDomain(string domain)
|
public bool UseMemoryDomain(string domain) => APIs.Mem.UseMemoryDomain(domain);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DomainList[domain] != null)
|
|
||||||
{
|
|
||||||
_currentMemoryDomain = DomainList[domain];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Unable to find domain: {domain}");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch // Just in case
|
|
||||||
{
|
|
||||||
Log($"Unable to find domain: {domain}");
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stmemhas = memory.hash_region( 0x100, 50, mainmemory.getname( ) );")]
|
[LuaMethodExample("local stmemhas = memory.hash_region( 0x100, 50, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("hash_region", "Returns a hash as a string of a region of memory, starting from addr, through count bytes. If the domain is unspecified, it uses the current region.")]
|
[LuaMethod("hash_region", "Returns a hash as a string of a region of memory, starting from addr, through count bytes. If the domain is unspecified, it uses the current region.")]
|
||||||
public string HashRegion(int addr, int count, string domain = null)
|
public string HashRegion(int addr, int count, string domain = null) => APIs.Mem.HashRegion(addr, count, domain);
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
|
|
||||||
// checks
|
|
||||||
if (addr < 0 || addr >= d.Size)
|
|
||||||
{
|
|
||||||
string error = $"Address {addr} is outside the bounds of domain {d.Name}";
|
|
||||||
Log(error);
|
|
||||||
throw new ArgumentOutOfRangeException(error);
|
|
||||||
}
|
|
||||||
if (addr + count > d.Size)
|
|
||||||
{
|
|
||||||
string error = $"Address {addr} + count {count} is outside the bounds of domain {d.Name}";
|
|
||||||
Log(error);
|
|
||||||
throw new ArgumentOutOfRangeException(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] data = new byte[count];
|
|
||||||
for (int i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
data[i] = d.PeekByte(addr + i);
|
|
||||||
}
|
|
||||||
|
|
||||||
using var hasher = System.Security.Cryptography.SHA256.Create();
|
|
||||||
return hasher.ComputeHash(data).BytesToHexString();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -151,44 +60,68 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.readbyte( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.readbyte( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("readbyte", "gets the value from the given address as an unsigned byte")]
|
[LuaMethod("readbyte", "gets the value from the given address as an unsigned byte")]
|
||||||
public uint ReadByte(int addr, string domain = null)
|
public uint ReadByte(int addr, string domain = null) => APIs.Mem.ReadByte(addr, domain);
|
||||||
{
|
|
||||||
return ReadUnsignedByte(addr, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("memory.writebyte( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.writebyte( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("writebyte", "Writes the given value to the given address as an unsigned byte")]
|
[LuaMethod("writebyte", "Writes the given value to the given address as an unsigned byte")]
|
||||||
public void WriteByte(int addr, uint value, string domain = null)
|
public void WriteByte(int addr, uint value, string domain = null) => APIs.Mem.WriteByte(addr, value, domain);
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr, value, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local nlmemrea = memory.readbyterange( 0x100, 30, mainmemory.getname( ) );")]
|
[LuaMethodExample("local nlmemrea = memory.readbyterange( 0x100, 30, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("readbyterange", "Reads the address range that starts from address, and is length long. Returns the result into a table of key value pairs (where the address is the key).")]
|
[LuaMethod("readbyterange", "Reads the address range that starts from address, and is length long. Returns the result into a table of key value pairs (where the address is the key).")]
|
||||||
public new LuaTable ReadByteRange(int addr, int length, string domain = null)
|
public LuaTable ReadByteRange(int addr, int length, string domain = null)
|
||||||
{
|
{
|
||||||
return base.ReadByteRange(addr, length, domain);
|
var result = APIs.Mem.ReadByteRange(addr, length, domain);
|
||||||
|
var table = Lua.NewTable();
|
||||||
|
var count = result.Count;
|
||||||
|
for (var i = 0; i != count; i++) table[i] = result[i];
|
||||||
|
return table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <remarks>TODO C# version requires a contiguous address range</remarks>
|
||||||
[LuaMethodExample("")]
|
[LuaMethodExample("")]
|
||||||
[LuaMethod("writebyterange", "Writes the given values to the given addresses as unsigned bytes")]
|
[LuaMethod("writebyterange", "Writes the given values to the given addresses as unsigned bytes")]
|
||||||
public new void WriteByteRange(LuaTable memoryblock, string domain = null)
|
public void WriteByteRange(LuaTable memoryblock, string domain = null)
|
||||||
{
|
{
|
||||||
base.WriteByteRange(memoryblock, domain);
|
#if true
|
||||||
|
foreach (var addr in memoryblock.Keys) APIs.Mem.WriteByte(LuaInt(addr), (uint) memoryblock[addr], domain);
|
||||||
|
#else
|
||||||
|
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
||||||
|
if (d.CanPoke())
|
||||||
|
{
|
||||||
|
foreach (var address in memoryblock.Keys)
|
||||||
|
{
|
||||||
|
var addr = LuaInt(address);
|
||||||
|
if (addr < d.Size)
|
||||||
|
{
|
||||||
|
d.PokeByte(addr, (byte)LuaInt(memoryblock[address]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in writebyterange()");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log($"Error: the domain {d.Name} is not writable");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local simemrea = memory.readfloat( 0x100, false, mainmemory.getname( ) );")]
|
[LuaMethodExample("local simemrea = memory.readfloat( 0x100, false, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("readfloat", "Reads the given address as a 32-bit float value from the main memory domain with th e given endian")]
|
[LuaMethod("readfloat", "Reads the given address as a 32-bit float value from the main memory domain with th e given endian")]
|
||||||
public new float ReadFloat(int addr, bool bigendian, string domain = null)
|
public float ReadFloat(int addr, bool bigendian, string domain = null)
|
||||||
{
|
{
|
||||||
return base.ReadFloat(addr, bigendian, domain);
|
APIs.Mem.SetBigEndian(bigendian);
|
||||||
|
return APIs.Mem.ReadFloat(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.writefloat( 0x100, 10.0, false, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.writefloat( 0x100, 10.0, false, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("writefloat", "Writes the given 32-bit float value to the given address and endian")]
|
[LuaMethod("writefloat", "Writes the given 32-bit float value to the given address and endian")]
|
||||||
public new void WriteFloat(int addr, double value, bool bigendian, string domain = null)
|
public void WriteFloat(int addr, double value, bool bigendian, string domain = null)
|
||||||
{
|
{
|
||||||
base.WriteFloat(addr, value, bigendian, domain);
|
APIs.Mem.SetBigEndian(bigendian);
|
||||||
|
APIs.Mem.WriteFloat(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -197,31 +130,19 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("local inmemrea = memory.read_s8( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local inmemrea = memory.read_s8( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_s8", "read signed byte")]
|
[LuaMethod("read_s8", "read signed byte")]
|
||||||
public int ReadS8(int addr, string domain = null)
|
public int ReadS8(int addr, string domain = null) => APIs.Mem.ReadS8(addr, domain);
|
||||||
{
|
|
||||||
return (sbyte)ReadUnsignedByte(addr, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s8( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s8( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s8", "write signed byte")]
|
[LuaMethod("write_s8", "write signed byte")]
|
||||||
public void WriteS8(int addr, uint value, string domain = null)
|
public void WriteS8(int addr, uint value, string domain = null) => APIs.Mem.WriteS8(addr, unchecked((int) value), domain);
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr, value, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u8( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u8( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u8", "read unsigned byte")]
|
[LuaMethod("read_u8", "read unsigned byte")]
|
||||||
public uint ReadU8(int addr, string domain = null)
|
public uint ReadU8(int addr, string domain = null) => APIs.Mem.ReadU8(addr, domain);
|
||||||
{
|
|
||||||
return ReadUnsignedByte(addr, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u8( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u8( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u8", "write unsigned byte")]
|
[LuaMethod("write_u8", "write unsigned byte")]
|
||||||
public void WriteU8(int addr, uint value, string domain = null)
|
public void WriteU8(int addr, uint value, string domain = null) => APIs.Mem.WriteU8(addr, value, domain);
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr, value, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -231,56 +152,64 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("read_s16_le", "read signed 2 byte value, little endian")]
|
[LuaMethod("read_s16_le", "read signed 2 byte value, little endian")]
|
||||||
public int ReadS16Little(int addr, string domain = null)
|
public int ReadS16Little(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadSignedLittleCore(addr, 2, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadS16(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s16_le( 0x100, -1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s16_le( 0x100, -1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s16_le", "write signed 2 byte value, little endian")]
|
[LuaMethod("write_s16_le", "write signed 2 byte value, little endian")]
|
||||||
public void WriteS16Little(int addr, int value, string domain = null)
|
public void WriteS16Little(int addr, int value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteSignedLittle(addr, value, 2, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteS16(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local inmemrea = memory.read_s16_be( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local inmemrea = memory.read_s16_be( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_s16_be", "read signed 2 byte value, big endian")]
|
[LuaMethod("read_s16_be", "read signed 2 byte value, big endian")]
|
||||||
public int ReadS16Big(int addr, string domain = null)
|
public int ReadS16Big(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadSignedBig(addr, 2, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadS16(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s16_be( 0x100, -1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s16_be( 0x100, -1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s16_be", "write signed 2 byte value, big endian")]
|
[LuaMethod("write_s16_be", "write signed 2 byte value, big endian")]
|
||||||
public void WriteS16Big(int addr, int value, string domain = null)
|
public void WriteS16Big(int addr, int value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteSignedBig(addr, value, 2, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteS16(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u16_le( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u16_le( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u16_le", "read unsigned 2 byte value, little endian")]
|
[LuaMethod("read_u16_le", "read unsigned 2 byte value, little endian")]
|
||||||
public uint ReadU16Little(int addr, string domain = null)
|
public uint ReadU16Little(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadUnsignedLittle(addr, 2, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadU16(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u16_le( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u16_le( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u16_le", "write unsigned 2 byte value, little endian")]
|
[LuaMethod("write_u16_le", "write unsigned 2 byte value, little endian")]
|
||||||
public void WriteU16Little(int addr, uint value, string domain = null)
|
public void WriteU16Little(int addr, uint value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteUnsignedLittle(addr, value, 2, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteU16(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u16_be( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u16_be( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u16_be", "read unsigned 2 byte value, big endian")]
|
[LuaMethod("read_u16_be", "read unsigned 2 byte value, big endian")]
|
||||||
public uint ReadU16Big(int addr, string domain = null)
|
public uint ReadU16Big(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadUnsignedBig(addr, 2, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadU16(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u16_be( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u16_be( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u16_be", "write unsigned 2 byte value, big endian")]
|
[LuaMethod("write_u16_be", "write unsigned 2 byte value, big endian")]
|
||||||
public void WriteU16Big(int addr, uint value, string domain = null)
|
public void WriteU16Big(int addr, uint value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteUnsignedBig(addr, value, 2, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteU16(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -291,56 +220,64 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("read_s24_le", "read signed 24 bit value, little endian")]
|
[LuaMethod("read_s24_le", "read signed 24 bit value, little endian")]
|
||||||
public int ReadS24Little(int addr, string domain = null)
|
public int ReadS24Little(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadSignedLittleCore(addr, 3, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadS24(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s24_le( 0x100, -1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s24_le( 0x100, -1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s24_le", "write signed 24 bit value, little endian")]
|
[LuaMethod("write_s24_le", "write signed 24 bit value, little endian")]
|
||||||
public void WriteS24Little(int addr, int value, string domain = null)
|
public void WriteS24Little(int addr, int value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteSignedLittle(addr, value, 3, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteS24(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local inmemrea = memory.read_s24_be( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local inmemrea = memory.read_s24_be( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_s24_be", "read signed 24 bit value, big endian")]
|
[LuaMethod("read_s24_be", "read signed 24 bit value, big endian")]
|
||||||
public int ReadS24Big(int addr, string domain = null)
|
public int ReadS24Big(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadSignedBig(addr, 3, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadS24(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s24_be( 0x100, -1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s24_be( 0x100, -1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s24_be", "write signed 24 bit value, big endian")]
|
[LuaMethod("write_s24_be", "write signed 24 bit value, big endian")]
|
||||||
public void WriteS24Big(int addr, int value, string domain = null)
|
public void WriteS24Big(int addr, int value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteSignedBig(addr, value, 3, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteS24(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u24_le( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u24_le( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u24_le", "read unsigned 24 bit value, little endian")]
|
[LuaMethod("read_u24_le", "read unsigned 24 bit value, little endian")]
|
||||||
public uint ReadU24Little(int addr, string domain = null)
|
public uint ReadU24Little(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadUnsignedLittle(addr, 3, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadU24(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u24_le( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u24_le( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u24_le", "write unsigned 24 bit value, little endian")]
|
[LuaMethod("write_u24_le", "write unsigned 24 bit value, little endian")]
|
||||||
public void WriteU24Little(int addr, uint value, string domain = null)
|
public void WriteU24Little(int addr, uint value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteUnsignedLittle(addr, value, 3, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteU24(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u24_be( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u24_be( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u24_be", "read unsigned 24 bit value, big endian")]
|
[LuaMethod("read_u24_be", "read unsigned 24 bit value, big endian")]
|
||||||
public uint ReadU24Big(int addr, string domain = null)
|
public uint ReadU24Big(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadUnsignedBig(addr, 3, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadU24(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u24_be( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u24_be( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u24_be", "write unsigned 24 bit value, big endian")]
|
[LuaMethod("write_u24_be", "write unsigned 24 bit value, big endian")]
|
||||||
public void WriteU24Big(int addr, uint value, string domain = null)
|
public void WriteU24Big(int addr, uint value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteUnsignedBig(addr, value, 3, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteU24(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -351,56 +288,64 @@ namespace BizHawk.Client.Common
|
||||||
[LuaMethod("read_s32_le", "read signed 4 byte value, little endian")]
|
[LuaMethod("read_s32_le", "read signed 4 byte value, little endian")]
|
||||||
public int ReadS32Little(int addr, string domain = null)
|
public int ReadS32Little(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadSignedLittleCore(addr, 4, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadS32(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s32_le( 0x100, -1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s32_le( 0x100, -1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s32_le", "write signed 4 byte value, little endian")]
|
[LuaMethod("write_s32_le", "write signed 4 byte value, little endian")]
|
||||||
public void WriteS32Little(int addr, int value, string domain = null)
|
public void WriteS32Little(int addr, int value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteSignedLittle(addr, value, 4, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteS32(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local inmemrea = memory.read_s32_be( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local inmemrea = memory.read_s32_be( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_s32_be", "read signed 4 byte value, big endian")]
|
[LuaMethod("read_s32_be", "read signed 4 byte value, big endian")]
|
||||||
public int ReadS32Big(int addr, string domain = null)
|
public int ReadS32Big(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadSignedBig(addr, 4, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadS32(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_s32_be( 0x100, -1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_s32_be( 0x100, -1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_s32_be", "write signed 4 byte value, big endian")]
|
[LuaMethod("write_s32_be", "write signed 4 byte value, big endian")]
|
||||||
public void WriteS32Big(int addr, int value, string domain = null)
|
public void WriteS32Big(int addr, int value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteSignedBig(addr, value, 4, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteS32(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u32_le( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u32_le( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u32_le", "read unsigned 4 byte value, little endian")]
|
[LuaMethod("read_u32_le", "read unsigned 4 byte value, little endian")]
|
||||||
public uint ReadU32Little(int addr, string domain = null)
|
public uint ReadU32Little(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadUnsignedLittle(addr, 4, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
return APIs.Mem.ReadU32(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u32_le( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u32_le( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u32_le", "write unsigned 4 byte value, little endian")]
|
[LuaMethod("write_u32_le", "write unsigned 4 byte value, little endian")]
|
||||||
public void WriteU32Little(int addr, uint value, string domain = null)
|
public void WriteU32Little(int addr, uint value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteUnsignedLittle(addr, value, 4, domain);
|
APIs.Mem.SetBigEndian(false);
|
||||||
|
APIs.Mem.WriteU32(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local uimemrea = memory.read_u32_be( 0x100, mainmemory.getname( ) );")]
|
[LuaMethodExample("local uimemrea = memory.read_u32_be( 0x100, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("read_u32_be", "read unsigned 4 byte value, big endian")]
|
[LuaMethod("read_u32_be", "read unsigned 4 byte value, big endian")]
|
||||||
public uint ReadU32Big(int addr, string domain = null)
|
public uint ReadU32Big(int addr, string domain = null)
|
||||||
{
|
{
|
||||||
return ReadUnsignedBig(addr, 4, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
return APIs.Mem.ReadU32(addr, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("memory.write_u32_be( 0x100, 1000, mainmemory.getname( ) );")]
|
[LuaMethodExample("memory.write_u32_be( 0x100, 1000, mainmemory.getname( ) );")]
|
||||||
[LuaMethod("write_u32_be", "write unsigned 4 byte value, big endian")]
|
[LuaMethod("write_u32_be", "write unsigned 4 byte value, big endian")]
|
||||||
public void WriteU32Big(int addr, uint value, string domain = null)
|
public void WriteU32Big(int addr, uint value, string domain = null)
|
||||||
{
|
{
|
||||||
WriteUnsignedBig(addr, value, 4, domain);
|
APIs.Mem.SetBigEndian();
|
||||||
|
APIs.Mem.WriteU32(addr, value, domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
|
@ -10,7 +10,7 @@ using BizHawk.Emulation.Common;
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
// ReSharper disable UnusedAutoPropertyAccessor.Local
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class MemorySavestateEmuLuaLibrary : LuaLibraryBase
|
public sealed class MemorySavestateEmuLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
public MemorySavestateEmuLuaLibrary(Lua lua)
|
public MemorySavestateEmuLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -20,56 +20,20 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
public override string Name => "memorysavestate";
|
public override string Name => "memorysavestate";
|
||||||
|
|
||||||
[RequiredService]
|
|
||||||
private IStatable StatableCore { get; set; }
|
|
||||||
|
|
||||||
private readonly Dictionary<Guid, byte[]> _memorySavestates = new Dictionary<Guid, byte[]>();
|
|
||||||
|
|
||||||
[LuaMethodExample("local mmsvstsvcst = memorysavestate.savecorestate( );")]
|
[LuaMethodExample("local mmsvstsvcst = memorysavestate.savecorestate( );")]
|
||||||
[LuaMethod("savecorestate", "creates a core savestate and stores it in memory. Note: a core savestate is only the raw data from the core, and not extras such as movie input logs, or framebuffers. Returns a unique identifer for the savestate")]
|
[LuaMethod("savecorestate", "creates a core savestate and stores it in memory. Note: a core savestate is only the raw data from the core, and not extras such as movie input logs, or framebuffers. Returns a unique identifer for the savestate")]
|
||||||
public string SaveCoreStateToMemory()
|
public string SaveCoreStateToMemory() => APIs.MemorySaveState.SaveCoreStateToMemory();
|
||||||
{
|
|
||||||
var guid = Guid.NewGuid();
|
|
||||||
var bytes = (byte[])StatableCore.SaveStateBinary().Clone();
|
|
||||||
|
|
||||||
_memorySavestates.Add(guid, bytes);
|
|
||||||
|
|
||||||
return guid.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("memorysavestate.loadcorestate( \"3fcf120f-0778-43fd-b2c5-460fb7d34184\" );")]
|
[LuaMethodExample("memorysavestate.loadcorestate( \"3fcf120f-0778-43fd-b2c5-460fb7d34184\" );")]
|
||||||
[LuaMethod("loadcorestate", "loads an in memory state with the given identifier")]
|
[LuaMethod("loadcorestate", "loads an in memory state with the given identifier")]
|
||||||
public void LoadCoreStateFromMemory(string identifier)
|
public void LoadCoreStateFromMemory(string identifier) => APIs.MemorySaveState.LoadCoreStateFromMemory(identifier);
|
||||||
{
|
|
||||||
var guid = new Guid(identifier);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var state = _memorySavestates[guid];
|
|
||||||
|
|
||||||
using var ms = new MemoryStream(state);
|
|
||||||
using var br = new BinaryReader(ms);
|
|
||||||
StatableCore.LoadStateBinary(br);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Log("Unable to find the given savestate in memory");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("memorysavestate.removestate( \"3fcf120f-0778-43fd-b2c5-460fb7d34184\" );")]
|
[LuaMethodExample("memorysavestate.removestate( \"3fcf120f-0778-43fd-b2c5-460fb7d34184\" );")]
|
||||||
[LuaMethod("removestate", "removes the savestate with the given identifier from memory")]
|
[LuaMethod("removestate", "removes the savestate with the given identifier from memory")]
|
||||||
public void DeleteState(string identifier)
|
public void DeleteState(string identifier) => APIs.MemorySaveState.DeleteState(identifier);
|
||||||
{
|
|
||||||
var guid = new Guid(identifier);
|
|
||||||
_memorySavestates.Remove(guid);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("memorysavestate.clearstatesfrommemory( );")]
|
[LuaMethodExample("memorysavestate.clearstatesfrommemory( );")]
|
||||||
[LuaMethod("clearstatesfrommemory", "clears all savestates stored in memory")]
|
[LuaMethod("clearstatesfrommemory", "clears all savestates stored in memory")]
|
||||||
public void ClearInMemoryStates()
|
public void ClearInMemoryStates() => APIs.MemorySaveState.ClearInMemoryStates();
|
||||||
{
|
|
||||||
_memorySavestates.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using NLua;
|
using NLua;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
public sealed class MovieLuaLibrary : LuaLibraryBase
|
public sealed class MovieLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
public MovieLuaLibrary(Lua lua)
|
public MovieLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -17,253 +17,108 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
[LuaMethodExample("if ( movie.startsfromsavestate( ) ) then\r\n\tconsole.log( \"Returns whether or not the movie is a savestate-anchored movie\" );\r\nend;")]
|
[LuaMethodExample("if ( movie.startsfromsavestate( ) ) then\r\n\tconsole.log( \"Returns whether or not the movie is a savestate-anchored movie\" );\r\nend;")]
|
||||||
[LuaMethod("startsfromsavestate", "Returns whether or not the movie is a savestate-anchored movie")]
|
[LuaMethod("startsfromsavestate", "Returns whether or not the movie is a savestate-anchored movie")]
|
||||||
public bool StartsFromSavestate()
|
public bool StartsFromSavestate() => APIs.Movie.StartsFromSavestate();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSavestate;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( movie.startsfromsaveram( ) ) then\r\n\tconsole.log( \"Returns whether or not the movie is a saveram-anchored movie\" );\r\nend;")]
|
[LuaMethodExample("if ( movie.startsfromsaveram( ) ) then\r\n\tconsole.log( \"Returns whether or not the movie is a saveram-anchored movie\" );\r\nend;")]
|
||||||
[LuaMethod("startsfromsaveram", "Returns whether or not the movie is a saveram-anchored movie")]
|
[LuaMethod("startsfromsaveram", "Returns whether or not the movie is a saveram-anchored movie")]
|
||||||
public bool StartsFromSaveram()
|
public bool StartsFromSaveram() => APIs.Movie.StartsFromSaveram();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.IsActive && Global.MovieSession.Movie.StartsFromSaveRam;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stmovfil = movie.filename( );")]
|
[LuaMethodExample("local stmovfil = movie.filename( );")]
|
||||||
[LuaMethod("filename", "Returns the file name including path of the currently loaded movie")]
|
[LuaMethod("filename", "Returns the file name including path of the currently loaded movie")]
|
||||||
public static string Filename()
|
public string Filename() => APIs.Movie.Filename();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.Filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local nlmovget = movie.getinput( 500 );")]
|
[LuaMethodExample("local nlmovget = movie.getinput( 500 );")]
|
||||||
[LuaMethod("getinput", "Returns a table of buttons pressed on a given frame of the loaded movie")]
|
[LuaMethod("getinput", "Returns a table of buttons pressed on a given frame of the loaded movie")]
|
||||||
public LuaTable GetInput(int frame)
|
public LuaTable GetInput(int frame)
|
||||||
{
|
{
|
||||||
if (!Global.MovieSession.Movie.IsActive)
|
var result = APIs.Movie.GetInput(frame);
|
||||||
{
|
var table = Lua.NewTable();
|
||||||
Log("No movie loaded");
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
return null;
|
return table;
|
||||||
}
|
|
||||||
|
|
||||||
var input = Lua.NewTable();
|
|
||||||
var adapter = Global.MovieSession.Movie.GetInputState(frame);
|
|
||||||
|
|
||||||
if (adapter == null)
|
|
||||||
{
|
|
||||||
Log("Can't get input of the last frame of the movie. Use the previous frame");
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var button in adapter.Definition.BoolButtons)
|
|
||||||
{
|
|
||||||
input[button] = adapter.IsPressed(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var button in adapter.Definition.FloatControls)
|
|
||||||
{
|
|
||||||
input[button] = adapter.GetFloat(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
return input;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local stmovget = movie.getinputasmnemonic( 500 );")]
|
[LuaMethodExample("local stmovget = movie.getinputasmnemonic( 500 );")]
|
||||||
[LuaMethod("getinputasmnemonic", "Returns the input of a given frame of the loaded movie in a raw inputlog string")]
|
[LuaMethod("getinputasmnemonic", "Returns the input of a given frame of the loaded movie in a raw inputlog string")]
|
||||||
public string GetInputAsMnemonic(int frame)
|
public string GetInputAsMnemonic(int frame) => APIs.Movie.GetInputAsMnemonic(frame);
|
||||||
{
|
|
||||||
if (Global.MovieSession.Movie.IsActive && frame < Global.MovieSession.Movie.InputLogLength)
|
|
||||||
{
|
|
||||||
var lg = Global.MovieSession.LogGeneratorInstance();
|
|
||||||
lg.SetSource(Global.MovieSession.Movie.GetInputState(frame));
|
|
||||||
return lg.GenerateLogEntry();
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( movie.getreadonly( ) ) then\r\n\tconsole.log( \"Returns true if the movie is in read-only mode, false if in read+write\" );\r\nend;")]
|
[LuaMethodExample("if ( movie.getreadonly( ) ) then\r\n\tconsole.log( \"Returns true if the movie is in read-only mode, false if in read+write\" );\r\nend;")]
|
||||||
[LuaMethod("getreadonly", "Returns true if the movie is in read-only mode, false if in read+write")]
|
[LuaMethod("getreadonly", "Returns true if the movie is in read-only mode, false if in read+write")]
|
||||||
public static bool GetReadOnly()
|
public bool GetReadOnly() => APIs.Movie.GetReadOnly();
|
||||||
{
|
|
||||||
return Global.MovieSession.ReadOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local ulmovget = movie.getrerecordcount();")]
|
[LuaMethodExample("local ulmovget = movie.getrerecordcount();")]
|
||||||
[LuaMethod("getrerecordcount", "Gets the rerecord count of the current movie.")]
|
[LuaMethod("getrerecordcount", "Gets the rerecord count of the current movie.")]
|
||||||
public static ulong GetRerecordCount()
|
public ulong GetRerecordCount() => APIs.Movie.GetRerecordCount();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.Rerecords;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( movie.getrerecordcounting( ) ) then\r\n\tconsole.log( \"Returns whether or not the current movie is incrementing rerecords on loadstate\" );\r\nend;")]
|
[LuaMethodExample("if ( movie.getrerecordcounting( ) ) then\r\n\tconsole.log( \"Returns whether or not the current movie is incrementing rerecords on loadstate\" );\r\nend;")]
|
||||||
[LuaMethod("getrerecordcounting", "Returns whether or not the current movie is incrementing rerecords on loadstate")]
|
[LuaMethod("getrerecordcounting", "Returns whether or not the current movie is incrementing rerecords on loadstate")]
|
||||||
public static bool GetRerecordCounting()
|
public bool GetRerecordCounting() => APIs.Movie.GetRerecordCounting();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.IsCountingRerecords;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( movie.isloaded( ) ) then\r\n\tconsole.log( \"Returns true if a movie is loaded in memory ( play, record, or finished modes ), false if not ( inactive mode )\" );\r\nend;")]
|
[LuaMethodExample("if ( movie.isloaded( ) ) then\r\n\tconsole.log( \"Returns true if a movie is loaded in memory ( play, record, or finished modes ), false if not ( inactive mode )\" );\r\nend;")]
|
||||||
[LuaMethod("isloaded", "Returns true if a movie is loaded in memory (play, record, or finished modes), false if not (inactive mode)")]
|
[LuaMethod("isloaded", "Returns true if a movie is loaded in memory (play, record, or finished modes), false if not (inactive mode)")]
|
||||||
public static bool IsLoaded()
|
public bool IsLoaded() => APIs.Movie.IsLoaded();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.IsActive;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local domovlen = movie.length( );")]
|
[LuaMethodExample("local domovlen = movie.length( );")]
|
||||||
[LuaMethod("length", "Returns the total number of frames of the loaded movie")]
|
[LuaMethod("length", "Returns the total number of frames of the loaded movie")]
|
||||||
public static double Length()
|
public double Length() => APIs.Movie.Length();
|
||||||
{
|
|
||||||
return Global.MovieSession.Movie.FrameCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stmovmod = movie.mode( );")]
|
[LuaMethodExample("local stmovmod = movie.mode( );")]
|
||||||
[LuaMethod("mode", "Returns the mode of the current movie. Possible modes: \"PLAY\", \"RECORD\", \"FINISHED\", \"INACTIVE\"")]
|
[LuaMethod("mode", "Returns the mode of the current movie. Possible modes: \"PLAY\", \"RECORD\", \"FINISHED\", \"INACTIVE\"")]
|
||||||
public static string Mode()
|
public string Mode() => APIs.Movie.Mode();
|
||||||
{
|
|
||||||
if (Global.MovieSession.Movie.IsFinished)
|
|
||||||
{
|
|
||||||
return "FINISHED";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.MovieSession.Movie.IsPlaying)
|
|
||||||
{
|
|
||||||
return "PLAY";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.MovieSession.Movie.IsRecording)
|
|
||||||
{
|
|
||||||
return "RECORD";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "INACTIVE";
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("movie.save( \"C:\\moviename.ext\" );")]
|
[LuaMethodExample("movie.save( \"C:\\moviename.ext\" );")]
|
||||||
[LuaMethod("save", "Saves the current movie to the disc. If the filename is provided (no extension or path needed), the movie is saved under the specified name to the current movie directory. The filename may contain a subdirectory, it will be created if it doesn't exist. Existing files won't get overwritten.")]
|
[LuaMethod("save", "Saves the current movie to the disc. If the filename is provided (no extension or path needed), the movie is saved under the specified name to the current movie directory. The filename may contain a subdirectory, it will be created if it doesn't exist. Existing files won't get overwritten.")]
|
||||||
public void Save(string filename = "")
|
public void Save(string filename = "") => APIs.Movie.Save();
|
||||||
{
|
|
||||||
if (!Global.MovieSession.Movie.IsActive)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(filename))
|
|
||||||
{
|
|
||||||
filename += $".{Global.MovieSession.Movie.PreferredExtension}";
|
|
||||||
var test = new FileInfo(filename);
|
|
||||||
if (test.Exists)
|
|
||||||
{
|
|
||||||
Log($"File {filename} already exists, will not overwrite");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.MovieSession.Movie.Filename = filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.MovieSession.Movie.Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("movie.setreadonly( false );")]
|
[LuaMethodExample("movie.setreadonly( false );")]
|
||||||
[LuaMethod("setreadonly", "Sets the read-only state to the given value. true for read only, false for read+write")]
|
[LuaMethod("setreadonly", "Sets the read-only state to the given value. true for read only, false for read+write")]
|
||||||
public static void SetReadOnly(bool readOnly)
|
public void SetReadOnly(bool readOnly) => APIs.Movie.SetReadOnly(readOnly);
|
||||||
{
|
|
||||||
Global.MovieSession.ReadOnly = readOnly;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("movie.setrerecordcount( 20.0 );")]
|
[LuaMethodExample("movie.setrerecordcount( 20.0 );")]
|
||||||
[LuaMethod("setrerecordcount", "Sets the rerecord count of the current movie.")]
|
[LuaMethod("setrerecordcount", "Sets the rerecord count of the current movie.")]
|
||||||
public static void SetRerecordCount(double count)
|
public void SetRerecordCount(double count) => APIs.Movie.SetRerecordCount(count);
|
||||||
{
|
|
||||||
// Lua numbers are always double, integer precision holds up
|
|
||||||
// to 53 bits, so throw an error if it's bigger than that.
|
|
||||||
const double precisionLimit = 9007199254740992d;
|
|
||||||
|
|
||||||
if (count > precisionLimit)
|
|
||||||
{
|
|
||||||
throw new Exception("Rerecord count exceeds Lua integer precision.");
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.MovieSession.Movie.Rerecords = (ulong)count;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("movie.setrerecordcounting( true );")]
|
[LuaMethodExample("movie.setrerecordcounting( true );")]
|
||||||
[LuaMethod("setrerecordcounting", "Sets whether or not the current movie will increment the rerecord counter on loadstate")]
|
[LuaMethod("setrerecordcounting", "Sets whether or not the current movie will increment the rerecord counter on loadstate")]
|
||||||
public static void SetRerecordCounting(bool counting)
|
public void SetRerecordCounting(bool counting) => APIs.Movie.SetRerecordCounting(counting);
|
||||||
{
|
|
||||||
Global.MovieSession.Movie.IsCountingRerecords = counting;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("movie.stop( );")]
|
[LuaMethodExample("movie.stop( );")]
|
||||||
[LuaMethod("stop", "Stops the current movie")]
|
[LuaMethod("stop", "Stops the current movie")]
|
||||||
public static void Stop()
|
public void Stop() => APIs.Movie.Stop();
|
||||||
{
|
|
||||||
Global.MovieSession.Movie.Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local domovget = movie.getfps( );")]
|
[LuaMethodExample("local domovget = movie.getfps( );")]
|
||||||
[LuaMethod("getfps", "If a movie is loaded, gets the frames per second used by the movie to determine the movie length time")]
|
[LuaMethod("getfps", "If a movie is loaded, gets the frames per second used by the movie to determine the movie length time")]
|
||||||
public static double GetFps()
|
public double GetFps() => APIs.Movie.GetFps();
|
||||||
{
|
|
||||||
if (Global.MovieSession.Movie.IsActive)
|
|
||||||
{
|
|
||||||
var movie = Global.MovieSession.Movie;
|
|
||||||
var system = movie.HeaderEntries[HeaderKeys.PLATFORM];
|
|
||||||
var pal = movie.HeaderEntries.ContainsKey(HeaderKeys.PAL)
|
|
||||||
&& movie.HeaderEntries[HeaderKeys.PAL] == "1";
|
|
||||||
|
|
||||||
return new PlatformFrameRates()[system, pal];
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local nlmovget = movie.getheader( );")]
|
[LuaMethodExample("local nlmovget = movie.getheader( );")]
|
||||||
[LuaMethod("getheader", "If a movie is active, will return the movie header as a lua table")]
|
[LuaMethod("getheader", "If a movie is active, will return the movie header as a lua table")]
|
||||||
public LuaTable GetHeader()
|
public LuaTable GetHeader()
|
||||||
{
|
{
|
||||||
var luaTable = Lua.NewTable();
|
var result = APIs.Movie.GetHeader();
|
||||||
if (Global.MovieSession.Movie.IsActive)
|
var table = Lua.NewTable();
|
||||||
{
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
foreach (var kvp in Global.MovieSession.Movie.HeaderEntries)
|
return table;
|
||||||
{
|
|
||||||
luaTable[kvp.Key] = kvp.Value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return luaTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local nlmovget = movie.getcomments( );")]
|
[LuaMethodExample("local nlmovget = movie.getcomments( );")]
|
||||||
[LuaMethod("getcomments", "If a movie is active, will return the movie comments as a lua table")]
|
[LuaMethod("getcomments", "If a movie is active, will return the movie comments as a lua table")]
|
||||||
public LuaTable GetComments()
|
public LuaTable GetComments()
|
||||||
{
|
{
|
||||||
var luaTable = Lua.NewTable();
|
var result = APIs.Movie.GetComments();
|
||||||
if (Global.MovieSession.Movie.IsActive)
|
var table = Lua.NewTable();
|
||||||
{
|
var count = result.Count;
|
||||||
for (int i = 0; i < Global.MovieSession.Movie.Comments.Count; i++)
|
for (var i = 0; i != count; i++) table[i] = result[i];
|
||||||
{
|
return table;
|
||||||
luaTable[i] = Global.MovieSession.Movie.Comments[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return luaTable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local nlmovget = movie.getsubtitles( );")]
|
[LuaMethodExample("local nlmovget = movie.getsubtitles( );")]
|
||||||
[LuaMethod("getsubtitles", "If a movie is active, will return the movie subtitles as a lua table")]
|
[LuaMethod("getsubtitles", "If a movie is active, will return the movie subtitles as a lua table")]
|
||||||
public LuaTable GetSubtitles()
|
public LuaTable GetSubtitles()
|
||||||
{
|
{
|
||||||
var luaTable = Lua.NewTable();
|
var result = APIs.Movie.GetSubtitles();
|
||||||
if (Global.MovieSession.Movie.IsActive)
|
var table = Lua.NewTable();
|
||||||
{
|
var count = result.Count;
|
||||||
for (int i = 0; i < Global.MovieSession.Movie.Subtitles.Count; i++)
|
for (var i = 0; i != count; i++) table[i] = result[i];
|
||||||
{
|
return table;
|
||||||
luaTable[i] = Global.MovieSession.Movie.Subtitles[i].ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return luaTable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data.SQLite;
|
|
||||||
using NLua;
|
using NLua;
|
||||||
|
|
||||||
// ReSharper disable UnusedMember.Global
|
// ReSharper disable UnusedMember.Global
|
||||||
namespace BizHawk.Client.Common
|
namespace BizHawk.Client.Common
|
||||||
{
|
{
|
||||||
[Description("A library for performing SQLite operations.")]
|
[Description("A library for performing SQLite operations.")]
|
||||||
public sealed class SqlLuaLibrary : LuaLibraryBase
|
public sealed class SqlLuaLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
public SqlLuaLibrary(Lua lua)
|
public SqlLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -18,131 +18,32 @@ namespace BizHawk.Client.Common
|
||||||
|
|
||||||
public override string Name => "SQL";
|
public override string Name => "SQL";
|
||||||
|
|
||||||
SQLiteConnection _mDBConnection;
|
|
||||||
|
|
||||||
[LuaMethodExample("local stSQLcre = SQL.createdatabase( \"eg_db\" );")]
|
[LuaMethodExample("local stSQLcre = SQL.createdatabase( \"eg_db\" );")]
|
||||||
[LuaMethod("createdatabase", "Creates a SQLite Database. Name should end with .db")]
|
[LuaMethod("createdatabase", "Creates a SQLite Database. Name should end with .db")]
|
||||||
public string CreateDatabase(string name)
|
public string CreateDatabase(string name) => APIs.Sql.CreateDatabase(name);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
SQLiteConnection.CreateFile(name);
|
|
||||||
return "Database Created Successfully";
|
|
||||||
}
|
|
||||||
catch (SQLiteException sqlEx)
|
|
||||||
{
|
|
||||||
return sqlEx.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[LuaMethodExample("local stSQLope = SQL.opendatabase( \"eg_db\" );")]
|
[LuaMethodExample("local stSQLope = SQL.opendatabase( \"eg_db\" );")]
|
||||||
[LuaMethod("opendatabase", "Opens a SQLite database. Name should end with .db")]
|
[LuaMethod("opendatabase", "Opens a SQLite database. Name should end with .db")]
|
||||||
public string OpenDatabase(string name)
|
public string OpenDatabase(string name) => APIs.Sql.OpenDatabase(name);
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var connBuilder = new SQLiteConnectionStringBuilder
|
|
||||||
{
|
|
||||||
DataSource = name,
|
|
||||||
Version = 3,
|
|
||||||
JournalMode = SQLiteJournalModeEnum.Wal, // Allows for reads and writes to happen at the same time
|
|
||||||
DefaultIsolationLevel = System.Data.IsolationLevel.ReadCommitted, // This only helps make the database lock left. May be pointless now
|
|
||||||
SyncMode = SynchronizationModes.Off, // This shortens the delay for do synchronous calls.
|
|
||||||
};
|
|
||||||
|
|
||||||
_mDBConnection = new SQLiteConnection(connBuilder.ToString());
|
|
||||||
_mDBConnection.Open();
|
|
||||||
_mDBConnection.Close();
|
|
||||||
return "Database Opened Successfully";
|
|
||||||
}
|
|
||||||
catch (SQLiteException sqlEx)
|
|
||||||
{
|
|
||||||
return sqlEx.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local stSQLwri = SQL.writecommand( \"CREATE TABLE eg_tab ( eg_tab_id integer PRIMARY KEY, eg_tab_row_name text NOT NULL ); INSERT INTO eg_tab ( eg_tab_id, eg_tab_row_name ) VALUES ( 1, 'Example table row' );\" );")]
|
[LuaMethodExample("local stSQLwri = SQL.writecommand( \"CREATE TABLE eg_tab ( eg_tab_id integer PRIMARY KEY, eg_tab_row_name text NOT NULL ); INSERT INTO eg_tab ( eg_tab_id, eg_tab_row_name ) VALUES ( 1, 'Example table row' );\" );")]
|
||||||
[LuaMethod("writecommand", "Runs a SQLite write command which includes CREATE,INSERT, UPDATE. " +
|
[LuaMethod("writecommand", "Runs a SQLite write command which includes CREATE,INSERT, UPDATE. " +
|
||||||
"Ex: create TABLE rewards (ID integer PRIMARY KEY, action VARCHAR(20)) ")]
|
"Ex: create TABLE rewards (ID integer PRIMARY KEY, action VARCHAR(20)) ")]
|
||||||
public string WriteCommand(string query = "")
|
public string WriteCommand(string query = "") => APIs.Sql.WriteCommand(query);
|
||||||
{
|
|
||||||
if (query == "")
|
|
||||||
{
|
|
||||||
return "query is empty";
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_mDBConnection.Open();
|
|
||||||
string sql = query;
|
|
||||||
SQLiteCommand command = new SQLiteCommand(sql, _mDBConnection);
|
|
||||||
command.ExecuteNonQuery();
|
|
||||||
_mDBConnection.Close();
|
|
||||||
|
|
||||||
return "Command ran successfully";
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (NullReferenceException)
|
|
||||||
{
|
|
||||||
return "Database not open.";
|
|
||||||
}
|
|
||||||
catch (SQLiteException sqlEx)
|
|
||||||
{
|
|
||||||
_mDBConnection.Close();
|
|
||||||
return sqlEx.Message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local obSQLrea = SQL.readcommand( \"SELECT * FROM eg_tab WHERE eg_tab_id = 1;\" );")]
|
[LuaMethodExample("local obSQLrea = SQL.readcommand( \"SELECT * FROM eg_tab WHERE eg_tab_id = 1;\" );")]
|
||||||
[LuaMethod("readcommand", "Run a SQLite read command which includes Select. Returns all rows into a LuaTable." +
|
[LuaMethod("readcommand", "Run a SQLite read command which includes Select. Returns all rows into a LuaTable." +
|
||||||
"Ex: select * from rewards")]
|
"Ex: select * from rewards")]
|
||||||
public dynamic ReadCommand(string query = "")
|
public dynamic ReadCommand(string query = "")
|
||||||
{
|
{
|
||||||
if (query == "")
|
var result = APIs.Sql.ReadCommand(query);
|
||||||
{
|
if (result is Dictionary<string, object> dict)
|
||||||
return "query is empty";
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
var table = Lua.NewTable();
|
var table = Lua.NewTable();
|
||||||
_mDBConnection.Open();
|
foreach (var kvp in dict) table[kvp.Key] = kvp.Value;
|
||||||
string sql = $"PRAGMA read_uncommitted =1;{query}";
|
|
||||||
using var command = new SQLiteCommand(sql, _mDBConnection);
|
|
||||||
SQLiteDataReader reader = command.ExecuteReader();
|
|
||||||
bool rows = reader.HasRows;
|
|
||||||
long rowCount = 0;
|
|
||||||
var columns = new List<string>();
|
|
||||||
for (int i = 0; i < reader.FieldCount; ++i) //Add all column names into list
|
|
||||||
{
|
|
||||||
columns.Add(reader.GetName(i));
|
|
||||||
}
|
|
||||||
while (reader.Read())
|
|
||||||
{
|
|
||||||
for (int i = 0; i < reader.FieldCount; ++i)
|
|
||||||
{
|
|
||||||
table[$"{columns[i]} {rowCount}"] = reader.GetValue(i);
|
|
||||||
}
|
|
||||||
rowCount += 1;
|
|
||||||
}
|
|
||||||
reader.Close();
|
|
||||||
_mDBConnection.Close();
|
|
||||||
if (rows == false)
|
|
||||||
{
|
|
||||||
return "No rows found";
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
return table;
|
||||||
|
|
||||||
}
|
|
||||||
catch (NullReferenceException)
|
|
||||||
{
|
|
||||||
return "Database not opened.";
|
|
||||||
}
|
|
||||||
catch (SQLiteException sqlEx)
|
|
||||||
{
|
|
||||||
_mDBConnection.Close();
|
|
||||||
return sqlEx.Message;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ using BizHawk.Client.Common;
|
||||||
namespace BizHawk.Client.EmuHawk
|
namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
[Description("A library for setting and retrieving dynamic data that will be saved and loaded with savestates")]
|
[Description("A library for setting and retrieving dynamic data that will be saved and loaded with savestates")]
|
||||||
public sealed class UserDataLibrary : LuaLibraryBase
|
public sealed class UserDataLibrary : DelegatingLuaLibrary
|
||||||
{
|
{
|
||||||
public UserDataLibrary(Lua lua)
|
public UserDataLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -19,48 +19,22 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
[LuaMethodExample("userdata.set(\"Unique key\", \"Current key data\");")]
|
[LuaMethodExample("userdata.set(\"Unique key\", \"Current key data\");")]
|
||||||
[LuaMethod("set", "adds or updates the data with the given key with the given value")]
|
[LuaMethod("set", "adds or updates the data with the given key with the given value")]
|
||||||
public void Set(string name, object value)
|
public void Set(string name, object value) => APIs.UserData.Set(name, value);
|
||||||
{
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
var t = value.GetType();
|
|
||||||
if (!t.IsPrimitive && t != typeof(string))
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Invalid type for userdata");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Global.UserBag[name] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("local obuseget = userdata.get( \"Unique key\" );")]
|
[LuaMethodExample("local obuseget = userdata.get( \"Unique key\" );")]
|
||||||
[LuaMethod("get", "gets the data with the given key, if the key does not exist it will return nil")]
|
[LuaMethod("get", "gets the data with the given key, if the key does not exist it will return nil")]
|
||||||
public object Get(string key)
|
public object Get(string key) => APIs.UserData.Get(key);
|
||||||
{
|
|
||||||
return Global.UserBag.ContainsKey(key)
|
|
||||||
? Global.UserBag[key]
|
|
||||||
: null;
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("userdata.clear( );")]
|
[LuaMethodExample("userdata.clear( );")]
|
||||||
[LuaMethod("clear", "clears all user data")]
|
[LuaMethod("clear", "clears all user data")]
|
||||||
public void Clear()
|
public void Clear() => APIs.UserData.Clear();
|
||||||
{
|
|
||||||
Global.UserBag.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( userdata.remove( \"Unique key\" ) ) then\r\n\tconsole.log( \"remove the data with the given key.Returns true if the element is successfully found and removed; otherwise, false.\" );\r\nend;")]
|
[LuaMethodExample("if ( userdata.remove( \"Unique key\" ) ) then\r\n\tconsole.log( \"remove the data with the given key.Returns true if the element is successfully found and removed; otherwise, false.\" );\r\nend;")]
|
||||||
[LuaMethod("remove", "remove the data with the given key. Returns true if the element is successfully found and removed; otherwise, false.")]
|
[LuaMethod("remove", "remove the data with the given key. Returns true if the element is successfully found and removed; otherwise, false.")]
|
||||||
public bool Remove(string key)
|
public bool Remove(string key) => APIs.UserData.Remove(key);
|
||||||
{
|
|
||||||
return Global.UserBag.Remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("if ( userdata.containskey( \"Unique key\" ) ) then\r\n\tconsole.log( \"returns whether or not there is an entry for the given key\" );\r\nend;")]
|
[LuaMethodExample("if ( userdata.containskey( \"Unique key\" ) ) then\r\n\tconsole.log( \"returns whether or not there is an entry for the given key\" );\r\nend;")]
|
||||||
[LuaMethod("containskey", "returns whether or not there is an entry for the given key")]
|
[LuaMethod("containskey", "returns whether or not there is an entry for the given key")]
|
||||||
public bool ContainsKey(string key)
|
public bool ContainsKey(string key) => APIs.UserData.ContainsKey(key);
|
||||||
{
|
|
||||||
return Global.UserBag.ContainsKey(key);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,259 +0,0 @@
|
||||||
using System;
|
|
||||||
using NLua;
|
|
||||||
using BizHawk.Emulation.Common;
|
|
||||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
|
||||||
|
|
||||||
namespace BizHawk.Client.Common
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Base class for the Memory and MainMemory lua libraries
|
|
||||||
/// </summary>
|
|
||||||
public abstract class LuaMemoryBase : LuaLibraryBase
|
|
||||||
{
|
|
||||||
[RequiredService]
|
|
||||||
protected IEmulator Emulator { get; set; }
|
|
||||||
|
|
||||||
[OptionalService]
|
|
||||||
protected IMemoryDomains MemoryDomainCore { get; set; }
|
|
||||||
|
|
||||||
protected LuaMemoryBase(Lua lua)
|
|
||||||
: base(lua) { }
|
|
||||||
|
|
||||||
protected LuaMemoryBase(Lua lua, Action<string> logOutputCallback)
|
|
||||||
: base(lua, logOutputCallback) { }
|
|
||||||
|
|
||||||
protected abstract MemoryDomain Domain { get; }
|
|
||||||
|
|
||||||
protected IMemoryDomains DomainList
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (MemoryDomainCore != null)
|
|
||||||
{
|
|
||||||
return MemoryDomainCore;
|
|
||||||
}
|
|
||||||
|
|
||||||
var error = $"Error: {Emulator.Attributes().CoreName} does not implement memory domains";
|
|
||||||
Log(error);
|
|
||||||
throw new NotImplementedException(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string VerifyMemoryDomain(string domain)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (DomainList[domain] == null)
|
|
||||||
{
|
|
||||||
Log($"Unable to find domain: {domain}, falling back to current");
|
|
||||||
return Domain.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return domain;
|
|
||||||
}
|
|
||||||
catch // Just in case
|
|
||||||
{
|
|
||||||
Log($"Unable to find domain: {domain}, falling back to current");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Domain.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadUnsignedByte(int addr, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
return d.PeekByte(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Warning: attempted read of {addr} outside the memory size of {d.Size}");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteUnsignedByte(int addr, uint v, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (d.CanPoke())
|
|
||||||
{
|
|
||||||
if (addr < Domain.Size)
|
|
||||||
{
|
|
||||||
d.PokeByte(addr, (byte)v);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Warning: attempted write to {addr} outside the memory size of {d.Size}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Error: the domain {d.Name} is not writable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static int U2S(uint u, int size)
|
|
||||||
{
|
|
||||||
var s = (int)u;
|
|
||||||
s <<= 8 * (4 - size);
|
|
||||||
s >>= 8 * (4 - size);
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int ReadSignedLittleCore(int addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
return U2S(ReadUnsignedLittle(addr, size, domain), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadUnsignedLittle(int addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
uint v = 0;
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
v |= ReadUnsignedByte(addr + i, domain) << (8 * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int ReadSignedBig(int addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
return U2S(ReadUnsignedBig(addr, size, domain), size);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadUnsignedBig(int addr, int size, string domain = null)
|
|
||||||
{
|
|
||||||
uint v = 0;
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
v |= ReadUnsignedByte(addr + i, domain) << (8 * (size - 1 - i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteSignedLittle(int addr, int v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
WriteUnsignedLittle(addr, (uint)v, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteUnsignedLittle(int addr, uint v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr + i, (v >> (8 * i)) & 0xFF, domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteSignedBig(int addr, int v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
WriteUnsignedBig(addr, (uint)v, size, domain);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteUnsignedBig(int addr, uint v, int size, string domain = null)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
WriteUnsignedByte(addr + i, (v >> (8 * (size - 1 - i))) & 0xFF, domain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected uint ReadSignedLittle(int addr, int size) // only used by mainmemory, so no domain can be passed
|
|
||||||
{
|
|
||||||
uint v = 0;
|
|
||||||
for (var i = 0; i < size; ++i)
|
|
||||||
{
|
|
||||||
v |= ReadUnsignedByte(addr + i) << (8 * i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
#region public Library implementations
|
|
||||||
|
|
||||||
protected LuaTable ReadByteRange(int addr, int length, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
var lastAddr = length + addr;
|
|
||||||
var table = Lua.NewTable();
|
|
||||||
if (lastAddr <= d.Size)
|
|
||||||
{
|
|
||||||
for (var i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
int a = addr + i;
|
|
||||||
var v = d.PeekByte(a);
|
|
||||||
table[i] = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Warning: Attempted read {lastAddr} outside memory domain size of {d.Size} in readbyterange()");
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteByteRange(LuaTable memoryblock, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (d.CanPoke())
|
|
||||||
{
|
|
||||||
foreach (var address in memoryblock.Keys)
|
|
||||||
{
|
|
||||||
var addr = LuaInt(address);
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
d.PokeByte(addr, (byte)LuaInt(memoryblock[address]));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Warning: Attempted write {addr} outside memory domain size of {d.Size} in writebyterange()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Error: the domain {d.Name} is not writable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected float ReadFloat(int addr, bool bigEndian, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
var val = d.PeekUint(addr, bigEndian);
|
|
||||||
var bytes = BitConverter.GetBytes(val);
|
|
||||||
return BitConverter.ToSingle(bytes, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Warning: Attempted read {addr} outside memory size of {d.Size}");
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void WriteFloat(int addr, double value, bool bigEndian, string domain = null)
|
|
||||||
{
|
|
||||||
var d = string.IsNullOrEmpty(domain) ? Domain : DomainList[VerifyMemoryDomain(domain)];
|
|
||||||
if (d.CanPoke())
|
|
||||||
{
|
|
||||||
if (addr < d.Size)
|
|
||||||
{
|
|
||||||
var dv = (float)value;
|
|
||||||
var bytes = BitConverter.GetBytes(dv);
|
|
||||||
var v = BitConverter.ToUInt32(bytes, 0);
|
|
||||||
d.PokeUint(addr, v, bigEndian);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Warning: Attempted write {addr} outside memory size of {d.Size}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"Error: the domain {Domain.Name} is not writable");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +1,18 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
using BizHawk.Client.ApiHawk;
|
|
||||||
using BizHawk.Client.Common;
|
using BizHawk.Client.Common;
|
||||||
|
|
||||||
namespace BizHawk.Client.EmuHawk
|
namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
public sealed class ApiContainer : IApiContainer
|
public sealed class ApiContainer : APISubsetContainer
|
||||||
{
|
{
|
||||||
public IComm Comm => (IComm)Libraries[typeof(CommApi)];
|
public IComm Comm => (IComm) Libraries[typeof(CommApi)];
|
||||||
public IEmu Emu => (IEmu)Libraries[typeof(EmuApi)];
|
public IGui Gui => (IGui) Libraries[typeof(GuiApi)];
|
||||||
public IGameInfo GameInfo => (IGameInfo)Libraries[typeof(GameInfoApi)];
|
public IInput Input => (IInput) Libraries[typeof(InputApi)];
|
||||||
public IGui Gui => (IGui)Libraries[typeof(GuiApi)];
|
public ISaveState SaveState => (ISaveState) Libraries[typeof(SaveStateApi)];
|
||||||
public IInput Input => (IInput)Libraries[typeof(InputApi)];
|
public ITool Tool => (ITool) Libraries[typeof(ToolApi)];
|
||||||
public IJoypad Joypad => (IJoypad)Libraries[typeof(JoypadApi)];
|
|
||||||
public IMem Mem => (IMem)Libraries[typeof(MemApi)];
|
public ApiContainer(Dictionary<Type, IExternalApi> libs) : base(libs) {}
|
||||||
public IMemEvents MemEvents => (IMemEvents)Libraries[typeof(MemEventsApi)];
|
|
||||||
public IMemorySaveState MemorySaveState => (IMemorySaveState)Libraries[typeof(MemorySaveStateApi)];
|
|
||||||
public IInputMovie Movie => (IInputMovie)Libraries[typeof(MovieApi)];
|
|
||||||
public ISaveState SaveState => (ISaveState)Libraries[typeof(SaveStateApi)];
|
|
||||||
public ISql Sql => (ISql)Libraries[typeof(SqlApi)];
|
|
||||||
public ITool Tool => (ITool)Libraries[typeof(ToolApi)];
|
|
||||||
public IUserData UserData => (IUserData)Libraries[typeof(UserDataApi)];
|
|
||||||
public Dictionary<Type, IExternalApi> Libraries { get; set; }
|
|
||||||
public ApiContainer(Dictionary<Type, IExternalApi> libs)
|
|
||||||
{
|
|
||||||
Libraries = libs;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,39 +9,45 @@ namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
public sealed class SaveStateApi : ISaveState
|
public sealed class SaveStateApi : ISaveState
|
||||||
{
|
{
|
||||||
public SaveStateApi() : base()
|
public SaveStateApi(Action<string> logCallback)
|
||||||
{ }
|
{
|
||||||
|
LogCallback = logCallback;
|
||||||
|
}
|
||||||
|
|
||||||
public void Load(string path)
|
public SaveStateApi() : this(Console.WriteLine) {}
|
||||||
|
|
||||||
|
private readonly Action<string> LogCallback;
|
||||||
|
|
||||||
|
public void Load(string path, bool suppressOSD)
|
||||||
{
|
{
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
Console.WriteLine($"could not find file: {path}");
|
LogCallback($"could not find file: {path}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GlobalWin.MainForm.LoadState(path, Path.GetFileName(path), true);
|
GlobalWin.MainForm.LoadState(path, Path.GetFileName(path), true, suppressOSD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadSlot(int slotNum)
|
public void LoadSlot(int slotNum, bool suppressOSD)
|
||||||
{
|
{
|
||||||
if (slotNum >= 0 && slotNum <= 9)
|
if (slotNum >= 0 && slotNum <= 9)
|
||||||
{
|
{
|
||||||
GlobalWin.MainForm.LoadQuickSave($"QuickSave{slotNum}", true);
|
GlobalWin.MainForm.LoadQuickSave($"QuickSave{slotNum}", true, suppressOSD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(string path)
|
public void Save(string path, bool suppressOSD)
|
||||||
{
|
{
|
||||||
GlobalWin.MainForm.SaveState(path, path, true);
|
GlobalWin.MainForm.SaveState(path, path, true, suppressOSD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveSlot(int slotNum)
|
public void SaveSlot(int slotNum, bool suppressOSD)
|
||||||
{
|
{
|
||||||
if (slotNum >= 0 && slotNum <= 9)
|
if (slotNum >= 0 && slotNum <= 9)
|
||||||
{
|
{
|
||||||
GlobalWin.MainForm.SaveQuickSave($"QuickSave{slotNum}");
|
GlobalWin.MainForm.SaveQuickSave($"QuickSave{slotNum}", true, suppressOSD);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -917,6 +917,7 @@
|
||||||
<Compile Include="tools\HexEditor\HexFind.Designer.cs">
|
<Compile Include="tools\HexEditor\HexFind.Designer.cs">
|
||||||
<DependentUpon>HexFind.cs</DependentUpon>
|
<DependentUpon>HexFind.cs</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="tools\Lua\Libraries\DelegatingLuaLibraryEmu.cs" />
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Client.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Client.cs" />
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Communication.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Communication.cs" />
|
||||||
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Console.cs" />
|
<Compile Include="tools\Lua\Libraries\EmuLuaLibrary.Console.cs" />
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using NLua;
|
||||||
|
|
||||||
|
using BizHawk.Client.Common;
|
||||||
|
|
||||||
|
namespace BizHawk.Client.EmuHawk
|
||||||
|
{
|
||||||
|
/// <summary>As <see cref="DelegatingLuaLibrary"/>, but also includes EmuHawk APIs via a <see cref="APIContainer"/>.</summary>
|
||||||
|
public abstract class DelegatingLuaLibraryEmu : DelegatingLuaLibrary
|
||||||
|
{
|
||||||
|
protected DelegatingLuaLibraryEmu(Lua lua) : base(lua) {}
|
||||||
|
|
||||||
|
protected DelegatingLuaLibraryEmu(Lua lua, Action<string> logOutputCallback) : base(lua, logOutputCallback) {}
|
||||||
|
|
||||||
|
public new ApiContainer APIs { protected get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@ using System.Diagnostics;
|
||||||
namespace BizHawk.Client.EmuHawk
|
namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
[Description("A library for manipulating the EmuHawk client UI")]
|
[Description("A library for manipulating the EmuHawk client UI")]
|
||||||
public sealed class EmuHawkLuaLibrary : LuaLibraryBase
|
public sealed class EmuHawkLuaLibrary : DelegatingLuaLibraryEmu
|
||||||
{
|
{
|
||||||
[RequiredService]
|
[RequiredService]
|
||||||
private IEmulator Emulator { get; set; }
|
private IEmulator Emulator { get; set; }
|
||||||
|
@ -225,31 +225,19 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
[LuaMethodExample("client.opencheats( );")]
|
[LuaMethodExample("client.opencheats( );")]
|
||||||
[LuaMethod("opencheats", "opens the Cheats dialog")]
|
[LuaMethod("opencheats", "opens the Cheats dialog")]
|
||||||
public static void OpenCheats()
|
public void OpenCheats() => APIs.Tool.OpenCheats();
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load<Cheats>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.openhexeditor( );")]
|
[LuaMethodExample("client.openhexeditor( );")]
|
||||||
[LuaMethod("openhexeditor", "opens the Hex Editor dialog")]
|
[LuaMethod("openhexeditor", "opens the Hex Editor dialog")]
|
||||||
public static void OpenHexEditor()
|
public void OpenHexEditor() => APIs.Tool.OpenHexEditor();
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load<HexEditor>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.openramwatch( );")]
|
[LuaMethodExample("client.openramwatch( );")]
|
||||||
[LuaMethod("openramwatch", "opens the RAM Watch dialog")]
|
[LuaMethod("openramwatch", "opens the RAM Watch dialog")]
|
||||||
public static void OpenRamWatch()
|
public void OpenRamWatch() => APIs.Tool.OpenRamWatch();
|
||||||
{
|
|
||||||
GlobalWin.Tools.LoadRamWatch(loadDialog: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.openramsearch( );")]
|
[LuaMethodExample("client.openramsearch( );")]
|
||||||
[LuaMethod("openramsearch", "opens the RAM Search dialog")]
|
[LuaMethod("openramsearch", "opens the RAM Search dialog")]
|
||||||
public static void OpenRamSearch()
|
public void OpenRamSearch() => APIs.Tool.OpenRamSearch();
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load<RamSearch>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.openrom( \"C:\\\" );")]
|
[LuaMethodExample("client.openrom( \"C:\\\" );")]
|
||||||
[LuaMethod("openrom", "opens the Open ROM dialog")]
|
[LuaMethod("openrom", "opens the Open ROM dialog")]
|
||||||
|
@ -261,24 +249,15 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
[LuaMethodExample("client.opentasstudio( );")]
|
[LuaMethodExample("client.opentasstudio( );")]
|
||||||
[LuaMethod("opentasstudio", "opens the TAStudio dialog")]
|
[LuaMethod("opentasstudio", "opens the TAStudio dialog")]
|
||||||
public static void OpenTasStudio()
|
public void OpenTasStudio() => APIs.Tool.OpenTasStudio();
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load<TAStudio>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.opentoolbox( );")]
|
[LuaMethodExample("client.opentoolbox( );")]
|
||||||
[LuaMethod("opentoolbox", "opens the Toolbox Dialog")]
|
[LuaMethod("opentoolbox", "opens the Toolbox Dialog")]
|
||||||
public static void OpenToolBox()
|
public void OpenToolBox() => APIs.Tool.OpenToolBox();
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load<ToolBox>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.opentracelogger( );")]
|
[LuaMethodExample("client.opentracelogger( );")]
|
||||||
[LuaMethod("opentracelogger", "opens the tracelogger if it is available for the given core")]
|
[LuaMethod("opentracelogger", "opens the tracelogger if it is available for the given core")]
|
||||||
public static void OpenTraceLogger()
|
public void OpenTraceLogger() => APIs.Tool.OpenTraceLogger();
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load<TraceLogger>();
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("client.pause( );")]
|
[LuaMethodExample("client.pause( );")]
|
||||||
[LuaMethod("pause", "Pauses the emulator")]
|
[LuaMethod("pause", "Pauses the emulator")]
|
||||||
|
@ -465,38 +444,16 @@ namespace BizHawk.Client.EmuHawk
|
||||||
[LuaMethod("gettool", "Returns an object that represents a tool of the given name (not case sensitive). If the tool is not open, it will be loaded if available. Use gettools to get a list of names")]
|
[LuaMethod("gettool", "Returns an object that represents a tool of the given name (not case sensitive). If the tool is not open, it will be loaded if available. Use gettools to get a list of names")]
|
||||||
public LuaTable GetTool(string name)
|
public LuaTable GetTool(string name)
|
||||||
{
|
{
|
||||||
var toolType = ReflectionUtil.GetTypeByName(name)
|
var selectedTool = APIs.Tool.GetTool(name);
|
||||||
.FirstOrDefault(x => typeof(IToolForm).IsAssignableFrom(x) && !x.IsInterface);
|
return selectedTool == null ? null : LuaHelper.ToLuaTable(Lua, selectedTool);
|
||||||
|
|
||||||
if (toolType != null)
|
|
||||||
{
|
|
||||||
GlobalWin.Tools.Load(toolType);
|
|
||||||
}
|
|
||||||
|
|
||||||
var selectedTool = GlobalWin.Tools.AvailableTools
|
|
||||||
.FirstOrDefault(tool => tool.GetType().Name.ToLower() == name.ToLower());
|
|
||||||
|
|
||||||
if (selectedTool != null)
|
|
||||||
{
|
|
||||||
return LuaHelper.ToLuaTable(Lua, selectedTool);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local nlclicre = client.createinstance( \"objectname\" );")]
|
[LuaMethodExample("local nlclicre = client.createinstance( \"objectname\" );")]
|
||||||
[LuaMethod("createinstance", "returns a default instance of the given type of object if it exists (not case sensitive). Note: This will only work on objects which have a parameterless constructor. If no suitable type is found, or the type does not have a parameterless constructor, then nil is returned")]
|
[LuaMethod("createinstance", "returns a default instance of the given type of object if it exists (not case sensitive). Note: This will only work on objects which have a parameterless constructor. If no suitable type is found, or the type does not have a parameterless constructor, then nil is returned")]
|
||||||
public LuaTable CreateInstance(string name)
|
public LuaTable CreateInstance(string name)
|
||||||
{
|
{
|
||||||
var possibleTypes = ReflectionUtil.GetTypeByName(name);
|
var instance = APIs.Tool.GetTool(name);
|
||||||
|
return instance == null ? null : LuaHelper.ToLuaTable(Lua, instance);
|
||||||
if (possibleTypes.Any())
|
|
||||||
{
|
|
||||||
var instance = Activator.CreateInstance(possibleTypes.First());
|
|
||||||
return LuaHelper.ToLuaTable(Lua, instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("client.displaymessages( true );")]
|
[LuaMethodExample("client.displaymessages( true );")]
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Windows.Forms;
|
using NLua;
|
||||||
|
|
||||||
using BizHawk.Client.Common;
|
using BizHawk.Client.Common;
|
||||||
using NLua;
|
|
||||||
|
|
||||||
namespace BizHawk.Client.EmuHawk
|
namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
public sealed class InputLuaLibrary : LuaLibraryBase
|
public sealed class InputLuaLibrary : DelegatingLuaLibraryEmu
|
||||||
{
|
{
|
||||||
public InputLuaLibrary(Lua lua)
|
public InputLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -21,32 +20,20 @@ namespace BizHawk.Client.EmuHawk
|
||||||
[LuaMethod("get", "Returns a lua table of all the buttons the user is currently pressing on their keyboard and gamepads\nAll buttons that are pressed have their key values set to true; all others remain nil.")]
|
[LuaMethod("get", "Returns a lua table of all the buttons the user is currently pressing on their keyboard and gamepads\nAll buttons that are pressed have their key values set to true; all others remain nil.")]
|
||||||
public LuaTable Get()
|
public LuaTable Get()
|
||||||
{
|
{
|
||||||
var buttons = Lua.NewTable();
|
var result = APIs.Input.Get();
|
||||||
foreach (var kvp in Global.ControllerInputCoalescer.BoolButtons().Where(kvp => kvp.Value))
|
var table = Lua.NewTable();
|
||||||
{
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
buttons[kvp.Key] = true;
|
return table;
|
||||||
}
|
|
||||||
|
|
||||||
return buttons;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[LuaMethodExample("local nlinpget = input.getmouse( );")]
|
[LuaMethodExample("local nlinpget = input.getmouse( );")]
|
||||||
[LuaMethod("getmouse", "Returns a lua table of the mouse X/Y coordinates and button states. Table keys are X, Y, Left, Middle, Right, XButton1, XButton2, Wheel.")]
|
[LuaMethod("getmouse", "Returns a lua table of the mouse X/Y coordinates and button states. Table keys are X, Y, Left, Middle, Right, XButton1, XButton2, Wheel.")]
|
||||||
public LuaTable GetMouse()
|
public LuaTable GetMouse()
|
||||||
{
|
{
|
||||||
var buttons = Lua.NewTable();
|
var result = APIs.Input.GetMouse();
|
||||||
|
var table = Lua.NewTable();
|
||||||
// TODO - need to specify whether in "emu" or "native" coordinate space.
|
foreach (var kvp in result) table[kvp.Key] = kvp.Value;
|
||||||
var p = GlobalWin.DisplayManager.UntransformPoint(Control.MousePosition);
|
return table;
|
||||||
buttons["X"] = p.X;
|
|
||||||
buttons["Y"] = p.Y;
|
|
||||||
buttons[MouseButtons.Left.ToString()] = (Control.MouseButtons & MouseButtons.Left) != 0;
|
|
||||||
buttons[MouseButtons.Middle.ToString()] = (Control.MouseButtons & MouseButtons.Middle) != 0;
|
|
||||||
buttons[MouseButtons.Right.ToString()] = (Control.MouseButtons & MouseButtons.Right) != 0;
|
|
||||||
buttons[MouseButtons.XButton1.ToString()] = (Control.MouseButtons & MouseButtons.XButton1) != 0;
|
|
||||||
buttons[MouseButtons.XButton2.ToString()] = (Control.MouseButtons & MouseButtons.XButton2) != 0;
|
|
||||||
buttons["Wheel"] = GlobalWin.MainForm.MouseWheelTracker;
|
|
||||||
return buttons;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
|
|
||||||
using NLua;
|
using NLua;
|
||||||
|
|
||||||
using BizHawk.Client.Common;
|
using BizHawk.Client.Common;
|
||||||
|
|
||||||
namespace BizHawk.Client.EmuHawk
|
namespace BizHawk.Client.EmuHawk
|
||||||
{
|
{
|
||||||
public sealed class SavestateLuaLibrary : LuaLibraryBase
|
public sealed class SavestateLuaLibrary : DelegatingLuaLibraryEmu
|
||||||
{
|
{
|
||||||
public SavestateLuaLibrary(Lua lua)
|
public SavestateLuaLibrary(Lua lua)
|
||||||
: base(lua) { }
|
: base(lua) { }
|
||||||
|
@ -19,43 +18,18 @@ namespace BizHawk.Client.EmuHawk
|
||||||
|
|
||||||
[LuaMethodExample("savestate.load( \"C:\\state.bin\" );")]
|
[LuaMethodExample("savestate.load( \"C:\\state.bin\" );")]
|
||||||
[LuaMethod("load", "Loads a savestate with the given path. If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes (and the path is ignored).")]
|
[LuaMethod("load", "Loads a savestate with the given path. If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes (and the path is ignored).")]
|
||||||
public void Load(string path, bool suppressOSD = false)
|
public void Load(string path, bool suppressOSD = false) => APIs.SaveState.Load(path, suppressOSD);
|
||||||
{
|
|
||||||
if (!File.Exists(path))
|
|
||||||
{
|
|
||||||
Log($"could not find file: {path}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GlobalWin.MainForm.LoadState(path, Path.GetFileName(path), true, suppressOSD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("savestate.loadslot( 7 );")]
|
[LuaMethodExample("savestate.loadslot( 7 );")]
|
||||||
[LuaMethod("loadslot", "Loads the savestate at the given slot number (must be an integer between 0 and 9). If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes with the slot number.")]
|
[LuaMethod("loadslot", "Loads the savestate at the given slot number (must be an integer between 0 and 9). If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes with the slot number.")]
|
||||||
public void LoadSlot(int slotNum, bool suppressOSD = false)
|
public void LoadSlot(int slotNum, bool suppressOSD = false) => APIs.SaveState.LoadSlot(slotNum, suppressOSD);
|
||||||
{
|
|
||||||
if (slotNum >= 0 && slotNum <= 9)
|
|
||||||
{
|
|
||||||
GlobalWin.MainForm.LoadQuickSave($"QuickSave{slotNum}", true, suppressOSD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("savestate.save( \"C:\\state.bin\" );")]
|
[LuaMethodExample("savestate.save( \"C:\\state.bin\" );")]
|
||||||
[LuaMethod("save", "Saves a state at the given path. If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes (and the path is ignored).")]
|
[LuaMethod("save", "Saves a state at the given path. If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes (and the path is ignored).")]
|
||||||
public void Save(string path, bool suppressOSD = false)
|
public void Save(string path, bool suppressOSD = false) => APIs.SaveState.Save(path, suppressOSD);
|
||||||
{
|
|
||||||
GlobalWin.MainForm.SaveState(path, path, true, suppressOSD);
|
|
||||||
}
|
|
||||||
|
|
||||||
[LuaMethodExample("savestate.saveslot( 7 );")]
|
[LuaMethodExample("savestate.saveslot( 7 );")]
|
||||||
[LuaMethod("saveslot", "Saves a state at the given save slot (must be an integer between 0 and 9). If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes with the slot number.")]
|
[LuaMethod("saveslot", "Saves a state at the given save slot (must be an integer between 0 and 9). If EmuHawk is deferring quicksaves, to TAStudio for example, that form will do what it likes with the slot number.")]
|
||||||
public void SaveSlot(int slotNum, bool suppressOSD = false)
|
public void SaveSlot(int slotNum, bool suppressOSD = false) => APIs.SaveState.SaveSlot(slotNum, suppressOSD);
|
||||||
{
|
|
||||||
if (slotNum >= 0 && slotNum <= 9)
|
|
||||||
{
|
|
||||||
GlobalWin.MainForm.SaveQuickSave($"QuickSave{slotNum}", true, suppressOSD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,13 +24,13 @@ namespace BizHawk.Client.EmuHawk
|
||||||
public EmuLuaLibrary(IEmulatorServiceProvider serviceProvider)
|
public EmuLuaLibrary(IEmulatorServiceProvider serviceProvider)
|
||||||
: this()
|
: this()
|
||||||
{
|
{
|
||||||
static APISubsetContainer InitApiHawkContainerInstance(IEmulatorServiceProvider sp, Action<string> logCallback)
|
static ApiContainer InitApiHawkContainerInstance(IEmulatorServiceProvider sp, Action<string> logCallback)
|
||||||
{
|
{
|
||||||
var ctorParamTypes = new[] { typeof(Action<string>) };
|
var ctorParamTypes = new[] { typeof(Action<string>) };
|
||||||
var ctorParams = new object[] { logCallback };
|
var ctorParams = new object[] { logCallback };
|
||||||
var libDict = new Dictionary<Type, IExternalApi>();
|
var libDict = new Dictionary<Type, IExternalApi>();
|
||||||
foreach (var api in Assembly.Load("BizHawk.Client.ApiHawk").GetTypes()
|
foreach (var api in Assembly.GetAssembly(typeof(EmuApi)).GetTypes()
|
||||||
.Concat(Assembly.GetAssembly(typeof(APISubsetContainer)).GetTypes())
|
.Concat(Assembly.GetAssembly(typeof(ToolApi)).GetTypes())
|
||||||
.Where(t => t.IsSealed && typeof(IExternalApi).IsAssignableFrom(t) && ServiceInjector.IsAvailable(sp, t)))
|
.Where(t => t.IsSealed && typeof(IExternalApi).IsAssignableFrom(t) && ServiceInjector.IsAvailable(sp, t)))
|
||||||
{
|
{
|
||||||
var ctorWithParams = api.GetConstructor(ctorParamTypes);
|
var ctorWithParams = api.GetConstructor(ctorParamTypes);
|
||||||
|
@ -38,7 +38,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
ServiceInjector.UpdateServices(sp, instance);
|
ServiceInjector.UpdateServices(sp, instance);
|
||||||
libDict.Add(api, instance);
|
libDict.Add(api, instance);
|
||||||
}
|
}
|
||||||
return ApiHawkContainerInstance = new APISubsetContainer(libDict);
|
return ApiHawkContainerInstance = new ApiContainer(libDict);
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaWait = new AutoResetEvent(false);
|
LuaWait = new AutoResetEvent(false);
|
||||||
|
@ -73,8 +73,11 @@ namespace BizHawk.Client.EmuHawk
|
||||||
instance.LuaRegister(lib, Docs);
|
instance.LuaRegister(lib, Docs);
|
||||||
instance.LogOutputCallback = ConsoleLuaLibrary.LogOutput;
|
instance.LogOutputCallback = ConsoleLuaLibrary.LogOutput;
|
||||||
ServiceInjector.UpdateServices(serviceProvider, instance);
|
ServiceInjector.UpdateServices(serviceProvider, instance);
|
||||||
if (instance is DelegatingLuaLibrary dlgInstance)
|
|
||||||
dlgInstance.APIs = ApiHawkContainerInstance ?? InitApiHawkContainerInstance(serviceProvider, ConsoleLuaLibrary.LogOutput);
|
ApiHawkContainerInstance ??= InitApiHawkContainerInstance(serviceProvider, ConsoleLuaLibrary.LogOutput);
|
||||||
|
if (instance is DelegatingLuaLibraryEmu dlgInstanceEmu) dlgInstanceEmu.APIs = ApiHawkContainerInstance; // this is necessary as the property has the `new` modifier
|
||||||
|
else if (instance is DelegatingLuaLibrary dlgInstance) dlgInstance.APIs = ApiHawkContainerInstance;
|
||||||
|
|
||||||
Libraries.Add(lib, instance);
|
Libraries.Add(lib, instance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +101,7 @@ namespace BizHawk.Client.EmuHawk
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <remarks>lazily instantiated</remarks>
|
/// <remarks>lazily instantiated</remarks>
|
||||||
private static APISubsetContainer ApiHawkContainerInstance;
|
private static ApiContainer ApiHawkContainerInstance;
|
||||||
|
|
||||||
private Lua _lua = new Lua();
|
private Lua _lua = new Lua();
|
||||||
private Lua _currThread;
|
private Lua _currThread;
|
||||||
|
|
Loading…
Reference in New Issue