Tool Ren'Py rpycCorrector 1.04 - RPYC signature corrector [formerly "sigCorrector"]

yhj3388

Newbie
Game Developer
Mar 16, 2019
18
7
First of all thanks for your script, will you also update your script for renpy8.0
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,863
16,012
First of all thanks for your script, will you also update your script for renpy8.0
Perhaps.

So far unrpyc do not works with Ren'Py 8.0, so the interest is relatively limited. And in the same time unrpyc now include a feature that do the same than this script. It's more limited, but it cover 90% of the possible use.
So, I guess that it will depend on what unrpyc will be able to do once ported for Ren'Py 8.0, as well as how many games made with it need more in depth works to be "corrected".
 

yhj3388

Newbie
Game Developer
Mar 16, 2019
18
7
Perhaps.

So far unrpyc do not works with Ren'Py 8.0, so the interest is relatively limited. And in the same time unrpyc now include a feature that do the same than this script. It's more limited, but it cover 90% of the possible use.
So, I guess that it will depend on what unrpyc will be able to do once ported for Ren'Py 8.0, as well as how many games made with it need more in depth works to be "corrected".
Hmm, ok, thanks for your reply!
 

Madeddy

Active Member
Dec 17, 2017
838
487
So far unrpyc do not works with Ren'Py 8.0...
Not officially.
However i have variants in which support 7.5.x and 8.0.x. The code for it comes from a few github users(in the issues of unrpyc), user VepsrP, which maintains a UnRen variant, and myself.

Note: The currently appearing new RenPy v7.6.x and 8.1.x will need again changes on Unrpyc.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,863
16,012
However i have variants in which support 7.5.x and 8.0.x.
But it's wrote in Python 2.x, right ? What, for now, limits its use to power users who have Python on their computer and know how to use it.
Not that your fork is useless, it's the opposite, but most of those who would use it would also be able to manually do what my script do, or to write a quick update for it.

Plus, what I forgot to mention previously, the reason behind this tool was mostly that un.rpyc couldn't works with altered rpyc files. It wasn't seen as valid by Ren'Py, while the pure standalone version wasn't recognizing the rpyc files as valid. But now that un.rpy exist, normally this shouldn't be a problem anymore ; at least with the 6.x and 7.x branches. Then later with the 8.x branch once it will be updated to python 3.x.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,863
16,012
I have also a python3 port in there. To apply the compatibility changes for renpy 8.0.x it was also needed logically.
Needed is a big word, it's just easier when you are not totally crazy.

By the way, you should update the said Python 3.x version to correct unrpyc.py:214
if not overwrite and out_filename.exists:
You're testing if the method exists exist, while what you want is to call it.

The only thing I found effectively missing is that you force the use of multiprocessing, what make it unusable with the version of Python embedded by Ren'Py. The initial version handled a one only process variation, since Pool can't be "faked" in case of import error, what made it more lambda user friendly.
But it's mostly me being me, you did a great job here.
 

Madeddy

Active Member
Dec 17, 2017
838
487
You're testing if the method exists exist, while what you want is to call it.
Yeah you're right.
I bugged this accidentally, but i noticed it already shortly after this change... because it did error on testing. :whistle: I just was too lazy to commit it and its just in the luxury v1.2.0 (more of a personal unrpyc playground). The other branches are cleaner. They have just the needed code for there target use. Nothing else.
The only thing I found effectively missing is that you force the use of multiprocessing, what make it unusable with the version of Python embedded by Ren'Py.
Yes, like said this branch is experimental so i cut this out. This one is for productive use with Renpy 7.5.x and 8.0.x: (missing multiprocessing is no prob there)
I think my branch naming and description ability's need perhaps some training. :oops:

But it's mostly me being me, you did a great job here.
Thanks, but VepsrP had also his hand in there.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,863
16,012
I just was lazy to commit it and its just in the luxury v1.2.0 version(more of a personal unrpyc playground).
Don't worry, starting to fix an issue with my variable viewer I discovered that I made an update, increased the version number, compiled all the files for both Python 2.x and 3.x, compressed everything... but never uploaded it. :oops:


I think my branch naming and description ability's need perhaps some training. :oops:
To be fair, as far as I remember I didn't really looked at the version, just downloading the one for Python 3.x that was the most recent. At this time I just needed a way to be sure that I can unrpyc 8.x files if I needed it to solve an issue with my tool. So, whatever if it was effectively stable or if I had to do some bug fixing time to time, as long as I didn't have to do the whole port myself.

And finally I never had to use it before today, with just the easy to fix issue I signaled.


Edit:
Just realized that since I had it on my computer since few months, why the fuck did I thought that it was in Python 2.x ?
Don't age, it don't do good thing to your brain...
 
Last edited:
  • Haha
Reactions: Madeddy

Madeddy

Active Member
Dec 17, 2017
838
487
Do you still maintain this? And is the tool intended to work in py3?

If yes for both Q, then it could use some adjustments. Would also be nice if you add support for the game in the code quote:
Bash:
(~/.xlib/RPG/_test/AttackOnSurveyCorps-0-16-0-pc)
olli@tty2*blue $ python rpycCorrector.py
rpycCorrector - v:1.04 (c) AON/SC4X 2019-2020

