Tool Ren'Py Generate Missing Linux Files For Any Ren'Py Game.

NandabaCanti

Active Member
Jan 4, 2018
677
754
A lot of Ren'Py games that get shared here, and elsewhere, have had their Linux files stripped out. While these games will run fine in Wine, there is no real reason to settle for a less than native experience. For that there is a great little script available on GitHub to restore the missing Linux files.



To get started, save the renpy2linux.sh file from the above link to the directory above the one where your target game is located. So if you have the game stored somewhere like "~/games/RenPy Game" where "RenPy Game" is the name of the game and the dir where its files are stored, then you would want to save the script to the parent "games" dir. Also make sure the script is flagged as executable.

Once you have the script the next step is to discover which version of Ren'Py the game is using. Often times you will find a log.txt file in the game dir. If not, then start the game with Wine to generate one, basically as soon as it reaches the title screen you can just shut it down and check the game dir for the newly made log file. In it, near the top, you will see a line like: "Ren'Py 6.99.11.1749". You just need the first 3 sets of numbers; the "6.99.11" part of that.

Once you have that version number it is time to go back to the dir above your game, open a console in it, so that the working path matches it. Then run the shell script with the following formatting:

./renpy2linux.sh "game dir name" "Ren'Py version #"

Using the above example, it would look something like:

./renpy2linux.sh "RenPy Game" 6.9.11

Now you just wait for the script to do its thing. It could take a few minutes, longer if the Ren'Py server is being a bit slow/unresponsive, so just wait until it is done. That is pretty much it, you can now go into the game's dir and launch it using the newly generated shell script you will find there.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,862
16,010
Why not trying to get the version by yourself ?
Code:
RENPYVER=grep "^Ren'Py [0-9]\.[0-9]" log.txt | awk '{s=split($2,v,".");for(i=1;i<s;i++){r=r v[i];if(i<s-1){r=r "."}};print r}'
then you test if RENPYVER is empty and prompt the user for the version if it's the case.
[note:The awk code was tested on FreeBSD, not Linux, but normally there no port's difference at this level]
 

NandabaCanti

Active Member
Jan 4, 2018
677
754
Thanks for that snippet and I agree that there shouldn't be anything stopping that from working on Linux, since grep and awk are standard utilities here too, but I'm not the author of that script. It was just something I found on the net through some searching around for a more automated way to restore the Linux files on games.

One thing I would suggest though, to make it more fool proof, would be to grab the version from a more reliable source, if you are going to do it with code. In the renpy subdir you can find an __init__.py file that contains a variable declaration that will look something like this:

version_tuple = (6, 99, 11, vc_version)

That gives you the 3 sections of the version number you need, the vc_version part is that 4 digit bit at the end that can be ignored from the log.txt file. If you would be willing to adjust your above code snippet to use that instead it would be worth submitting it as a patch or feature suggestion to that github page.
 

Madeddy

Active Member
Dec 17, 2017
838
487
Funny. The things is, you don't need to it this way. It's easier.
The script detects and downloads the renpy v of the game, grabs there the starter for your game, copys it to your game folder renamed. One dl of ~90Mib(+/-10) for every game you do this. :WutFace:

If ren'py is anyway downloaded from the script, then you can also do it by yourself, copy your .../[insert_game-folder-name]/game/* (more is not needed) over and start it simply over the renpy launcher.

I tested it just now in the actual renpy v 6.99.14.1 with babysitter and this runs original in v 6.99.11. How far back compatibility reaches do i not know.

One renpy copy for all games. I hate the fact somewhat, that every game and update comes with a renpy copy. I have dozens of this buggers who eat my space.
Greets
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,862
16,010
One thing I would suggest though, to make it more fool proof, would be to grab the version from a more reliable source, if you are going to do it with code. In the renpy subdir you can find an __init__.py file that contains a variable declaration that will look something like this:

version_tuple = (6, 99, 11, vc_version)
Code:
RENPYVER="ERROR"
RENPYVER=grep "^version_tuple =" renpy/__init__.py | awk '{for(i=1;i<NF;i++){match($i,/[0-9]+/);if(RLENGTH!=-1){if(length(r)>0){r=r "."};r=r substr($i,RSTART,RLENGTH)}};print r}'
The awk code is fully validated, but like the only *nix I can access is a working host, I haven't made deep tests ; I used an echo instead of the real file.
Else, as security keep the first assignation. This way, testing if RENPYVER is still "ERROR" will catch every errors, including any changes in Ren'py code, then fallback to a prompt to the user.
It should do it like this, but I have a doubt regarding the grep syntax. Some blurred memories about a caveat when I ported sh scripts from Linux back in time, but I can't put my hand on it.


I tested it just now in the actual renpy v 6.99.14.1 with babysitter and this runs original in v 6.99.11. How far back compatibility reaches do i not know.
I agree that there's a way to be more efficient, by using a memory cache to keep already downloaded SDKs, by example. But I do NOT at all recommend using another version of Ren'py to fill the blank. It worked for you because the game you used for the test have a really basic code, but it can backfire quickly.
Believe me on this one, I past two months tracking changes in Ren'py for my tool, I know how tricky they can be and how a single line changed can break everything.
 
  • Like
Reactions: SenMizeri

NandabaCanti

Active Member
Jan 4, 2018
677
754
That grep/awk command seems to work as far as I can tell (for me on Manjaro anyhow). I just picked several Ren'Py games at random to run it against and each time I got the proper version number back. Should be totally worth submitting that code snippet to the Github page for the script. The author should be able to test it further as well.
 
Mar 3, 2020
106
311
This doesn't work for Ren'Py 7 games.

... so here you go! Save the following, or the attached file, as renpy7-to-linux.sh.

(v2, to fix an embarrassing bug.)


An updated version (now with support for Ren'Py 8.0.x!) is available in a dedicated thread.

You don't have permission to view the spoiler content. Log in or register now.
 
Last edited:
  • Like
Reactions: Woobydooby

Madeddy

Active Member
Dec 17, 2017
838
487
This doesn't work for Ren'Py 7 games.

... so here you go! Save the following, or the attached file, as renpy7-to-linux.sh.
Huh? You state this does'nt work with v7 but your script name suggestion says otherwise...? What is it?
o_O
Also, without v7 support i see not much use. Greets
 

Madeddy

Active Member
Dec 17, 2017
838
487
"This" meaning the script in post 1, not my script. (Mine is v7-only.)
Obviously did i not get the meaning. Thanks for clearing up and the script. (y)

For my part i use mostly a actual SDK for this and generate game distribution manually. In my experience its not good to stay in the pre v7.4 renpy versions of the v7 series, because there is a GPU performance bug in it with linux.
 
Dec 24, 2020
30
15
This doesn't work for Ren'Py 7 games.

... so here you go! Save the following, or the attached file, as renpy7-to-linux.sh.

(v2, to fix an embarrassing bug.)

Bash:
#!/bin/bash -eu

NAME=$(basename "$0")

die() {
  echo "$NAME:" "$1" 1>&2
  exit 1
}

if [ ! -d game ] || [ ! -d renpy ]; then
  die "This doesn't seem to be a Ren'Py game directory."
fi

shopt -s nullglob
PYFILES=(./*.py)
if (( ${#PYFILES[@]} > 1 )); then
  die "too many root-level .py files found"
elif (( ${#PYFILES[@]} < 1 )); then
  die "no root-level .py file found"
fi
TITLE=$(basename "${PYFILES[0]}" .py)
echo "$NAME: Converting Ren'Py title '$TITLE'..."

# Don't use `python` to get this; it might not be Python 2.
# Don't use `python2` to get this -- it might not be installed!
#
# (But we'll always have camels.)
RENPY_VERSION=$(perl -ne '
  BEGIN { $r=qr/\s*(\d+)\s*/; }
  if (/version_tuple = \($r,$r,$r/ and $1 == "7") {
    print "$1.$2.$3\n"; exit 0;
  }' renpy/__init__.py
)

if [ -z "$RENPY_VERSION" ]; then
  die "couldn't determine Ren'Py version"
fi

CACHE_DIR="$HOME/.renpy/.sdk-cache"
mkdir -p "$CACHE_DIR"

SDK_FILE="$CACHE_DIR/renpy-$RENPY_VERSION-sdk.zip"
if [ ! -f "$SDK_FILE" ]; then
  echo "$NAME: Downloading renpy-$RENPY_VERSION-sdk.zip..."
  wget -P "$CACHE_DIR" "https://www.renpy.org/dl/$RENPY_VERSION/renpy-$RENPY_VERSION-sdk.zip"
else
  echo "$NAME: Download skipped (renpy-$RENPY_VERSION-sdk.zip found in $CACHE_DIR)..."
fi

unzip -qqo "$SDK_FILE" "renpy-$RENPY_VERSION-sdk/renpy.sh" "renpy-$RENPY_VERSION-sdk/lib/linux-*"
rm -rf ./lib/linux-*
mv ./"renpy-$RENPY_VERSION-sdk"/lib/linux-* ./lib
for LINUX_LIB in ./lib/linux-*; do
  ln -sr "$LINUX_LIB/renpy" "$LINUX_LIB/$TITLE"
  chmod u+x "$LINUX_LIB"/renpy
done
mv ./"renpy-$RENPY_VERSION-sdk"/renpy.sh ./"$TITLE".sh
chmod u+x ./"$TITLE".sh
rm -rf ./"renpy-$RENPY_VERSION-sdk"

echo "$NAME: done!"
before anything, if i say stupid shit its due to the fact that im a moron
im trying to use your file to make a .sh file for a game i cant seem to run with wine, i pasted the whole thing into a blank gedit document and named it "renlinux.sh", then i threw it into the game folder and tried to execute it but i get this

renlinux.sh: Converting Ren'Py title 'AhsokaInExxxile'...
renlinux.sh: Downloading renpy-7.4.8-sdk.zip...
--2022-06-19 02:58:34--
Resolviendo ( )... 96.43.136.250
Conectando con (www.renpy.org)[96.43.136.250]:443... conectado.
ERROR: no se puede verificar el certificado de , emitido por “/C=US/O=Let's Encrypt/CN=R3”:
El certificado emitido ha expirado.
Para conectar inseguramente a , use `--no-check-certificate'.

(i speak spanish so my system is in spanish)
i tried doing : "wget --no-check-certificate " for the sake of doing what terminal does since i have no clue what to do and it seems to download a html file that when i run it, it basicly opens the website (?

may i get some help pls?
 
Mar 3, 2020
106
311
ERROR: no se puede verificar el certificado de , emitido por “/C=US/O=Let's Encrypt/CN=R3”:
El certificado emitido ha expirado.
Exactly what this says: your system thinks renpy.org's HTTPS certificate has expired. It's wrong about that, as far as I can tell — the certificate I'm getting from renpy.org doesn't expire until August 11. Is your system date set incorrectly?
 

Woobydooby

New Member
Jan 5, 2022
10
3
This doesn't work for Ren'Py 7 games.

... so here you go! Save the following, or the attached file, as renpy7-to-linux.sh.

(v2, to fix an embarrassing bug.)

Bash:
#!/bin/bash -eu

NAME=$(basename "$0")

die() {
  echo "$NAME:" "$1" 1>&2
  exit 1
}

if [ ! -d game ] || [ ! -d renpy ]; then
  die "This doesn't seem to be a Ren'Py game directory."
fi

shopt -s nullglob
PYFILES=(./*.py)
if (( ${#PYFILES[@]} > 1 )); then
  die "too many root-level .py files found"
elif (( ${#PYFILES[@]} < 1 )); then
  die "no root-level .py file found"
fi
TITLE=$(basename "${PYFILES[0]}" .py)
echo "$NAME: Converting Ren'Py title '$TITLE'..."

# Don't use `python` to get this; it might not be Python 2.
# Don't use `python2` to get this -- it might not be installed!
#
# (But we'll always have camels.)
RENPY_VERSION=$(perl -ne '
  BEGIN { $r=qr/\s*(\d+)\s*/; }
  if (/version_tuple = \($r,$r,$r/ and $1 == "7") {
    print "$1.$2.$3\n"; exit 0;
  }' renpy/__init__.py
)

if [ -z "$RENPY_VERSION" ]; then
  die "couldn't determine Ren'Py version"
fi

CACHE_DIR="$HOME/.renpy/.sdk-cache"
mkdir -p "$CACHE_DIR"

SDK_FILE="$CACHE_DIR/renpy-$RENPY_VERSION-sdk.zip"
if [ ! -f "$SDK_FILE" ]; then
  echo "$NAME: Downloading renpy-$RENPY_VERSION-sdk.zip..."
  wget -P "$CACHE_DIR" "https://www.renpy.org/dl/$RENPY_VERSION/renpy-$RENPY_VERSION-sdk.zip"
else
  echo "$NAME: Download skipped (renpy-$RENPY_VERSION-sdk.zip found in $CACHE_DIR)..."
fi

unzip -qqo "$SDK_FILE" "renpy-$RENPY_VERSION-sdk/renpy.sh" "renpy-$RENPY_VERSION-sdk/lib/linux-*"
rm -rf ./lib/linux-*
mv ./"renpy-$RENPY_VERSION-sdk"/lib/linux-* ./lib
for LINUX_LIB in ./lib/linux-*; do
  ln -sr "$LINUX_LIB/renpy" "$LINUX_LIB/$TITLE"
  chmod u+x "$LINUX_LIB"/renpy
done
mv ./"renpy-$RENPY_VERSION-sdk"/renpy.sh ./"$TITLE".sh
chmod u+x ./"$TITLE".sh
rm -rf ./"renpy-$RENPY_VERSION-sdk"

echo "$NAME: done!"
Thanks for the script! This has worked flawlessly on three v7.4.8 games. Saves the hassle of spinning up a VM and having to use that which shall not be named.

Cheers!