savestates for vb. this includes savestates for mmap_heap. unfortunately, usage of mmap_heap was scrapped as the things going into it were better suited for invisible/sealed. it may be eventually useful

This commit is contained in:
nattthebear 2017-05-29 11:26:38 -04:00
parent 3677f55992
commit 2887ba5823
16 changed files with 240 additions and 59 deletions

View File

@ -8,6 +8,7 @@ namespace BizHawk.Common.BufferExtensions
{ {
public static class BufferExtensions public static class BufferExtensions
{ {
[Obsolete] // do we know of any situation where SaveAsHexFast doesn't work?
public static void SaveAsHex(this byte[] buffer, TextWriter writer) public static void SaveAsHex(this byte[] buffer, TextWriter writer)
{ {
foreach (var b in buffer) foreach (var b in buffer)
@ -39,6 +40,7 @@ namespace BizHawk.Common.BufferExtensions
writer.WriteLine(); writer.WriteLine();
} }
[Obsolete] // do we know of any situation where SaveAsHexFast doesn't work?
public static void SaveAsHex(this byte[] buffer, TextWriter writer, int length) public static void SaveAsHex(this byte[] buffer, TextWriter writer, int length)
{ {
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)

View File

@ -33,10 +33,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
{ {
Path = comm.CoreFileProvider.DllPath(), Path = comm.CoreFileProvider.DllPath(),
Filename = "snes9x.wbx", Filename = "snes9x.wbx",
NormalHeapSizeKB = 1024, SbrkHeapSizeKB = 1024,
SealedHeapSizeKB = 12 * 1024, SealedHeapSizeKB = 12 * 1024,
InvisibleHeapSizeKB = 6 * 1024, InvisibleHeapSizeKB = 6 * 1024,
SpecialHeapSizeKB = 64 PlainHeapSizeKB = 64
}); });
_core = BizInvoker.GetInvoker<LibSnes9x>(_exe, _exe); _core = BizInvoker.GetInvoker<LibSnes9x>(_exe, _exe);

View File

@ -1,8 +1,10 @@
using BizHawk.Common.BizInvoke; using BizHawk.Common.BizInvoke;
using BizHawk.Common.BufferExtensions;
using BizHawk.Emulation.Common; using BizHawk.Emulation.Common;
using BizHawk.Emulation.Cores.Waterbox; using BizHawk.Emulation.Cores.Waterbox;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -11,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
{ {
[CoreAttributes("Virtual Boyee", "???", true, false, "0.9.44.1", [CoreAttributes("Virtual Boyee", "???", true, false, "0.9.44.1",
"https://mednafen.github.io/releases/", false)] "https://mednafen.github.io/releases/", false)]
public class VirtualBoyee : IEmulator, IVideoProvider, ISoundProvider public class VirtualBoyee : IEmulator, IVideoProvider, ISoundProvider, IStatable
{ {
private PeRunner _exe; private PeRunner _exe;
private LibVirtualBoyee _boyee; private LibVirtualBoyee _boyee;
@ -26,11 +28,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
{ {
Path = comm.CoreFileProvider.DllPath(), Path = comm.CoreFileProvider.DllPath(),
Filename = "vb.wbx", Filename = "vb.wbx",
NormalHeapSizeKB = 4 * 1024, SbrkHeapSizeKB = 256,
SealedHeapSizeKB = 12 * 1024, SealedHeapSizeKB = 4 * 1024,
InvisibleHeapSizeKB = 6 * 1024, InvisibleHeapSizeKB = 256,
SpecialHeapSizeKB = 64, PlainHeapSizeKB = 256
MmapHeapSizeKB = 16 * 1024
}); });
_boyee = BizInvoker.GetInvoker<LibVirtualBoyee>(_exe, _exe); _boyee = BizInvoker.GetInvoker<LibVirtualBoyee>(_exe, _exe);
@ -39,6 +40,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
{ {
throw new InvalidOperationException("Core rejected the rom"); throw new InvalidOperationException("Core rejected the rom");
} }
_exe.Seal();
} }
private bool _disposed = false; private bool _disposed = false;
@ -191,5 +194,63 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
public SyncSoundMode SyncMode => SyncSoundMode.Sync; public SyncSoundMode SyncMode => SyncSoundMode.Sync;
#endregion #endregion
// TODO
public int LagCount { get; set; }
public bool IsLagFrame { get; set; }
#region IStatable
public bool BinarySaveStatesPreferred
{
get { return true; }
}
public void SaveStateText(TextWriter writer)
{
var temp = SaveStateBinary();
temp.SaveAsHexFast(writer);
// write extra copy of stuff we don't use
writer.WriteLine("Frame {0}", Frame);
}
public void LoadStateText(TextReader reader)
{
string hex = reader.ReadLine();
byte[] state = new byte[hex.Length / 2];
state.ReadFromHexFast(hex);
LoadStateBinary(new BinaryReader(new MemoryStream(state)));
}
public void LoadStateBinary(BinaryReader reader)
{
_exe.LoadStateBinary(reader);
// other variables
Frame = reader.ReadInt32();
LagCount = reader.ReadInt32();
IsLagFrame = reader.ReadBoolean();
// any managed pointers that we sent to the core need to be resent now!
}
public void SaveStateBinary(BinaryWriter writer)
{
_exe.SaveStateBinary(writer);
// other variables
writer.Write(Frame);
writer.Write(LagCount);
writer.Write(IsLagFrame);
}
public byte[] SaveStateBinary()
{
var ms = new MemoryStream();
var bw = new BinaryWriter(ms);
SaveStateBinary(bw);
bw.Flush();
ms.Close();
return ms.ToArray();
}
#endregion
} }
} }

