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
{
[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++)

View File

@ -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);

View File

@ -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
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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.

View File

@ -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) { }

View File

@ -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 *);

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 \
-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)

View File

@ -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)
{

View File

@ -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 &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();
// 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);

View File

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

View File

@ -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;