diff options
Diffstat (limited to 'unrpyc')
-rw-r--r-- | unrpyc/Makefile | 4 | ||||
-rw-r--r-- | unrpyc/decompiler.py | 241 | ||||
-rw-r--r-- | unrpyc/unrpyc.py | 9 |
3 files changed, 127 insertions, 127 deletions
diff --git a/unrpyc/Makefile b/unrpyc/Makefile index 4fb222d..56d207b 100644 --- a/unrpyc/Makefile +++ b/unrpyc/Makefile @@ -19,6 +19,10 @@ ui-strings.json.o ui-strings_FR.json.o: ui-strings%.json.o: ui-strings%.rpyc *.p python unrpyc.py --clobber $< $@ sed -i -e 's/ \["init_language", "[a-z]*", \],//;s/^\]}$$/}/' $@ +ui_settings.json.o: ui_settings.rpyc *.py + python unrpyc.py --clobber $< --ignore-python $@ + sed -i -e 's/,,/,/g;/: *,$$/d' $@ + %.json.o: %.rpyc *.py python unrpyc.py --clobber $< $@ diff --git a/unrpyc/decompiler.py b/unrpyc/decompiler.py index ee55ef1..ab91732 100644 --- a/unrpyc/decompiler.py +++ b/unrpyc/decompiler.py @@ -21,20 +21,24 @@ import ast as python_ast import renpy.ast as ast import renpy.atl as atl -import code +import pdb import json DECOMPILE_SCREENS = False -global firstLabel firstLabel = True -global warnedATL warnedATL = False +ignorePython = False -def pretty_print_ast(out_file, ast): +def pretty_print_ast(out_file, ast, ignore_python): + global ignorePython + ignorePython = ignore_python out_file.write('{') for stmt in ast: print_statement(out_file, stmt, 0) - out_file.write(']}') + if ignore_python: + out_file.write('}') + else: + out_file.write(']}') def indent(f, level): # Print indentation @@ -57,115 +61,109 @@ def escape_string(s): # multiple of the same block are immediately after # each other. def print_atl(f, atl_block, indent_level): - if not warnedATL: - global warnedATL - warnedATL = True - print("ATL not yet implemented") - return if not atl_block.statements: indent(f, indent_level) for stmt in atl_block.statements: indent(f, indent_level) if type(stmt) is atl.RawMultipurpose: - # warper - if stmt.warp_function: - f.write("warp %s" % (stmt.warp_function.strip(), )) - f.write(" %s " % (stmt.duration.strip(), )) - elif stmt.warper: - f.write(stmt.warper) - f.write(" %s " % (stmt.duration.strip(), )) - elif stmt.duration.strip() != '0': - f.write('pause') - f.write(" %s" % (stmt.duration.strip(), )) - - # revolution - if stmt.revolution: - f.write("%s " % (stmt.revolution, )) - - # circles - if stmt.circles != "0": - f.write("circles %s " % (stmt.circles.strip(), )) - - # splines - for (name, exprs) in stmt.splines: - f.write("%s " % (name, )) - for expr in exprs: - f.write("knot %s " % (expr.strip(), )) - - # properties - for (k, v) in stmt.properties: - f.write("%s %s " % (k, v.strip())) + ## warper + #if stmt.warp_function: + # f.write("warp %s" % (stmt.warp_function.strip(), )) + # f.write(" %s " % (stmt.duration.strip(), )) + #elif stmt.warper: + # f.write(stmt.warper) + # f.write(" %s " % (stmt.duration.strip(), )) + #elif stmt.duration.strip() != '0': + # f.write('pause') + # f.write(" %s" % (stmt.duration.strip(), )) + + ## revolution + #if stmt.revolution: + # f.write("%s " % (stmt.revolution, )) + + ## circles + #if stmt.circles != "0": + # f.write("circles %s " % (stmt.circles.strip(), )) + + ## splines + #for (name, exprs) in stmt.splines: + # f.write("%s " % (name, )) + # for expr in exprs: + # f.write("knot %s " % (expr.strip(), )) + + ## properties + #for (k, v) in stmt.properties: + # f.write("%s %s " % (k, v.strip())) # with for (expr, with_expr) in stmt.expressions: - f.write("%s " % (expr.strip(), )) - if with_expr: - f.write("with %s " % (with_expr, )) - - f.write("\n") - - elif type(stmt) is atl.RawBlock: - # what does stmt.animation do? - f.write("block:\n") - print_atl(f, stmt, indent_level + 1) - - elif type(stmt) is atl.RawChoice: - first = True - for (chance, block) in stmt.choices: - if first: - first = False - else: - indent(f, indent_level) - - f.write("choice") - if chance != "1.0": - f.write(" %s" % (chance, )) - f.write(":\n") - print_atl(f, block, indent_level + 1) - - elif type(stmt) is atl.RawContainsExpr: - f.write("contains %s\n" % (stmt.expression, )) - - elif type(stmt) is atl.RawEvent: - f.write("event %s\n" % (stmt.name, )) - - elif type(stmt) is atl.RawFunction: - f.write("function %s\n" % (stmt.expr, )) - - elif type(stmt) is atl.RawOn: - first = True - for name, block in list(stmt.handlers.items()): - if first: - first = False - else: - indent(f, indent_level) - - f.write("on %s:\n" % (name, )) - print_atl(f, block, indent_level + 1) - - elif type(stmt) is atl.RawParallel: - first = True - for block in stmt.blocks: - if first: - first = False - else: - indent(f, indent_level) - - f.write("parallel:\n") - print_atl(f, block, indent_level + 1) - - elif type(stmt) is atl.RawRepeat: - f.write("repeat") - if stmt.repeats: - f.write(" %s" % (stmt.repeats, )) # not sure if this is even a string - f.write("\n") - - elif type(stmt) is atl.RawTime: - f.write("time %s\n" % (stmt.time, )) - - else: - f.write("TODO atl.%s\n" % type(stmt).__name__) + if expr.strip()[0] == '"': + f.write("%s " % (expr.strip(), )) + #if with_expr: + # f.write("with %s " % (with_expr, )) + + #elif type(stmt) is atl.RawBlock: + # # what does stmt.animation do? + # f.write("block:\n") + # print_atl(f, stmt, indent_level + 1) + + #elif type(stmt) is atl.RawChoice: + # first = True + # for (chance, block) in stmt.choices: + # if first: + # first = False + # else: + # indent(f, indent_level) + + # f.write("choice") + # if chance != "1.0": + # f.write(" %s" % (chance, )) + # f.write(":\n") + # print_atl(f, block, indent_level + 1) + + #elif type(stmt) is atl.RawContainsExpr: + # f.write("contains %s\n" % (stmt.expression, )) + + #elif type(stmt) is atl.RawEvent: + # f.write("event %s\n" % (stmt.name, )) + + #elif type(stmt) is atl.RawFunction: + # f.write("function %s\n" % (stmt.expr, )) + + #elif type(stmt) is atl.RawOn: + # first = True + # for name, block in list(stmt.handlers.items()): + # if first: + # first = False + # else: + # indent(f, indent_level) + + # f.write("on %s:\n" % (name, )) + # print_atl(f, block, indent_level + 1) + + #elif type(stmt) is atl.RawParallel: + # first = True + # for block in stmt.blocks: + # if first: + # first = False + # else: + # indent(f, indent_level) + + # f.write("parallel:\n") + # print_atl(f, block, indent_level + 1) + + #elif type(stmt) is atl.RawRepeat: + # f.write("repeat") + # if stmt.repeats: + # f.write(" %s" % (stmt.repeats, )) # not sure if this is even a string + # f.write("\n") + + #elif type(stmt) is atl.RawTime: + # f.write("time %s\n" % (stmt.time, )) + + #else: + # f.write("TODO atl.%s\n" % type(stmt).__name__) def print_imspec(f, imspec): if imspec[1] is not None: # Expression @@ -280,26 +278,16 @@ class PrintRenPython(python_ast.NodeVisitor): id = node.targets[0].id if id == 'suppress_window_before_timeskip' or id == 'suppress_window_after_timeskip' or id == '_window': return - self.f.write(self.visit(node.targets[0])) - self.f.write(': ') - self.f.write(self.visit(node.value)) - self.f.write(',\n') + return "%s: %s,\n" % (self.visit(node.targets[0]), self.visit(node.value)) def visit_Call(self, node): - self.f.write('[') - self.f.write(self.visit(node.func)) - self.f.write(', ') - self.f.write(', '.join(map(self.visit, node.args))) - self.f.write(', ') - self.f.write(', '.join(map(self.visit, node.keywords))) - self.f.write('],\n') + return '[%s, %s, %s],' % (self.visit(node.func), ', '.join(map(self.visit, node.args)), ', '.join(map(self.visit, node.keywords))) def visit_Compare(self, node): - self.f.write('[') - self.f.write(self.visit(node.left)) - self.f.write(', ') - self.f.write(self.visit(node.comparators[0])) - self.f.write('], ') + return '[%s, %s], ' % (self.visit(node.left), self.visit(node.comparators[0])) + + def visit_Expression(self, node): + return self.visit(node.body) def quote(self, string): return '"%s"' % string @@ -333,6 +321,9 @@ class PrintRenPython(python_ast.NodeVisitor): return self.visit(node.value) def print_Python(f, stmt, indent_level, early=False): + if ignorePython: + return + code_src = stmt.code.source stripped_code = code_src.strip() @@ -354,14 +345,16 @@ def print_Init(f, stmt, indent_level): print_statement(f, s, indent_level + 1) def print_Image(f, stmt, indent_level): - f.write("image %s" % (' '.join(stmt. imgname), )) + f.write('"%s": ' % ('_'.join(stmt.imgname), )) if stmt.code is not None: - f.write(" = %s\n" % (stmt.code.source, )) + ret = PrintRenPython(f).visit(compile(stmt.code.source, '<unknown>', 'eval', python_ast.PyCF_ONLY_AST)) + f.write(ret) else: - f.write("\n") print_atl(f, stmt.atl, indent_level + 1) + f.write(',\n') def print_Transform(f, stmt, indent_level): + return f.write("transform %s" % (stmt.varname, )) if stmt.parameters is not None: print_params(f, stmt.parameters) diff --git a/unrpyc/unrpyc.py b/unrpyc/unrpyc.py index f423cc8..6bdde42 100644 --- a/unrpyc/unrpyc.py +++ b/unrpyc/unrpyc.py @@ -94,7 +94,7 @@ def read_ast_from_file(in_file): data, stmts = pickle.loads(raw_contents) return stmts -def decompile_rpyc(input_filename, out_filename, overwrite=False): +def decompile_rpyc(input_filename, out_filename, overwrite=False, ignore_python=False): # Output filename is input filename but with .rpy extension path, ext = os.path.splitext(input_filename) @@ -108,7 +108,7 @@ def decompile_rpyc(input_filename, out_filename, overwrite=False): ast = read_ast_from_file(in_file) with codecs.open(out_filename, 'w', encoding='utf-8') as out_file: - decompiler.pretty_print_ast(out_file, ast) + decompiler.pretty_print_ast(out_file, ast, ignore_python) return True if __name__ == "__main__": @@ -122,6 +122,9 @@ if __name__ == "__main__": parser.add_option('-b', '--basedir', action='store', dest='basedir', help="specify the game base directory in which the 'renpy' directory is located") + parser.add_option('-p', '--ignore-python', action='store_true', dest='ignore_python', + default=False, help="ignore python blocks") + options, args = parser.parse_args() @@ -134,7 +137,7 @@ if __name__ == "__main__": parser.print_help(); parser.error("Incorrect number of arguments: expected 2, got %d." % (len(args))) - decompile_rpyc(args[0], args[1], options.clobber) + decompile_rpyc(args[0], args[1], options.clobber, options.ignore_python) else: import_renpy() |