View File

@ -45,10 +45,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
{ {
Path = comm.CoreFileProvider.DllPath(), Path = comm.CoreFileProvider.DllPath(),
Filename = "gpgx.wbx", Filename = "gpgx.wbx",
NormalHeapSizeKB = 256, SbrkHeapSizeKB = 256,
SealedHeapSizeKB = 36 * 1024, SealedHeapSizeKB = 36 * 1024,
InvisibleHeapSizeKB = 4 * 1024, InvisibleHeapSizeKB = 4 * 1024,
SpecialHeapSizeKB = 64 PlainHeapSizeKB = 64
}); });
Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf); Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf);

View File

@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{ {
if (!Sealed) if (!Sealed)
{ {
Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.R); Memory.Protect(Memory.Start, Used, MemoryBlock.Protection.R);
_hash = WaterboxUtils.Hash(Memory.GetStream(Memory.Start, Used, false)); _hash = WaterboxUtils.Hash(Memory.GetStream(Memory.Start, Used, false));
Sealed = true; Sealed = true;
} }

View File

@ -19,7 +19,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// </summary> /// </summary>
public string Name { get; private set; } public string Name { get; private set; }
public byte[] XorHash { get; private set; } /// <summary>
/// total number of bytes allocated
/// </summary>
public ulong Used { get; private set; }
/// <summary> /// <summary>
/// get a page index within the block /// get a page index within the block
@ -39,9 +42,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
private class Bin private class Bin
{ {
/// <summary>
/// first page# in this bin, inclusive
/// </summary>
public int StartPage; public int StartPage;
/// <summary>
/// numbe of pages in this bin
/// </summary>
public int PageCount; public int PageCount;
/// <summary>
/// first page# not in this bin
/// </summary>
public int EndPage => StartPage + PageCount;
public MemoryBlock.Protection Protection; public MemoryBlock.Protection Protection;
/// <summary>
/// true if not mapped (we distinguish between PROT_NONE and not mapped)
/// </summary>
public bool Free public bool Free
{ {
get get
@ -78,6 +94,17 @@ namespace BizHawk.Emulation.Cores.Waterbox
return false; return false;
} }
} }
/// <summary>
/// activate the protection specified by this block
/// </summary>
public void ApplyProtection(MemoryBlock m)
{
var prot = Free ? MemoryBlock.Protection.None : Protection;
var start = ((ulong)StartPage << WaterboxUtils.PageShift) + m.Start;
var length = (ulong)PageCount << WaterboxUtils.PageShift;
m.Protect(start, length, prot);
}
} }
private Bin _root; private Bin _root;
@ -153,19 +180,30 @@ namespace BizHawk.Emulation.Cores.Waterbox
best.Protection = prot; best.Protection = prot;
var ret = GetStartAddr(best.StartPage); var ret = GetStartAddr(best.StartPage);
Memory.Protect(ret, ((ulong)numPages) << WaterboxUtils.PageShift, prot); var totalSize = ((ulong)numPages) << WaterboxUtils.PageShift;
Memory.Protect(ret, totalSize, prot);
Used += totalSize;
Console.WriteLine($"Allocated {totalSize} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)");
return ret; return ret;
} }
public ulong Remap(ulong start, ulong oldSize, ulong newSize, bool canMove) public ulong Remap(ulong start, ulong oldSize, ulong newSize, bool canMove)
{ {
// TODO: what is the expected behavior when everything requested for remap is allocated,
// but with different protections?
if (start < Memory.Start || start + oldSize > Memory.End) if (start < Memory.Start || start + oldSize > Memory.End)
return 0; return 0;
var oldStartPage = GetPage(start); var oldStartPage = GetPage(start);
var oldStartBin = GetBinForStartPage(oldStartPage); var oldStartBin = GetBinForStartPage(oldStartPage);
if (oldSize == 0 && canMove) if (oldSize == 0 && canMove)
{
if (oldStartBin.Free)
return 0;
else
return Map(newSize, oldStartBin.Protection); return Map(newSize, oldStartBin.Protection);
}
var oldNumPages = WaterboxUtils.PagesNeeded(oldSize); var oldNumPages = WaterboxUtils.PagesNeeded(oldSize);
var oldEndPage = oldStartPage + oldNumPages; var oldEndPage = oldStartPage + oldNumPages;
@ -181,14 +219,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
// increase size // increase size
// the only way this will work in place is if all of the remaining space is free // the only way this will work in place is if all of the remaining space is free
Bin nextBin; Bin nextBin;
if (oldEndBin.StartPage + oldEndBin.PageCount == oldEndPage // if end bin is too bag, space after that is used by something else if (oldEndBin.EndPage == 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 = oldEndBin.Next) != null // can't go off the edge
&& nextBin.Free && nextBin.Free
&& nextBin.StartPage + nextBin.PageCount >= newEndPage) && nextBin.EndPage >= newEndPage)
{ {
nextBin.Protection = oldStartBin.Protection; nextBin.Protection = oldStartBin.Protection;
if (nextBin.Cleave(newEndPage - nextBin.StartPage)) if (nextBin.Cleave(newEndPage - nextBin.StartPage))
nextBin.Next.Free = true; nextBin.Next.Free = true;
nextBin.ApplyProtection(Memory);
var oldTotalSize = ((ulong)oldNumPages) << WaterboxUtils.PageShift;
var newTotalSize = ((ulong)newNumPages) << WaterboxUtils.PageShift;
Used += newTotalSize;
Used -= oldTotalSize;
Console.WriteLine($"Reallocated from {oldTotalSize} bytes to {newTotalSize} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)");
return start; return start;
} }
// could not increase in place, so move // could not increase in place, so move
@ -270,17 +316,21 @@ namespace BizHawk.Emulation.Cores.Waterbox
freeBin.Free = true; freeBin.Free = true;
} }
MemoryBlock.Protection lastEaten = MemoryBlock.Protection.None; MemoryBlock.Protection lastEaten = MemoryBlock.Protection.None;
while (freeBin.StartPage + freeBin.PageCount < endPage) while (freeBin.EndPage < endPage)
{ {
freeBin.PageCount += freeBin.Next.PageCount; freeBin.PageCount += freeBin.Next.PageCount;
lastEaten = freeBin.Next.Protection; lastEaten = freeBin.Next.Protection;
freeBin.Next = freeBin.Next.Next; freeBin.Next = freeBin.Next.Next;
} }
if (freeBin.Cleave(freeBin.StartPage + freeBin.PageCount - endPage)) if (freeBin.Cleave(freeBin.EndPage - endPage))
{ {
freeBin.Next.Protection = lastEaten; freeBin.Next.Protection = lastEaten;
} }
Memory.Protect(GetStartAddr(startPage), ((ulong)numPages) << WaterboxUtils.PageShift, MemoryBlock.Protection.None); freeBin.ApplyProtection(Memory);
var totalSize = ((ulong)numPages) << WaterboxUtils.PageShift;
Used -= totalSize;
Console.WriteLine($"Freed {totalSize} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)");
} }
public void Dispose() public void Dispose()
@ -292,12 +342,76 @@ namespace BizHawk.Emulation.Cores.Waterbox
} }
} }
public void SaveStateBinary(BinaryWriter writer) public void SaveStateBinary(BinaryWriter bw)
{ {
bw.Write(Name);
bw.Write(Memory.Size);
bw.Write(Used);
bw.Write(Memory.XorHash);
var bin = _root;
do
{
bw.Write(bin.PageCount);
bw.Write((byte)bin.Protection);
if (!bin.Free)
{
var start = GetStartAddr(bin.StartPage);
var length = (ulong)bin.PageCount << WaterboxUtils.PageShift;
if (bin.Protection == MemoryBlock.Protection.None)
Memory.Protect(start, length, MemoryBlock.Protection.R);
Memory.GetXorStream(start, length, false).CopyTo(bw.BaseStream);
if (bin.Protection == MemoryBlock.Protection.None)
Memory.Protect(start, length, MemoryBlock.Protection.None);
}
bin = bin.Next;
} while (bin != null);
bw.Write(-1);
} }
public void LoadStateBinary(BinaryReader reader) public void LoadStateBinary(BinaryReader br)
{ {
var name = br.ReadString();
if (name != Name)
throw new InvalidOperationException(string.Format("Name did not match for mapheap {0}", Name));
var size = br.ReadUInt64();
if (size != Memory.Size)
throw new InvalidOperationException(string.Format("Size did not match for mapheap {0}", Name));
var used = br.ReadUInt64();
var hash = br.ReadBytes(Memory.XorHash.Length);
if (!hash.SequenceEqual(Memory.XorHash))
throw new InvalidOperationException(string.Format("Hash did not match for mapheap {0}. Is this the same rom?", Name));
Used = 0;
int startPage = 0;
int pageCount;
Bin scratch = new Bin(), curr = scratch;
while ((pageCount = br.ReadInt32()) != -1)
{
var next = new Bin
{
StartPage = startPage,
PageCount = pageCount,
Protection = (MemoryBlock.Protection)br.ReadByte()
};
startPage += pageCount;
if (!next.Free)
{
var start = GetStartAddr(next.StartPage);
var length = (ulong)pageCount << WaterboxUtils.PageShift;
Memory.Protect(start, length, MemoryBlock.Protection.RW);
WaterboxUtils.CopySome(br.BaseStream, Memory.GetXorStream(start, length, true), (long)length);
Used += length;
}
next.ApplyProtection(Memory);
curr.Next = next;
curr = next;
}
if (used != Used)
throw new InvalidOperationException(string.Format("Inernal error loading mapheap {0}", Name));
_root = scratch.Next;
} }
} }
} }

