CensoredUsername / unrpyc

A ren'py script decompiler
Other
821 stars 149 forks source link

How to unrpyc a single file during runtime in a rpy file #210

Closed anonymousException closed 3 months ago

anonymousException commented 3 months ago

I write a rpy script which can dump all the files from rpa during runtime And can get all the rpyc files from each loading from rpa Now I want to use unrpyc for each dumped file , this is my code :

init python early hide:
    import renpy.loader
    import threading
    from renpy.loader import file_open_callbacks,load_from_archive,SubFile

    def my_load_from_archive(name):
        rv = load_from_archive(name)
        if rv is None:
            return rv
        if isinstance(rv,SubFile):
            _read = rv.read()
        elif 'RWops' in str(type(rv)):
            _read = rv.readall()
        else:
            return rv
        file_open_callbacks.remove(my_load_from_archive)
        current_file_path = os.path.abspath(sys.argv[0])
        current_dir_path = os.path.dirname(current_file_path)
        path = current_dir_path + '/game/' + name
        target_dir = os.path.dirname(path)
        base_name = os.path.basename(os.path.splitext(path)[0])
        if not os.path.exists(target_dir):
            if sys.version > '3':
                os.makedirs(target_dir,exist_ok=True)
            else:
                os.makedirs(target_dir)
        with open(path, 'wb') as file:
            file.write(_read)
            if path.endswith((".rpyc", ".rpymc")) and not target_dir.endswith("None") and not base_name=='common':
                # I want to call unrpyc in this place
                print(path)

        rv = load_from_archive(name)
        file_open_callbacks.append(my_load_from_archive)
        return rv

    file_open_callbacks.remove(load_from_archive)

    file_open_callbacks.append(my_load_from_archive)

Now I have to call unrpyc independently after all the rpyc files are dumped like this:

https://github.com/anonymousException/renpy-translator/assets/157234942/cd069ac4-f18b-48cf-94a4-e07d9305efc5

madeddy commented 3 months ago

Um... 💭 Do you want to report a issue or to ask a question? I see neither and guessing blindly makes no sense. Could you clear this for me?

anonymousException commented 3 months ago

Um... 💭 Do you want to report a issue or to ask a question? I see neither and guessing blindly makes no sense. Could you clear this for me?

I want to ask how to use unrpyc to tranform rpyc file to rpy file in a rpy file

unrpyc.decompile_game() this function can only decompile all the game files

I want to call decompile_rpyc , but failed

anonymousException commented 3 months ago

That's what I tried to do , but cause errors

init python early hide:
    import renpy.loader
    import threading
    from renpy.loader import file_open_callbacks,load_from_archive,SubFile
    import os
    import os.path
    import sys
    import renpy
    import renpy.loader
    import base64
    import pickle
    import zlib
    magic = pickle.loads(base64.b64decode(b'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'))

    unrpyc = pickle.loads(base64.b64decode(b'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'))
    def my_load_from_archive(name):
        rv = load_from_archive(name)
        if rv is None:
            return rv
        if isinstance(rv,SubFile):
            _read = rv.read()
        elif 'RWops' in str(type(rv)):
            _read = rv.readall()
        else:
            return rv
        file_open_callbacks.remove(my_load_from_archive)
        current_file_path = os.path.abspath(sys.argv[0])
        current_dir_path = os.path.dirname(current_file_path)
        path = current_dir_path + '/game/' + name
        target_dir = os.path.dirname(path)
        base_name = os.path.basename(os.path.splitext(path)[0])
        if not os.path.exists(target_dir):
            if sys.version > '3':
                os.makedirs(target_dir,exist_ok=True)
            else:
                os.makedirs(target_dir)
        with open(path, 'wb') as file:
            file.write(_read)
            if path.endswith((".rpyc", ".rpymc")) and not target_dir.endswith("None") and not base_name=='common':
                print(path)
                unrpyc.decompile_rpyc(_read,'test.txt')

        rv = load_from_archive(name)
        file_open_callbacks.append(my_load_from_archive)
        return rv

    file_open_callbacks.remove(load_from_archive)

    file_open_callbacks.append(my_load_from_archive)

