Skip to content

Instantly share code, notes, and snippets.

@RGamberini
Created December 7, 2019 03:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RGamberini/83abe0150d3687528d282f420757f310 to your computer and use it in GitHub Desktop.
Save RGamberini/83abe0150d3687528d282f420757f310 to your computer and use it in GitHub Desktop.
import ctypes
import time
from mem_edit import Process
from controller import refreshShop, getFocus, refreshMaronaCreate, buyPhantom, buyWeapon
import psutil
def findProcessIdByName(processName):
'''
Get a list of all the PIDs of a all the running process whose name contains
the given string processName
'''
listOfProcessObjects = []
# Iterate over the all the running process
for proc in psutil.process_iter():
try:
pinfo = proc.as_dict(attrs=['pid', 'name', 'create_time'])
# Check if process name contains the given name string.
if processName.lower() in pinfo['name'].lower():
listOfProcessObjects.append(pinfo)
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return listOfProcessObjects
def getTitleDatabase():
result = {}
with open('formatted.txt', 'r') as f:
for line in f.readlines():
info = list(map(str.strip, line.split(",")))
result[info[0]] = list(map(int, info[1:]))
return result
pid = findProcessIdByName("Phantom Brave PC.exe")[0]['pid'] # GOTTA HAVE THAT PID
titleDatabase = getTitleDatabase()
def getAscii(startAddr, size, count):
asciis = []
buffer = (ctypes.c_byte * size)() # CREATE A BYTE BUFFER
with Process.open_process(pid) as p:
for i in range(count):
p.read_memory(startAddr + (size * i), buffer)
asciiBuffer = []
for byte in buffer:
if byte != 0x00:
asciiBuffer.append(byte)
else:
break
asciis.append(asciiBuffer)
return asciis
def prettyPrintAsciis(asciis):
for i in range(len(asciis)):
print(i)
print("\t", end="")
print(list(map(hex, asciis[i])))
try:
print("\t", end="")
print("".join(map(chr, asciis[i])))
except:
print("\t", end="")
print("INDEX {0} DOES NOT WORK".format(i))
"""
FOR GETTING THE TITLES OF PHANTOMS IN MARONA'S CREATE
"""
def getCreateStartAddr():
"""
WE FIND THE STARTING ADDRESS I.E. THE ADDRESS OF THE FIRST PHANTOM'S TITLE
BY FIRST FINDING ALL THE MEMORY ADDRESSES CONTAINING 'Nameless Soul'
THEN FILTERING DOWN TO THE FIRST ADDRESS AFTER 0XC1BB0000
"""
toFind = ctypes.create_string_buffer(b"Nameless Soul")
with Process.open_process(pid) as p:
startAddr = list(filter(lambda x: x >0x1CBB0000, p.search_all_memory(toFind)))[0]
startAddr += 23
return startAddr
# MARONA_CREATE_STARTADDR = getCreateStartAddr()
MARONA_CREATE_STARTADDR = 0x0
def getTitles():
size = 2232
count = 21
startAddr = getCreateStartAddr()
prettyPrintAsciis(getAscii(startAddr, size, count))
def getCreatureTypes():
size = 58
startAddr = 0x27525724
count = 25
asciis = getAscii(startAddr, size, count)
# prettyPrintAsciis(getAscii(startAddr, size, count))
# ", ".join(list(map(chr, for ascii in asciis)))
# x = "\", \"".join(["".join(list(map(chr, ascii))) for ascii in asciis])
# print(x)
def findDarkWpn():
size = 720
startAddr = 0x00F27430
count = 15
asciis = getAscii(startAddr, size, count)
weapons = ["".join(list(map(chr, ascii))) for ascii in asciis]
found = False
for weapon in weapons:
if "Dark Wpn" in weapon:
found = True
print("FOUND ONE")
return False
if not found:
refreshShop()
return True
def findFailureTitle():
size = 2232
count = 21
startAddr = MARONA_CREATE_STARTADDR
asciis = getAscii(startAddr, size, count)
phantoms = ["".join(list(map(chr, ascii))) for ascii in asciis]
print(phantoms)
phantoms.pop(1)
for phantom in phantoms:
if "Failure" in phantom:
buyPhantom(phantoms.index(phantom))
return False
refreshMaronaCreate()
return True
def findBestTitle():
size = 720
startAddr = 0x00907430
count = 15
asciis = getAscii(startAddr, size, count)
weapons = ["".join(list(map(chr, ascii))) for ascii in asciis]
print(weapons)
for weapon in weapons:
if "Chief" in weapon or "Techno" in weapon:
print("Found a {0}".format(weapon))
buyWeapon(weapons.index(weapon))
refreshShop()
return False
else:
refreshShop()
return True
START = {
"ENEMY LV": 0x00DCBF2C,# MAGIC NUMBER FOUND IN CHEAT ENGINE BY SEARCHING FOR ENEMY LV
"FLOOR NUMBER": 0x00DCBF30,
"MAIN ENEMY": 0x00DCBF80,
"RELEVANT": 0x00DCBF52,
"END": 0x00DCBF7E
}
CREATURES = dict(zip(
range(1, 20),
["Male", "Female", "Feeble", "Puny", "Warrior", "Mage", "Artisan", "Beast", "Giant", "Creepy", "Horror", "Owl", "DemiMan", "Chibi", "Putty", "Slime", "Common", "Shroom", "Weird"]
))
CREATURES[33] = 'Variable'
def scrapeAllDungeonInfo():
"""
FOR SCRAPING MEMORY AROUND DUNGEON INFOBOX (BASED ON MEMORY POSITION OF ENEMY LV)
"""
size = START["END"] - START["ENEMY LV"]
buffer = (ctypes.c_ubyte * size)()
with Process.open_process(pid) as p:
with open("out.txt", 'w') as out:
name = ""
while name != "q":
name = input()
p.read_memory(START["RELEVANT"], buffer)
# print(name, end=" ")
# print(' '.join('{:02X}'.format(a) for a in buffer))
out.write(name)
out.write(' '.join('{:02X}'.format(a) for a in buffer))
out.write("\n")
# print(" ".join(list(map(hex, buffer))))
def getDungeonInfoBox():
addresses = (
("ENEMY LV", lambda n: n),
("FLOOR NUMBER", lambda n: n),
("MAIN ENEMY", lambda n: CREATURES[n])
)
buffer = (ctypes.c_ubyte * 1)()
with Process.open_process(pid) as p:
for address, func in addresses:
p.read_memory(START[address], buffer)
print("{0}: {1}".format(address, func(buffer[0])))
getFocus()
i = 0
# while i < 3:
# if not findFailureTitle():
# i += 1
# time.sleep(2.5)
# seq2 = ["ENTER", "S", "S", "ENTER"]
# pressSeq(seq2, delay=.2)
# while findBestTitle():
# continue
while i < 16:
if not findBestTitle():
i += 1
# refreshShop()
# findFailureTitle()
findBestTitle()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment