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:
parent
3677f55992
commit
2887ba5823
|
@ -8,6 +8,7 @@ namespace BizHawk.Common.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)
|
||||
{
|
||||
foreach (var b in buffer)
|
||||
|
@ -39,6 +40,7 @@ namespace BizHawk.Common.BufferExtensions
|
|||
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)
|
||||
{
|
||||
for (int i = 0; i < length; i++)
|
||||
|
|
|
@ -33,10 +33,10 @@ namespace BizHawk.Emulation.Cores.Nintendo.SNES9X
|
|||
{
|
||||
Path = comm.CoreFileProvider.DllPath(),
|
||||
Filename = "snes9x.wbx",
|
||||
NormalHeapSizeKB = 1024,
|
||||
SbrkHeapSizeKB = 1024,
|
||||
SealedHeapSizeKB = 12 * 1024,
|
||||
InvisibleHeapSizeKB = 6 * 1024,
|
||||
SpecialHeapSizeKB = 64
|
||||
PlainHeapSizeKB = 64
|
||||
});
|
||||
|
||||
_core = BizInvoker.GetInvoker<LibSnes9x>(_exe, _exe);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using BizHawk.Common.BizInvoke;
|
||||
using BizHawk.Common.BufferExtensions;
|
||||
using BizHawk.Emulation.Common;
|
||||
using BizHawk.Emulation.Cores.Waterbox;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -11,7 +13,7 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
|
|||
{
|
||||
[CoreAttributes("Virtual Boyee", "???", true, false, "0.9.44.1",
|
||||
"https://mednafen.github.io/releases/", false)]
|
||||
public class VirtualBoyee : IEmulator, IVideoProvider, ISoundProvider
|
||||
public class VirtualBoyee : IEmulator, IVideoProvider, ISoundProvider, IStatable
|
||||
{
|
||||
private PeRunner _exe;
|
||||
private LibVirtualBoyee _boyee;
|
||||
|
@ -26,11 +28,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
|
|||
{
|
||||
Path = comm.CoreFileProvider.DllPath(),
|
||||
Filename = "vb.wbx",
|
||||
NormalHeapSizeKB = 4 * 1024,
|
||||
SealedHeapSizeKB = 12 * 1024,
|
||||
InvisibleHeapSizeKB = 6 * 1024,
|
||||
SpecialHeapSizeKB = 64,
|
||||
MmapHeapSizeKB = 16 * 1024
|
||||
SbrkHeapSizeKB = 256,
|
||||
SealedHeapSizeKB = 4 * 1024,
|
||||
InvisibleHeapSizeKB = 256,
|
||||
PlainHeapSizeKB = 256
|
||||
});
|
||||
|
||||
_boyee = BizInvoker.GetInvoker<LibVirtualBoyee>(_exe, _exe);
|
||||
|
@ -39,6 +40,8 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
|
|||
{
|
||||
throw new InvalidOperationException("Core rejected the rom");
|
||||
}
|
||||
|
||||
_exe.Seal();
|
||||
}
|
||||
|
||||
private bool _disposed = false;
|
||||
|
@ -191,5 +194,63 @@ namespace BizHawk.Emulation.Cores.Consoles.Nintendo.VB
|
|||
public SyncSoundMode SyncMode => SyncSoundMode.Sync;
|
||||
|
||||
#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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,10 +45,10 @@ namespace BizHawk.Emulation.Cores.Consoles.Sega.gpgx64
|
|||
{
|
||||
Path = comm.CoreFileProvider.DllPath(),
|
||||
Filename = "gpgx.wbx",
|
||||
NormalHeapSizeKB = 256,
|
||||
SbrkHeapSizeKB = 256,
|
||||
SealedHeapSizeKB = 36 * 1024,
|
||||
InvisibleHeapSizeKB = 4 * 1024,
|
||||
SpecialHeapSizeKB = 64
|
||||
PlainHeapSizeKB = 64
|
||||
});
|
||||
|
||||
Core = BizInvoker.GetInvoker<LibGPGX>(_elf, _elf);
|
||||
|
|
|
@ -73,7 +73,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
{
|
||||
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));
|
||||
Sealed = true;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
/// </summary>
|
||||
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>
|
||||
/// get a page index within the block
|
||||
|
@ -39,9 +42,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
|
||||
private class Bin
|
||||
{
|
||||
/// <summary>
|
||||
/// first page# in this bin, inclusive
|
||||
/// </summary>
|
||||
public int StartPage;
|
||||
/// <summary>
|
||||
/// numbe of pages in this bin
|
||||
/// </summary>
|
||||
public int PageCount;
|
||||
/// <summary>
|
||||
/// first page# not in this bin
|
||||
/// </summary>
|
||||
public int EndPage => StartPage + PageCount;
|
||||
public MemoryBlock.Protection Protection;
|
||||
/// <summary>
|
||||
/// true if not mapped (we distinguish between PROT_NONE and not mapped)
|
||||
/// </summary>
|
||||
public bool Free
|
||||
{
|
||||
get
|
||||
|
@ -78,6 +94,17 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
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;
|
||||
|
@ -153,19 +180,30 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
best.Protection = prot;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
var oldStartPage = GetPage(start);
|
||||
var oldStartBin = GetBinForStartPage(oldStartPage);
|
||||
if (oldSize == 0 && canMove)
|
||||
return Map(newSize, oldStartBin.Protection);
|
||||
{
|
||||
if (oldStartBin.Free)
|
||||
return 0;
|
||||
else
|
||||
return Map(newSize, oldStartBin.Protection);
|
||||
}
|
||||
|
||||
var oldNumPages = WaterboxUtils.PagesNeeded(oldSize);
|
||||
var oldEndPage = oldStartPage + oldNumPages;
|
||||
|
@ -181,14 +219,22 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
// 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
|
||||
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.Free
|
||||
&& nextBin.StartPage + nextBin.PageCount >= newEndPage)
|
||||
&& nextBin.EndPage >= newEndPage)
|
||||
{
|
||||
nextBin.Protection = oldStartBin.Protection;
|
||||
if (nextBin.Cleave(newEndPage - nextBin.StartPage))
|
||||
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;
|
||||
}
|
||||
// could not increase in place, so move
|
||||
|
@ -270,17 +316,21 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
freeBin.Free = true;
|
||||
}
|
||||
MemoryBlock.Protection lastEaten = MemoryBlock.Protection.None;
|
||||
while (freeBin.StartPage + freeBin.PageCount < endPage)
|
||||
while (freeBin.EndPage < endPage)
|
||||
{
|
||||
freeBin.PageCount += freeBin.Next.PageCount;
|
||||
lastEaten = freeBin.Next.Protection;
|
||||
freeBin.Next = freeBin.Next.Next;
|
||||
}
|
||||
if (freeBin.Cleave(freeBin.StartPage + freeBin.PageCount - endPage))
|
||||
if (freeBin.Cleave(freeBin.EndPage - endPage))
|
||||
{
|
||||
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()
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,25 +28,25 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
/// how large the normal heap should be. it services sbrk calls
|
||||
/// can be 0, but sbrk calls will crash.
|
||||
/// </summary>
|
||||
public uint NormalHeapSizeKB { get; set; }
|
||||
public uint SbrkHeapSizeKB { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
public uint SealedHeapSizeKB { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
public uint InvisibleHeapSizeKB { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// 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, and any alloc_plain() calls
|
||||
/// </summary>
|
||||
public uint SpecialHeapSizeKB { get; set; }
|
||||
public uint PlainHeapSizeKB { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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));
|
||||
}
|
||||
|
||||
[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")]
|
||||
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,
|
||||
// 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")]
|
||||
|
@ -241,7 +247,6 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
[BizExport(CallingConvention.Cdecl, EntryPoint = "n12")]
|
||||
public UIntPtr Brk(UIntPtr _p)
|
||||
{
|
||||
// does MUSL use this?
|
||||
var heap = _parent._heap;
|
||||
|
||||
var start = heap.Memory.Start;
|
||||
|
@ -570,7 +575,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
/// <summary>
|
||||
/// extra savestated heap
|
||||
/// </summary>
|
||||
private Heap _specheap;
|
||||
private Heap _plainheap;
|
||||
|
||||
/// <summary>
|
||||
/// memory map emulation
|
||||
|
@ -678,10 +683,10 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
ConnectAllImports();
|
||||
|
||||
// load all heaps
|
||||
_heap = CreateHeapHelper(opt.NormalHeapSizeKB, "brk-heap", true);
|
||||
_heap = CreateHeapHelper(opt.SbrkHeapSizeKB, "brk-heap", true);
|
||||
_sealedheap = CreateHeapHelper(opt.SealedHeapSizeKB, "sealed-heap", true);
|
||||
_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)
|
||||
{
|
||||
|
@ -695,7 +700,11 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
|
||||
_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
|
||||
var libcEnter = _exports["libc.so"].SafeResolve("__libc_entry_routine");
|
||||
|
@ -748,6 +757,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
{
|
||||
pe.SealImportsAndTakeXorSnapshot();
|
||||
}
|
||||
if (_mmapheap != null)
|
||||
_mmapheap.Memory.SaveXorSnapshot();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -811,7 +822,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
|
|||
_heap = null;
|
||||
_sealedheap = null;
|
||||
_invisibleheap = null;
|
||||
_specheap = null;
|
||||
_plainheap = null;
|
||||
_mmapheap = null;
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -3,4 +3,5 @@
|
|||
// this is just used to build a dummy .so file that isn't used
|
||||
void *alloc_sealed(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) { }
|
||||
|
|
|
@ -23,6 +23,11 @@ void *alloc_sealed(size_t size);
|
|||
// you are absolutely sure will not harm savestates
|
||||
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
|
||||
void _debug_puts(const char *);
|
||||
|
||||
|
|
|
@ -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 -g
|
||||
-O3 -flto
|
||||
|
||||
TARGET = vb.wbx
|
||||
|
||||
|
@ -29,8 +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
|
||||
cp $< $@
|
||||
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)
|
||||
|
|
|
@ -42,6 +42,7 @@ found freely through public domain sources.
|
|||
// CPU routines
|
||||
|
||||
#include "vb.h"
|
||||
#include <emulibc.h>
|
||||
|
||||
//#include "pcfx.h"
|
||||
//#include "debug.h"
|
||||
|
@ -70,7 +71,7 @@ V810::V810()
|
|||
IOWrite16 = 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(MemWriteBus32, 0, sizeof(MemWriteBus32));
|
||||
|
@ -81,7 +82,6 @@ V810::V810()
|
|||
|
||||
V810::~V810()
|
||||
{
|
||||
Kill();
|
||||
}
|
||||
|
||||
INLINE void V810::RecalcIPendingCache(void)
|
||||
|
@ -344,11 +344,6 @@ bool V810::Init(V810_Emu_Mode mode, bool vb_mode)
|
|||
return (TRUE);
|
||||
}
|
||||
|
||||
void V810::Kill(void)
|
||||
{
|
||||
FastMapAllocList.clear();
|
||||
}
|
||||
|
||||
void V810::SetInt(int level)
|
||||
{
|
||||
assert(level >= -1 && level <= 15);
|
||||
|
@ -357,7 +352,7 @@ void V810::SetInt(int level)
|
|||
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++)
|
||||
{
|
||||
|
@ -365,8 +360,7 @@ uint8 *V810::SetFastMap(uint32 addresses[], uint32 length, unsigned int num_addr
|
|||
}
|
||||
assert((length & (V810_FAST_MAP_PSIZE - 1)) == 0);
|
||||
|
||||
FastMapAllocList.emplace_back(std::unique_ptr<uint8[]>(new uint8[length + V810_FAST_MAP_TRAMPOLINE_SIZE]));
|
||||
uint8 *ret = FastMapAllocList.back().get();
|
||||
auto ret = (uint8*)allocator(length + V810_FAST_MAP_TRAMPOLINE_SIZE);
|
||||
|
||||
for (unsigned int i = length; i < length + V810_FAST_MAP_TRAMPOLINE_SIZE; i += 2)
|
||||
{
|
||||
|
|
|
@ -142,7 +142,6 @@ class V810
|
|||
|
||||
// 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;
|
||||
void Kill(void) MDFN_COLD;
|
||||
|
||||
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;
|
||||
|
||||
// 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)
|
||||
{
|
||||
|
@ -295,8 +294,7 @@ class V810
|
|||
uint32 dst_cache;
|
||||
bool have_src_cache, have_dst_cache;
|
||||
|
||||
uint8 *FastMap[(1ULL << 32) / V810_FAST_MAP_PSIZE];
|
||||
std::vector<std::unique_ptr<uint8[]>> FastMapAllocList;
|
||||
uint8** FastMap;
|
||||
|
||||
// For CacheDump and CacheRestore
|
||||
void CacheOpMemStore(v810_timestamp_t ×tamp, uint32 A, uint32 V);
|
||||
|
|
|
@ -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();
|
||||
|
||||
// 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();
|
||||
|
||||
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();
|
||||
|
||||
memset(GPRAM, 0, GPRAM_Mask + 1);
|
||||
|
|
|
@ -374,10 +374,6 @@ void VIP_Init(void)
|
|||
VidSettingsDirty = true;
|
||||
}
|
||||
|
||||
void VIP_Kill(void)
|
||||
{
|
||||
}
|
||||
|
||||
void VIP_Power(void)
|
||||
{
|
||||
Repeat = 0;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
namespace MDFN_IEN_VB
|
||||
{
|
||||
void VIP_Init(void) MDFN_COLD;
|
||||
void VIP_Kill(void) MDFN_COLD;
|
||||
void VIP_Power(void) MDFN_COLD;
|
||||
|
||||
void VIP_SetInstantDisplayHack(bool) MDFN_COLD;
|
||||
|
|
Loading…
Reference in New Issue