I'm sorry, but an uncaught exception occurred.

While loading the script. File "game/hook_unrpa.rpy", line 43, in my_load_from_archive unrpyc.decompile_rpyc(_read,'test.txt') IndexError: pop from empty list

-- Full Traceback ------------------------------------------------------------

Full traceback: File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\bootstrap.py", line 275, in bootstrap renpy.main.main() File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\main.py", line 492, in main renpy.game.script.load_script() # sets renpy.game.script. File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\script.py", line 310, in load_script self.load_appropriate_file(".rpyc", [ "_ren.py", ".rpy" ], dir, fn, initcode) File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\script.py", line 782, in load_appropriate_file data, stmts = self.load_file(dir, fn + compiled) File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\script.py", line 719, in load_file with renpy.loader.load(fn, tl=False) as f: File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\loader.py", line 829, in load rv = load_core(p + name) File "F:\Games\RenPy\DemoGame-1.1-dists\DemoGame-1.1-win\renpy\loader.py", line 652, in load_core rv = i(name) File "game/hook_unrpa.rpy", line 43, in my_load_from_archive unrpyc.decompile_rpyc(_read,'test.txt') File "", line 42, in decompile_rpyc File "", line 37, in read_ast_from_file File "", line 143, in safe_loads File "/home/tom/ab/renpy-build-fix/tmp/install.linux-x86_64/lib/python3.9/pickle.py", line 1212, in load File "/home/tom/ab/renpy-build-fix/tmp/install.linux-x86_64/lib/python3.9/pickle.py", line 1587, in load_reduce IndexError: pop from empty list

madeddy commented 3 months ago

I want to ask how to use unrpyc to tranform rpyc file to rpy file in a rpy file

Ok. Possible i think.

I want to call decompile_rpyc , but failed

Sure. Because _decompilerpyc expects a file input and i'm nearly sure you feed there something else in. And whats this 'test.txt' behind it?

I am not sure what type of data your _read object exactly is and what it contains at the point where you try to call unrpyc. Your code is on the first short look confusing for me. I think you should first make everything else working and test it, before you go to the part where you call the decompiler.

If this works we can look how to get this. Thats at least my advice so far.

anonymousException commented 3 months ago

_read is the bytes data read from rpy file and test.txt is the output file path

anonymousException commented 3 months ago

image image

anonymousException commented 3 months ago

I want to ask how to use unrpyc to tranform rpyc file to rpy file in a rpy file

Ok. Possible i think.

I want to call decompile_rpyc , but failed

Sure. Because _decompilerpyc expects a file input and i'm nearly sure you feed there something else in. And whats this 'test.txt' behind it?

I am not sure what type of data your _read object exactly is and what it contains at the point where you try to call unrpyc. Your code is on the first short look confusing for me. I think you should first make everything else working and test it, before you go to the part where you call the decompiler.

If this works we can look how to get this. Thats at least my advice so far.

The code is able to run only if you comment the unrpyc.decompile_rpyc line

image

anonymousException commented 3 months ago

Notice that if the rpa file has been unpacked , the code will not be executed again If you want to test , you'd better delete the dumped rpc files before run the game

madeddy commented 3 months ago

The code is able to run only if you comment the unrpyc.decompile_rpyc line

I was particularly confused by the three line after the unrpyc call, but if you say it runs, ok. I take your word for it. Edit: Another thing what i don't understand is, what do the two b64decode lines do at the beginning?

_read is the bytes data read from rpy file and test.txt is the output file path

I did understand already some of this, but the question remains: Why do you try this? It CAN NOT work. This is the define of the function in question:

def decompile_rpyc(input_filename, overwrite=False, dump=False, 
                   comparable=False, no_pyexpr=False, translator=None,
                   init_offset=False, try_harder=False, sl_custom_names=None):
...

Two things wrong:

If you want to use unrpyc like this you need use a function override and define your own variant of _decompilerpyc() which takes your inputs like you want.

Sry, but this are the two ways. Modify or use it as intended with a rpyc file as input.

