public void LoadStateBinary(BinaryReader br) { var name = br.ReadString(); if (name != Name) { // probable cause: internal error throw new InvalidOperationException($"Name did not match for heap {Name}"); } var used = br.ReadUInt64(); if (used > Memory.Size) { throw new InvalidOperationException($"Heap {Name} used {used} larger than available {Memory.Size}"); } if (!Sealed) { var hash = br.ReadBytes(Memory.XorHash.Length); if (!hash.SequenceEqual(Memory.XorHash)) { throw new InvalidOperationException($"Hash did not match for heap {Name}. Is this the same rom with the same SyncSettings?"); } var oldUsedAligned = WaterboxUtils.AlignUp(Used); var usedAligned = WaterboxUtils.AlignUp(used); if (usedAligned > oldUsedAligned) { // grow var s = Memory.Start + oldUsedAligned; var l = usedAligned - oldUsedAligned; Memory.Protect(s, l, MemoryBlock.Protection.RW); } else if (usedAligned < oldUsedAligned) { // shrink var s = Memory.Start + usedAligned; var l = oldUsedAligned - usedAligned; // like elsewhere, we zero on free to avoid nondeterminism if later reallocated WaterboxUtils.ZeroMemory(Z.US(s), (long)l); Memory.Protect(s, l, MemoryBlock.Protection.None); } var ms = Memory.GetXorStream(Memory.Start, usedAligned, true); WaterboxUtils.CopySome(br.BaseStream, ms, (long)usedAligned); Used = used; } else { var hash = br.ReadBytes(_hash.Length); if (!hash.SequenceEqual(_hash)) { throw new InvalidOperationException($"Hash did not match for heap {Name}. Is this the same rom with the same SyncSettings?"); } } }
public void LoadStateBinary(BinaryReader br) { Enter(); try { if (br.ReadUInt64() != MAGIC) { throw new InvalidOperationException("Magic not magic enough!"); } if (!br.ReadBytes(_elfhash.Length).SequenceEqual(_elfhash)) { throw new InvalidOperationException("Elf changed disguise!"); } if (br.ReadInt64() != _loadoffset) { throw new InvalidOperationException("Trickys elves moved on you!"); } foreach (var sec in _elf.Sections.Where(s => (s.Flags & SectionFlags.Writable) != 0)) { var len = br.ReadInt64(); if (sec.Size != len) { throw new InvalidOperationException("Unexpected section size for " + sec.Name); } var ms = _base.GetStream((ulong)(sec.LoadAddress + _loadoffset), (ulong)sec.Size, true); WaterboxUtils.CopySome(br.BaseStream, ms, len); } if (_heap != null) { _heap.LoadStateBinary(br); } if (_sealedheap != null) { _sealedheap.LoadStateBinary(br); } if (br.ReadUInt64() != MAGIC) { throw new InvalidOperationException("Magic not magic enough!"); } // the syscall trampolines were overwritten in loadstate (they're in .bss), and if we're cross-session, // are no longer valid. cores must similiarly resend any external pointers they gave the core. ConnectAllClibPatches(); } finally { Exit(); } }
public void LoadStateBinary(BinaryReader br) { 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"); } if (br.ReadUInt64() != MAGIC) { // file id is missing. probable cause: garbage savestate throw new InvalidOperationException("Savestate corrupted!"); } if (!br.ReadBytes(_fileHash.Length).SequenceEqual(_fileHash)) { // the .dll file that is loaded now has a different hash than the .dll that created the savestate throw new InvalidOperationException("Core consistency check failed. Is this a savestate from a different version?"); } if (!br.ReadBytes(Memory.XorHash.Length).SequenceEqual(Memory.XorHash)) { // the post-Seal memory state is different. probable cause: different rom or different version of rom, // different syncsettings throw new InvalidOperationException("Memory consistency check failed. Is this savestate from different SyncSettings?"); } if (br.ReadUInt64() != Start) { // dll loaded somewhere else. probable cause: internal logic error. // unlikely to get this far if the previous checks pssed throw new InvalidOperationException("Trickys elves moved on you!"); } Memory.Protect(Memory.AddressRange.Start, Memory.Size, MemoryBlockBase.Protection.RW); foreach (var s in _sections) { if (!s.W || s == _invisible) { continue; } if (br.ReadUInt64() != s.SavedSize) { throw new InvalidOperationException("Unexpected section size for " + s.Name); } var ms = Memory.GetXorStream(s.Start, s.SavedSize, true); WaterboxUtils.CopySome(br.BaseStream, ms, (long)s.SavedSize); } ProtectMemory(); }
public void LoadStateBinary(BinaryReader br) { if (!_everythingSealed) { // operations happening in the wrong order. probable cause: internal logic error. make sure frontend calls Seal throw new InvalidOperationException(".wbxsyscall section must be closed before loading state"); } if (br.ReadUInt64() != MAGIC) { // file id is missing. probable cause: garbage savestate throw new InvalidOperationException("Savestate corrupted!"); } var elfHash = br.ReadBytes(_elfHash.Length); if (_skipCoreConsistencyCheck) { throw new InvalidOperationException("We decided that the core consistency check should always run"); } else { if (!elfHash.SequenceEqual(_elfHash)) { // the .dll file that is loaded now has a different hash than the .dll that created the savestate throw new InvalidOperationException("Core consistency check failed. Is this a savestate from a different version?"); } } var xorHash = br.ReadBytes(Memory.XorHash.Length); if (!_skipMemoryConsistencyCheck) { if (!xorHash.SequenceEqual(Memory.XorHash)) { // the post-Seal memory state is different. probable cause: different rom or different version of rom, // different syncsettings throw new InvalidOperationException("Memory consistency check failed. Is this savestate from different SyncSettings?"); } } var len = Memory.EndExclusive - _saveStart; if (br.ReadUInt64() != len) { throw new InvalidOperationException("Unexpected saved length"); } var ms = Memory.GetXorStream(_saveStart, len, true); WaterboxUtils.CopySome(br.BaseStream, ms, (long)len); }
public void LoadStateBinary(BinaryReader br) { var name = br.ReadString(); if (name != Name) { throw new InvalidOperationException($"Name did not match for {nameof(MapHeap)} {Name}"); } var size = br.ReadUInt64(); if (size != Memory.Size) { throw new InvalidOperationException($"Size did not match for {nameof(MapHeap)} {Name}"); } var used = br.ReadUInt64(); var hash = br.ReadBytes(Memory.XorHash.Length); if (!hash.SequenceEqual(Memory.XorHash)) { throw new InvalidOperationException($"Hash did not match for {nameof(MapHeap)} {Name}. Is this the same rom?"); } if (br.BaseStream.Read(_pagesAsBytes, 0, _pagesAsBytes.Length) != _pagesAsBytes.Length) { throw new InvalidOperationException("Unexpected error reading!"); } Used = 0; Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.RW); var dsts = Memory.GetXorStream(Memory.Start, Memory.Size, true); for (int i = 0, addr = 0; i < _pages.Length; i++, addr += WaterboxUtils.PageSize) { if (_pages[i] != FREE) { dsts.Seek(addr, SeekOrigin.Begin); WaterboxUtils.CopySome(br.BaseStream, dsts, WaterboxUtils.PageSize); Used += (uint)WaterboxUtils.PageSize; } } if (Used != used) { throw new InvalidOperationException("Internal savestate error"); } if (br.ReadUInt64() != MAGIC) { throw new InvalidOperationException("Savestate internal error"); } RefreshAllProtections(); }
public void StoreSaveRam(byte[] data) { using (_exe.EnterExit()) { if (data.Length != _saveramSize) { throw new InvalidOperationException("Saveram size mismatch"); } using (_exe.EnterExit()) { var source = new MemoryStream(data, false); foreach (var area in _saveramAreas) { WaterboxUtils.CopySome(source, new MemoryDomainStream(area), area.Size); } } } }
public void LoadStateBinary(BinaryReader br) { var name = br.ReadString(); if (name != Name) { // probable cause: internal error throw new InvalidOperationException(string.Format("Name did not match for heap {0}", Name)); } var used = br.ReadUInt64(); if (used > Memory.Size) { throw new InvalidOperationException(string.Format("Heap {0} used {1} larger than available {2}", Name, used, Memory.Size)); } if (!Sealed) { var hash = br.ReadBytes(Memory.XorHash.Length); if (!hash.SequenceEqual(Memory.XorHash)) { throw new InvalidOperationException(string.Format("Hash did not match for heap {0}. Is this the same rom with the same SyncSettings?", Name)); } var usedAligned = WaterboxUtils.AlignUp(used); Memory.Protect(Memory.Start, Memory.Size, MemoryBlock.Protection.None); Memory.Protect(Memory.Start, used, MemoryBlock.Protection.RW); var ms = Memory.GetXorStream(Memory.Start, usedAligned, true); WaterboxUtils.CopySome(br.BaseStream, ms, (long)usedAligned); Used = used; } else { var hash = br.ReadBytes(_hash.Length); if (!hash.SequenceEqual(_hash)) { throw new InvalidOperationException(string.Format("Hash did not match for heap {0}. Is this the same rom with the same SyncSettings?", Name)); } } }
public void SaveStateBinary(BinaryWriter bw) { bw.Write(Name); bw.Write(Memory.Size); bw.Write(Used); bw.Write(Memory.XorHash); bw.Write(_pagesAsBytes); Memory.Protect(Memory.Start, Memory.Size, MemoryBlockBase.Protection.R); var srcs = Memory.GetXorStream(Memory.Start, Memory.Size, false); for (int i = 0, addr = 0; i < _pages.Length; i++, addr += WaterboxUtils.PageSize) { if (_pages[i] != FREE) { srcs.Seek(addr, SeekOrigin.Begin); WaterboxUtils.CopySome(srcs, bw.BaseStream, WaterboxUtils.PageSize); } } bw.Write(MAGIC); RefreshAllProtections(); }