View File

@ -28,25 +28,25 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// how large the normal heap should be. it services sbrk calls /// how large the normal heap should be. it services sbrk calls
/// can be 0, but sbrk calls will crash. /// can be 0, but sbrk calls will crash.
/// </summary> /// </summary>
public uint NormalHeapSizeKB { get; set; } public uint SbrkHeapSizeKB { get; set; }
/// <summary> /// <summary>
/// how large the sealed heap should be. it services special allocations that become readonly after init /// 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 /// Must be > 0 and at least large enough to store argv and envp, and any alloc_sealed() calls
/// </summary> /// </summary>
public uint SealedHeapSizeKB { get; set; } public uint SealedHeapSizeKB { get; set; }
/// <summary> /// <summary>
/// how large the invisible heap should be. it services special allocations which are not savestated /// 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 /// Must be > 0 and at least large enough for the internal vtables, and any alloc_invisible() calls
/// </summary> /// </summary>
public uint InvisibleHeapSizeKB { get; set; } public uint InvisibleHeapSizeKB { get; set; }
/// <summary> /// <summary>
/// how large the special heap should be. it is savestated, and contains ?? /// how large the "plain" heap should be. it is savestated, and contains
/// Must be > 0 and at least large enough for the internal pthread structure /// Must be > 0 and at least large enough for the internal pthread structure, and any alloc_plain() calls
/// </summary> /// </summary>
public uint SpecialHeapSizeKB { get; set; } public uint PlainHeapSizeKB { get; set; }
/// <summary> /// <summary>
/// how large the mmap heap should be. it is savestated. /// how large the mmap heap should be. it is savestated.
@ -205,6 +205,12 @@ namespace BizHawk.Emulation.Cores.Waterbox
return Z.US(_parent._invisibleheap.Allocate((ulong)size, 16)); return Z.US(_parent._invisibleheap.Allocate((ulong)size, 16));
} }
[BizExport(CallingConvention.Cdecl, EntryPoint = "alloc_plain")]
public IntPtr AllocPlain(UIntPtr size)
{
return Z.US(_parent._plainheap.Allocate((ulong)size, 16));
}
[BizExport(CallingConvention.Cdecl, EntryPoint = "_debug_puts")] [BizExport(CallingConvention.Cdecl, EntryPoint = "_debug_puts")]
public void DebugPuts(IntPtr s) public void DebugPuts(IntPtr s)
{ {
@ -229,7 +235,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
{ {
// as the inits are done in a defined order with a defined memory map, // as the inits are done in a defined order with a defined memory map,
// we don't need to savestate _pthreadSelf // we don't need to savestate _pthreadSelf
_pthreadSelf = Z.US(_parent._specheap.Allocate(65536, 1)); _pthreadSelf = Z.US(_parent._plainheap.Allocate(65536, 1));
} }
[BizExport(CallingConvention.Cdecl, EntryPoint = "log_output")] [BizExport(CallingConvention.Cdecl, EntryPoint = "log_output")]
@ -241,7 +247,6 @@ namespace BizHawk.Emulation.Cores.Waterbox
[BizExport(CallingConvention.Cdecl, EntryPoint = "n12")] [BizExport(CallingConvention.Cdecl, EntryPoint = "n12")]
public UIntPtr Brk(UIntPtr _p) public UIntPtr Brk(UIntPtr _p)
{ {
// does MUSL use this?
var heap = _parent._heap; var heap = _parent._heap;
var start = heap.Memory.Start; var start = heap.Memory.Start;
@ -570,7 +575,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// <summary> /// <summary>
/// extra savestated heap /// extra savestated heap
/// </summary> /// </summary>
private Heap _specheap; private Heap _plainheap;
/// <summary> /// <summary>
/// memory map emulation /// memory map emulation
@ -678,10 +683,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
ConnectAllImports(); ConnectAllImports();
// load all heaps // load all heaps
_heap = CreateHeapHelper(opt.NormalHeapSizeKB, "brk-heap", true); _heap = CreateHeapHelper(opt.SbrkHeapSizeKB, "brk-heap", true);
_sealedheap = CreateHeapHelper(opt.SealedHeapSizeKB, "sealed-heap", true); _sealedheap = CreateHeapHelper(opt.SealedHeapSizeKB, "sealed-heap", true);
_invisibleheap = CreateHeapHelper(opt.InvisibleHeapSizeKB, "invisible-heap", false); _invisibleheap = CreateHeapHelper(opt.InvisibleHeapSizeKB, "invisible-heap", false);
_specheap = CreateHeapHelper(opt.SpecialHeapSizeKB, "special-heap", true); _plainheap = CreateHeapHelper(opt.PlainHeapSizeKB, "plain-heap", true);
if (opt.MmapHeapSizeKB != 0) if (opt.MmapHeapSizeKB != 0)
{ {
@ -695,7 +700,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
_syscalls.Init(); _syscalls.Init();
//System.Diagnostics.Debugger.Break(); if (System.Diagnostics.Debugger.IsAttached)
{
Console.WriteLine("About to enter unmanaged code");
System.Diagnostics.Debugger.Break();
}
// run unmanaged init code // run unmanaged init code
var libcEnter = _exports["libc.so"].SafeResolve("__libc_entry_routine"); var libcEnter = _exports["libc.so"].SafeResolve("__libc_entry_routine");
@ -748,6 +757,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
{ {
pe.SealImportsAndTakeXorSnapshot(); pe.SealImportsAndTakeXorSnapshot();
} }
if (_mmapheap != null)
_mmapheap.Memory.SaveXorSnapshot();
} }
} }
@ -811,7 +822,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
_heap = null; _heap = null;
_sealedheap = null; _sealedheap = null;
_invisibleheap = null; _invisibleheap = null;
_specheap = null; _plainheap = null;
_mmapheap = null; _mmapheap = null;
} }
} }

