Faster memory access, pid skipping, file rename
This commit is contained in:
parent
eca1b2112b
commit
c8a33191cc
1 changed files with 33 additions and 128 deletions
|
@ -1,7 +1,9 @@
|
|||
import ctypes
|
||||
import struct
|
||||
from struct import pack, unpack
|
||||
from ctypes import wintypes, sizeof, addressof, POINTER, pointer
|
||||
from ctypes.wintypes import DWORD, ULONG, LONG, WORD
|
||||
from multiprocessing import shared_memory
|
||||
|
||||
# Various Windows structs/enums needed for operation
|
||||
NULL = 0
|
||||
|
@ -84,8 +86,8 @@ class PSAPI_WORKING_SET_EX_INFORMATION(ctypes.Structure):
|
|||
# print(i, getattr(self, i))
|
||||
|
||||
|
||||
# The following code is a port of aldelaro5's Dolphin memory access methods
|
||||
# for Windows into Python+ctypes.
|
||||
# The find_dolphin function is based on WindowsDolphinProcess::findPID() from
|
||||
# aldelaro5's Dolphin memory engine
|
||||
# https://github.com/aldelaro5/Dolphin-memory-engine
|
||||
|
||||
"""
|
||||
|
@ -114,12 +116,11 @@ SOFTWARE."""
|
|||
class Dolphin(object):
|
||||
def __init__(self):
|
||||
self.pid = -1
|
||||
self.handle = -1
|
||||
self.shmem = None
|
||||
|
||||
self.address_start = 0
|
||||
self.mem1_start = 0
|
||||
self.mem2_start = 0
|
||||
self.mem2_exists = False
|
||||
def reset(self):
|
||||
self.pid = -1
|
||||
self.memory = None
|
||||
|
||||
def find_dolphin(self, skip_pids=[]):
|
||||
entry = PROCESSENTRY32()
|
||||
|
@ -130,7 +131,6 @@ class Dolphin(object):
|
|||
a = ULONG(addressof(entry))
|
||||
|
||||
self.pid = -1
|
||||
self.handle = -1
|
||||
|
||||
if ctypes.windll.kernel32.Process32First(snapshot, pointer(entry)):
|
||||
if entry.th32ProcessID not in skip_pids and entry.szExeFile in (b"Dolphin.exe", b"DolphinQt2.exe", b"DolphinWx.exe"):
|
||||
|
@ -148,108 +148,36 @@ class Dolphin(object):
|
|||
if self.pid == -1:
|
||||
return False
|
||||
|
||||
self.handle = ctypes.windll.kernel32.OpenProcess(
|
||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE,
|
||||
False, self.pid)
|
||||
|
||||
return True
|
||||
|
||||
def get_emu_info(self):
|
||||
info = MEMORY_BASIC_INFORMATION()
|
||||
MEM1_found = False
|
||||
|
||||
p = NULL
|
||||
|
||||
while ctypes.windll.kernel32.VirtualQueryEx(self.handle, ctypes.c_void_p(p), pointer(info), sizeof(info)) == sizeof(info):
|
||||
|
||||
p += info.RegionSize
|
||||
|
||||
if info.RegionSize == 0x4000000:
|
||||
region_base_address = info.BaseAddress
|
||||
|
||||
if MEM1_found and info.BaseAddress > self.address_start + 0x10000000:
|
||||
break
|
||||
|
||||
page_info = PSAPI_WORKING_SET_EX_INFORMATION()
|
||||
page_info.VirtualAddress = info.BaseAddress
|
||||
|
||||
if ctypes.windll.psapi.QueryWorkingSetEx(
|
||||
self.handle,
|
||||
pointer(page_info),
|
||||
sizeof(PSAPI_WORKING_SET_EX_INFORMATION)
|
||||
):
|
||||
if (page_info.Valid):
|
||||
self.mem2_start = region_base_address
|
||||
self.mem2_exists = True
|
||||
|
||||
elif not MEM1_found and info.RegionSize == 0x2000000 and info.Type == MEM_MAPPED:
|
||||
page_info = PSAPI_WORKING_SET_EX_INFORMATION()
|
||||
page_info.VirtualAddress = info.BaseAddress
|
||||
|
||||
if ctypes.windll.psapi.QueryWorkingSetEx(
|
||||
self.handle,
|
||||
pointer(page_info),
|
||||
sizeof(PSAPI_WORKING_SET_EX_INFORMATION)
|
||||
):
|
||||
print(page_info.Valid)
|
||||
if (page_info.Valid):
|
||||
self.address_start = info.BaseAddress
|
||||
MEM1_found = True
|
||||
|
||||
if MEM1_found and self.mem2_exists:
|
||||
break
|
||||
|
||||
if self.address_start == 0:
|
||||
return False
|
||||
|
||||
return True
|
||||
def init_shared_memory(self):
|
||||
self.mem = shared_memory.SharedMemory('dolphin-emu.'+str(self.pid))
|
||||
|
||||
def read_ram(self, offset, size):
|
||||
buffer = (ctypes.c_char*size)()
|
||||
read = ctypes.c_ulong(0)
|
||||
|
||||
result = ctypes.windll.kernel32.ReadProcessMemory(
|
||||
self.handle,
|
||||
ctypes.c_void_p(self.address_start+offset),
|
||||
ctypes.pointer(buffer),
|
||||
size,
|
||||
ctypes.pointer(read))
|
||||
return result and read.value == size, buffer
|
||||
return self.mem.buf[offset:offset+size]
|
||||
|
||||
def write_ram(self, offset, data):
|
||||
buffer = (ctypes.c_char*len(data))(*data)
|
||||
read = ctypes.c_ulong(0)
|
||||
|
||||
result = ctypes.windll.kernel32.WriteProcessMemory(
|
||||
self.handle,
|
||||
ctypes.c_void_p(self.address_start+offset),
|
||||
ctypes.pointer(buffer),
|
||||
len(data),
|
||||
ctypes.pointer(read))
|
||||
|
||||
return result and read.value == len(data)
|
||||
self.mem.buf[offset:offset+len(data)] = data
|
||||
|
||||
def read_uint32(self, addr):
|
||||
assert addr >= 0x80000000
|
||||
success, value = self.read_ram(addr-0x80000000, 4)
|
||||
value = self.read_ram(addr-0x80000000, 4)
|
||||
|
||||
if success:
|
||||
return struct.unpack(">I", value)[0]
|
||||
else:
|
||||
return None
|
||||
return unpack(">I", value)[0]
|
||||
|
||||
def write_uint32(self, addr, val):
|
||||
assert addr >= 0x80000000
|
||||
return self.write_ram(addr - 0x80000000, pack(">I", val))
|
||||
|
||||
def read_float(self, addr):
|
||||
assert addr >= 0x80000000
|
||||
success, value = self.read_ram(addr - 0x80000000, 4)
|
||||
|
||||
if success:
|
||||
return struct.unpack(">f", value)[0]
|
||||
else:
|
||||
return None
|
||||
return unpack(">f", value)[0]
|
||||
|
||||
def write_float(self, addr, val):
|
||||
assert addr >= 0x80000000
|
||||
return self.write_ram(addr - 0x80000000, struct.pack(">f", val))
|
||||
return self.write_ram(addr - 0x80000000, pack(">f", val))
|
||||
|
||||
|
||||
"""with open("ctypes.txt", "w") as f:
|
||||
|
@ -267,54 +195,31 @@ if __name__ == "__main__":
|
|||
else:
|
||||
print("Didn't find Dolphin")
|
||||
|
||||
print(dolphin.pid, dolphin.handle)
|
||||
"""pipe = r'\\.\\PIPE\\dolphin-emu.'+str(dolphin.pid)
|
||||
pipe = r'\\.\\pipe\\WiFiNetworkManagerTask'
|
||||
print(pipe)
|
||||
|
||||
with open(pipe, "r+b") as f:
|
||||
pass"""
|
||||
|
||||
print(dolphin.pid)
|
||||
|
||||
dolphin.init_shared_memory()
|
||||
"""
|
||||
if dolphin.get_emu_info():
|
||||
print("We found MEM1 and/or MEM2!", dolphin.address_start, dolphin.mem2_start)
|
||||
else:
|
||||
print("We didn't find it...")
|
||||
print("We didn't find it...")"""
|
||||
|
||||
import random
|
||||
|
||||
randint = random.randint
|
||||
from timeit import default_timer
|
||||
|
||||
start = default_timer()
|
||||
|
||||
randint = random.randint
|
||||
pack = struct.pack
|
||||
unpack = struct.unpack
|
||||
write_ram = dolphin.write_ram
|
||||
read_ram = dolphin.read_ram
|
||||
|
||||
print("Testing WinApi method")
|
||||
for i in range(500000):
|
||||
value = randint(0, 2**32-1)
|
||||
write_ram(0, pack(">I", value))
|
||||
|
||||
success, result = read_ram(0, 4)
|
||||
assert unpack(">I", result)[0] == value
|
||||
|
||||
print(default_timer()-start)
|
||||
|
||||
from multiprocessing import shared_memory
|
||||
mem = shared_memory.SharedMemory('dolphin-emu.'+str(dolphin.pid))
|
||||
buf = mem.buf
|
||||
|
||||
print("Testing Shared Memory Method")
|
||||
start = default_timer()
|
||||
for i in range(500000):
|
||||
count = 500000
|
||||
for i in range(count):
|
||||
value = randint(0, 2**32-1)
|
||||
buf[0:4] = pack(">I", value)
|
||||
dolphin.write_uint32(0x80000000, value)
|
||||
|
||||
result = bytes(buf[0:4])
|
||||
assert unpack(">I", result)[0] == value
|
||||
|
||||
print(default_timer()-start)
|
||||
result = dolphin.read_uint32(0x80000000)
|
||||
assert result == value
|
||||
diff = default_timer()-start
|
||||
print(count/diff, "per sec")
|
||||
print("time: ", diff)
|
||||
|
Loading…
Reference in a new issue