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:
parent
277c25c349
commit
9ab8b50c82
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue