Cleanup Util
This commit is contained in:
parent
8de0355228
commit
ff2efca658
|
@ -261,7 +261,7 @@ namespace BizHawk.Client.Common
|
|||
if (blob[0] == '0' && (blob[1] == 'x' || blob[1] == 'X'))
|
||||
{
|
||||
// hex
|
||||
return Util.HexStringToBytes(blob.Substring(2));
|
||||
return blob.Substring(2).HexStringToBytes();
|
||||
}
|
||||
|
||||
// base64
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using BizHawk.Common;
|
||||
using BizHawk.Emulation.Common.IEmulatorExtensions;
|
||||
|
||||
namespace BizHawk.Client.Common
|
||||
|
@ -388,4 +387,36 @@ namespace BizHawk.Client.Common
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class VLInteger
|
||||
{
|
||||
public static void WriteUnsigned(uint value, byte[] data, ref int index)
|
||||
{
|
||||
// This is optimized for good performance on both the x86 and x64 JITs. Don't change anything without benchmarking.
|
||||
do
|
||||
{
|
||||
var x = value & 0x7FU;
|
||||
value >>= 7;
|
||||
data[index++] = (byte)((value != 0U ? 0x80U : 0U) | x);
|
||||
}
|
||||
while (value != 0U);
|
||||
}
|
||||
|
||||
public static uint ReadUnsigned(byte[] data, ref int index)
|
||||
{
|
||||
// This is optimized for good performance on both the x86 and x64 JITs. Don't change anything without benchmarking.
|
||||
var value = 0U;
|
||||
var shiftCount = 0;
|
||||
bool isLastByte; // Negating the comparison and moving it earlier in the loop helps a lot on x86 for some reason
|
||||
do
|
||||
{
|
||||
var x = (uint)data[index++];
|
||||
isLastByte = (x & 0x80U) == 0U;
|
||||
value |= (x & 0x7FU) << shiftCount;
|
||||
shiftCount += 7;
|
||||
}
|
||||
while (!isLastByte);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,14 +10,14 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
public Type GetTool(string name)
|
||||
{
|
||||
var toolType = ReflectionUtil.GetTypeByName(name).FirstOrDefault(x => typeof(IToolForm).IsAssignableFrom(x) && !x.IsInterface);
|
||||
var toolType = Util.GetTypeByName(name).FirstOrDefault(x => typeof(IToolForm).IsAssignableFrom(x) && !x.IsInterface);
|
||||
if (toolType != null) GlobalWin.Tools.Load(toolType);
|
||||
return GlobalWin.Tools.AvailableTools.FirstOrDefault(tool => tool.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
|
||||
}
|
||||
|
||||
public object CreateInstance(string name)
|
||||
{
|
||||
var found = ReflectionUtil.GetTypeByName(name).FirstOrDefault();
|
||||
var found = Util.GetTypeByName(name).FirstOrDefault();
|
||||
return found != null ? Activator.CreateInstance(found) : null;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,5 +14,6 @@
|
|||
<Compile Include="../Version/svnrev.cs" />
|
||||
<Compile Include="../Version/VersionInfo.cs" />
|
||||
<Compile Remove="Extensions/BinaryReaderExtensions.cs" />
|
||||
<Compile Remove="SuperGloballyUniqueID.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -184,11 +184,11 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ReadByteBuffer(_br, useNull);
|
||||
val = _br.ReadByteBuffer(useNull);
|
||||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, val);
|
||||
_bw.WriteByteBuffer(val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
val = Util.HexStringToBytes(Item(name));
|
||||
val = Item(name).HexStringToBytes();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -221,7 +221,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToBoolBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToBoolBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new bool[0];
|
||||
|
@ -229,7 +229,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.BoolBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,8 +239,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToBoolBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToBoolBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -251,7 +251,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new bool[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.BoolBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
public void Sync(string name, ref short[] val, bool useNull)
|
||||
|
@ -262,7 +262,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToShortBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToShortBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new short[0];
|
||||
|
@ -270,7 +270,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.ShortBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToUshortBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToUShortBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new ushort[0];
|
||||
|
@ -290,7 +290,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.UshortBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,8 +300,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToShortBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToShortBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -312,7 +312,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new short[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.ShortBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,8 +322,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToUshortBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToUShortBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -334,7 +334,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new ushort[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.UshortBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,7 +346,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToIntBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToIntBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new int[0];
|
||||
|
@ -354,7 +354,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.IntBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,8 +364,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToIntBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToIntBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -376,7 +376,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new int[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.IntBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToUintBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToUIntBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new uint[0];
|
||||
|
@ -396,7 +396,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.UintBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,8 +406,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToUintBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToUIntBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -418,7 +418,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new uint[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.UintBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,7 +430,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToFloatBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToFloatBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new float[0];
|
||||
|
@ -438,7 +438,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.FloatBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,8 +448,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToFloatBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToFloatBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -460,7 +460,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new float[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.FloatBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +472,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else if (IsReader)
|
||||
{
|
||||
val = Util.ByteBufferToDoubleBuffer(Util.ReadByteBuffer(_br, false));
|
||||
val = _br.ReadByteBuffer(false).ToDoubleBuffer();
|
||||
if (val == null && !useNull)
|
||||
{
|
||||
val = new double[0];
|
||||
|
@ -480,7 +480,7 @@ namespace BizHawk.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
Util.WriteByteBuffer(_bw, Util.DoubleBufferToByteBuffer(val));
|
||||
_bw.WriteByteBuffer(val.ToUByteBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -490,8 +490,8 @@ namespace BizHawk.Common
|
|||
{
|
||||
if (Present(name))
|
||||
{
|
||||
var bytes = Util.HexStringToBytes(Item(name));
|
||||
val = Util.ByteBufferToDoubleBuffer(bytes);
|
||||
var bytes = Item(name).HexStringToBytes();
|
||||
val = bytes.ToDoubleBuffer();
|
||||
}
|
||||
|
||||
if (val != null && val.Length == 0 && useNull)
|
||||
|
@ -502,7 +502,7 @@ namespace BizHawk.Common
|
|||
else
|
||||
{
|
||||
var temp = val ?? new double[0];
|
||||
_tw.WriteLine("{0} {1}", name, Util.DoubleBufferToByteBuffer(temp).BytesToHexString());
|
||||
_tw.WriteLine("{0} {1}", name, temp.ToUByteBuffer().BytesToHexString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
namespace BizHawk.Common
|
||||
{
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
internal static class SuperGloballyUniqueID
|
||||
{
|
||||
private static readonly string StaticPart = $"bizhawk-{Process.GetCurrentProcess().Id}-{Guid.NewGuid()}";
|
||||
|
||||
private static int ctr;
|
||||
|
||||
public static string Next()
|
||||
{
|
||||
int myctr;
|
||||
lock (typeof(SuperGloballyUniqueID)) myctr = ctr++;
|
||||
return $"{StaticPart}-{myctr}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +1,325 @@
|
|||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Common
|
||||
namespace BizHawk.Common
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
public static unsafe class Util
|
||||
{
|
||||
public static void CopyStream(Stream src, Stream dest, long len)
|
||||
{
|
||||
const int size = 0x2000;
|
||||
byte[] buffer = new byte[size];
|
||||
var buffer = new byte[size];
|
||||
while (len > 0)
|
||||
{
|
||||
long todo = len;
|
||||
if (len > size) todo = size;
|
||||
int n = src.Read(buffer, 0, (int)todo);
|
||||
var todo = Math.Min(len, size);
|
||||
var n = src.Read(buffer, 0, (int) todo);
|
||||
dest.Write(buffer, 0, n);
|
||||
len -= n;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits 250ms for a file to vanish. Returns whether it succeeded
|
||||
/// </summary>
|
||||
public static bool TryWaitForFileToVanish(string path)
|
||||
/// <exception cref="InvalidOperationException">issues with parsing <paramref name="src"/></exception>
|
||||
/// <remarks>TODO use <see cref="MemoryStream(int)"/> and <see cref="MemoryStream.ToArray"/> instead of using <see cref="MemoryStream(byte[])"/> and keeping a reference to the array? --yoshi</remarks>
|
||||
public static byte[] DecompressGzipFile(Stream src)
|
||||
{
|
||||
for (int i = 0; i < 25; i++) // 250ms
|
||||
{
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
System.Threading.Thread.Sleep(10);
|
||||
}
|
||||
return false;
|
||||
var tmp = new byte[4];
|
||||
if (src.Read(tmp, 0, 2) != 2) throw new InvalidOperationException("Unexpected end of stream");
|
||||
if (tmp[0] != 0x1F || tmp[1] != 0x8B) throw new InvalidOperationException("GZIP header not present");
|
||||
src.Seek(-4, SeekOrigin.End);
|
||||
src.Read(tmp, 0, 4);
|
||||
src.Seek(0, SeekOrigin.Begin);
|
||||
using var gs = new GZipStream(src, CompressionMode.Decompress, true);
|
||||
var data = new byte[BitConverter.ToInt32(tmp, 0)];
|
||||
using var ms = new MemoryStream(data);
|
||||
gs.CopyTo(ms);
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to moves `pathWant` out of the way to `pathBackup`, delaying as needed to accomodate filesystem being sucky.
|
||||
/// `pathWant` might not be removed after all, in case it's snagged by something.
|
||||
/// </summary>
|
||||
public static bool TryMoveBackupFile(string pathWant, string pathBackup)
|
||||
/// <remarks>adapted from https://stackoverflow.com/a/3928856/7467292, values are compared using <see cref="EqualityComparer.Default">EqualityComparer.Default</see></remarks>
|
||||
public static bool DictionaryEqual<TKey, TValue>(IDictionary<TKey, TValue> a, IDictionary<TKey, TValue> b)
|
||||
where TKey : notnull
|
||||
{
|
||||
// If the path we want is available we dont actually have to make a backup
|
||||
if (!File.Exists(pathWant))
|
||||
if (a == b) return true;
|
||||
if (a.Count != b.Count) return false;
|
||||
var comparer = EqualityComparer<TValue>.Default;
|
||||
return a.All(kvp => b.TryGetValue(kvp.Key, out var bVal) && comparer.Equals(kvp.Value, bVal));
|
||||
}
|
||||
|
||||
/// <param name="filesize">in bytes</param>
|
||||
/// <returns>human-readable filesize (converts units up to tebibytes)</returns>
|
||||
public static string FormatFileSize(long filesize)
|
||||
{
|
||||
if (filesize < 1024) return $"{filesize} B";
|
||||
if (filesize < 1048576) return $"{filesize / 1024.0:.##} KiB";
|
||||
if (filesize < 1073741824) return $"{filesize / 1048576.0:.##} MiB";
|
||||
if (filesize < 1099511627776) return $"{filesize / 1073741824.0:.##} GiB";
|
||||
return $"{filesize / 1099511627776.0:.##} TiB";
|
||||
}
|
||||
|
||||
/// <returns>all <see cref="Type">Types</see> with the name <paramref name="className"/></returns>
|
||||
/// <remarks>adapted from https://stackoverflow.com/a/13727044/7467292</remarks>
|
||||
public static IList<Type> GetTypeByName(string className) => AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(asm => asm.GetTypes().Where(type => className.Equals(type.Name, StringComparison.InvariantCultureIgnoreCase))).ToList();
|
||||
|
||||
/// <exception cref="ArgumentException"><paramref name="str"/> has an odd number of chars or contains a char not in <c>[0-9A-Fa-f]</c></exception>
|
||||
public static byte[] HexStringToBytes(this string str)
|
||||
{
|
||||
if (str.Length % 2 != 0) throw new ArgumentException();
|
||||
static int CharToNybble(char c)
|
||||
{
|
||||
return true;
|
||||
if ('0' <= c && c <= '9') return c - 0x30;
|
||||
if ('A' <= c && c <= 'F') return c - 0x37;
|
||||
if ('a' <= c && c <= 'f') return c - 0x57;
|
||||
throw new ArgumentException();
|
||||
}
|
||||
using var ms = new MemoryStream();
|
||||
for (int i = 0, l = str.Length / 2; i != l; i++) ms.WriteByte((byte) ((CharToNybble(str[2 * i]) << 4) + CharToNybble(str[2 * i + 1])));
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
public static int Memcmp(void* a, void* b, int len)
|
||||
{
|
||||
var ba = (byte*) a;
|
||||
var bb = (byte*) b;
|
||||
for (var i = 0; i != len; i++)
|
||||
{
|
||||
var _a = ba[i];
|
||||
var _b = bb[i];
|
||||
var c = _a - _b;
|
||||
if (c != 0) return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void Memset(void* ptr, int val, int len)
|
||||
{
|
||||
var bptr = (byte*) ptr;
|
||||
for (var i = 0; i != len; i++) bptr[i] = (byte) val;
|
||||
}
|
||||
|
||||
public static byte[]? ReadByteBuffer(this BinaryReader br, bool returnNull)
|
||||
{
|
||||
var len = br.ReadInt32();
|
||||
if (len == 0 && returnNull) return null;
|
||||
var ret = new byte[len];
|
||||
var ofs = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
var done = br.Read(ret, ofs, len);
|
||||
ofs += done;
|
||||
len -= done;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <remarks>Any non-zero element is interpreted as <see langword="true"/>.</remarks>
|
||||
public static bool[] ToBoolBuffer(this byte[] buf)
|
||||
{
|
||||
var ret = new bool[buf.Length];
|
||||
for (int i = 0, len = buf.Length; i != len; i++) ret[i] = buf[i] != 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static double[] ToDoubleBuffer(this byte[] buf)
|
||||
{
|
||||
var len = buf.Length;
|
||||
var ret = new double[len / 8];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static float[] ToFloatBuffer(this byte[] buf)
|
||||
{
|
||||
var len = buf.Length / 4;
|
||||
var ret = new float[len];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, len); //TODO bug? the last arg should be in bytes
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <remarks>Each set of 4 elements in <paramref name="buf"/> becomes 1 element in the returned buffer. The first of each set is interpreted as the LSB, with the 4th being the MSB. Elements are used as raw bits without regard for sign.</remarks>
|
||||
public static int[] ToIntBuffer(this byte[] buf)
|
||||
{
|
||||
var len = buf.Length / 4;
|
||||
var ret = new int[len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++) ret[i] = (buf[4 * i + 3] << 24) | (buf[4 * i + 2] << 16) | (buf[4 * i + 1] << 8) | buf[4 * i];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <remarks>Each pair of elements in <paramref name="buf"/> becomes 1 element in the returned buffer. The first of each pair is interpreted as the LSB. Elements are used as raw bits without regard for sign.</remarks>
|
||||
public static short[] ToShortBuffer(this byte[] buf)
|
||||
{
|
||||
var len = buf.Length / 2;
|
||||
var ret = new short[len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++) ret[i] = (short) ((buf[2 * i + 1] << 8) | buf[2 * i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] ToUByteBuffer(this bool[] buf)
|
||||
{
|
||||
var ret = new byte[buf.Length];
|
||||
for (int i = 0, len = buf.Length; i != len; i++) ret[i] = buf[i] ? (byte) 1 : (byte) 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] ToUByteBuffer(this double[] buf)
|
||||
{
|
||||
var len = buf.Length * 8;
|
||||
var ret = new byte[len];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] ToUByteBuffer(this float[] buf)
|
||||
{
|
||||
var len = buf.Length * 4;
|
||||
var ret = new byte[len];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <remarks>Each element of <paramref name="buf"/> becomes 4 elements in the returned buffer, with the LSB coming first. Elements are used as raw bits without regard for sign.</remarks>
|
||||
public static byte[] ToUByteBuffer(this int[] buf)
|
||||
{
|
||||
var len = buf.Length;
|
||||
var ret = new byte[4 * len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++)
|
||||
{
|
||||
ret[4 * i] = (byte) buf[i];
|
||||
ret[4 * i + 1] = (byte) (buf[i] >> 8);
|
||||
ret[4 * i + 2] = (byte) (buf[i] >> 16);
|
||||
ret[4 * i + 3] = (byte) (buf[i] >> 24);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <remarks>Each element of <paramref name="buf"/> becomes 2 elements in the returned buffer, with the LSB coming first. Elements are used as raw bits without regard for sign.</remarks>
|
||||
public static byte[] ToUByteBuffer(this short[] buf)
|
||||
{
|
||||
var len = buf.Length;
|
||||
var ret = new byte[2 * len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++)
|
||||
{
|
||||
ret[2 * i] = (byte) buf[i];
|
||||
ret[2 * i + 1] = (byte) (buf[i] >> 8);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ToUByteBuffer(int[])"/>
|
||||
public static byte[] ToUByteBuffer(this uint[] buf)
|
||||
{
|
||||
var len = buf.Length;
|
||||
var ret = new byte[4 * len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++)
|
||||
{
|
||||
ret[4 * i] = (byte) buf[i];
|
||||
ret[4 * i + 1] = (byte) (buf[i] >> 8);
|
||||
ret[4 * i + 2] = (byte) (buf[i] >> 16);
|
||||
ret[4 * i + 3] = (byte) (buf[i] >> 24);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ToUByteBuffer(short[])"/>
|
||||
public static byte[] ToUByteBuffer(this ushort[] buf)
|
||||
{
|
||||
var len = buf.Length;
|
||||
var ret = new byte[2 * len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++)
|
||||
{
|
||||
ret[2 * i] = (byte) buf[i];
|
||||
ret[2 * i + 1] = (byte) (buf[i] >> 8);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ToIntBuffer"/>
|
||||
public static uint[] ToUIntBuffer(this byte[] buf)
|
||||
{
|
||||
var len = buf.Length / 4;
|
||||
var ret = new uint[len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++) ret[i] = (uint) ((buf[4 * i + 3] << 24) | (buf[4 * i + 2] << 16) | (buf[4 * i + 1] << 8) | buf[4 * i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ToShortBuffer"/>
|
||||
public static ushort[] ToUShortBuffer(this byte[] buf)
|
||||
{
|
||||
var len = buf.Length / 2;
|
||||
var ret = new ushort[len];
|
||||
unchecked
|
||||
{
|
||||
for (var i = 0; i != len; i++) ret[i] = (ushort) ((buf[2 * i + 1] << 8) | buf[2 * i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>Tries really hard to keep the contents of <paramref name="desiredPath"/> saved (as <paramref name="backupPath"/>) while freeing that path to be used for a new file.</summary>
|
||||
/// <remarks>If both <paramref name="desiredPath"/> and <paramref name="backupPath"/> exist, <paramref name="backupPath"/> is always deleted.</remarks>
|
||||
public static bool TryMoveBackupFile(string desiredPath, string backupPath)
|
||||
{
|
||||
if (!File.Exists(desiredPath)) return true; // desired path already free
|
||||
|
||||
// delete any existing backup
|
||||
try
|
||||
{
|
||||
if (File.Exists(pathBackup))
|
||||
{
|
||||
File.Delete(pathBackup);
|
||||
}
|
||||
if (File.Exists(backupPath)) File.Delete(backupPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// just give up on the whole thing in case of exceptions. pathWant will get overwritten by the caller.
|
||||
return false;
|
||||
return false; // if Exists or Delete threw, there's not much we can do -- the caller will either overwrite the file or fail itself
|
||||
}
|
||||
|
||||
// deletes are asynchronous, need to wait for it to be gone
|
||||
if(!TryWaitForFileToVanish(pathBackup))
|
||||
// deletions are asynchronous, so wait for a while and then give up
|
||||
static bool TryWaitForFileToVanish(string path)
|
||||
{
|
||||
// gave up waiting for existing backup to be gone. the whole thing's a total loss
|
||||
for (var i = 25; i != 0; i--)
|
||||
{
|
||||
if (!File.Exists(path)) return true;
|
||||
Thread.Sleep(10);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!TryWaitForFileToVanish(backupPath)) return false;
|
||||
|
||||
// the backup path is available now, so perform the backup and then wait for it to finish
|
||||
try
|
||||
{
|
||||
// actually move pathWant out of the way to pathBackup now that pathBackup is free
|
||||
File.Move(pathWant, pathBackup);
|
||||
File.Move(desiredPath, backupPath);
|
||||
return TryWaitForFileToVanish(desiredPath);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Eat it, this will happen rarely and the user will rarely need the file, so the odds of simply not making the backup is very unlikely
|
||||
return false;
|
||||
return false; // this will be hit in the unlikely event that something else wrote to the backup path after we checked it was okay
|
||||
}
|
||||
|
||||
// hmm these might be asynchronous too
|
||||
// wait for the move to complete, at least enough for pathWant to be cleared up
|
||||
return TryWaitForFileToVanish(pathWant);
|
||||
}
|
||||
|
||||
/// <exception cref="ArgumentException"><paramref name="str"/> has an odd number of chars or contains a char not in <c>[0-9A-Fa-f]</c></exception>
|
||||
/// <remarks>could be extension method</remarks>
|
||||
public static byte[] HexStringToBytes(string str)
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
if (str.Length % 2 != 0)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
int len = str.Length / 2;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
int d = 0;
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
var c = char.ToLower(str[(i * 2) + j]);
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
d += c - '0';
|
||||
}
|
||||
else if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
d += (c - 'a') + 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
d <<= 4;
|
||||
}
|
||||
}
|
||||
|
||||
ms.WriteByte((byte)d);
|
||||
}
|
||||
|
||||
return ms.ToArray();
|
||||
}
|
||||
|
||||
// Could be extension method
|
||||
public static void WriteByteBuffer(BinaryWriter bw, byte[] data)
|
||||
public static void WriteByteBuffer(this BinaryWriter bw, byte[]? data)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
|
@ -146,388 +331,5 @@ namespace BizHawk.Common
|
|||
bw.Write(data);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool[] ByteBufferToBoolBuffer(byte[] buf)
|
||||
{
|
||||
var ret = new bool[buf.Length];
|
||||
for (int i = 0; i < buf.Length; i++)
|
||||
{
|
||||
ret[i] = buf[i] != 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] BoolBufferToByteBuffer(bool[] buf)
|
||||
{
|
||||
var ret = new byte[buf.Length];
|
||||
for (int i = 0; i < buf.Length; i++)
|
||||
{
|
||||
ret[i] = (byte)(buf[i] ? 1 : 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static short[] ByteBufferToShortBuffer(byte[] buf)
|
||||
{
|
||||
int num = buf.Length / 2;
|
||||
var ret = new short[num];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i] = (short)(buf[i * 2] | (buf[i * 2 + 1] << 8));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] ShortBufferToByteBuffer(short[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new byte[num * 2];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i * 2 + 0] = (byte)(buf[i] & 0xFF);
|
||||
ret[i * 2 + 1] = (byte)((buf[i] >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static ushort[] ByteBufferToUshortBuffer(byte[] buf)
|
||||
{
|
||||
int num = buf.Length / 2;
|
||||
var ret = new ushort[num];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i] = (ushort)(buf[i * 2] | (buf[i * 2 + 1] << 8));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] UshortBufferToByteBuffer(ushort[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new byte[num * 2];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i * 2 + 0] = (byte)(buf[i] & 0xFF);
|
||||
ret[i * 2 + 1] = (byte)((buf[i] >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static uint[] ByteBufferToUintBuffer(byte[] buf)
|
||||
{
|
||||
int num = buf.Length / 4;
|
||||
var ret = new uint[num];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i] = (uint)(buf[i * 4] | (buf[i * 4 + 1] << 8) | (buf[i * 4 + 2] << 16) | (buf[i * 4 + 3] << 24));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] UintBufferToByteBuffer(uint[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new byte[num * 4];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i * 4 + 0] = (byte)(buf[i] & 0xFF);
|
||||
ret[i * 4 + 1] = (byte)((buf[i] >> 8) & 0xFF);
|
||||
ret[i * 4 + 2] = (byte)((buf[i] >> 16) & 0xFF);
|
||||
ret[i * 4 + 3] = (byte)((buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int[] ByteBufferToIntBuffer(byte[] buf)
|
||||
{
|
||||
int num = buf.Length / 4;
|
||||
var ret = new int[num];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i] = buf[(i * 4) + 3];
|
||||
ret[i] <<= 8;
|
||||
ret[i] |= buf[(i * 4) + 2];
|
||||
ret[i] <<= 8;
|
||||
ret[i] |= buf[(i * 4) + 1];
|
||||
ret[i] <<= 8;
|
||||
ret[i] |= buf[(i * 4)];
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] IntBufferToByteBuffer(int[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new byte[num * 4];
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
ret[i * 4 + 0] = (byte)(buf[i] & 0xFF);
|
||||
ret[i * 4 + 1] = (byte)((buf[i] >> 8) & 0xFF);
|
||||
ret[i * 4 + 2] = (byte)((buf[i] >> 16) & 0xFF);
|
||||
ret[i * 4 + 3] = (byte)((buf[i] >> 24) & 0xFF);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static float[] ByteBufferToFloatBuffer(byte[] buf)
|
||||
{
|
||||
int num = buf.Length / sizeof(float);
|
||||
var ret = new float[num];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] FloatBufferToByteBuffer(float[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new byte[num * sizeof(float)];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, ret.Length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static double[] ByteBufferToDoubleBuffer(byte[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new double[num / sizeof(double)];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, num);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] DoubleBufferToByteBuffer(double[] buf)
|
||||
{
|
||||
int num = buf.Length;
|
||||
var ret = new byte[num * sizeof(double)];
|
||||
Buffer.BlockCopy(buf, 0, ret, 0, ret.Length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static byte[] ReadByteBuffer(BinaryReader br, bool returnNull)
|
||||
{
|
||||
int len = br.ReadInt32();
|
||||
if (len == 0 && returnNull)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var ret = new byte[len];
|
||||
int ofs = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
int done = br.Read(ret, ofs, len);
|
||||
ofs += done;
|
||||
len -= done;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static int Memcmp(void* a, void* b, int len)
|
||||
{
|
||||
var ba = (byte*)a;
|
||||
var bb = (byte*)b;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
byte _a = ba[i];
|
||||
byte _b = bb[i];
|
||||
int c = _a - _b;
|
||||
if (c != 0)
|
||||
{
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static void Memset(void* ptr, int val, int len)
|
||||
{
|
||||
var bptr = (byte*)ptr;
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
bptr[i] = (byte)val;
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatFileSize(long filesize)
|
||||
{
|
||||
decimal size = filesize;
|
||||
|
||||
string suffix;
|
||||
if (size > 1024 * 1024 * 1024)
|
||||
{
|
||||
size /= 1024 * 1024 * 1024;
|
||||
suffix = "GB";
|
||||
}
|
||||
else if (size > 1024 * 1024)
|
||||
{
|
||||
size /= 1024 * 1024;
|
||||
suffix = "MB";
|
||||
}
|
||||
else if (size > 1024)
|
||||
{
|
||||
size /= 1024;
|
||||
suffix = "KB";
|
||||
}
|
||||
else
|
||||
{
|
||||
suffix = "B";
|
||||
}
|
||||
|
||||
const string precision = "2";
|
||||
return string.Format($"{{0:N{precision}}}{{1}}", size, suffix);
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/3928822/comparing-2-dictionarystring-string-instances
|
||||
public static bool DictionaryEqual<TKey, TValue>(
|
||||
IDictionary<TKey, TValue> first, IDictionary<TKey, TValue> second)
|
||||
{
|
||||
if (first == second)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((first == null) || (second == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (first.Count != second.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var comparer = EqualityComparer<TValue>.Default;
|
||||
|
||||
foreach (var kvp in first)
|
||||
{
|
||||
if (!second.TryGetValue(kvp.Key, out var secondValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!comparer.Equals(kvp.Value, secondValue))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <exception cref="InvalidOperationException">issues with parsing <paramref name="src"/></exception>
|
||||
public static byte[] DecompressGzipFile(Stream src)
|
||||
{
|
||||
var tmp = new byte[4];
|
||||
if (src.Read(tmp, 0, 2) != 2)
|
||||
throw new InvalidOperationException("Unexpected end of stream");
|
||||
if (tmp[0] != 0x1f || tmp[1] != 0x8b)
|
||||
throw new InvalidOperationException("GZIP header not present");
|
||||
src.Seek(-4, SeekOrigin.End);
|
||||
src.Read(tmp, 0, 4);
|
||||
int size = BitConverter.ToInt32(tmp, 0);
|
||||
var data = new byte[size];
|
||||
var ms = new MemoryStream(data);
|
||||
src.Seek(0, SeekOrigin.Begin);
|
||||
using (var gs = new GZipStream(src, CompressionMode.Decompress, true))
|
||||
gs.CopyTo(ms);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
public static class VLInteger
|
||||
{
|
||||
public static void WriteUnsigned(uint value, byte[] data, ref int index)
|
||||
{
|
||||
// This is optimized for good performance on both the x86 and x64 JITs. Don't change anything without benchmarking.
|
||||
do
|
||||
{
|
||||
uint x = value & 0x7FU;
|
||||
value >>= 7;
|
||||
data[index++] = (byte)((value != 0U ? 0x80U : 0U) | x);
|
||||
}
|
||||
while (value != 0U);
|
||||
}
|
||||
|
||||
public static uint ReadUnsigned(byte[] data, ref int index)
|
||||
{
|
||||
// This is optimized for good performance on both the x86 and x64 JITs. Don't change anything without benchmarking.
|
||||
uint value = 0U;
|
||||
int shiftCount = 0;
|
||||
bool isLastByte; // Negating the comparison and moving it earlier in the loop helps a lot on x86 for some reason
|
||||
do
|
||||
{
|
||||
uint x = (uint)data[index++];
|
||||
isLastByte = (x & 0x80U) == 0U;
|
||||
value |= (x & 0x7FU) << shiftCount;
|
||||
shiftCount += 7;
|
||||
}
|
||||
while (!isLastByte);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class NotTestedException : Exception
|
||||
{
|
||||
}
|
||||
|
||||
internal class SuperGloballyUniqueID
|
||||
{
|
||||
private static readonly string StaticPart;
|
||||
private static int ctr;
|
||||
|
||||
static SuperGloballyUniqueID()
|
||||
{
|
||||
StaticPart = $"bizhawk-{System.Diagnostics.Process.GetCurrentProcess().Id}-{Guid.NewGuid()}";
|
||||
}
|
||||
|
||||
public static string Next()
|
||||
{
|
||||
int myctr;
|
||||
lock (typeof(SuperGloballyUniqueID))
|
||||
{
|
||||
myctr = ctr++;
|
||||
}
|
||||
|
||||
return $"{StaticPart}-{myctr}";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ReflectionUtil
|
||||
{
|
||||
// http://stackoverflow.com/questions/9273629/avoid-giving-namespace-name-in-type-gettype
|
||||
/// <summary>
|
||||
/// Gets a all Type instances matching the specified class name with just non-namespace qualified class name.
|
||||
/// </summary>
|
||||
/// <param name="className">Name of the class sought.</param>
|
||||
/// <returns>Types that have the class name specified. They may not be in the same namespace.</returns>
|
||||
public static Type[] GetTypeByName(string className)
|
||||
{
|
||||
var returnVal = new List<Type>();
|
||||
|
||||
foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
Type[] assemblyTypes = a.GetTypes();
|
||||
for (int j = 0; j < assemblyTypes.Length; j++)
|
||||
{
|
||||
if (assemblyTypes[j].Name.ToLower() == className.ToLower())
|
||||
{
|
||||
returnVal.Add(assemblyTypes[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnVal.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ using BizHawk.Common.NumberExtensions;
|
|||
|
||||
namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
||||
{
|
||||
using System;
|
||||
|
||||
/*
|
||||
* Spectravideo Compumate Add-on Kevtris Documentation
|
||||
|
||||
|
@ -275,7 +277,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
|
|||
}
|
||||
|
||||
// Attempting to read while in write mode
|
||||
throw new NotTestedException();
|
||||
throw new Exception("this hasn't been tested");
|
||||
}
|
||||
|
||||
public override byte ReadMemory(ushort addr)
|
||||
|
|
Loading…
Reference in New Issue