waterbox: Allow special section attributes to put variables directly in sealed or invisible. This can be easier to use than the heaps for adapting some existing code

This commit is contained in:
nattthebear 2017-07-11 18:46:25 -04:00
parent 277c25c349
commit 9ab8b50c82
3 changed files with 47 additions and 31 deletions

View File

@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// </summary>
public Dictionary<string, IntPtr> ExportsByName { get; } = new Dictionary<string, IntPtr>();
public Dictionary<string, Dictionary<string, IntPtr>> ImportsByModule { get; } =
public Dictionary<string, Dictionary<string, IntPtr>> ImportsByModule { get; } =
new Dictionary<string, Dictionary<string, IntPtr>>();
private class Section
@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
private readonly Dictionary<string, Section> _sectionsByName = new Dictionary<string, Section>();
private readonly List<Section> _sections = new List<Section>();
private Section _imports;
private Section _sealed;
private Section _invisible;
public string ModuleName { get; }
@ -67,8 +69,9 @@ namespace BizHawk.Emulation.Cores.Waterbox
/// </summary>
public IntPtr DtorList { get; private set; }
// true if the imports have been set to readonly
private bool _importsSealed = false;
// true if the seal process has completed, including .idata and .sealed set to readonly,
// xorstate taken
private bool _everythingSealed = false;
/*[UnmanagedFunctionPointer(CallingConvention.Winapi)]
private delegate bool DllEntry(IntPtr instance, int reason, IntPtr reserved);
@ -165,6 +168,8 @@ namespace BizHawk.Emulation.Cores.Waterbox
_sectionsByName.Add(section.Name, section);
}
_sectionsByName.TryGetValue(".idata", out _imports);
_sectionsByName.TryGetValue(".sealed", out _sealed);
_sectionsByName.TryGetValue(".invis", out _invisible);
Mount();
}
@ -317,7 +322,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
// this is called once internally when bootstrapping, and externally
// when we need to restore a savestate from another run. so imports might or might not be sealed
if (_importsSealed && _imports != null)
if (_everythingSealed && _imports != null)
Memory.Protect(_imports.Start, _imports.Size, MemoryBlock.Protection.RW);
Dictionary<string, IntPtr> imports;
@ -330,33 +335,38 @@ namespace BizHawk.Emulation.Cores.Waterbox
}
}
if (_importsSealed && _imports != null)
if (_everythingSealed && _imports != null)
Memory.Protect(_imports.Start, _imports.Size, _imports.Prot);
}
public void SealImportsAndTakeXorSnapshot()
{
if (_importsSealed)
throw new InvalidOperationException("Imports already sealed!");
if (_everythingSealed)
throw new InvalidOperationException("PeWrapper already sealed!");
// save import values, then zero them all (for hash purposes), then take our snapshot, then load them again,
// then set the .idata area to read only
byte[] impData = null;
if (_imports != null)
{
var data = new byte[_imports.Size];
Marshal.Copy(Z.US(_imports.Start), data, 0, (int)_imports.Size);
impData = new byte[_imports.Size];
Marshal.Copy(Z.US(_imports.Start), impData, 0, (int)_imports.Size);
WaterboxUtils.ZeroMemory(Z.US(_imports.Start), (long)_imports.Size);
Memory.SaveXorSnapshot();
Marshal.Copy(data, 0, Z.US(_imports.Start), (int)_imports.Size);
}
Memory.SaveXorSnapshot();
if (_imports != null)
{
Marshal.Copy(impData, 0, Z.US(_imports.Start), (int)_imports.Size);
_imports.W = false;
Memory.Protect(_imports.Start, _imports.Size, _imports.Prot);
}
else
if (_sealed != null)
{
Memory.SaveXorSnapshot();
_sealed.W = false;
Memory.Protect(_sealed.Start, _sealed.Size, _sealed.Prot);
}
_importsSealed = true;
_everythingSealed = true;
}
private bool _disposed = false;
@ -375,7 +385,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
public void SaveStateBinary(BinaryWriter bw)
{
if (!_importsSealed)
if (!_everythingSealed)
throw new InvalidOperationException(".idata sections must be closed before saving state");
bw.Write(MAGIC);
@ -385,7 +395,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
foreach (var s in _sections)
{
if (!s.W)
if (!s.W || s == _invisible)
continue;
var ms = Memory.GetXorStream(s.Start, s.SavedSize, false);
@ -396,7 +406,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
public void LoadStateBinary(BinaryReader br)
{
if (!_importsSealed)
if (!_everythingSealed)
// operations happening in the wrong order. probable cause: internal logic error. make sure frontend calls Seal
throw new InvalidOperationException(".idata sections must be closed before loading state");
@ -419,7 +429,7 @@ namespace BizHawk.Emulation.Cores.Waterbox
foreach (var s in _sections)
{
if (!s.W)
if (!s.W || s == _invisible)
continue;
if (br.ReadUInt64() != s.SavedSize)

View File

@ -31,6 +31,12 @@ void *alloc_plain(size_t size);
// send a debug string somewhere, bypassing stdio
void _debug_puts(const char *);
// put data in a section that will have similar behavior characteristics to alloc_sealed
#define ECL_SEALED __attribute__((section(".sealed")))
// put data in a section that will have similar behavior characteristics to alloc_invisible
#define ECL_INVISIBLE __attribute__((section(".invis")))
#ifdef __cplusplus
}
#endif

View File

@ -675,7 +675,7 @@ struct MyFrameInfo : public FrameInfo
};
static EmulateSpecStruct Ess;
static int32_t LineWidths[480];
static uint32_t FrameBuffer[1024 * 480];
ECL_INVISIBLE static uint32_t FrameBuffer[1024 * 480];
EXPORT bool Init(int numDisks, const uint8_t *bios)
{
@ -805,21 +805,21 @@ EXPORT void SetInputCallback(void (*callback)())
}
// settings
int Setting_HighDotclockWidth = 341;
int Setting_CdSpeed = 2;
int Setting_SlStart = 4;
int Setting_SlEnd = 235;
ECL_SEALED int Setting_HighDotclockWidth = 341;
ECL_SEALED int Setting_CdSpeed = 2;
ECL_SEALED int Setting_SlStart = 4;
ECL_SEALED int Setting_SlEnd = 235;
double Setting_ResampRateError = 0.0000009;
int Setting_ResampQuality = 3;
ECL_SEALED double Setting_ResampRateError = 0.0000009;
ECL_SEALED int Setting_ResampQuality = 3;
int Setting_CpuEmulation = 2; // 0 = fast, 1 = accurate, 2 = auto
bool Setting_NoSpriteLimit;
bool Setting_AdpcmBuggy = false;
bool Setting_AdpcmNoClicks = true;
bool Setting_ChromaInterpolate = false;
ECL_SEALED int Setting_CpuEmulation = 2; // 0 = fast, 1 = accurate, 2 = auto
ECL_SEALED bool Setting_NoSpriteLimit;
ECL_SEALED bool Setting_AdpcmBuggy = false;
ECL_SEALED bool Setting_AdpcmNoClicks = true;
ECL_SEALED bool Setting_ChromaInterpolate = false;
int Setting_PortDevice[2];
ECL_SEALED int Setting_PortDevice[2];
struct FrontendSettings
{