core.memory_manipulator#
The memory_manipulator module is a wrapper around pymem for memory read and write access.
It implements some of the basic CheatEngine functionalities in Python. The game is controlled by changing the values of ingame properties in the process memory. We cannot write to static memory addresses since the process memory layout is dynamic and changes every time the game loads. Memory locations are given as chains of pointers instead which we have to resolve to get the current address for each attribute. These pointer chains were largely copied from available Dark Souls III cheat tables.
Note
Not all game properties of interest were included in the cheat tables. Some values and their pointer chains were determined by us and are by no means guaranteed to be stable. Please report any memory read or write error to help us identify unstable pointer chains!
Warning
We cache resolved pointer chains to increase read and write access times. This requires manual
cache clearing. For details see MemoryManipulator.clear_cache().
The MemoryManipulator is writing from an external process to a memory region in use by the game
process. You will see race conditions during writing, particularly for values with high frequency
writes in the game loop (e.g. coordinates). Be sure to include checks if writes were successful and
have taken effect in the game when you write to these memory locations.
- class soulsgym.core.memory_manipulator.AddressRecord#
Bases:
TypedDictType definition for an address record.
- class soulsgym.core.memory_manipulator.MemoryManipulator(*args: Any, **kwargs: Any)#
Bases:
objectHandle reads and writes to the game process memory.
The
MemoryManipulatorwrapspymemfunctions for memory read and writes. It manages the game memory pointers, address resolving and decoding.- __init__(process_name: str = 'DarkSoulsIII.exe')#
Initialize the cache and pointer attributes.
If the game is not open, the pointer values can’t be inferred which causes an exception.
- Parameters:
process_name – The target process name. Should always be DarkSoulsIII.exe, unless the app name changes.
- resolve_record(record: AddressRecord) int#
Resolve an address record by following its pointer chain to the final address.
Resolved addresses are cached to increase performance. If the program reallocates memory, the cached addresses are no longer valid and the cache has to be cleared.
Warning
Can’t detect an invalid cache, this is the user’s responsibility!
- Parameters:
record – The address record. Address records must contain at least the base and offsets keys.
- Returns:
The resolved address.
- clear_cache()#
Clear the reference look-up cache of the memory manipulator.
The
MemoryManipulatorcaches all pointer chains it resolves to speed up the reads and writes. If the game reloads, these addresses are no longer guaranteed to be valid and the address cache has to be cleared in order to resolve the new addresses of all values. Cache validation by reading the player death count is omitted since it incurs additional overhead for read operations and offsets any performance gains made by using an address cache.Warning
We do not validate the cache before reading from a cached address! It is the users’s responsibility to clear the cache on reload!
- read_record(record: AddressRecord) int | float | str | bytes#
Resolve the record address and read the value into the hinted type.
- Parameters:
record – The address record.
- Returns:
The read value.
- write_record(record: AddressRecord, value: int | float | bytes)#
Resolve the record address and write the value to the address.
The provided value has to match the type hint of the record.
Note
We support reading string records, but not writing them.
- Parameters:
record – The address record.
value – The value to write. Type has to match the type hint of the record.
- read_int(address: int) int#
Read an integer from memory.
- Parameters:
address – The read address.
- Returns:
The integer value.
- Raises:
pym.exception.MemoryReadError – An error with the memory read occured.
- read_float(address: int) float#
Read a float from memory.
- Parameters:
address – The read address.
- Returns:
The float value.
- Raises:
pym.exception.MemoryReadError – An error with the memory read occured.
- read_string(address: int, length: int, null_term: bool = True, codec: str = 'utf-16') str#
Read a string from memory.
- Parameters:
address – The read address.
length – The expected (maximum) string length.
null_term – String should be cut after double 0x00.
codec – The codec used to decode the bytes.
- Returns:
The string.
- Raises:
pym.exception.MemoryReadError – An error with the memory read occured.
UnicodeDecodeError – An error with the decoding of the read bytes occured.
- read_bytes(address: int, length: int) bytes#
Read raw bytes from memory.
- Parameters:
address – The read address.
length – The bytes length.
- Returns:
The raw bytes.
- Raises:
pym.exception.MemoryReadError – An error with the memory read occured.
- write_bit(address: int, index: int, value: int)#
Write a single bit.
- Parameters:
address – The write address.
index – The index of the bit (0 … 7).
value – The value of the bit (0/1).
- Raises:
pym.exception.MemoryWriteError – An error with the memory write occured.
- write_int(address: int, value: int)#
Write an integer to memory.
- Parameters:
address – The write address.
value – The value of the integer.
- Raises:
pym.exception.MemoryWriteError – An error with the memory write occured.
- write_float(address: int, value: float)#
Write a float to memory.
- Parameters:
address – The write address.
value – The value of the float.
- Raises:
pym.exception.MemoryWriteError – An error with the memory write occured.
- write_bytes(address: int, buffer: bytes)#
Write a series of bytes to memory.
- Parameters:
address – The write address for the first byte.
buffer – The bytes.
- Raises:
pym.exception.MemoryWriteError – An error with the memory write occured.