/home/olli/.xlib/RPG/_test/AttackOnSurveyCorps-0-16-0-pc/rpycCorrector.py:109: DeprecationWarning: 'U' mode is deprecated
FH = open(pyOrgFile if os.path.isfile(pyOrgFile) else pyFile, "rU")
Signature: RENPY RPC2 AoSC [altered signature]
/home/olli/.xlib/RPG/_test/AttackOnSurveyCorps-0-16-0-pc/rpycCorrector.py:134: DeprecationWarning: 'U' mode is deprecated
FH = open(pyOrgFile if os.path.isfile(pyOrgFile) else pyFile, "rU")
Searching for the used RPYC encoding

/!\ Things gone wrong: RPYC files are using an unknown encoding.
Oh i forgot nearly:
Signature: RENPY RPC2 AoSC [altered signature]
If you want a rpyc from this, shoot!
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,863
16,012
Do you still maintain this? And is the tool intended to work in py3?
Not really for the first, and totally not for the second ;)
I'm already late to fix bugs in my variable viewer :(


I was thinking about something, why are we bothering with external tools ?

Initially I started working on this because un.rpyc was precisely a "rpyc" file.
But to what extend do we really need to works externally like un.rpyc is actually doing ?
To what extend should un.rpyc need to be changed for something like:
Python:
python early hide:
    # Place here the path to unrpyc files
    unrpycBase = "[...]
    if not unrpycBase in renpy.sys.path: renpy.sys.path.append( unrpycBase )

init python hide:
    import unrpyc
    unrpyc()
to works ?

And by extension, do we really need all unrpyc code ?

If you regard Ren'Py, since few years it include the Interactive Director tool, that give you the code ; through a renpy.script.Script object I guess. I never had the time to really look at it, so I'm not sure how far it goes and if it include init bloc and independent statements like define or image.
But if it cover the whole AST, then it should be possible to have a version of un.rpyc that don't need to be adjusted time to time, and that wouldn't care about rpyc obfuscation, because working directly inside Ren'Py, with Ren'Py code, after the rpyc files have been loaded by it, and by using data directly gave by Ren'Py.

If it's the case, I guess that the whole code would be below one hundred lines. Some kind of:
Python:
init python hide:
    class UnrpycFile( object ):
        def __init__( self ):
            self.lines = []

    class UnrpycLine( object ):
        def __init__( self, number, value ):
            self.lineNumber = number
            self.text = value

    # Here starts the purely hypothetical part
    def unrpyc():
        unrpycFiles = {}

        for atom in script:
            if not atom.file in unrpycFiles:
                unrpycFiles[atom.file] = UnrpycFile()

            code = format the atom entity into (multi lines if needed) text

            unrpycFiles[atom.file].lines.appened( UnrpycLine( atom.line, code ) )

        for file in unrpycFiles:
            create file
            lineNumber = 0
            for atom in sorted( unrpycFiles[file].lines, key = lambda x: x.lineNumber ):
                write blank lines if needed, accordingly to lineNumber and atom.LineNumber
                write atom.text
                lineNumber += how many line have been added
            close file

    unrpyc()
At most with the help of a hijack of "start" label, if the game need to be started for the script to be available:
Python:
init python:
    config.label_overrides["start"] = "unrpycStart"
    config.label_overrides["startOut"] = "start"

label unrpycStart:
    $ unrpyc()
    jump startOut
Hijacking "_invoke_main_menu" should also works I guess.

It wouldn't works with older versions of Ren'Py, but it's not a problem since older versions of un.rpyc works with them.

Like you know un.rpyc way more than me, take a look if you've a bit of free time. You would surely see the possibilities, and identify the possible issues, way better than me.
 

Madeddy

Active Member
Dec 17, 2017
838
487
Not really for the first, and totally not for the second ;)
No problemo.
Would have been just a small advantage as the game reappears with this now and then.
To what extend should un.rpyc need to be changed for something like: ... to works ?
In a way(!) that's what roughly happens. Just so we're on the same page and not talking diff things:
The most easy way to tell this is probably this: The injector was made Dec 2014 and some years later "another tool" appeared which does something similar...

vader_i_am_your_father.gif

Could naturally also by chance. Ask sam if you want, if he inspired was. :whistle:
  • Unren is a user executed shell/batch script.
    • It uses Ren'Pys integrated python to run the embedded* py-tools.
  • un.rpyc is a automatic renpy executed rpyc(compiled Ren'Py source file)
    • it has a single line Ren'Py code so the engine runs it
    • the rest is python and the embedded* unrpyc app.
*embedded = for unren base64 encoded and for un.rpyc pickled and zlib compressed

And by extension, do we really need all unrpyc code ?
Of the unrpyc modules included in un.rpyc you don't need:
  • astdump.py
  • translate.py
  • testcasedecompiler,py
  • deobfuscate.py is already left out
  • unrpyc.py is replaced by unrpyc-compile.py
The thing is, this three files are still imported in __init__.py and would for every release to be cut out, so you get a second file version for the injector. To much hassle i guess, even if it is not much work.

In the end it comes down to this AFAIK:
Ren'Py does never write the files it packed or compiled back to drive. Just into memory while running.
- For the archive files(rpa) Ren'Py has most of the code and the archived files where never changed. (All the rpa unpackers need not really all their code, we could Ren'Py hijack for most of it.)
- For the rpy source files its different. Ren'Py changes the code to a AST before it makes a rpyc. The engine can reverse the rpyc part and get the AST out, but has not the code to reverse it back to rpy code. There comes unrpyc into play with the "mirror" code to get the AST back to rpy code. (but not the comments, theyre gone)

In the end you can get the infos how to unpack rpa files or how to get the AST out of the rpyc from Ren'Py, regardless what the game devs did to these files. Its always in the engine. And in most case it should be possible to hijack this.
 
Last edited: