Beispiel #1
0
        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?");
                }
            }
        }
Beispiel #2
0
        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();
            }
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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();
        }
Beispiel #6
0
 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);
             }
         }
     }
 }
Beispiel #7
0
        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));
                }
            }
        }
Beispiel #8
0
        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();
        }