pikmin2/ptr_checker.py
EpochFlame 8d29c1f6ea Initial commit
Squashed all of the commits thus far that have been miscellaneous tweaks and small changes to fix the original repo that have had nothing to do with the decompilation itself.

Co-Authored-By: EpochFlame <82550703+EpochFlame@users.noreply.github.com>
2021-09-27 21:57:49 +01:00

207 lines
7.3 KiB
Python

#!/usr/bin/env python3
# ====================================
# Ptr checker v0.0.9 (by RevoSucks)
# ====================================
# WARNING, seriously, get a puke bucket. This is just a file i am writing for my own sole use.
# If you want to use it, I have some advice for you: D.O.N.T.
# It stands for dooooooonnnnnn't use it. Ever.
# ------------------
# Imports
# ------------------
import os, fnmatch, math
# ------------------
# Defines
# ------------------
# Path to baserom.dol
baserom_path = "baserom.dol"
map_path = "build/pikmin2.usa/pikmin2.map"
# ------------------
# Methods
# ------------------
# Return a list of searchable '.s' files in a given folder recursively.
def findExt(folder):
matches = []
for root, dirnames, filenames in os.walk(folder):
for filename in filenames:
if filename.endswith('.s'):
matches.append(os.path.join(root, filename))
#print(matches)
return matches
# Name is passed in as the address initially. If we cannot find it, return the string of the address.
def getMatchingTextSymbolFromAddress(name):
# Strip the 0x from the start.
#print("DEBUG: ", str(hex(name))[2:].zfill(8))
result = str(hex(name))[2:].zfill(8)
matches = [result, '(entry of ']
# First open the .map file.
map = open(map_path, 'r')
Lines = map.readlines()
# Parse over the map until a match is found.
for line in Lines:
# Does the line have the 2 expected strings?
if all(x in line for x in matches):
# We found the line.
#print("Match found! Line: ", line)
# Split the name out and return it.
return line.split(' ')[9]
# We're done, close it.
map.close()
return hex(name)
# Build a list of the pointers and scan each word.
def dumpVirtualTable(line):
# Init the table.
table = ""
# Open baserom.dol for processing.
f = open(baserom_path, 'rb')
address = line.split(' ')[2][:-1]
size = line.split(' ')[3]
#print("ADDR: ", address)
#print("SIZE: ", size)
f.seek(int(address, 16))
entries = int(size, 16) / 4
while entries != 0:
entry = int.from_bytes(f.read(4), byteorder='big')
if entry == 0:
str_to_print = "0"
elif (entry & 0xFF000000) == 0x80000000:
str_to_print = str(getMatchingTextSymbolFromAddress(entry))
else:
str_to_print = str(hex(entry))
table = table + " .4byte " + str_to_print + "\n"
entries = entries - 1
return table
def isBaseromEntrySus(line):
with open(baserom_path, 'rb') as f: # context management to close file for us
address = line.split(' ')[2][:-1]
size = line.split(' ')[3]
lower_four = 4 * math.floor(int(size, 16)/4) # Floor the size to the lower multiple of 4 if needed.
entries = int(size, 16) / 4
f.seek(int(address, 16))
while entries > 0:
entry = int.from_bytes(f.read(4), byteorder='big', signed=False)
if (entry & 0xFF000000) == 0x80000000 and entry != 0x80000000:
print("Suspicious Ptr: ", str(hex(entry)))
return True
entries -= 1
return False
# Same as isBaseromEntrySus but check for rodata str. Man this file is a mess.
def isBaseromEntrySus_ShouldDump(line):
with open(baserom_path, 'rb') as f: # context management to close file for us
address = line.split(' ')[2][:-1]
size = line.split(' ')[3]
lower_four = 4 * math.floor(int(size, 16)/4) # Floor the size to the lower multiple of 4 if needed.
entries = int(size, 16) / 4
f.seek(int(address, 16))
while entries > 0:
entry = int.from_bytes(f.read(4), byteorder='big', signed=False)
if (entry & 0xFF000000) == 0x80000000 and entry != 0x80000000:
text_sym = getMatchingTextSymbolFromAddress(entry)
if text_sym != str(hex(entry)):
if text_sym[:2] == "$$":
return True
entries -= 1
return False
def isBaseromEntryPurePtrTable(line):
table = ""
with open(baserom_path, 'rb') as f: # context management to close file for us
address = line.split(' ')[2][:-1]
size = line.split(' ')[3]
lower_four = 4 * math.floor(int(size, 16)/4) # Floor the size to the lower multiple of 4 if needed.
entries = int(size, 16) / 4
f.seek(int(address, 16))
# If any values are neither 0 nor a
while entries > 0:
entry = int.from_bytes(f.read(4), byteorder='big', signed=False)
if entry == 0:
str_to_print = "0"
elif (entry & 0xFF000000) == 0x80000000:
str_to_print = getMatchingTextSymbolFromAddress(entry)
print("DEBUG: ", str_to_print)
elif entry == 0xFFFFFFFF:
str_to_print = "-1"
else:
return line # Not a pure pure table. Keep the entry.
if str_to_print[:2] == "0x":
return line # Not a pure pure table. Keep the entry.
table = table + " .4byte " + str_to_print + "\n"
entries = entries - 1
return table
def dumpActorTable(line):
table = ""
with open(baserom_path, 'rb') as f: # context management to close file for us
address = line.split(' ')[2][:-1]
size = line.split(' ')[3]
lower_four = 4 * math.floor(int(size, 16)/4) # Floor the size to the lower multiple of 4 if needed.
entries = int(size, 16) / 4
f.seek(int(address, 16))
# If any values are neither 0 nor a
while entries > 0:
entry = int.from_bytes(f.read(4), byteorder='big', signed=False)
if entry == 0:
str_to_print = "0"
elif (entry & 0xFF000000) == 0x80000000:
str_to_print = getMatchingTextSymbolFromAddress(entry)
print("DEBUG: ", str_to_print)
elif entry == 0xFFFFFFFF:
str_to_print = "-1"
else:
str_to_print = str(entry)
table = table + " .4byte " + str_to_print + "\n"
entries = entries - 1
return table
# -----------------------------------
# Config
# -----------------------------------
print_baserom_calls = True
# -----------------------------------
# ------------------
# Main code
# ------------------
asm_files = findExt("asm")
#asm_files = ['/c/sms/asm/NPC/NpcInitData.s']
print("Checking all files for possible ptrs...")
# Using readlines()
for i in asm_files:
file1 = open(i, 'r')
Lines = file1.readlines()
file1.close()
file1 = open(i, 'w')
count = 0
line_array = [] #array of current line and last two lines
line_array.append("")
line_array.append("")
line_array.append("")
file_sus = False
for line in Lines:
line_array[0] = line_array[1]
line_array[1] = line_array[2]
line_array[2] = line
# Do something with the line here. Does the line belong to a baserom.dol call for a __vt__?
if "__vt__" in line_array[1] and "baserom.dol" in line:
file1.write(dumpVirtualTable(line))
else:
file1.write(line)
if file_sus == True:
print("Sus: ", i, "Count: ", count, "\n")
file1.close()
print("Done")
#print(os.getcwd())