Binary file not shown.

View File

@ -3,4 +3,5 @@
// this is just used to build a dummy .so file that isn't used // this is just used to build a dummy .so file that isn't used
void *alloc_sealed(size_t size) { return NULL; } void *alloc_sealed(size_t size) { return NULL; }
void *alloc_invisible(size_t size) { return NULL; } void *alloc_invisible(size_t size) { return NULL; }
void *alloc_plain(size_t size) { return NULL; }
void _debug_puts(const char *s) { } void _debug_puts(const char *s) { }

View File

@ -23,6 +23,11 @@ void *alloc_sealed(size_t size);
// you are absolutely sure will not harm savestates // you are absolutely sure will not harm savestates
void *alloc_invisible(size_t size); void *alloc_invisible(size_t size);
// allocate memory from the "plain" pool. this memory can never be freed.
// this memory is savestated normally.
// useful to avoid malloc() overhead for things that will never be freed
void *alloc_plain(size_t size);
// send a debug string somewhere, bypassing stdio // send a debug string somewhere, bypassing stdio
void _debug_puts(const char *); void _debug_puts(const char *);

View File

@ -4,7 +4,7 @@ CCFLAGS:= -I. -I../emulibc \
-Wall -Werror=pointer-to-int-cast -Werror=int-to-pointer-cast -Werror=implicit-function-declaration \ -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 \ -std=c++0x -fomit-frame-pointer -fvisibility=hidden -fno-exceptions -fno-rtti \
-DLSB_FIRST \ -DLSB_FIRST \
-O0 -g -O3 -flto
TARGET = vb.wbx TARGET = vb.wbx
@ -29,8 +29,8 @@ $(TARGET).in: $(OBJS)
@$(CC) -o $@ $(LDFLAGS) $(CCFLAGS) $(OBJS) ../emulibc/libemuhost.so @$(CC) -o $@ $(LDFLAGS) $(CCFLAGS) $(OBJS) ../emulibc/libemuhost.so
$(TARGET): $(TARGET).in $(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 $< $@ # cp $< $@
clean: clean:
rm -rf $(OBJ_DIR) rm -rf $(OBJ_DIR)

View File

@ -42,6 +42,7 @@ found freely through public domain sources.
// CPU routines // CPU routines
#include "vb.h" #include "vb.h"
#include <emulibc.h>
//#include "pcfx.h" //#include "pcfx.h"
//#include "debug.h" //#include "debug.h"
@ -70,7 +71,7 @@ V810::V810()
IOWrite16 = NULL; IOWrite16 = NULL;
IOWrite32 = NULL; IOWrite32 = NULL;
memset(FastMap, 0, sizeof(FastMap)); FastMap = (uint8**)alloc_sealed((1ULL << 32) / V810_FAST_MAP_PSIZE * sizeof(*FastMap));
memset(MemReadBus32, 0, sizeof(MemReadBus32)); memset(MemReadBus32, 0, sizeof(MemReadBus32));
memset(MemWriteBus32, 0, sizeof(MemWriteBus32)); memset(MemWriteBus32, 0, sizeof(MemWriteBus32));
@ -81,7 +82,6 @@ V810::V810()
V810::~V810() V810::~V810()
{ {
Kill();
} }
INLINE void V810::RecalcIPendingCache(void) INLINE void V810::RecalcIPendingCache(void)
@ -344,11 +344,6 @@ bool V810::Init(V810_Emu_Mode mode, bool vb_mode)
return (TRUE); return (TRUE);
} }
void V810::Kill(void)
{
FastMapAllocList.clear();
}
void V810::SetInt(int level) void V810::SetInt(int level)
{ {
assert(level >= -1 && level <= 15); assert(level >= -1 && level <= 15);
@ -357,7 +352,7 @@ void V810::SetInt(int level)
RecalcIPendingCache(); RecalcIPendingCache();
} }
uint8 *V810::SetFastMap(uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name) uint8* V810::SetFastMap(void *(*allocator)(size_t size), uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name)
{ {
for (unsigned int i = 0; i < num_addresses; i++) for (unsigned int i = 0; i < num_addresses; i++)
{ {
@ -365,8 +360,7 @@ uint8 *V810::SetFastMap(uint32 addresses[], uint32 length, unsigned int num_addr
} }
assert((length & (V810_FAST_MAP_PSIZE - 1)) == 0); assert((length & (V810_FAST_MAP_PSIZE - 1)) == 0);
FastMapAllocList.emplace_back(std::unique_ptr<uint8[]>(new uint8[length + V810_FAST_MAP_TRAMPOLINE_SIZE])); auto ret = (uint8*)allocator(length + V810_FAST_MAP_TRAMPOLINE_SIZE);
uint8 *ret = FastMapAllocList.back().get();
for (unsigned int i = length; i < length + V810_FAST_MAP_TRAMPOLINE_SIZE; i += 2) for (unsigned int i = length; i < length + V810_FAST_MAP_TRAMPOLINE_SIZE; i += 2)
{ {

View File

@ -142,7 +142,6 @@ class V810
// Pass TRUE for vb_mode if we're emulating a VB-specific enhanced V810 CPU core // Pass TRUE for vb_mode if we're emulating a VB-specific enhanced V810 CPU core
bool Init(V810_Emu_Mode mode, bool vb_mode) MDFN_COLD; bool Init(V810_Emu_Mode mode, bool vb_mode) MDFN_COLD;
void Kill(void) MDFN_COLD;
void SetInt(int level); void SetInt(int level);
@ -156,7 +155,7 @@ class V810
void SetIOWriteHandlers(void MDFN_FASTCALL (*write8)(v810_timestamp_t &, uint32, uint8), void MDFN_FASTCALL (*write16)(v810_timestamp_t &, uint32, uint16), void MDFN_FASTCALL (*write32)(v810_timestamp_t &, uint32, uint32)) MDFN_COLD; void SetIOWriteHandlers(void MDFN_FASTCALL (*write8)(v810_timestamp_t &, uint32, uint8), void MDFN_FASTCALL (*write16)(v810_timestamp_t &, uint32, uint16), void MDFN_FASTCALL (*write32)(v810_timestamp_t &, uint32, uint32)) MDFN_COLD;
// Length specifies the number of bytes to map in, at each location specified by addresses[] (for mirroring) // Length specifies the number of bytes to map in, at each location specified by addresses[] (for mirroring)
uint8 *SetFastMap(uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name) MDFN_COLD; uint8 *SetFastMap(void *(*allocator)(size_t size), uint32 addresses[], uint32 length, unsigned int num_addresses, const char *name) MDFN_COLD;
INLINE void ResetTS(v810_timestamp_t new_base_timestamp) INLINE void ResetTS(v810_timestamp_t new_base_timestamp)
{ {
@ -295,8 +294,7 @@ class V810
uint32 dst_cache; uint32 dst_cache;
bool have_src_cache, have_dst_cache; bool have_src_cache, have_dst_cache;
uint8 *FastMap[(1ULL << 32) / V810_FAST_MAP_PSIZE]; uint8** FastMap;
std::vector<std::unique_ptr<uint8[]>> FastMapAllocList;
// For CacheDump and CacheRestore // For CacheDump and CacheRestore
void CacheOpMemStore(v810_timestamp_t &timestamp, uint32 A, uint32 V); void CacheOpMemStore(v810_timestamp_t &timestamp, uint32 A, uint32 V);

View File

@ -582,7 +582,7 @@ EXPORT int Load(const uint8 *rom, int length)
} }
} }
WRAM = VB_V810->SetFastMap(&Map_Addresses[0], 65536, Map_Addresses.size(), "WRAM"); WRAM = VB_V810->SetFastMap(alloc_plain, &Map_Addresses[0], 65536, Map_Addresses.size(), "WRAM");
Map_Addresses.clear(); Map_Addresses.clear();
// Round up the ROM size to 65536(we mirror it a little later) // Round up the ROM size to 65536(we mirror it a little later)
@ -597,7 +597,7 @@ EXPORT int Load(const uint8 *rom, int length)
} }
} }
GPROM = VB_V810->SetFastMap(&Map_Addresses[0], GPROM_Mask + 1, Map_Addresses.size(), "Cart ROM"); GPROM = VB_V810->SetFastMap(alloc_sealed, &Map_Addresses[0], GPROM_Mask + 1, Map_Addresses.size(), "Cart ROM");
Map_Addresses.clear(); Map_Addresses.clear();
memcpy(GPROM, rom, rom_size); memcpy(GPROM, rom, rom_size);
@ -633,7 +633,7 @@ EXPORT int Load(const uint8 *rom, int length)
} }
} }
GPRAM = VB_V810->SetFastMap(&Map_Addresses[0], GPRAM_Mask + 1, Map_Addresses.size(), "Cart RAM"); GPRAM = VB_V810->SetFastMap(alloc_plain, &Map_Addresses[0], GPRAM_Mask + 1, Map_Addresses.size(), "Cart RAM");
Map_Addresses.clear(); Map_Addresses.clear();
memset(GPRAM, 0, GPRAM_Mask + 1); memset(GPRAM, 0, GPRAM_Mask + 1);

View File

@ -374,10 +374,6 @@ void VIP_Init(void)
VidSettingsDirty = true; VidSettingsDirty = true;
} }
void VIP_Kill(void)
{
}
void VIP_Power(void) void VIP_Power(void)
{ {
Repeat = 0; Repeat = 0;

View File

@ -24,7 +24,6 @@
namespace MDFN_IEN_VB namespace MDFN_IEN_VB
{ {
void VIP_Init(void) MDFN_COLD; void VIP_Init(void) MDFN_COLD;
void VIP_Kill(void) MDFN_COLD;
void VIP_Power(void) MDFN_COLD; void VIP_Power(void) MDFN_COLD;
void VIP_SetInstantDisplayHack(bool) MDFN_COLD; void VIP_SetInstantDisplayHack(bool) MDFN_COLD;