def validate(self, romfile, cont=None): if not self.args.romless: romstream = helper.stream(romfile) roms = self.rpl.childrenByType("ROM") totalfails = [] for x in roms: successes, fails = x.validate(romstream) totalfails += fails #endfor if totalfails: self.romsec.note("Failed the following checks: %s" % helper.list2english([ ("%s[%i]" % fail if type(fail) is tuple else fail) for fail in totalfails ])) if cont: self.ieframe.pack_forget() self.ccframe.pack(fill=Tk.X) self.cont = cont #endif return False #endif #endif return True
def main(): global debug parser = argparse.ArgumentParser( description = TITLE + " by Wa (logicplace.com)\n" "Easily replace resources in ROMs (or other binary formats) by use of" " a standard descriptor format.", usage = "Usage: %(prog)s [options] {-x | -i | -m} ROM RPL [Struct names...]\n" " %(prog)s -h [RPL | lib]\n" " %(prog)s -t [RPL] [-l libs] [-s Struct types...]", formatter_class=argparse.RawDescriptionHelpFormatter, add_help = False, ) action = parser.add_mutually_exclusive_group() action.add_argument("--help", "-h", "-?", #"/?", "/h", help = argparse.SUPPRESS, action = "store_true" ) action.add_argument("--version", #"/v", help = "Show version number and exit.", action = "store_true" ) action.add_argument("--import", "-i", #"/i", dest = "importing", help = "Import resources in the ROM via the descriptor.", nargs = 2, metavar = ("ROM", "RPL") ) action.add_argument("--export", "-x", #"/x", help = "Export resources from the ROM via the descriptor.", nargs = 2, metavar = ("ROM", "RPL") ) action.add_argument("--makefile", "-m", "--binary", "-b", #"/m", "/b", help = "Create a new file. This will overwrite an existing file.\n" "Implies -r", nargs = 2, metavar = ("ROM", "RPL") ) action.add_argument("--template", "-t", #"/t", help = "Generate a descriptor skeleton for the given module.\n" 'Use "rpl" to generate the basic one.\n' "If no destination is given, result is printed to stdout.", action = "store_true" ) action.add_argument("--run", help = "Run a RPL without involving a ROM. Implies --romless", nargs = 1, metavar = ("RPL") ) action.add_argument("--gui", help = "Open the GUI.", action = "store_true" ) parser.add_argument("--libs", "-l", #"/l", help = "What libs to load for template creation.", nargs = "*" ) parser.add_argument("--structs", "-s", #"/s", help = "What structs to include in the template.", nargs = "*" ) parser.add_argument("--romless", "-r", #"/r", help = "Do not perform validations in ROM struct, and" " do not warn if there isn't a ROM struct.", action = "store_true" ) parser.add_argument("--blank", help = "Run action without creating or modifying a ROM file.", action = "store_true" ) parser.add_argument("--define", "-d", #"/d", help = "Define a value that can be referenced by @Defs.name\n" "Values are interpreted as RPL data, be aware of this in regards to" " strings vs. literals.", action = "append", nargs = 2, metavar = ("name", "value"), default = [] ) parser.add_argument("--folder", "-f", #"/f", help = "Folder to export to, or import from. By default this is the" " current folder.", default = "." ) parser.add_argument("--debug", help = argparse.SUPPRESS, action = "store_true" ) parser.add_argument("args", nargs="*", help=argparse.SUPPRESS) args = parser.parse_args(sys.argv[1:]) debug = args.debug # Windows help flag. if args.args and args.args[0] == "/?": args.help = True args.args.pop(0) #endif if args.help: if len(args.args) >= 1: if args.args[0][-3:] == "rpl": # Load a RPL file's help. thing = rpl.RPL() thing.parse(args.args[0], ["RPL"]) rplStruct = thing.childrenByType("RPL") if not rplStruct: return 0 help = rplStruct[0]["help"].get() # Abuse argparse's help generator. filehelp = argparse.ArgumentParser( description = help[0].get(), usage = argparse.SUPPRESS ) for x in help[1:]: defkey, defhelp = tuple([y.get() for y in x.get()]) filehelp.add_argument("-d" + defkey, help=defhelp) #endfor filehelp.print_help() else: # Load a lib's help. tmp = getattr(__import__("rpl." + args.args[0], globals(), locals()), args.args[0]) tmp.printHelp(args.args[1:]) #endif else: parser.print_help() elif args.version: print(TITLE + " - v" + VERSION) elif args.template: thing = rpl.RPL() # Load requested libs. if args.libs: rplStruct = rpl.StructRPL() rplStruct["lib"] = rpl.List(map(rpl.String, args.libs)) thing.load(rplStruct) #endif structs = args.structs if structs and not args.romless: structs = ["ROM"] + structs print(thing.template(structs)) elif args.run: thing = rpl.RPL() thing.parse(args.run[0]) # Do defines. for x in args.define: thing.addDef(*x) # Run RPL. start = time() thing.run(args.folder, args.args) print("Finished executing. Time taken: %.3fs" % (time() - start)) elif args.importing or args.export or args.makefile: # Regular form. thing = rpl.RPL() # Grab filenames. if args.importing: romfile, rplfile = tuple(args.importing) elif args.export: romfile, rplfile = tuple(args.export) elif args.makefile: romfile, rplfile = tuple(args.makefile) thing.parse(rplfile) if not args.romless and not args.makefile: romstream = helper.stream(romfile) roms = thing.childrenByType("ROM") for x in roms: successes, fails = x.validate(romstream) if fails: print("Failed the following checks: %s" % helper.list2english([ ("%s[%i]" % fail if type(fail) is tuple else fail) for fail in fails ])) answer = "." while answer not in "yYnN": answer = raw_input("Continue anyway (y/n)? ") if answer in "nN": return 1 #endif #endfor #endif # Do defines. for x in args.define: thing.addDef(*x) # Run imports. start = time() if args.importing: thing.importData(romstream, args.folder, args.args, args.blank) helper.prntc("Finished %s." % ("blank import" if args.blank else "importing")) romstream.close() elif args.export: thing.exportData(romstream, args.folder, args.args, args.blank) helper.prntc("Finished %s." % ("blank export" if args.blank else "exporting")) romstream.close() elif args.makefile: try: os.unlink(romfile) except OSError as err: if err.errno == 2: pass else: helper.err('Could not delete "%s": %s' % (romfile, err.strerror)) return 1 #endif #endtry thing.importData(romfile, args.folder, args.args, args.blank) helper.prntc("Finished %s." % ("build test" if args.blank else "building")) #endif print("Time taken: %.3fs" % (time() - start)) else: return GUI().run(args) #endif return 0
def guessFiles(self, romfile, rplfile, folder): # Fancy guesswork~ romnote, rplnote = u"", u"" if not rplfile and romfile: # Look for a similarly named RPL file nearby. name = os.path.splitext(romfile)[0] search = [os.path.splitext(x)[0] for x in glob.glob("*.rpl") + glob.glob("*/*.rpl")] try: rplfile = difflib.get_close_matches(name, search)[0] except IndexError: pass #endif if not rplfile and folder: # Check if there's only one rpl file in the passed folder, and use that. rpls = glob.glob(os.path.join(folder, "*.rpl")) if len(rpls) == 1: rplfile = os.path.abspath(rpls[0]) #endif if not rplfile: # Check if there's only one rpl file in the cwd, and use that. rpls = glob.glob("*.rpl") if len(rpls) == 1: rplfile = os.path.abspath(rpls[0]) #endif if rplfile and not romfile: if not self.rpl.children: try: self.rpl.parse(rplfile) except (rpl.RPLError, helper.RPLInternal) as err: rplnote = unicode(err) #endif # Collect search area. top = os.path.dirname(rplfile) searches = [x for x in ( # eg. CoolGame/ROM CoolGame/RPL glob.glob(os.path.join(top, "*")) + # eg. CoolGame/ROM CoolGame/dev/RPL glob.glob(os.path.join(os.path.dirname(top), "*")) + # eg. CoolGame/RPL CoolGame/build/ROM glob.glob(os.path.join(top, "*", "*")) ) if os.path.isfile(x)] # Is there a ROM struct we can use for verification? rom = self.rpl.childrenByType("ROM") if rom: successes, curfails = 0, 0 # Check files against ROM struct validation. for x in searches: stream = helper.stream(x) succs, fails = 0, 0 for r in rom: s, f = r.validate(stream) succs += s fails += len(f) #endfor if succs > successes: romfile, successes, curfails = x, succs, fails if fails == 0: break #endif #endfor if romfile and curfails: romnote = u"There were %i ROM validation failures." % curfails else: # Filter out some known extensions, like archives... searches = [x for x in searches if ( x.split(os.extsep)[-1] not in [ "rpl", "zip", "rar", "tar", "gz", "7z", "lzh", "lz", "bz2", "lzma", "lha", "tgz" ] )] # Look for a similarly named ROM file nearby. name = os.path.splitext(romfile)[0] noext = [os.path.split(x)[0] for x in searches] # Compare names without extensions. try: result = difflib.get_close_matches(name, noext)[0] except IndexError: pass # Look up name with extension and store as the romfile. else: romfile = searches[noext.index(result)] #endif #endif if rplfile and not folder: # It's probably nearby... Parse and look for directory structure. if not self.rpl.children: try: self.rpl.parse(rplfile) except (rpl.RPLError, helper.RPLInternal) as err: rplnote = unicode(err) #endif if self.rpl.children: files = [] for x in self.rpl.recurse(): try: x.open except AttributeError: pass else: if x.manage([]): files.append(x) #endtry #endfor # Compare directory structure of RPL with subdirs. toplevel, best = os.path.abspath(os.path.dirname(rplfile)), 0 for top, dirs, _ in os.walk(toplevel, followlinks=True): if top.replace(toplevel, "", 1).count(os.sep) >= 2: dirs = [] ltop = list(os.path.split(top)) success, fail = 0, 0 for x in files: fn = x.open(ltop, ext="", retName=True) if os.path.exists(fn) or glob.glob(os.extsep.join((fn, "*"))): success += 1 else: fail += 1 #endif if success > best: folder, best = top, success if fail == 0: break #endif #endfor # If nothing else, this can start in the same directory as the RPL file. if not folder: folder = toplevel #endif #endif if not folder: # If we double clicked the executable, don't set the folder. cwd = os.path.realpath(os.getcwd()) if os.path.dirname(os.path.realpath(sys.argv[0])) != cwd: # Otherwise default to cwd. folder = cwd #endif #endif return romfile, rplfile, folder, romnote, rplnote