From 9ab8b50c82e195f3fbd9f0573e0cd8eecca67789 Mon Sep 17 00:00:00 2001 From: nattthebear Date: Tue, 11 Jul 2017 18:46:25 -0400 Subject: [PATCH] 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 --- BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs | 46 +++++++++++-------- waterbox/emulibc/emulibc.h | 6 +++ waterbox/pcfx/pcfx.cpp | 26 +++++------ 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs b/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs index bb7cb2e9fb..bd057d9e70 100644 --- a/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs +++ b/BizHawk.Emulation.Cores/Waterbox/PeWrapper.cs @@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Waterbox /// public Dictionary ExportsByName { get; } = new Dictionary(); - public Dictionary> ImportsByModule { get; } = + public Dictionary> ImportsByModule { get; } = new Dictionary>(); private class Section @@ -42,6 +42,8 @@ namespace BizHawk.Emulation.Cores.Waterbox private readonly Dictionary _sectionsByName = new Dictionary(); private readonly List
_sections = new List
(); private Section _imports; + private Section _sealed; + private Section _invisible; public string ModuleName { get; } @@ -67,8 +69,9 @@ namespace BizHawk.Emulation.Cores.Waterbox /// 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 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) diff --git a/waterbox/emulibc/emulibc.h b/waterbox/emulibc/emulibc.h index 90e705a5d5..da0eccc7c8 100644 --- a/waterbox/emulibc/emulibc.h +++ b/waterbox/emulibc/emulibc.h @@ -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 diff --git a/waterbox/pcfx/pcfx.cpp b/waterbox/pcfx/pcfx.cpp index 92088182fc..f9c3ec2bb4 100644 --- a/waterbox/pcfx/pcfx.cpp +++ b/waterbox/pcfx/pcfx.cpp @@ -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 {