diff --git a/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs b/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs
index b40ec818a1..a25b5dfcfe 100644
--- a/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs
+++ b/BizHawk.Client.ApiHawk/Classes/BizHawkSystemIdToCoreSystemEnumConverter.cs
@@ -96,6 +96,9 @@ namespace BizHawk.Client.ApiHawk
case "WSWAN":
return CoreSystem.WonderSwan;
+ case "VB":
+ return 0; // like I give a shit
+
default:
throw new IndexOutOfRangeException(string.Format("{0} is missing in convert list", value));
}
diff --git a/BizHawk.Emulation.Common/Database/Database.cs b/BizHawk.Emulation.Common/Database/Database.cs
index c14f807f15..9a791c87c0 100644
--- a/BizHawk.Emulation.Common/Database/Database.cs
+++ b/BizHawk.Emulation.Common/Database/Database.cs
@@ -331,6 +331,10 @@ namespace BizHawk.Emulation.Common
case ".DO":
game.System = "AppleII";
break;
+
+ case ".VB":
+ game.System = "VB";
+ break;
}
game.Name = Path.GetFileNameWithoutExtension(fileName)?.Replace('_', ' ');
diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 3066f74cdd..f84c59f64e 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -1279,6 +1279,7 @@
+
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs
index dc438c19b1..e6485786b5 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/VB/VirtualBoyee.cs
@@ -25,10 +25,11 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
{
Path = comm.CoreFileProvider.DllPath(),
Filename = "vb.wbx",
- NormalHeapSizeKB = 1024,
+ NormalHeapSizeKB = 4 * 1024,
SealedHeapSizeKB = 12 * 1024,
InvisibleHeapSizeKB = 6 * 1024,
- SpecialHeapSizeKB = 64
+ SpecialHeapSizeKB = 64,
+ MmapHeapSizeKB = 16 * 1024
});
_boyee = BizInvoker.GetInvoker(_exe, _exe);
@@ -112,22 +113,22 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
#region IVideoProvider
- private int[] _videoBuffer = new int[0];
+ private int[] _videoBuffer = new int[256 * 192];
public int[] GetVideoBuffer()
{
- throw new NotImplementedException();
+ return _videoBuffer;
}
- public int VirtualWidth { get; private set; }
- public int VirtualHeight { get; private set; }
+ public int VirtualWidth { get; private set; } = 256;
+ public int VirtualHeight { get; private set; } = 192;
- public int BufferWidth { get; private set; }
- public int BufferHeight { get; private set; }
+ public int BufferWidth { get; private set; } = 256;
+ public int BufferHeight { get; private set; } = 192;
- public int VsyncNumerator { get; private set; }
+ public int VsyncNumerator { get; private set; } = 60;
- public int VsyncDenominator { get; private set; }
+ public int VsyncDenominator { get; private set; } = 1;
public int BackgroundColor => unchecked((int)0xff000000);
diff --git a/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs b/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs
new file mode 100644
index 0000000000..d9a3bc305b
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Waterbox/MapHeap.cs
@@ -0,0 +1,303 @@
+using BizHawk.Emulation.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+
+namespace BizHawk.Emulation.Cores.Waterbox
+{
+ ///
+ /// a heap that supports basic alloc, free, and realloc calls
+ ///
+ internal sealed class MapHeap : IBinaryStateable, IDisposable
+ {
+ public MemoryBlock Memory { get; private set; }
+ ///
+ /// name, used in identifying errors
+ ///
+ public string Name { get; private set; }
+
+ public byte[] XorHash { get; private set; }
+
+ ///
+ /// get a page index within the block
+ ///
+ private int GetPage(ulong addr)
+ {
+ return (int)((addr - Memory.Start) >> WaterboxUtils.PageShift);
+ }
+
+ ///
+ /// get a start address for a page index within the block
+ ///
+ private ulong GetStartAddr(int page)
+ {
+ return ((ulong)page << WaterboxUtils.PageShift) + Memory.Start;
+ }
+
+ private class Bin
+ {
+ public int StartPage;
+ public int PageCount;
+ public MemoryBlock.Protection Protection;
+ public bool Free
+ {
+ get
+ {
+ return (byte)Protection == 255;
+ }
+ set
+ {
+ Protection = value ? (MemoryBlock.Protection)255 : MemoryBlock.Protection.None;
+ }
+ }
+
+ public Bin Next;
+
+ ///
+ /// split this bin, keeping only numPages pages
+ ///
+ public bool Cleave(int numPages)
+ {
+ int nextPages = PageCount - numPages;
+ if (nextPages > 0)
+ {
+ Next = new Bin
+ {
+ StartPage = StartPage + numPages,
+ PageCount = nextPages,
+ Next = Next
+ };
+ PageCount = numPages;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ private Bin _root;
+
+ public MapHeap(ulong start, ulong size, string name)
+ {
+ size = WaterboxUtils.AlignUp(size);
+ Memory = new MemoryBlock(start, size);
+ Name = name;
+ Console.WriteLine("Created mapheap `{1}` at {0:x16}:{2:x16}", start, name, start + size);
+
+ _root = new Bin
+ {
+ StartPage = 0,
+ PageCount = (int)(size >> WaterboxUtils.PageShift),
+ Free = true
+ };
+ }
+
+ ///
+ /// gets the bin that contains a page
+ ///
+ private Bin GetBinForStartPage(int page)
+ {
+ Bin curr = _root;
+ while (curr.StartPage + curr.PageCount <= page)
+ curr = curr.Next;
+ return curr;
+ }
+
+ ///
+ /// gets the bin that contains the page before the passed page, returning null if
+ /// any bin along the way is Free
+ ///
+ private Bin GetBinForEndPageEnsureAllocated(int page, Bin start)
+ {
+ Bin curr = start;
+ while (curr != null && curr.StartPage + curr.PageCount < page)
+ {
+ if (curr.Free)
+ return null;
+ curr = curr.Next;
+ }
+ return curr;
+ }
+
+ public ulong Map(ulong size, MemoryBlock.Protection prot)
+ {
+ int numPages = WaterboxUtils.PagesNeeded(size);
+ Bin best = null;
+ Bin curr = _root;
+
+ // find smallest potential bin
+ do
+ {
+ if (curr.Free && curr.PageCount >= numPages)
+ {
+ if (best == null || curr.PageCount < best.PageCount)
+ {
+ best = curr;
+ if (curr.PageCount == numPages)
+ break;
+ }
+ }
+ curr = curr.Next;
+ } while (curr != null);
+
+ if (best == null)
+ return 0;
+
+ if (best.Cleave(numPages))
+ best.Next.Free = true;
+ best.Protection = prot;
+
+ var ret = GetStartAddr(best.StartPage);
+ Memory.Protect(ret, ((ulong)numPages) << WaterboxUtils.PageShift, prot);
+ return ret;
+ }
+
+ public ulong Remap(ulong start, ulong oldSize, ulong newSize, bool canMove)
+ {
+ if (start < Memory.Start || start + oldSize > Memory.End)
+ return 0;
+
+ var oldStartPage = GetPage(start);
+ var oldStartBin = GetBinForStartPage(oldStartPage);
+ if (oldSize == 0 && canMove)
+ return Map(newSize, oldStartBin.Protection);
+
+ var oldNumPages = WaterboxUtils.PagesNeeded(oldSize);
+ var oldEndPage = oldStartPage + oldNumPages;
+ // first, check if the requested area is actually mapped
+ var oldEndBin = GetBinForEndPageEnsureAllocated(oldEndPage, oldStartBin);
+ if (oldEndBin == null)
+ return 0;
+
+ var newNumPages = WaterboxUtils.PagesNeeded(newSize);
+ var newEndPage = oldStartPage + newNumPages;
+ if (newEndPage > oldEndPage)
+ {
+ // increase size
+ // the only way this will work in place is if all of the remaining space is free
+ Bin nextBin;
+ if (oldEndBin.StartPage + oldEndBin.PageCount == oldEndPage // if end bin is too bag, space after that is used by something else
+ && (nextBin = oldEndBin.Next) != null // can't go off the edge
+ && nextBin.Free
+ && nextBin.StartPage + nextBin.PageCount >= newEndPage)
+ {
+ nextBin.Protection = oldStartBin.Protection;
+ if (nextBin.Cleave(newEndPage - nextBin.StartPage))
+ nextBin.Next.Free = true;
+ return start;
+ }
+ // could not increase in place, so move
+ if (!canMove)
+ return 0;
+
+ // if there's some free space right before `start`, and some right after, but not enough
+ // to extend in place, it's possible that a realloc would succeed reusing the same space,
+ // but would fail anywhere else due to heavy memory pressure.
+
+ // that would be a much more complicated algorithm; we'd need to compute a new allocation
+ // as if this one had been freed, but still be able to preserve this if that allocation
+ // still failed. instead, we ignore this case.
+ var ret = Map(newSize, oldStartBin.Protection);
+ if (ret != 0)
+ {
+ // move data
+ // NB: oldSize > 0
+ Memory.Protect(start, oldSize, MemoryBlock.Protection.R);
+ var ss = Memory.GetStream(start, oldSize, false);
+ Memory.Protect(ret, oldSize, MemoryBlock.Protection.RW);
+ var ds = Memory.GetStream(ret, oldSize, true);
+ ss.CopyTo(ds);
+ Memory.Protect(ret, oldSize, oldStartBin.Protection);
+ UnmapPagesInternal(oldStartPage, oldNumPages, oldStartBin);
+ return ret;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ else if (newEndPage < oldEndPage)
+ {
+ // shrink in place
+ var s = GetBinForStartPage(newEndPage);
+ UnmapPagesInternal(newEndPage, oldEndPage - newEndPage, s);
+ return start;
+ }
+ else
+ {
+ // no change
+ return start;
+ }
+ }
+
+ public bool Unmap(ulong start, ulong size)
+ {
+ if (start < Memory.Start || start + size > Memory.End)
+ return false;
+ if (size == 0)
+ return true;
+
+ var startPage = GetPage(start);
+ var numPages = WaterboxUtils.PagesNeeded(size);
+ var endPage = startPage + numPages;
+ // check to see if the requested area is actually mapped
+ var startBin = GetBinForStartPage(startPage);
+ if (GetBinForEndPageEnsureAllocated(endPage, startBin) == null)
+ return false;
+
+ UnmapPagesInternal(startPage, numPages, startBin);
+ return true;
+ }
+
+ ///
+ /// frees some pages. assumes they are all allocated
+ ///
+ private void UnmapPagesInternal(int startPage, int numPages, Bin startBin)
+ {
+ // from the various paths we took to get here, we must be unmapping at least one page
+
+ var endPage = startPage + numPages;
+ Bin freeBin = startBin;
+ if (!freeBin.Free && freeBin.StartPage != startPage)
+ {
+ freeBin.Cleave(startPage - freeBin.StartPage);
+ freeBin = freeBin.Next;
+ freeBin.Free = true;
+ }
+ MemoryBlock.Protection lastEaten = MemoryBlock.Protection.None;
+ while (freeBin.StartPage + freeBin.PageCount < endPage)
+ {
+ freeBin.PageCount += freeBin.Next.PageCount;
+ lastEaten = freeBin.Next.Protection;
+ freeBin.Next = freeBin.Next.Next;
+ }
+ if (freeBin.Cleave(freeBin.StartPage + freeBin.PageCount - endPage))
+ {
+ freeBin.Next.Protection = lastEaten;
+ }
+ Memory.Protect(GetStartAddr(startPage), ((ulong)numPages) << WaterboxUtils.PageShift, MemoryBlock.Protection.None);
+ }
+
+ public void Dispose()
+ {
+ if (Memory != null)
+ {
+ Memory.Dispose();
+ Memory = null;
+ }
+ }
+
+ public void SaveStateBinary(BinaryWriter writer)
+ {
+ }
+
+ public void LoadStateBinary(BinaryReader reader)
+ {
+ }
+ }
+}
diff --git a/BizHawk.Emulation.Cores/Waterbox/MemoryBlock.cs b/BizHawk.Emulation.Cores/Waterbox/MemoryBlock.cs
index 3ec79c374c..7c00c0b8cf 100644
--- a/BizHawk.Emulation.Cores/Waterbox/MemoryBlock.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/MemoryBlock.cs
@@ -7,96 +7,8 @@ using System.IO;
namespace BizHawk.Emulation.Cores.Waterbox
{
- // C# is annoying: arithmetic operators for native ints are not exposed.
- // So we store them as long/ulong instead in many places, and use these helpers
- // to convert to IntPtr when needed
-
- public static class Z
- {
- public static IntPtr US(ulong l)
- {
- if (IntPtr.Size == 8)
- return (IntPtr)(long)l;
- else
- return (IntPtr)(int)l;
- }
-
- public static UIntPtr UU(ulong l)
- {
- if (UIntPtr.Size == 8)
- return (UIntPtr)l;
- else
- return (UIntPtr)(uint)l;
- }
-
- public static IntPtr SS(long l)
- {
- if (IntPtr.Size == 8)
- return (IntPtr)l;
- else
- return (IntPtr)(int)l;
- }
-
- public static UIntPtr SU(long l)
- {
- if (UIntPtr.Size == 8)
- return (UIntPtr)(ulong)l;
- else
- return (UIntPtr)(uint)l;
- }
- }
-
public sealed class MemoryBlock : IDisposable
{
- ///
- /// system page size
- ///
- public static int PageSize { get; private set; }
-
- ///
- /// bitshift corresponding to PageSize
- ///
- private static readonly int PageShift;
- ///
- /// bitmask corresponding to PageSize
- ///
- private static readonly ulong PageMask;
-
- static MemoryBlock()
- {
- int p = PageSize = Environment.SystemPageSize;
- while (p != 1)
- {
- p >>= 1;
- PageShift++;
- }
- PageMask = (ulong)(PageSize - 1);
- }
-
- ///
- /// true if addr is aligned
- ///
- private static bool Aligned(ulong addr)
- {
- return (addr & PageMask) == 0;
- }
-
- ///
- /// align address down to previous page boundary
- ///
- private static ulong AlignDown(ulong addr)
- {
- return addr & ~PageMask;
- }
-
- ///
- /// align address up to next page boundary
- ///
- private static ulong AlignUp(ulong addr)
- {
- return ((addr - 1) | PageMask) + 1;
- }
-
///
/// starting address of the memory block
///
@@ -140,7 +52,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
if (addr < Start || addr >= End)
throw new ArgumentOutOfRangeException();
- return (int)((addr - Start) >> PageShift);
+ return (int)((addr - Start) >> WaterboxUtils.PageShift);
}
///
@@ -148,7 +60,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
private ulong GetStartAddr(int page)
{
- return ((ulong)page << PageShift) + Start;
+ return ((ulong)page << WaterboxUtils.PageShift) + Start;
}
///
@@ -167,11 +79,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
public MemoryBlock(ulong start, ulong size)
{
- if (!Aligned(start))
+ if (!WaterboxUtils.Aligned(start))
throw new ArgumentOutOfRangeException();
if (size == 0)
throw new ArgumentOutOfRangeException();
- size = AlignUp(size);
+ size = WaterboxUtils.AlignUp(size);
_handle = Kernel32.CreateFileMapping(Kernel32.INVALID_HANDLE_VALUE, IntPtr.Zero,
Kernel32.FileMapProtection.PageExecuteReadWrite | Kernel32.FileMapProtection.SectionCommit, (uint)(size >> 32), (uint)size, null);
@@ -325,10 +237,13 @@ namespace BizHawk.Emulation.Cores.Waterbox
if (Active) // it's legal to Protect() if we're not active; the information is just saved for the next activation
{
- // TODO: if using another OS's memory protection calls, they must give the same non-aligned behavior
- // as VirtualProtect, or this must be changed
+ var computedStart = WaterboxUtils.AlignDown(start);
+ var computedEnd = WaterboxUtils.AlignUp(start + length);
+ var computedLength = computedEnd - computedStart;
+
Kernel32.MemoryProtection old;
- if (!Kernel32.VirtualProtect(Z.UU(start), Z.UU(length), p, out old))
+ if (!Kernel32.VirtualProtect(Z.UU(computedStart),
+ Z.UU(computedLength), p, out old))
throw new InvalidOperationException("VirtualProtect() returned FALSE!");
}
}
diff --git a/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs b/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs
index e3de218abc..ca87779b27 100644
--- a/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/PeRunner.cs
@@ -26,23 +26,33 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
/// how large the normal heap should be. it services sbrk calls
+ /// can be 0, but sbrk calls will crash.
///
public uint NormalHeapSizeKB { get; set; }
///
/// how large the sealed heap should be. it services special allocations that become readonly after init
+ /// Must be > 0 and at least large enough to store argv and envp
///
public uint SealedHeapSizeKB { get; set; }
///
/// how large the invisible heap should be. it services special allocations which are not savestated
+ /// Must be > 0 and at least large enough for the internal vtables
///
public uint InvisibleHeapSizeKB { get; set; }
///
/// how large the special heap should be. it is savestated, and contains ??
+ /// Must be > 0 and at least large enough for the internal pthread structure
///
public uint SpecialHeapSizeKB { get; set; }
+
+ ///
+ /// how large the mmap heap should be. it is savestated.
+ /// can be 0, but mmap calls will crash.
+ ///
+ public uint MmapHeapSizeKB { get; set; }
}
@@ -385,6 +395,57 @@ namespace BizHawk.Emulation.Cores.Waterbox
time.NanoSeconds = 0;
return 0;
}
+
+ [BizExport(CallingConvention.Cdecl, EntryPoint = "n9")]
+ public IntPtr MMap(IntPtr address, UIntPtr size, int prot, int flags, int fd, IntPtr offs)
+ {
+ if (address != IntPtr.Zero)
+ return Z.SS(-1);
+ MemoryBlock.Protection mprot;
+ switch (prot)
+ {
+ case 0: mprot = MemoryBlock.Protection.None; break;
+ default:
+ case 6: // W^X
+ case 7: // W^X
+ case 4: // exec only????
+ case 2: return Z.SS(-1); // write only????
+ case 3: mprot = MemoryBlock.Protection.RW; break;
+ case 1: mprot = MemoryBlock.Protection.R; break;
+ case 5: mprot = MemoryBlock.Protection.RX; break;
+ }
+ if ((flags & 0x20) == 0)
+ {
+ // MAP_ANONYMOUS is required
+ return Z.SS(-1);
+ }
+ if ((flags & 0xf00) != 0)
+ {
+ // various unsupported flags
+ return Z.SS(-1);
+ }
+
+ var ret = _parent._mmapheap.Map((ulong)size, mprot);
+ return ret == 0 ? Z.SS(-1) : Z.US(ret);
+ }
+ [BizExport(CallingConvention.Cdecl, EntryPoint = "n25")]
+ public IntPtr MRemap(UIntPtr oldAddress, UIntPtr oldSize,
+ UIntPtr newSize, int flags)
+ {
+ if ((flags & 2) != 0)
+ {
+ // don't support MREMAP_FIXED
+ return Z.SS(-1);
+ }
+ var ret = _parent._mmapheap.Remap((ulong)oldAddress, (ulong)oldSize, (ulong)newSize,
+ (flags & 1) != 0);
+ return ret == 0 ? Z.SS(-1) : Z.US(ret);
+ }
+ [BizExport(CallingConvention.Cdecl, EntryPoint = "n11")]
+ public int MUnmap(UIntPtr address, UIntPtr size)
+ {
+ return _parent._mmapheap.Unmap((ulong)address, (ulong)size) ? 0 : -1;
+ }
}
///
@@ -511,6 +572,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
///
private Heap _specheap;
+ ///
+ /// memory map emulation
+ ///
+ private MapHeap _mmapheap;
+
///
/// all loaded PE files
///
@@ -548,15 +614,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
private Heap CreateHeapHelper(uint sizeKB, string name, bool saveStated)
{
- var heap = new Heap(_nextStart, sizeKB * 1024, name);
- heap.Memory.Activate();
- ComputeNextStart(sizeKB * 1024);
- AddMemoryBlock(heap.Memory);
- if (saveStated)
- _savestateComponents.Add(heap);
- _disposeList.Add(heap);
- _heaps.Add(heap);
- return heap;
+ if (sizeKB != 0)
+ {
+ var heap = new Heap(_nextStart, sizeKB * 1024, name);
+ heap.Memory.Activate();
+ ComputeNextStart(sizeKB * 1024);
+ AddMemoryBlock(heap.Memory);
+ if (saveStated)
+ _savestateComponents.Add(heap);
+ _disposeList.Add(heap);
+ _heaps.Add(heap);
+ return heap;
+ }
+ else
+ {
+ return null;
+ }
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@@ -566,7 +639,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
Initialize(_nextStart);
using (this.EnterExit())
- {
+ {
// load any predefined exports
_psx = new Psx(this);
_exports.Add("libpsxscl.so", BizExvoker.GetExvoker(_psx));
@@ -610,6 +683,16 @@ namespace BizHawk.Emulation.Cores.Waterbox
_invisibleheap = CreateHeapHelper(opt.InvisibleHeapSizeKB, "invisible-heap", false);
_specheap = CreateHeapHelper(opt.SpecialHeapSizeKB, "special-heap", true);
+ if (opt.MmapHeapSizeKB != 0)
+ {
+ _mmapheap = new MapHeap(_nextStart, opt.MmapHeapSizeKB * 1024, "mmap-heap");
+ _mmapheap.Memory.Activate();
+ ComputeNextStart(opt.MmapHeapSizeKB * 1024);
+ AddMemoryBlock(_mmapheap.Memory);
+ _savestateComponents.Add(_mmapheap);
+ _disposeList.Add(_mmapheap);
+ }
+
_syscalls.Init();
//System.Diagnostics.Debugger.Break();
@@ -729,6 +812,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
_sealedheap = null;
_invisibleheap = null;
_specheap = null;
+ _mmapheap = null;
}
}
}
diff --git a/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs b/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs
index 2790ef4820..f91960f482 100644
--- a/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs
@@ -294,11 +294,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
s.Size);
}
Console.WriteLine("GDB Symbol Load:");
- Console.WriteLine("add-sym {0} {1} -s .data {2} -s .bss {3}",
- ModuleName,
- _sectionsByName[".text"].Start,
- _sectionsByName[".data"].Start,
- _sectionsByName[".bss"].Start);
+ var symload = $"add-sym {ModuleName} {_sectionsByName[".text"].Start}";
+ if (_sectionsByName.ContainsKey(".data"))
+ symload += $" -s .data {_sectionsByName[".data"].Start}";
+ if (_sectionsByName.ContainsKey(".bss"))
+ symload += $" -s .bss {_sectionsByName[".bss"].Start}";
+ Console.WriteLine(symload);
}
public IntPtr Resolve(string entryPoint)
diff --git a/BizHawk.Emulation.Cores/Waterbox/WaterboxUtils.cs b/BizHawk.Emulation.Cores/Waterbox/WaterboxUtils.cs
index db93aa3b64..4477642d4b 100644
--- a/BizHawk.Emulation.Cores/Waterbox/WaterboxUtils.cs
+++ b/BizHawk.Emulation.Cores/Waterbox/WaterboxUtils.cs
@@ -56,5 +56,101 @@ namespace BizHawk.Emulation.Cores.Waterbox
{
return DateTime.UtcNow.Ticks;
}
+
+ ///
+ /// system page size
+ ///
+ public static int PageSize { get; private set; }
+
+ ///
+ /// bitshift corresponding to PageSize
+ ///
+ public static int PageShift { get; private set; }
+ ///
+ /// bitmask corresponding to PageSize
+ ///
+ public static ulong PageMask { get; private set; }
+
+ static WaterboxUtils()
+ {
+ int p = PageSize = Environment.SystemPageSize;
+ while (p != 1)
+ {
+ p >>= 1;
+ PageShift++;
+ }
+ PageMask = (ulong)(PageSize - 1);
+ }
+
+ ///
+ /// true if addr is aligned
+ ///
+ public static bool Aligned(ulong addr)
+ {
+ return (addr & PageMask) == 0;
+ }
+
+ ///
+ /// align address down to previous page boundary
+ ///
+ public static ulong AlignDown(ulong addr)
+ {
+ return addr & ~PageMask;
+ }
+
+ ///
+ /// align address up to next page boundary
+ ///
+ public static ulong AlignUp(ulong addr)
+ {
+ return ((addr - 1) | PageMask) + 1;
+ }
+
+ ///
+ /// return the minimum number of pages needed to hold size
+ ///
+ public static int PagesNeeded(ulong size)
+ {
+ return (int)((size + PageMask) >> PageShift);
+ }
+ }
+
+ // C# is annoying: arithmetic operators for native ints are not exposed.
+ // So we store them as long/ulong instead in many places, and use these helpers
+ // to convert to IntPtr when needed
+
+ public static class Z
+ {
+ public static IntPtr US(ulong l)
+ {
+ if (IntPtr.Size == 8)
+ return (IntPtr)(long)l;
+ else
+ return (IntPtr)(int)l;
+ }
+
+ public static UIntPtr UU(ulong l)
+ {
+ if (UIntPtr.Size == 8)
+ return (UIntPtr)l;
+ else
+ return (UIntPtr)(uint)l;
+ }
+
+ public static IntPtr SS(long l)
+ {
+ if (IntPtr.Size == 8)
+ return (IntPtr)l;
+ else
+ return (IntPtr)(int)l;
+ }
+
+ public static UIntPtr SU(long l)
+ {
+ if (UIntPtr.Size == 8)
+ return (UIntPtr)(ulong)l;
+ else
+ return (UIntPtr)(uint)l;
+ }
}
}
diff --git a/waterbox/vb/Makefile b/waterbox/vb/Makefile
index b3f5d5b4e4..20a9605c0e 100644
--- a/waterbox/vb/Makefile
+++ b/waterbox/vb/Makefile
@@ -4,7 +4,7 @@ CCFLAGS:= -I. -I../emulibc \
-Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \
-std=c++0x -fomit-frame-pointer -fvisibility=hidden -fno-exceptions -fno-rtti \
-DLSB_FIRST \
- -O0
+ -O0 -g
TARGET = vb.wbx
@@ -29,7 +29,8 @@ $(TARGET).in: $(OBJS)
@$(CC) -o $@ $(LDFLAGS) $(CCFLAGS) $(OBJS) ../emulibc/libemuhost.so
$(TARGET): $(TARGET).in
- strip $< -o $@ -R /4 -R /14 -R /29 -R /41 -R /55 -R /67 -R /78 -R /89 -R /104
+# strip $< -o $@ -R /4 -R /14 -R /29 -R /41 -R /55 -R /67 -R /78 -R /89 -R /104
+ cp $< $@
clean:
rm -rf $(OBJ_DIR)
diff --git a/waterbox/vb/vb.wbx b/waterbox/vb/vb.wbx
deleted file mode 100644
index 7cb3242652..0000000000
Binary files a/waterbox/vb/vb.wbx and /dev/null differ
diff --git a/waterbox/vb/vb.wbx.in b/waterbox/vb/vb.wbx.in
deleted file mode 100644
index ab4e53bbe2..0000000000
Binary files a/waterbox/vb/vb.wbx.in and /dev/null differ