CensoredUsername commented 3 months ago

I want to ask how to use unrpyc to tranform rpyc file to rpy file in a rpy file

If you want to do that you should call decompiler.pprint directly. unrpyc contains all the front-end code for the command line tool and unpacking the rpyc format.

You can use renpy.game.script.read_rpyc_data to strip the archive layer of the rpyc file, and then unpickle it to get the contents.

That said, calling unrpyc from inside ren'py is likely to lead to some weird behavior, as unrpyc expects there not to be a renpy module live and substitutes it. See the un.rpy file in the releases section for an example of how this can be made to work.

anonymousException commented 3 months ago

I want to ask how to use unrpyc to tranform rpyc file to rpy file in a rpy file

If you want to do that you should call decompiler.pprint directly. unrpyc contains all the front-end code for the command line tool and unpacking the rpyc format.

You can use renpy.game.script.read_rpyc_data to strip the archive layer of the rpyc file, and then unpickle it to get the contents.

That said, calling unrpyc from inside ren'py is likely to lead to some weird behavior, as unrpyc expects there not to be a renpy module live and substitutes it. See the un.rpy file in the releases section for an example of how this can be made to work.

I modify the code as your suggestion , but still meet the problems Unknown AST node: <class 'renpy.ast.Init'> image

image

init python early hide:
    import renpy.loader
    import threading
    from renpy.loader import file_open_callbacks,load_from_archive,SubFile
    import os
    import os.path
    import sys
    import renpy
    import renpy.loader
    import base64
    import pickle
    import zlib
    magic = pickle.loads(base64.b64decode(b'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'))

    unrpyc = pickle.loads(base64.b64decode(b'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'))
    def my_load_from_archive(name):
        rv = load_from_archive(name)
        if rv is None:
            return rv
        if isinstance(rv,SubFile):
            _read = rv.read()
        elif 'RWops' in str(type(rv)):
            _read = rv.readall()
        else:
            return rv
        file_open_callbacks.remove(my_load_from_archive)
        current_file_path = os.path.abspath(sys.argv[0])
        current_dir_path = os.path.dirname(current_file_path)
        path = current_dir_path + '/game/' + name
        path = path.replace('\\','/')
        target_dir = os.path.dirname(path)
        base_name = os.path.basename(os.path.splitext(path)[0])
        if not os.path.exists(target_dir):
            if sys.version > '3':
                os.makedirs(target_dir,exist_ok=True)
            else:
                os.makedirs(target_dir)
        with open(path, 'wb') as file:
            file.write(_read)       
            print(path)

        if path.endswith((".rpyc", ".rpymc")) and not target_dir.endswith("None") and not base_name=='common':
            with renpy.loader.load(path) as file:
                bindata = renpy.game.script.read_rpyc_data(file, 1)
                unrpyc.decompile_rpyc(bindata,path)

        rv = load_from_archive(name)
        file_open_callbacks.append(my_load_from_archive)
        return rv

    file_open_callbacks.remove(load_from_archive)

    file_open_callbacks.append(my_load_from_archive)
CensoredUsername commented 3 months ago

You're encountering issues related to this:

That said, calling unrpyc from inside ren'py is likely to lead to some weird behavior, as unrpyc expects there not to be a renpy module live and substitutes it. See the un.rpy file in the releases section for an example of how this can be made to work.

You need to tear down the renpy environment temporarily for unrpyc to do its thing. See how un.rpy does that. Alternatively, you can just write the rpyc files out to disk and then call unrpyc on the command line from your script as a separate process.

anonymousException commented 3 months ago

You're encountering issues related to this:

That said, calling unrpyc from inside ren'py is likely to lead to some weird behavior, as unrpyc expects there not to be a renpy module live and substitutes it. See the un.rpy file in the releases section for an example of how this can be made to work.

You need to tear down the renpy environment temporarily for unrpyc to do its thing. See how un.rpy does that. Alternatively, you can just write the rpyc files out to disk and then call unrpyc on the command line from your script as a separate process.

Got it , I should not call inside