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.MemoryManipulator(*args: Any, **kwargs: Any)#

Handle reads and writes to the game process memory.

The MemoryManipulator wraps pymem functions for memory read and writes. It manages the game memory pointers, address resolving and decoding.

clear_cache()#

Clear the reference look-up cache of the memory manipulator.

The MemoryManipulator caches 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!

resolve_address(addr_offsets: list[int], base: int) int#

Resolve an address by its offsets and a base.

Looks up the address cache first.

Warning

Can’t detect an invalid cache, this is the user’s responsibility!

Parameters
  • addr_offsets – The offsets which will be resolved iteratively. The first offset is the offset to the base itself.

  • base – The base offset from the start of the program’s memory.

Returns

The resolved address.

Raises

pym.exception.MemoryReadError – An error with the memory read occured.

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.