Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhanced compatibility #199

Merged
merged 4 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 36 additions & 10 deletions decompiler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ def print_transform(self, ast):
if ast.parameters is not None:
self.write(reconstruct_paraminfo(ast.parameters))

# atl attribute: since 6.10
if ast.atl is not None:
self.write(":")
self.print_atl(ast.atl)
Expand All @@ -199,6 +200,7 @@ def print_show(self, ast):
self.write("with %s" % self.paired_with)
self.paired_with = True

# atl attribute: since 6.10
if ast.atl is not None:
self.write(":")
self.print_atl(ast.atl)
Expand Down Expand Up @@ -234,6 +236,7 @@ def print_scene(self, ast):
self.write("with %s" % self.paired_with)
self.paired_with = True

# atl attribute: since 6.10
if ast.atl is not None:
self.write(":")
self.print_atl(ast.atl)
Expand Down Expand Up @@ -263,6 +266,7 @@ def print_with(self, ast):

self.paired_with = ast.paired

# paired_with attribute since 6.7.1
elif self.paired_with:
# Check if it was consumed by a show/scene statement
if self.paired_with is not True:
Expand Down Expand Up @@ -332,7 +336,7 @@ def print_label(self, ast):
self.write("label %s%s%s:" % (
ast.name,
reconstruct_paraminfo(ast.parameters),
" hide" if ast.hide else ""))
" hide" if getattr(ast, "hide", False) else ""))
self.print_nodes(ast.block, 1)
finally:
if self.missing_init:
Expand Down Expand Up @@ -544,7 +548,8 @@ def print_menu(self, ast):
self.write(" %s" % self.label_inside_menu.name)
self.label_inside_menu = None

if ast.arguments is not None:
# arguments attribute added in 7.1.4
if getattr(ast, "arguments", None) is not None:
self.write(reconstruct_arginfo(ast.arguments))

self.write(":")
Expand All @@ -558,7 +563,13 @@ def print_menu(self, ast):
self.indent()
self.write("set %s" % ast.set)

for (label, condition, block), arguments in zip(ast.items, ast.item_arguments):
# item_arguments attribute since 7.1.4
if hasattr(ast, "item_arguments"):
item_arguments = ast.item_arguments
else:
item_arguments = [None] * len(ast.items)

for (label, condition, block), arguments in zip(ast.items, item_arguments):
if self.options.translator:
label = self.options.translator.strings.get(label, label)

Expand Down Expand Up @@ -611,7 +622,8 @@ def print_python(self, ast, early=False):
self.write(" early")
if ast.hide:
self.write(" hide")
if ast.store != "store":
# store attribute added in 6.14
if getattr(ast, "store", "store") != "store":
self.write(" in ")
# Strip prepended "store."
self.write(ast.store[6:])
Expand Down Expand Up @@ -640,13 +652,18 @@ def print_define(self, ast):
priority = " %d" % (init.priority - self.init_offset)

index = ""
if ast.index is not None:
# index attribute added in 7.4
if getattr(ast, "index", None) is not None:
index = "[%s]" % ast.index.source

if ast.store == "store":
self.write("define%s %s%s %s %s" % (priority, ast.varname, index, ast.operator, ast.code.source))
# operator attribute added in 7.4
operator = getattr(ast, "operator", "=")

# store attribute added in 6.18.2
if getattr(ast, "store", "store") == "store":
self.write("define%s %s%s %s %s" % (priority, ast.varname, index, operator, ast.code.source))
else:
self.write("define%s %s.%s%s %s %s" % (priority, ast.store[6:], ast.varname, index, ast.operator, ast.code.source))
self.write("define%s %s.%s%s %s %s" % (priority, ast.store[6:], ast.varname, index, operator, ast.code.source))

@dispatch(renpy.ast.Default)
def print_default(self, ast):
Expand Down Expand Up @@ -695,7 +712,8 @@ def print_userstatement(self, ast):
self.indent()
self.write(ast.line)

if ast.block:
# block attribute since 6.13.0
if getattr(ast, "block", None):
with self.increase_indent():
self.print_lex(ast.block)

Expand Down Expand Up @@ -777,7 +795,9 @@ def print_translatestring(self, ast):
self.advance_to_line(ast.linenumber)
self.indent()
self.write('old "%s"' % string_escape(ast.old))
self.advance_to_line(ast.newloc[1])
# newlock attribute since 6.99
if hasattr(ast, "newloc"):
self.advance_to_line(ast.newloc[1])
self.indent()
self.write('new "%s"' % string_escape(ast.new))

Expand All @@ -804,6 +824,12 @@ def print_translateblock(self, ast):
def print_screen(self, ast):
self.require_init()
screen = ast.screen
if isinstance(screen, renpy.screenlang.ScreenLangScreen):
raise Exception(
"Decompiling screen language version 1 screens is no longer supported. "
"use the legacy branch of unrpyc if this is required"
)

if isinstance(screen, renpy.sl2.slast.SLScreen):
self.linenumber = sl2decompiler.pprint(
self.out_file, screen, self.options,
Expand Down
30 changes: 30 additions & 0 deletions decompiler/renpycompat.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,36 @@ def __setstate__(self, state):
else:
self.update(state)

# Before ren'py 7.5/8.0 they lived in renpy.python, so for compatibility we keep it here.
@SPECIAL_CLASSES.append
class RevertableList(magic.FakeStrict, list):
__module__ = "renpy.python"

def __new__(cls):
return list.__new__(cls)


@SPECIAL_CLASSES.append
class RevertableDict(magic.FakeStrict, dict):
__module__ = "renpy.python"

def __new__(cls):
return dict.__new__(cls)


@SPECIAL_CLASSES.append
class RevertableSet(magic.FakeStrict, set):
__module__ = "renpy.python"

def __new__(cls):
return set.__new__(cls)

def __setstate__(self, state):
if isinstance(state, tuple):
self.update(state[0].keys())
else:
self.update(state)


CLASS_FACTORY = magic.FakeClassFactory(SPECIAL_CLASSES, magic.FakeStrict)

Expand Down
60 changes: 50 additions & 10 deletions decompiler/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,31 @@ def reconstruct_paraminfo(paraminfo):
rv.append("**")
rv.append(paraminfo.extrakw)

elif hasattr(paraminfo, "extrapos"):
# ren'py 7.4 and below, python 2 style
positional = [i for i in paraminfo.parameters if i[0] in paraminfo.positional]
nameonly = [i for i in paraminfo.parameters if i not in positional]
for parameter in positional:
rv.append(sep())
rv.append(parameter[0])
if parameter[1] is not None:
rv.append("=%s" % parameter[1])
if paraminfo.extrapos:
rv.append(sep())
rv.append("*%s" % paraminfo.extrapos)
if nameonly:
if not paraminfo.extrapos:
rv.append(sep())
rv.append("*")
for parameter in nameonly:
rv.append(sep())
rv.append(parameter[0])
if parameter[1] is not None:
rv.append("=%s" % parameter[1])
if paraminfo.extrakw:
rv.append(sep())
rv.append("**%s" % paraminfo.extrakw)

else:
# ren'py 7.7/8.2 and above.
# positional only, /, positional or keyword, *, keyword only, ***
Expand Down Expand Up @@ -309,16 +334,31 @@ def reconstruct_arginfo(arginfo):
rv = ["("]
sep = First("", ", ")

# ren'py 7.5 and above, PEP 448 compliant
for i, (name, val) in enumerate(arginfo.arguments):
rv.append(sep())
if name is not None:
rv.append("%s=" % name)
elif i in arginfo.starred_indexes:
rv.append("*")
elif i in arginfo.doublestarred_indexes:
rv.append("**")
rv.append(val)
if hasattr(arginfo, "starred_indexes"):
# ren'py 7.5 and above, PEP 448 compliant
for i, (name, val) in enumerate(arginfo.arguments):
rv.append(sep())
if name is not None:
rv.append("%s=" % name)
elif i in arginfo.starred_indexes:
rv.append("*")
elif i in arginfo.doublestarred_indexes:
rv.append("**")
rv.append(val)

else:
# ren'py 7.4 and below, python 2 style
for (name, val) in arginfo.arguments:
rv.append(sep())
if name is not None:
rv.append("%s=" % name)
rv.append(val)
if arginfo.extrapos:
rv.append(sep())
rv.append("*%s" % arginfo.extrapos)
if arginfo.extrakw:
rv.append(sep())
rv.append("**%s" % arginfo.extrakw)

rv.append(")")

Expand Down
3 changes: 2 additions & 1 deletion unrpyc.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,11 @@ def read_ast_from_file(in_file):

# add some detection of ren'py 7 files
if is_rpyc_v1 or pickle_detect_python2(contents):
version = "6" if is_rpyc_v1 else "7"
with printlock:
print(
"Warning: analysis found signs that this .rpyc file was generated by ren'py \n"
" version 7 or below, while this unrpyc version targets ren'py version 8. \n"
f" version {version} or below, while this unrpyc version targets ren'py version 8. \n"
" Decompilation will still be attempted, but errors or incorrect \n"
" decompilation might occur. ")

Expand Down