public MagicManager(Process process, int[] romPtrBaseSuggestions, int[] ramPtrBaseSuggestions, int offset) { GC.Collect(); this.process = process; bool isRomFound = false; bool isRamFound = false; foreach (uint romPtrBaseSuggestion in romPtrBaseSuggestions) { romPtrBase = romPtrBaseSuggestion; if (IsRomBaseValid()) { isRomFound = true; break; } } foreach (uint ramPtrBaseSuggestion in ramPtrBaseSuggestions) { ramPtrBase = ramPtrBaseSuggestion; if (IsRamBaseValid()) { isRamFound = true; break; } } long MaxAddress = 0xffffffff; long address = 0; do { if (isRomFound && isRamFound) { break; } MEMORY_BASIC_INFORMATION m; int result = VirtualQueryEx(process.Handle, new UIntPtr((uint)address), out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); if (address == (long)m.BaseAddress + (long)m.RegionSize || result == 0) { break; } if (m.AllocationProtect != 0) { bool readSuccess = process.ReadValue(new IntPtr(address + offset), out uint value); if (readSuccess) { if (!isRamFound && ((value & ramMagicMask) == ramMagic)) { ramPtrBase = (uint)(address + offset); isRamFound = true; } if (!isRomFound && value == romMagic) { romPtrBase = (uint)(address + offset); isRomFound = true; } } } address = (long)m.BaseAddress + (long)m.RegionSize; }while (address <= MaxAddress); if (!isRomFound || !isRamFound) { throw new ArgumentException("Failed to find rom and ram!"); } uint[] mem; { byte[] bytes = process.ReadBytes(new IntPtr(ramPtrBase), 0x400000); int size = bytes.Count() / 4; mem = new uint[size]; for (int idx = 0; idx < size; idx++) { mem[idx] = BitConverter.ToUInt32(bytes, 4 * idx); } } DecompManager dm = new DecompManager(mem); if (!dm.gSaveBuffer.HasValue) { throw new ArgumentException("Failed to gSaveBuffer!"); } saveBufferOffset = dm.gSaveBuffer.Value & 0xffffff; saveFileSize = dm.gSaveFileSize.Value; verificationBytes = dm.VerificationBytes; verificationOffset = dm.VerificationOffset.Value; isDecomp = saveBufferOffset != 0x207700; // TODO: This is inaccurate }
public MagicManager(Process process, long[] romPtrBaseSuggestions, long[] ramPtrBaseSuggestions, int offset, bool exScan) { GC.Collect(); this.process = process; bool isRomFound = false; bool isRamFound = false; foreach (uint romPtrBaseSuggestion in romPtrBaseSuggestions) { romPtrBase = romPtrBaseSuggestion; if (IsRomBaseValid()) { isRomFound = true; break; } } foreach (uint ramPtrBaseSuggestion in ramPtrBaseSuggestions) { ramPtrBase = ramPtrBaseSuggestion; if (IsRamBaseValid()) { isRamFound = true; break; } } ulong parallelStart = 0; ulong parallelEnd = 0; foreach (ProcessModule module in process.Modules) { if (module.ModuleName.Contains("parallel_n64")) { parallelStart = (ulong)module.BaseAddress; parallelEnd = parallelStart + (ulong)module.ModuleMemorySize; } } ulong MaxAddress = process.Is64Bit() ? 0x800000000000U : 0xffffffffU; ulong address = 0; do { if (isRomFound && isRamFound) { break; } MEMORY_BASIC_INFORMATION m; int result = VirtualQueryEx(process.Handle, new UIntPtr(address), out m, (uint)Marshal.SizeOf(typeof(MEMORY_BASIC_INFORMATION))); if (address == (ulong)m.BaseAddress + (ulong)m.RegionSize || result == 0) { break; } AllocationProtect prot = (AllocationProtect)(m.Protect & 0xff); if (prot == AllocationProtect.PAGE_EXECUTE_READWRITE || prot == AllocationProtect.PAGE_EXECUTE_WRITECOPY || prot == AllocationProtect.PAGE_READWRITE || prot == AllocationProtect.PAGE_WRITECOPY || prot == AllocationProtect.PAGE_READONLY) { uint value; bool readSuccess = process.ReadValue(new IntPtr((long)(address + (ulong)offset)), out value); if (readSuccess) { if (!isRamFound && ((value & ramMagicMask) == ramMagic)) { ramPtrBase = address + (ulong)offset; isRamFound = true; } if (!isRomFound && value == romMagic) { romPtrBase = address + (ulong)offset; isRomFound = true; } } // scan only large regions - we want to find g_rdram ulong regionSize = (ulong)m.RegionSize; if (parallelStart <= address && address <= parallelEnd && regionSize >= 0x800000) { // g_rdram is aligned to 0x1000 ulong maxCnt = (ulong)m.RegionSize / 0x1000; for (ulong num = 0; num < maxCnt; num++) { readSuccess = process.ReadValue(new IntPtr((long)(address + num * 0x1000)), out value); if (readSuccess) { if (!isRamFound && ((value & ramMagicMask) == ramMagic)) { ramPtrBase = address + num * 0x1000; isRamFound = true; } } if (isRamFound) { break; } } } } address = (ulong)m.BaseAddress + (ulong)m.RegionSize; }while (address <= MaxAddress); if (!isRomFound || !isRamFound) { throw new ArgumentException("Failed to find rom and ram!"); } uint[] mem; { byte[] bytes = process.ReadBytes(new IntPtr((long)ramPtrBase), 0x400000); int size = bytes.Count() / 4; mem = new uint[size]; for (int idx = 0; idx < size; idx++) { mem[idx] = BitConverter.ToUInt32(bytes, 4 * idx); } } DecompManager dm = new DecompManager(mem); if (!dm.gSaveBuffer.HasValue) { throw new ArgumentException("Failed to gSaveBuffer!"); } saveBufferOffset = dm.gSaveBuffer.Value & 0xffffff; saveFileSize = dm.gSaveFileSize.Value; verificationBytes = dm.VerificationBytes; verificationOffset = dm.VerificationOffset.Value; isDecomp = saveBufferOffset != 0x207700; // TODO: This is inaccurate }