Exemplo n.º 1
0
	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
Exemplo n.º 2
0
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
Exemplo n.º 3
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