Guide: AM2R (Another Metroid 2 Remake) on RPi 4
-
@mitu said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
mkdir build && cd build [...] md_ret_require="$md_build/build/gmloader"
With this, will the retained file save to
$md_inst/
or does it keep the path structure$md_inst/build/
? Maybe I'll usebin
if it keeps the folder structure; I've seen that one used before.You don't need any
moveConfigDir
unless the configuration folder exists/will be created bygmloader
when running the game. It's usually needed if you want to expose some config file/folder in/opt/retropie/configs
, so they're available as file shares for users to inspect/copy/modify files.The configuration folder is created by
gmloader
andconfig.ini
andsave1
files were created there. I do want to expose these inopt/retropie/configs
so they're available as file shares for backup/etc.You can do the
addPort
in the configure function. If you don't find anapk
, then no port will be added - that's ok since you can't add something that doesn't exist.What if the user doesn't have the apk files yet, but we still want to set up the
emulators.cfg
so they can add their own apks and launch scripts in the future? Or do we assume that if they know how to do that, they can make their own emulators.cfg too, and we only focus on the fully-automated method?In that case, I suppose we check for the files and if there are none, we display a message that tells the user to add their file(s) and re-run the installer?
I think I still need some help with the actual function that adds the ports, too. The one I wrote is more of a workflow outline, but I don't think it's going to work as written. That's because if I just do:
for apk in /path/*.apk
...and there are .apk files, it works fine, but if there are none, then it still returns a single entry as
/path/*.apk
, which then gets passed to:addPort "gmloader" "droidports" "*" "/opt/retropie/ports/gmloader/bin/gmloader %ROM%" "/path/*.apk"
...which I imagine isn't parsed as anything useful with those wildcards in there.
I could test for files and then just do the "for" if they exist. Would that look something like this?
function add_files_gmloader() { local files=() [[ -f "$romdir/ports/droidports/*.apk" ]] && files+=("$romdir/ports/droidports/*.apk") [[ -f "$romdir/ports/droidports/*.APK" ]] && files+=("$romdir/ports/droidports/*.APK") if [[ -n "$files" ]]; then for apk in $files; do local apk_filename="${apk##*/}" local apk_basename="${apk_filename%.*}" addPort "$md_id" "droidports" "$apk_basename" "$md_inst/gmloader %ROM%" "$apk" moveConfigDir "$home/.config/$apk_basename" "$md_conf_root/droidports/$apk_basename" done else echo "No APK(s) found. Please place your APK file(s) in $romdir/ports/droidports and re-run this installer." fi } function configure_gmloader() { mkRomDir "ports/droidports" add_files_gmloader }
Again, something like that, but not quite exactly that. I don't think my
[[ ]]
test syntax is right. Or something isn't right, because I've run this slightly-modified version on my system, and while thels
shows the APK files do exist at the path, the script is still reporting "No APK(s) found" instead of echoing theaddPort
commands:pi@retropie:~ $ cat temp/foobar/test.sh function add_files_gmloader() { local home="/home/pi" local romdir="$home/RetroPie/roms" local md_conf_root="/opt/retropie/configs/ports" local md_id="gmloader" local files=() [[ -f "$romdir/ports/droidports/*.apk" ]] && files+=("$romdir/ports/droidports/*.apk") [[ -f "$romdir/ports/droidports/*.APK" ]] && files+=("$romdir/ports/droidports/*.APK") ls "$romdir/ports/droidports" if [[ -n "$files" ]]; then for apk in $files; do local apk_filename="${apk##*/}" local apk_basename="${apk_filename%.*}" echo addPort "$md_id" "droidports" "$apk_basename" "$md_inst/gmloader %ROM%" "$apk" echo moveConfigDir "$home/.config/$apk_basename" "$md_conf_root/droidports/$apk_basename" done else echo "No APK(s) found. Please place your APK file(s) in $romdir/ports/droidports and re-run this installer." fi } function configure_gmloader() { echo mkRomDir "ports/droidports" add_files_gmloader } configure_gmloader pi@retropie:~ $ bash temp/foobar/test.sh mkRomDir ports/droidports am2r_155.apk am2r_155_hq.apk FooBar.APK No APK(s) found. Please place your APK file(s) in /home/pi/RetroPie/roms/ports/droidports and re-run this installer. pi@retropie:~ $
Thoughts?
-
mkdir build && cd build [...] md_ret_require="$md_build/build/gmloader"
With this, will the retained file save to
$md_inst/
or does it keep the path structure$md_inst/build/
? Maybe I'll usebin
if it keeps the folder structure; I've seen that one used before.The filestructure is not copied, just the file(s), they'll end up in
$md_inst
(/opt/retropie/ports/gmloader
).The configuration folder is created by
gmloader
andconfig.ini
andsave1
files were created there. I do want to expose these inopt/retropie/configs
so they're available as file shares for backup/etc.Ok, but in this case you only need to run it once (in
configure
) and not for eachapk
file.What if the user doesn't have the apk files yet, but we still want to set up the
emulators.cfg
so they can add their own apks and launch scripts in the future? Or do we assume that if they know how to do that, they can make their own emulators.cfg too, and we only focus on the fully-automated method?I usually don't assume any post-configuration is needed and just copying the games and installing an emulator should be enough so that I can start the games - i.e. no fiddling necessary.
In that case, I suppose we check for the files and if there are none, we display a message that tells the user to add their file(s) and re-run the installer?
Yes, you can add a status message after configuration to show what ports have been added (based on the
.apk
files detected).I think I still need some help with the actual function that adds the ports, too. The one I wrote is more of a workflow outline, but I don't think it's going to work as written. That's because if I just do:
[...]Look at how
configedit
enumerates.cfg
files and do something similar:while read config; do config=${config//$path\//} configs+=("$config") options+=("$i" "$config") ((i++)) done < <(find "$path" -type f -regex "$include" ! -regex "$exclude" ! -regex ".*/downloaded_images/.*" | sort)
(from here).
-
@mitu said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
The configuration folder is created by
gmloader
andconfig.ini
andsave1
files were created there. I do want to expose these inopt/retropie/configs
so they're available as file shares for backup/etc.Ok, but in this case you only need to run it once (in
configure
) and not for eachapk
file....but the config folder is unique to each APK.
am2r_155.apk
->~/.config/am2r_155/
;FooBar.APK
->~/.config/FooBar/
, etc. Don't we need to do amoveConfigDir
on each of these individually, or am I missing something?I usually don't assume any post-configuration is needed and just copying the games and installing an emulator should be enough so that I can start the games - i.e. no fiddling necessary.
Fair enough. If they really want to fiddle they can do it after installing the first APK automatically, once the
emulators.cfg
is configured (or they can configure it themselves.)Yes, you can add a status message after configuration to show what ports have been added (based on the
.apk
files detected).And of course I'll want to put this in a dialog box with an "Ok" button and not just echoed to the terminal like I have here. But that's a task for later, since I still need to get the function working before I can report on what it did.
Look at how
configedit
enumerates.cfg
files and do something similar:while read config; do config=${config//$path\//} configs+=("$config") options+=("$i" "$config") ((i++)) done < <(find "$path" -type f -regex "$include" ! -regex "$exclude" ! -regex ".*/downloaded_images/.*" | sort)
(from here).
I'm gonna have to teach myself some more scripting before that makes any sense to me. I had a feeling
while read
was gonna be the way to go, but I'm less familiar with its usage, and the rest of that section is over my head.Something like:
local files=() local file while read file; do file="/path/*.apk" files+=("$file") done if [[ -n "$files" ]]; then <function to addPort on "$files"> else <message to add files and re-install> fi
...or am I way off?
-
The configuration folder is created by
gmloader
andconfig.ini
andsave1
files were created there. I do want to expose these inopt/retropie/configs
so they're available as file shares for backup/etc.Ok, but in this case you only need to run it once (in
configure
) and not for eachapk
file....but the config folder is unique to each APK.
am2r_155.apk
->~/.config/am2r_155/
;FooBar.APK
->~/.config/FooBar/
, etc. Don't we need to do amoveConfigDir
on each of these individually, or am I missing something?If each game gets its own folder, then yes, it makes sense to symlink each one, though it's not ideal. It would be better if each game would have its own config folder under
$HOME/.config/gmloader
.And of course I'll want to put this in a dialog box with an "Ok" button and not just echoed to the terminal like I have here. But that's a task for later, since I still need to get the function working before I can report on what it did.
You want to avoid dialogs which require user interaction, since the installer can run non-interactively (i.e. on upgrades).
[..]
I'm gonna have to teach myself some more scripting before that makes any sense to me. I had a feelingwhile read
was gonna be the way to go, but I'm less familiar with its usage, and the rest of that section is over my head.Something like:
local files=() local file while read file; do file="/path/*.apk" files+=("$file") done if [[ -n "$files" ]]; then <function to addPort on "$files"> else <message to add files and re-install> fi
No,
-n
is used for single value vars, not for arrays.
Use thewhile
, the whole 'magic' is in the command that lists the values which is run afterdone
:while read file; do # do something with the file done < < (# command to list the files you want to loop over)
-
@mitu said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
It would be better if each game would have its own config folder under
$HOME/.config/gmloader
.I agree but I didn't write the software. Is this something that we can config?
You want to avoid dialogs which require user interaction, since the installer can run non-interactively (i.e. on upgrades).
Okay. What, do we write it to a log, then? Would I just use
echo
then, like I've done above, or what?I was thinking, like, the user installs the module, then it doesn't find any APKs (because they haven't put any there yet, because for example the rom folder hasn't been created yet because they haven't installed it ever before). It needs to tell the user to add the APKs and re-run the installer. It needs to tell them this in a place that they will see it, and it needs to stay there long enough for them to see it.
Are there any other ports that function similar that I can check out to base this on?
Edit: I guess it's not much different than the shareware games you can provide full versions for. You either install it once or create the folder manually; then you add your game files, then you install it again to import the game files. I guess that's just how it is. So the note in the
rp_module_help
to put your APKs in the rom folder is enough, or...? It's okay that after the initial installation, we leave it in a state where theemulators.cfg
isn't configured yet?No,
-n
is used for single value vars, not for arrays.
Use thewhile
, the whole 'magic' is in the command that lists the values which is run afterdone
:while read file; do # do something with the file done < < (# command to list the files you want to loop over)
Am I getting warmer?
function configure_gmloader() { mkRomDir "ports/droidports" while read apk; do local apk_filename="${apk##*/}" local apk_basename="${apk_filename%.*}" addPort "$md_id" "droidports" "$apk_basename" "$md_inst/gmloader %ROM%" "$apk" moveConfigDir "$home/.config/$apk_basename" "$md_conf_root/droidports/$apk_basename" done < < ls "$romdir/ports/droidports/*.apk" "$romdir/ports/droidports/*.APK" }
Edit:
done < < (find "$romdir/ports/droidports" \( -name "*.apk" -o -name "*.APK" \))
??
Edit edit: not there yet. The
find
command works on its own but not in this test script?pi@retropie:~/temp/foobar $ find "/home/pi/RetroPie/roms/ports/droidports" \( -name "*.apk" -o -name "*.APK" \) /home/pi/RetroPie/roms/ports/droidports/am2r_155_hq.apk /home/pi/RetroPie/roms/ports/droidports/am2r_155.apk /home/pi/RetroPie/roms/ports/droidports/FOOBAR.APK pi@retropie:~/temp/foobar $ cat test.sh function configure_gmloader() { echo mkRomDir "ports/droidports" local home="/home/pi" local romdir="$home/RetroPie/roms" local md_conf_root="/opt/retropie/configs/ports" local md_id="gmloader" while read apk; do local apk_filename="${apk##*/}" local apk_basename="${apk_filename%.*}" echo addPort "$md_id" "droidports" "$apk_basename" "$md_inst/gmloader %ROM%" "$apk" echo moveConfigDir "$home/.config/$apk_basename" "$md_conf_root/droidports/$apk_basename" done < < (find "$romdir/ports/droidports" \( -name "*.apk" -o -name "*.APK" \)) } configure_gmloader pi@retropie:~/temp/foobar $ bash test.sh test.sh: line 14: syntax error near unexpected token `<' test.sh: line 14: ` done < < (find "$romdir/ports/droidports" \( -name "*.apk" -o -name "*.APK" \))' pi@retropie:~/temp/foobar $
-
So I got my test function working, after I found the problem (I had an extra space that wasn't supposed to be there, after the second
<
.)Is this ready for prime time? Or at least, do you see anything broken, before I give it a test-drive?
#!/usr/bin/env bash # This file is part of The RetroPie Project # # The RetroPie Project is the legal property of its developers, whose names are # too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source. # # See the LICENSE.md file at the top-level directory of this distribution and # at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md # rp_module_id="gmloader" rp_module_desc="GMLoader - play GameMaker Studio games for Android on non-Android operating systems" rp_module_help="ROM Extensions: .apk .APK\n\nCopy your APK files to $romdir/ports/droidports and then re-run this installer." rp_module_repo="git https://github.com/JohnnyonFlame/droidports.git master faf3970" rp_module_licence="GPL3 https://github.com/JohnnyonFlame/droidports/blob/master/LICENSE.md" rp_module_section="exp" rp_module_flags="!all rpi4" function depends_gmloader() { getDepends libopenal-dev libfreetype6-dev zlib1g-dev libbz2-dev libpng-dev libzip-dev libsdl2-image-dev cmake } function sources_gmloader() { gitPullOrClone } function build_gmloader() { mkdir build && cd build cmake CMakeLists.txt -DCMAKE_BUILD_TYPE=Release -DPLATFORM=linux -DPORT=gmloader .. make md_ret_require="$md_build/build/gmloader" } function install_gmloader() { md_ret_files="$md_build/build/gmloader" } function configure_gmloader() { mkRomDir "ports/droidports" while read apk; do local apk_filename="${apk##*/}" local apk_basename="${apk_filename%.*}" addPort "$md_id" "droidports" "$apk_basename" "$md_inst/gmloader %ROM%" "$apk" moveConfigDir "$home/.config/$apk_basename" "$md_conf_root/droidports/$apk_basename" done < <(find "$romdir/ports/droidports" \( -name "$*.apk" -o -name "*.APK" \)) }
EDIT: something still didn't work:
pi@retropie:~/RetroPie-Setup/logs $ tail rps_2021-11-29_201831.log [ 96%] Building C object CMakeFiles/gmloader.dir/platform/linux/so_util_linux.c.o [100%] Linking C executable gmloader [100%] Built target gmloader /home/pi /home/pi/RetroPie-Setup/tmp/build/gmloader /home/pi Could not successfully install GMLoader - play GameMaker Studio games for Android on non-Android operating systems (/home/pi/RetroPie-Setup/tmp/build/gmloader//home/pi/RetroPie-Setup/tmp/build/gmloader/build/gmloader not found). /home/pi Log ended at: Mon 29 Nov 2021 08:19:28 PM PST Total running time: 0 hours, 0 mins, 57 secs pi@retropie:~/RetroPie-Setup/logs $
Looking through the other modules, it seems no one is using
md_ret_files
like I am. I changed it to justmd_ret_files="build/gmloader"
(no $md_build/ path), and it did complete.Now, two issues:
The executable from the installation differs from the one I built manually. I can't test if it works or not until tomorrow, probably. But why aren't they identical?
Only one of my APK files was configured with a
~/.config
folder and launch script. The droidports folder hasam2r_155.apk am2r_155_hq.apk FOOBAR.APK
; only the dummy apk FOOBAR was configured when I ran the install. When I bash my test function, it returns all three:pi@retropie:~ $ bash temp/foobar/test.sh mkRomDir ports/droidports addPort gmloader droidports FOOBAR /opt/retropie/ports/gmloader/gmloader %ROM% /home/pi/RetroPie/roms/ports/droidports/FOOBAR.APK moveConfigDir /home/pi/.config/FOOBAR /opt/retropie/configs/ports/droidports/FOOBAR addPort gmloader droidports am2r_155_hq /opt/retropie/ports/gmloader/gmloader %ROM% /home/pi/RetroPie/roms/ports/droidports/am2r_155_hq.apk moveConfigDir /home/pi/.config/am2r_155_hq /opt/retropie/configs/ports/droidports/am2r_155_hq addPort gmloader droidports am2r_155 /opt/retropie/ports/gmloader/gmloader %ROM% /home/pi/RetroPie/roms/ports/droidports/am2r_155.apk moveConfigDir /home/pi/.config/am2r_155 /opt/retropie/configs/ports/droidports/am2r_155 pi@retropie:~ $
-
@sleve_mcdichael said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
Are there any other ports that function similar that I can check out to base this on?
Yes, Quake2 or Wolfenstein work similarly - if the games are detected during install, then the corresponding port entries are added. For printing messages, I think there's a
printMsgs
helper function you can use.The executable from the installation differs from the one I built manually. I can't test if it works or not until tomorrow, probably. But why aren't they identical?
Compilation flags may be different, the setup script tries to optimize the build by adding platform specific tweaks.
-
Only one of my APK files was configured with a ~/.config folder and launch script.
Found the typo!
-
@sleve_mcdichael i would like to include your script in my Port list I have going here once its all done of course
and have it posted on my Github for easy download and install.
Of course you get full creditcant wait to give it a try
-
@mitu said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
Compilation flags may be different, the setup script tries to optimize the build by adding platform specific tweaks.
The installed version still runs the game and loads my save.
Why does it say "update is available", immediately after installation?
I found the typo that broke the
configure
function.I think this is almost ready.
It doesn't log very much. There's a "-debug" version we can build that is more verbose. Should we build & install them both at the same time so the
-debug
version is available from the start, or split it up into two separate modules so the initial installation is more streamlined, but users can still install the debug version only if they need it?Pro-combined:
Only clone into the repo once
Both executables in the same/opt/retropie/ports/gmloader
directory
Cons:
Takes longer since it has to build both (but, it's only like a minute for each one.)
Extra file (but only 1.5MB) that they may not even need.Pro-split:
Faster installation (each) since it only builds the one you need.
Cons:
Have to clone into the repo two times if you want to install both versions.
Executables in separategmloader
andgmloader-debug
dirs. -
@sleve_mcdichael said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
Why does it say "update is available", immediately after installation?
Probably because your script is not commited to the git repo and the setup script doesn't know the date of its last modification.
Should we build & install them both at the same time so the -debug version is available from the start, or split it up into two separate modules so the initial installation is more streamlined, but users can still install the debug version only if they need it?
I don't think it's needed.
-
@mitu said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
@sleve_mcdichael said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
I don't think it's needed.Sure, less is more, right? I think it's ready to go live, then. Please test:
wget https://raw.githubusercontent.com/s1eve-mcdichae1/GMLoader-RPi/main/gmloader.sh -P $HOME/RetroPie-Setup/scriptmodules/ports/
If for some reason the debug module is desired, then just edit the file, find the "build" function and change
-DCMAKE_BUILD_TYPE=Release
to-DCMAKE_BUILD_TYPE=Debug
, then re-install. This will log verbose output toruncommand.log
. -
@sleve_mcdichael works great.
I will be linking your script on my post. if you dont mind.Now we need a list of the games that will work. lol
-
@exarkuniv said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
Now we need a list of the games that will work. lol
I don't know how to get any of the rest of these or how to get them in APK format, but there's a partial list here:
www.reddit.com/r/AM2R/comments/pgp2x7/am2r_raspberry_pi_take_4/hbh8vgr
- Minit (Android, linux w/ wrapper)
- Downwell (linux w/ wrapper, game crashes on death, still haven't investigated why)
- Maldita Castilla (ouya)
- Retro Highway (Android)
- Underswap Demo (Android)
- Nuclear Throne (Linux build converted to gms1.4.1804 + wrapper)
- AM2R 1.5.2 and 1.5.5 (Android)
- Psycron Demo (Windows w/ Wrapper)
- Unworthy (Windows w/ Wrapper, runs too slow to be usable even on pi4)
Someone also mentioned Gato Roboto, which looks cool as heck.
-
@sleve_mcdichael its better then nothing.
still very cool
-
Update: refined the "find" command that configured the games. Now uses:
done < <(find "$romdir/ports/droidports" -maxdepth 1 -type f \( -name "*.apk" -o -name "*.APK" \))
1:
-type f
- we don't want to return directories even if they're called*.apk
. This forces it to only return files.2:
-maxdepth 1
- nothing inherently wrong with using subdirs and normally it would work just fine, but if a user has two files with the same name in different dirs (for example, bothFooBar.apk
andsubdir/FooBar.apk
) then their launch scripts and config dirs will conflict. Setting -maxdepth 1 forces it to only return files in the main droidports directory so there can be no filename conflicts. (Edit: FooBar.apk and FooBar.APK would still conflict. Don't do that, I guess. Anyone know a way to safeguard against this that's simple and easy enough for a noob like me to understand?) -
@sleve_mcdichael
find
knows about-iname
, the command can be shortened tofind "$romdir/ports/droidports" -maxdepth 1 -type f -iname \*.apk
-
@mitu said in Guide: AM2R (Another Metroid 2 Remake) on Pi 4:
\*.apk
That's the same as
"*.apk"
? Is one preferred or "more correct" over the other? -
@sleve_mcdichael It's just shorter, you can use which version you prefer.
-
I tried the port and AM2R works without issues on my Pi4. Great work !
Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.
Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.