generate_cheat_db.py (2764B)
1 import sys 2 import re 3 import xml.etree.ElementTree as ET 4 from xml.sax.saxutils import unescape 5 6 class GameEntry: 7 def __init__(self, title, serials): 8 self.title = title 9 self.serials = serials 10 11 def __repr__(self): 12 return self.title + " (" + ",".join(self.serials) + ")" 13 14 15 def get_serials(s): 16 out = [] 17 for it in s.split("/"): 18 for it2 in it.split(","): 19 for it3 in it2.split("~"): 20 i = it3.find('(') 21 if i > 0: 22 it3 = it3[:i-1] 23 it3 = re.sub("[^A-Za-z0-9-]", "", it3) 24 out.append(it3.strip()) 25 print(out) 26 return out 27 28 29 def parse_xml(path): 30 entries = {} 31 tree = ET.parse(path) 32 for child in tree.getroot(): 33 name = child.get("name") 34 if name is None: 35 continue 36 37 title = "" 38 description = child.find("description") 39 if description is not None: 40 title = description.text 41 42 serials = [] 43 for grandchild in child.iterfind("info"): 44 gname = grandchild.get("name") 45 gvalue = grandchild.get("value") 46 #print(gname, gvalue) 47 if gname is not None and gname == "serial" and gvalue is not None: 48 serials.extend(get_serials(gvalue)) 49 50 if len(serials) > 0: 51 entries[name] = GameEntry(title, serials) 52 53 return entries 54 55 56 def write_codes(entries, fout, name, codes): 57 if name == "" or len(codes) == 0: 58 return 59 60 if name not in entries: 61 print("Unknown game '%s'" % name) 62 return 63 64 entry = entries[name] 65 fout.write(";%s\n" % entry.title) 66 for serial in entry.serials: 67 fout.write(":%s\n" % serial) 68 fout.write("\n".join(codes)) 69 fout.write("\n\n") 70 71 72 def rewrite_dat(entries, inpath, outpath): 73 fin = open(inpath, "r", encoding="utf-8") 74 fout = open(outpath, "w", encoding="utf-8") 75 76 current_name = "" 77 code_lines = [] 78 79 for line in fin.readlines(): 80 if line[0] == ' ' or line[0] == ';' or line[:2] == "##": 81 continue 82 83 line = line.strip() 84 if len(line) == 0: 85 continue 86 87 line = unescape(line) 88 89 if line[0] == ':': 90 write_codes(entries, fout, current_name, code_lines) 91 current_name = line[1:].split(':')[0].strip() 92 code_lines = [] 93 else: 94 code_lines.append(line) 95 96 write_codes(entries, fout, current_name, code_lines) 97 98 fin.close() 99 fout.close() 100 101 102 if __name__ == "__main__": 103 if len(sys.argv) < 4: 104 print("usage: %s <psx.xml path> <cheatpsx.dat> <output file>" % sys.argv[0]) 105 sys.exit(1) 106 107 entries = parse_xml(sys.argv[1]) 108 rewrite_dat(entries, sys.argv[2], sys.argv[3])