summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
authorcleartonic <cleartonic@gmail.com>2019-11-01 11:34:32 -0500
committercleartonic <cleartonic@gmail.com>2019-11-01 11:34:32 -0500
commite1491cf4c5b9a97a24c8c2b083a710c1afa97b8b (patch)
treebf1ae8f0a5ee9032532bdda8140420546e736d31 /util
parentbdd1cd04b6dd0636663229c2c6b542c7f7fef6ed (diff)
static pokemon: add limit 600 bst. add log distribution analyzer. fix settings for static pokemon
Diffstat (limited to 'util')
-rw-r--r--util/analyze_distribution.py83
-rw-r--r--util/narcparser.py660
-rw-r--r--util/ref/bw2_trainers.txt473
-rw-r--r--util/ref/bw_trainers.txt370
4 files changed, 1256 insertions, 330 deletions
diff --git a/util/analyze_distribution.py b/util/analyze_distribution.py
new file mode 100644
index 0000000..69eed84
--- /dev/null
+++ b/util/analyze_distribution.py
@@ -0,0 +1,83 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Fri Nov 1 09:53:43 2019
+
+@author: cleartonic
+"""
+
+import pandas as pd
+import os
+pd.options.display.max_rows = 999
+THIS_FILENAME = os.path.basename(__file__)
+THIS_PATHNAME = os.path.dirname(__file__)
+
+'''
+For this script, drop in a log file for either bw1 or bw2
+Into the log subdirectory relative to this file
+Name the file "bw.log" or "bw2.log"
+
+Argument for bw or bw2 to pass in, default bw
+
+Returns a dataframe sorted by Pokemon count
+Use "df" in console, or methods such as "df.head()" "df.describe()"
+
+There are some pokemon outliers at the top of the lists,
+solely because of rivals having similar Pokemon (they are excluded from placement history, but
+appear in the main game)
+'''
+
+if not os.path.exists(os.path.join("log")):
+ os.mkdir(os.path.join("log"))
+
+
+def analyze(version='bw'):
+ if not (version == 'bw' or version == 'bw2'):
+ print("Error on version")
+ else:
+ with open(os.path.join(THIS_PATHNAME,'ref','%s_trainers.txt' % version),'r') as file:
+ data = file.readlines()
+ bw2_ref = [x.strip() for x in data]
+
+ with open(os.path.join(THIS_PATHNAME,'log','%s.log' % version),'r') as file:
+ data = file.readlines()
+
+ idx = data.index("--Trainers Pokemon--\n")
+ if version == 'bw':
+ data = data[idx:idx+616]
+ if version == 'bw2':
+ data = data[idx:idx+816]
+
+ log_trainers = [x.strip() for x in data]
+
+
+
+ poke_dict = {}
+ for x in log_trainers:
+ try:
+ num = x.split(" (")[0].replace("#","")
+ if num in bw2_ref:
+ temp = x.split(") - ")[1].split(", ")
+ pokes = [x.split(" Lv")[0].strip() for x in temp]
+
+ for poke in pokes:
+ if poke in poke_dict:
+ poke_dict[poke] = poke_dict[poke] + 1
+ else:
+ poke_dict[poke] = 1
+ except:
+ pass
+
+ df = pd.DataFrame(poke_dict,index=[0]).T
+ df.columns = ['num']
+ df = df.sort_values(by='num',ascending=False)
+ return df
+
+print('''This script will take a log file and output a dataframe sorted by main trainer Pokemon distribution.
+ For this script, drop in a log file in this directory for either bw1 or bw2, name the file "bw.log" or "bw2.log"''')
+try:
+ version = input("Input version, either bw or bw2\n")
+ df = analyze(version)
+ print(df)
+ print("Number of Pokemon: %s" % (df.shape[0]))
+except:
+ print("Error, put in proper version & make sure log file is present & named correctly.") \ No newline at end of file
diff --git a/util/narcparser.py b/util/narcparser.py
index a14548d..7c7d0de 100644
--- a/util/narcparser.py
+++ b/util/narcparser.py
@@ -1,331 +1,331 @@
-import argparse, sys, os
-
-def main():
- try:
- with open(sys.argv[1],"rb") as f:
- word = f.read(4)
- while word != b'BTAF':
- word = f.read(4)
- table_length = read_word(f)
- file_count = read_word(f)
- file_offsets = []
- for i in range(file_count):
- file_offsets.append(read_word(f))
- f.seek(4,os.SEEK_CUR)
- print(str(i) + ": ",end='')
- print_hex_word(file_offsets[i])
- f.seek(-4,os.SEEK_CUR)
- file_offsets.append(read_word(f))
- word = f.read(4)
- while word != b'GMIF':
- word = f.read(4)
- file_table_length = read_word(f)
- file_table_offset = f.tell()
- print("File table length: ",end='')
- print_hex_word(file_table_length)
- print("File table offset: ",end='')
- print_hex_word(file_table_offset)
- readline = ""
- print("Ready to search. Enter help for list of commands")
- while readline != "quit":
- readline = input('Enter command: ')
- args = readline.split()
- if args[0] == "help":
- list_commands()
- elif args[0] == "sr": # Search
- if len(args) < 2:
- print("Usage: sr x")
- print("x should be a hexadecimal number")
- else:
- if args[1][:2] == "0x":
- target = int(args[1][2:],16)
- else:
- target = int(args[1],16)
- upper_byte = 0
- if target % 2**32 > 2**8:
- upper_byte = target >> 8
- target = target & 0xFF
- for i in range(file_count):
- f.seek(file_table_offset + file_offsets[i])
- local_offset_in_file = read_word(f)
- first_global_offset = f.tell() + local_offset_in_file
- while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
- offset_in_file = f.tell() + local_offset_in_file
- return_position = f.tell()
- f.seek(offset_in_file)
- data = 0
- while data != 0x02002F and f.tell() < file_table_offset + file_offsets[i+1]:
- data = read_byte(f)
- if data == target:
- if upper_byte == 0:
- print("Found target value in file " + str(i) + " at offset ",end='')
- print_hex_word(f.tell())
- else:
- data = read_byte(f)
- f.seek(-1,os.SEEK_CUR)
- if data == upper_byte:
- print("Found target value in file " + str(i) + " at offset ",end='')
- print_hex_word(f.tell())
- if data == 0x2F:
- f.seek(-1,os.SEEK_CUR)
- data = read_word(f)
- if data != 0x02002F:
- f.seek(-3,os.SEEK_CUR)
- f.seek(return_position)
- local_offset_in_file = read_word(f)
- elif args[0] == "msr": # Multiple search
- if len(args) < 2:
- print("Usage: msr x [y z ...]")
- print("x, y, z ... should be hexadecimal numbers")
- else:
- target = []
- upper_byte = []
- for i in range(1,len(args)):
- if args[i][:2] == "0x":
- target.append(int(args[i][2:],16))
- else:
- target.append(int(args[i],16))
- if target[i-1] % 2**32 > 2**8:
- upper_byte.append(target[i-1] >> 8)
- target[i-1] = target[i-1] & 0xFF
- else:
- upper_byte.append(0)
- for i in range(file_count):
- found_in_file = []
- f.seek(file_table_offset + file_offsets[i])
- local_offset_in_file = read_word(f)
- first_global_offset = f.tell() + local_offset_in_file
- while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
- offset_in_file = f.tell() + local_offset_in_file
- return_position = f.tell()
- f.seek(offset_in_file)
- data = 0
- while data != 0x02002F and f.tell() < file_table_offset + file_offsets[i+1]:
- data = read_byte(f)
- for j,t in enumerate(target):
- if data == t:
- if upper_byte[j] == 0:
- found_in_file.append((t,f.tell()))
- else:
- data = read_byte(f)
- f.seek(-1,os.SEEK_CUR)
- if data == upper_byte[j]:
- found_in_file.append((t + (upper_byte[j] << 8),f.tell()-1))
- if data == 0x2F:
- f.seek(-1,os.SEEK_CUR)
- data = read_word(f)
- if data != 0x02002F:
- f.seek(-3,os.SEEK_CUR)
- f.seek(return_position)
- local_offset_in_file = read_word(f)
- if len(found_in_file) >= 1:
- target_copy = target.copy()
- for (val,_) in found_in_file:
- for j,t in enumerate(target_copy):
- if val == t + (upper_byte[j] << 8):
- target_copy.remove(t)
- if len(target_copy) == 0:
- print("Found in file " + str(i) + ": ")
- for (val,offset) in found_in_file:
- print_hex(val,'')
- print(" at offset ",end='')
- print_hex_word(offset)
- elif args[0] == "rsr": # Raw search
- if len(args) < 2:
- print("Usage: rsr x")
- print("x should be a hexadecimal number")
- else:
- if args[1][:2] == "0x":
- target = int(args[1][2:],16)
- else:
- target = int(args[1],16)
- upper_byte = 0
- if target % 2**32 > 2**8:
- upper_byte = target >> 8
- target = target & 0xFF
- for i in range(file_count):
- f.seek(file_table_offset + file_offsets[i])
- while f.tell() < file_table_offset + file_offsets[i+1]:
- data = read_byte(f)
- if data == target:
- if upper_byte == 0:
- print("Found target value in file " + str(i) + " at offset ",end='')
- print_hex_word(f.tell())
- else:
- data = read_byte(f)
- f.seek(-1,os.SEEK_CUR)
- if data == upper_byte:
- print("Found target value in file " + str(i) + " at offset ",end='')
- print_hex_word(f.tell())
- elif args[0] == "rmsr": # Raw multiple search
- if len(args) < 2:
- print("Usage: rmsr x [y z ...]")
- print("x, y, z ... should be hexadecimal numbers")
- else:
- target = []
- upper_byte = []
- for i in range(1,len(args)):
- if args[i][:2] == "0x":
- target.append(int(args[i][2:],16))
- else:
- target.append(int(args[i],16))
- if target[i-1] % 2**32 > 2**8:
- upper_byte.append(target[i-1] >> 8)
- target[i-1] = target[i-1] & 0xFF
- else:
- upper_byte.append(0)
- for i in range(file_count):
- found_in_file = []
- f.seek(file_table_offset + file_offsets[i])
- while f.tell() < file_table_offset + file_offsets[i+1]:
- data = read_byte(f)
- for j,t in enumerate(target):
- if data == t:
- if upper_byte[j] == 0:
- found_in_file.append((t,f.tell()))
- else:
- data = read_byte(f)
- f.seek(-1,os.SEEK_CUR)
- if data == upper_byte[j]:
- found_in_file.append((t + (upper_byte[j] << 8),f.tell()-1))
- if len(found_in_file) >= 1:
- target_copy = target.copy()
- for (val,_) in found_in_file:
- for j,t in enumerate(target_copy):
- if val == t + (upper_byte[j] << 8):
- target_copy.remove(t)
- if len(target_copy) == 0:
- print("Found in file " + str(i) + ": ")
- for (val,offset) in found_in_file:
- print_hex(val,'')
- print(" at offset ",end='')
- print_hex_word(offset)
- elif args[0] == "lsf": # List file
- if len(args) < 2:
- print("Usage: lsf fileno")
- else:
- print("Searching file " + args[1] + "!")
- f.seek(file_table_offset + file_offsets[int(args[1])])
- local_offset_in_file = read_word(f)
- first_global_offset = f.tell() + local_offset_in_file
- while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
- offset_in_file = f.tell() + local_offset_in_file
- print("Relative offset: 0x" + '%X' % local_offset_in_file + " read at 0x" + '%X' % (f.tell() - 4),end='')
- print(", global offset: 0x" + '%X' % offset_in_file)
- return_position = f.tell()
- f.seek(offset_in_file)
- data = 0
- while data != 0x02002F and f.tell() < file_table_offset + file_offsets[int(args[1])+1]:
- data = read_byte(f)
- print_hex_byte(data,'','')
- print(' ',end='')
- if data == 0x2F:
- f.seek(-1,os.SEEK_CUR)
- data = read_word(f)
- if data == 0x02002F:
- print_hex_byte(0x00,'','')
- print(' ',end='')
- print_hex_byte(0x02,'','')
- print(' ',end='')
- print_hex_byte(0x00,'','')
- print(' ',end='')
- else:
- print_hex_byte(0x2F,'','')
- print(' ',end='')
- f.seek(-3,os.SEEK_CUR)
- print("\n")
- f.seek(return_position)
- local_offset_in_file = read_word(f)
- elif args[0] == "fof": # File offset
- if len(args) < 2:
- print("Usage: fof fileno")
- else:
- print("Offset for file " + args[1] + ": 0x" + '%X' % (file_table_offset + file_offsets[int(args[1])]))
- elif args[0] == "srs": # Search static
- if len(args) < 2:
- print("Usage: srs index")
- else:
- if args[1][:2] == "0x":
- target = int(args[1][2:],16)
- else:
- target = int(args[1],16)
- for i in range(file_count):
- f.seek(file_table_offset + file_offsets[i])
- local_offset_in_file = read_word(f)
- first_global_offset = f.tell() + local_offset_in_file
- while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
- offset_in_file = f.tell() + local_offset_in_file
- return_position = f.tell()
- f.seek(offset_in_file)
- data = 0
- while data != 0x02002F and f.tell() < file_table_offset + file_offsets[i+1]:
- data = read_byte(f)
- if data == 0x2A:
- f.seek(-1,os.SEEK_CUR)
- data = read_word(f)
- if data == 0x8000002A:
- item = read_halfword(f)
- if item == target:
- print("Found item in file " + str(i) + " at offset 0x" + '%X' % (f.tell() - 2))
- else:
- f.seek(-3,os.SEEK_CUR)
- if data == 0x2F:
- f.seek(-1,os.SEEK_CUR)
- data = read_word(f)
- if data != 0x02002F:
- f.seek(-3,os.SEEK_CUR)
- f.seek(return_position)
- local_offset_in_file = read_word(f)
- elif args[0] == "lsai": # List all items
- if len(args) == 3:
- range_start = int(args[1],16)
- range_end = int(args[2],16) # 6A1564C
- else:
- range_start = 0
- range_end = file_count
- with open("itemprices.txt","w") as it:
- for i in range(range_start, range_end):
- f.seek(file_table_offset + file_offsets[i])
- it.write("{" + str(i) + ", " + str(int.from_bytes(f.read(2),byteorder='little')) + "},\n")
- #print("Item 0x" + '%X' % i + " price: " + str(int.from_bytes(f.read(2),byteorder='little') * 10))
- except IndexError:
- print("Error: No file specified")
- sys.exit(2)
- except IOError:
- print("Error: File does not exist")
- sys.exit(2)
-
-def list_commands():
- print("")
- print("List of commands:")
- print(" help: You are here")
- print(" sr: Search for a single hex value")
- print(" msr: Search for multiple hex values, separated by spaces")
- print(" rsr: Search for a single hex value, ignoring file structure")
- print(" rmsr: Search for multiple hex values, separated by spaces, ignoring file structure")
- print(" srs: Search for a static item (hex value). As a side effect, also lists hidden items")
- print(" lsf: Search for a specific file (decimal value) and list its contents")
- print(" fof: Show the base offset for a file")
- print(" quit: Exit the program")
- print("")
-
-def print_hex(hex_value,endsymbol='\n',prefix='0x'):
- print(prefix + "{:X}".format(hex_value),end=endsymbol)
-
-def print_hex_byte(hex_value,endsymbol='\n',prefix='0x'):
- print(prefix + "{:0>2X}".format(hex_value),end=endsymbol)
-
-def print_hex_word(hex_value,endsymbol='\n',prefix='0x'):
- print(prefix + "{:0>8X}".format(hex_value),end=endsymbol)
-
-def read_byte(file):
- return int.from_bytes(file.read(1),byteorder='little')
-
-def read_halfword(file):
- return int.from_bytes(file.read(2),byteorder='little')
-
-def read_word(file):
- return int.from_bytes(file.read(4),byteorder='little')
-
-if __name__ == "__main__":
+import argparse, sys, os
+
+def main():
+ try:
+ with open(sys.argv[1],"rb") as f:
+ word = f.read(4)
+ while word != b'BTAF':
+ word = f.read(4)
+ table_length = read_word(f)
+ file_count = read_word(f)
+ file_offsets = []
+ for i in range(file_count):
+ file_offsets.append(read_word(f))
+ f.seek(4,os.SEEK_CUR)
+ print(str(i) + ": ",end='')
+ print_hex_word(file_offsets[i])
+ f.seek(-4,os.SEEK_CUR)
+ file_offsets.append(read_word(f))
+ word = f.read(4)
+ while word != b'GMIF':
+ word = f.read(4)
+ file_table_length = read_word(f)
+ file_table_offset = f.tell()
+ print("File table length: ",end='')
+ print_hex_word(file_table_length)
+ print("File table offset: ",end='')
+ print_hex_word(file_table_offset)
+ readline = ""
+ print("Ready to search. Enter help for list of commands")
+ while readline != "quit":
+ readline = input('Enter command: ')
+ args = readline.split()
+ if args[0] == "help":
+ list_commands()
+ elif args[0] == "sr": # Search
+ if len(args) < 2:
+ print("Usage: sr x")
+ print("x should be a hexadecimal number")
+ else:
+ if args[1][:2] == "0x":
+ target = int(args[1][2:],16)
+ else:
+ target = int(args[1],16)
+ upper_byte = 0
+ if target % 2**32 > 2**8:
+ upper_byte = target >> 8
+ target = target & 0xFF
+ for i in range(file_count):
+ f.seek(file_table_offset + file_offsets[i])
+ local_offset_in_file = read_word(f)
+ first_global_offset = f.tell() + local_offset_in_file
+ while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
+ offset_in_file = f.tell() + local_offset_in_file
+ return_position = f.tell()
+ f.seek(offset_in_file)
+ data = 0
+ while data != 0x02002F and f.tell() < file_table_offset + file_offsets[i+1]:
+ data = read_byte(f)
+ if data == target:
+ if upper_byte == 0:
+ print("Found target value in file " + str(i) + " at offset ",end='')
+ print_hex_word(f.tell())
+ else:
+ data = read_byte(f)
+ f.seek(-1,os.SEEK_CUR)
+ if data == upper_byte:
+ print("Found target value in file " + str(i) + " at offset ",end='')
+ print_hex_word(f.tell())
+ if data == 0x2F:
+ f.seek(-1,os.SEEK_CUR)
+ data = read_word(f)
+ if data != 0x02002F:
+ f.seek(-3,os.SEEK_CUR)
+ f.seek(return_position)
+ local_offset_in_file = read_word(f)
+ elif args[0] == "msr": # Multiple search
+ if len(args) < 2:
+ print("Usage: msr x [y z ...]")
+ print("x, y, z ... should be hexadecimal numbers")
+ else:
+ target = []
+ upper_byte = []
+ for i in range(1,len(args)):
+ if args[i][:2] == "0x":
+ target.append(int(args[i][2:],16))
+ else:
+ target.append(int(args[i],16))
+ if target[i-1] % 2**32 > 2**8:
+ upper_byte.append(target[i-1] >> 8)
+ target[i-1] = target[i-1] & 0xFF
+ else:
+ upper_byte.append(0)
+ for i in range(file_count):
+ found_in_file = []
+ f.seek(file_table_offset + file_offsets[i])
+ local_offset_in_file = read_word(f)
+ first_global_offset = f.tell() + local_offset_in_file
+ while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
+ offset_in_file = f.tell() + local_offset_in_file
+ return_position = f.tell()
+ f.seek(offset_in_file)
+ data = 0
+ while data != 0x02002F and f.tell() < file_table_offset + file_offsets[i+1]:
+ data = read_byte(f)
+ for j,t in enumerate(target):
+ if data == t:
+ if upper_byte[j] == 0:
+ found_in_file.append((t,f.tell()))
+ else:
+ data = read_byte(f)
+ f.seek(-1,os.SEEK_CUR)
+ if data == upper_byte[j]:
+ found_in_file.append((t + (upper_byte[j] << 8),f.tell()-1))
+ if data == 0x2F:
+ f.seek(-1,os.SEEK_CUR)
+ data = read_word(f)
+ if data != 0x02002F:
+ f.seek(-3,os.SEEK_CUR)
+ f.seek(return_position)
+ local_offset_in_file = read_word(f)
+ if len(found_in_file) >= 1:
+ target_copy = target.copy()
+ for (val,_) in found_in_file:
+ for j,t in enumerate(target_copy):
+ if val == t + (upper_byte[j] << 8):
+ target_copy.remove(t)
+ if len(target_copy) == 0:
+ print("Found in file " + str(i) + ": ")
+ for (val,offset) in found_in_file:
+ print_hex(val,'')
+ print(" at offset ",end='')
+ print_hex_word(offset)
+ elif args[0] == "rsr": # Raw search
+ if len(args) < 2:
+ print("Usage: rsr x")
+ print("x should be a hexadecimal number")
+ else:
+ if args[1][:2] == "0x":
+ target = int(args[1][2:],16)
+ else:
+ target = int(args[1],16)
+ upper_byte = 0
+ if target % 2**32 > 2**8:
+ upper_byte = target >> 8
+ target = target & 0xFF
+ for i in range(file_count):
+ f.seek(file_table_offset + file_offsets[i])
+ while f.tell() < file_table_offset + file_offsets[i+1]:
+ data = read_byte(f)
+ if data == target:
+ if upper_byte == 0:
+ print("Found target value in file " + str(i) + " at offset ",end='')
+ print_hex_word(f.tell())
+ else:
+ data = read_byte(f)
+ f.seek(-1,os.SEEK_CUR)
+ if data == upper_byte:
+ print("Found target value in file " + str(i) + " at offset ",end='')
+ print_hex_word(f.tell())
+ elif args[0] == "rmsr": # Raw multiple search
+ if len(args) < 2:
+ print("Usage: rmsr x [y z ...]")
+ print("x, y, z ... should be hexadecimal numbers")
+ else:
+ target = []
+ upper_byte = []
+ for i in range(1,len(args)):
+ if args[i][:2] == "0x":
+ target.append(int(args[i][2:],16))
+ else:
+ target.append(int(args[i],16))
+ if target[i-1] % 2**32 > 2**8:
+ upper_byte.append(target[i-1] >> 8)
+ target[i-1] = target[i-1] & 0xFF
+ else:
+ upper_byte.append(0)
+ for i in range(file_count):
+ found_in_file = []
+ f.seek(file_table_offset + file_offsets[i])
+ while f.tell() < file_table_offset + file_offsets[i+1]:
+ data = read_byte(f)
+ for j,t in enumerate(target):
+ if data == t:
+ if upper_byte[j] == 0:
+ found_in_file.append((t,f.tell()))
+ else:
+ data = read_byte(f)
+ f.seek(-1,os.SEEK_CUR)
+ if data == upper_byte[j]:
+ found_in_file.append((t + (upper_byte[j] << 8),f.tell()-1))
+ if len(found_in_file) >= 1:
+ target_copy = target.copy()
+ for (val,_) in found_in_file:
+ for j,t in enumerate(target_copy):
+ if val == t + (upper_byte[j] << 8):
+ target_copy.remove(t)
+ if len(target_copy) == 0:
+ print("Found in file " + str(i) + ": ")
+ for (val,offset) in found_in_file:
+ print_hex(val,'')
+ print(" at offset ",end='')
+ print_hex_word(offset)
+ elif args[0] == "lsf": # List file
+ if len(args) < 2:
+ print("Usage: lsf fileno")
+ else:
+ print("Searching file " + args[1] + "!")
+ f.seek(file_table_offset + file_offsets[int(args[1])])
+ local_offset_in_file = read_word(f)
+ first_global_offset = f.tell() + local_offset_in_file
+ while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
+ offset_in_file = f.tell() + local_offset_in_file
+ print("Relative offset: 0x" + '%X' % local_offset_in_file + " read at 0x" + '%X' % (f.tell() - 4),end='')
+ print(", global offset: 0x" + '%X' % offset_in_file)
+ return_position = f.tell()
+ f.seek(offset_in_file)
+ data = 0
+ while data != 0x02002F and f.tell() < file_table_offset + file_offsets[int(args[1])+1]:
+ data = read_byte(f)
+ print_hex_byte(data,'','')
+ print(' ',end='')
+ if data == 0x2F:
+ f.seek(-1,os.SEEK_CUR)
+ data = read_word(f)
+ if data == 0x02002F:
+ print_hex_byte(0x00,'','')
+ print(' ',end='')
+ print_hex_byte(0x02,'','')
+ print(' ',end='')
+ print_hex_byte(0x00,'','')
+ print(' ',end='')
+ else:
+ print_hex_byte(0x2F,'','')
+ print(' ',end='')
+ f.seek(-3,os.SEEK_CUR)
+ print("\n")
+ f.seek(return_position)
+ local_offset_in_file = read_word(f)
+ elif args[0] == "fof": # File offset
+ if len(args) < 2:
+ print("Usage: fof fileno")
+ else:
+ print("Offset for file " + args[1] + ": 0x" + '%X' % (file_table_offset + file_offsets[int(args[1])]))
+ elif args[0] == "srs": # Search static
+ if len(args) < 2:
+ print("Usage: srs index")
+ else:
+ if args[1][:2] == "0x":
+ target = int(args[1][2:],16)
+ else:
+ target = int(args[1],16)
+ for i in range(file_count):
+ f.seek(file_table_offset + file_offsets[i])
+ local_offset_in_file = read_word(f)
+ first_global_offset = f.tell() + local_offset_in_file
+ while local_offset_in_file & 0xFFFF != 0xFD13 and f.tell() - 4 < first_global_offset:
+ offset_in_file = f.tell() + local_offset_in_file
+ return_position = f.tell()
+ f.seek(offset_in_file)
+ data = 0
+ while data != 0x02002F and f.tell() < file_table_offset + file_offsets[i+1]:
+ data = read_byte(f)
+ if data == 0x2A:
+ f.seek(-1,os.SEEK_CUR)
+ data = read_word(f)
+ if data == 0x8000002A:
+ item = read_halfword(f)
+ if item == target:
+ print("Found item in file " + str(i) + " at offset 0x" + '%X' % (f.tell() - 2))
+ else:
+ f.seek(-3,os.SEEK_CUR)
+ if data == 0x2F:
+ f.seek(-1,os.SEEK_CUR)
+ data = read_word(f)
+ if data != 0x02002F:
+ f.seek(-3,os.SEEK_CUR)
+ f.seek(return_position)
+ local_offset_in_file = read_word(f)
+ elif args[0] == "lsai": # List all items
+ if len(args) == 3:
+ range_start = int(args[1],16)
+ range_end = int(args[2],16) # 6A1564C
+ else:
+ range_start = 0
+ range_end = file_count
+ with open("itemprices.txt","w") as it:
+ for i in range(range_start, range_end):
+ f.seek(file_table_offset + file_offsets[i])
+ it.write("{" + str(i) + ", " + str(int.from_bytes(f.read(2),byteorder='little')) + "},\n")
+ #print("Item 0x" + '%X' % i + " price: " + str(int.from_bytes(f.read(2),byteorder='little') * 10))
+ except IndexError:
+ print("Error: No file specified")
+ sys.exit(2)
+ except IOError:
+ print("Error: File does not exist")
+ sys.exit(2)
+
+def list_commands():
+ print("")
+ print("List of commands:")
+ print(" help: You are here")
+ print(" sr: Search for a single hex value")
+ print(" msr: Search for multiple hex values, separated by spaces")
+ print(" rsr: Search for a single hex value, ignoring file structure")
+ print(" rmsr: Search for multiple hex values, separated by spaces, ignoring file structure")
+ print(" srs: Search for a static item (hex value). As a side effect, also lists hidden items")
+ print(" lsf: Search for a specific file (decimal value) and list its contents")
+ print(" fof: Show the base offset for a file")
+ print(" quit: Exit the program")
+ print("")
+
+def print_hex(hex_value,endsymbol='\n',prefix='0x'):
+ print(prefix + "{:X}".format(hex_value),end=endsymbol)
+
+def print_hex_byte(hex_value,endsymbol='\n',prefix='0x'):
+ print(prefix + "{:0>2X}".format(hex_value),end=endsymbol)
+
+def print_hex_word(hex_value,endsymbol='\n',prefix='0x'):
+ print(prefix + "{:0>8X}".format(hex_value),end=endsymbol)
+
+def read_byte(file):
+ return int.from_bytes(file.read(1),byteorder='little')
+
+def read_halfword(file):
+ return int.from_bytes(file.read(2),byteorder='little')
+
+def read_word(file):
+ return int.from_bytes(file.read(4),byteorder='little')
+
+if __name__ == "__main__":
main() \ No newline at end of file
diff --git a/util/ref/bw2_trainers.txt b/util/ref/bw2_trainers.txt
new file mode 100644
index 0000000..7746a9a
--- /dev/null
+++ b/util/ref/bw2_trainers.txt
@@ -0,0 +1,473 @@
+4
+5
+6
+133
+134
+135
+136
+137
+138
+139
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+164
+165
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+237
+238
+239
+240
+242
+243
+244
+245
+247
+248
+249
+250
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+372
+373
+374
+375
+376
+377
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+497
+498
+499
+500
+501
+502
+503
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+580
+581
+583
+584
+585
+586
+587
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+679
+680
+681
+682
+683
+690
+691
+692
+703
+704
+705
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+745
+746
+747
+748
+749
+750
+751
+752
+754
+755
+756
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+786
+787
+788
+789
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812 \ No newline at end of file
diff --git a/util/ref/bw_trainers.txt b/util/ref/bw_trainers.txt
new file mode 100644
index 0000000..21fb1ed
--- /dev/null
+++ b/util/ref/bw_trainers.txt
@@ -0,0 +1,370 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+137
+138
+139
+140
+141
+142
+143
+144
+145
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+186
+187
+188
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+212
+213
+214
+215
+216
+217
+218
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+315
+316
+401
+402
+408
+409
+412
+413
+438
+439
+441
+442
+443
+445
+447
+450
+460
+461
+462
+465
+466
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+484
+485
+488
+489
+490
+501
+502
+503
+504
+505
+506
+513
+514
+515
+516
+517
+518
+519
+520
+526
+531
+532
+533
+534
+535
+536
+537
+538
+544
+545
+546
+549
+550
+552
+553
+554
+555
+556
+557
+582
+583
+584
+585
+586
+587
+600
+601
+602
+603
+604
+605
+606
+607
+610
+611
+612
+613 \ No newline at end of file