From 0dece7163e3dd6ebe2e2d7bde938686ae158649b Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Thu, 18 Jan 2024 14:31:47 +0100 Subject: [PATCH 1/9] Game Downloader: Add ability to view compatible patches --- functions/crc32.py | 11 ++++++ functions/game_downloader.sh | 57 +++++++++++++++++++++++++++++++ tools/configurator.sh | 66 +++++++++++++++++++++++++++++++++++- 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 functions/crc32.py create mode 100755 functions/game_downloader.sh diff --git a/functions/crc32.py b/functions/crc32.py new file mode 100644 index 000000000..4dc8bf46c --- /dev/null +++ b/functions/crc32.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +import os, sys +import zlib + +def crc32(fileName): + prev = 0 + for eachLine in open(fileName,"rb"): + prev = zlib.crc32(eachLine, prev) + return "%X"%(prev & 0xFFFFFFFF) + +print(crc32(sys.argv[1]).lower()) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh new file mode 100755 index 000000000..d85015da6 --- /dev/null +++ b/functions/game_downloader.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +game_downloader_setup() { + crc32_cmd="python3 /app/libexec/crc32.py" + + # "hacks" is the general name which includes ROM Hacks, Homebrew and Ports + hacks_repo_url="https://raw.githubusercontent.com/Libretto7/best-romhacks/main" + hacks_db_path="$HOME/.var/app/net.retrodeck.retrodeck/data/hacks_metadata.db" + + # set up hacks database + sqlite3 $hacks_db_path < <(curl -sL "$hacks_repo_url"/db_setup.sql) + + declare -g hacks_db_cmd="sqlite3 $hacks_db_path" +} + +collect_base_rom_crc32s() { + # Register all crc32 checksums of potential base ROMs and their paths into the dictionary "base_roms" + + declare -gA base_roms + + for rom in ${roms_folder}/*/*; do + if [[ "$(basename "$rom")" != "systeminfo.txt" ]]; then + crc32="$($crc32_cmd "$rom")" + base_roms["$crc32"]="$rom" + fi + done +} + +build_patches_array() { + # Set up array that contains the names of patches compatible with available base ROMs + + declare -ga compatible_romhack_patches=() + + for base_crc32 in "${!base_roms[@]}"; do + + current_base_compatible_patches="$($hacks_db_cmd "SELECT name FROM main WHERE base_crc32 = '""$base_crc32""'")" + + if [[ ! -z "$(printf "$current_base_compatible_patches")" ]]; then # if there are compatible patches for this base + # Add available patches to array + + # TODO: Remove redundancy within this line. Puts the patches names separated by newlines into an array + IFS='|' read -r -a array_of_compatible_patches <<< $(echo "$current_base_compatible_patches" | tr '\n' '|') + + for patch in "${array_of_compatible_patches[@]}"; do + compatible_romhack_patches+=("$patch") + done + fi + done +} + +get_compatible_romhacks() { + # Provide global array "compatible_romhack_patches" which contains names of available, compatible romhack patches + + game_downloader_setup + collect_base_rom_crc32s + build_patches_array +} diff --git a/tools/configurator.sh b/tools/configurator.sh index cebebeab7..470343bf8 100644 --- a/tools/configurator.sh +++ b/tools/configurator.sh @@ -97,6 +97,7 @@ source /app/libexec/global.sh # - Browse the wiki # - USB Import tool # - Install: RetroDECK Starter Pack +# - Game Downloader # DIALOG TREE FUNCTIONS @@ -1176,7 +1177,8 @@ configurator_developer_dialog() { "Change Update Channel" "Change between normal and cooker builds" \ "Browse the Wiki" "Browse the RetroDECK wiki online" \ "USB Import" "Prepare a USB device for ROMs or import an existing collection" \ - "Install RetroDECK Starter Pack" "Install the optional RetroDECK starter pack" ) + "Install RetroDECK Starter Pack" "Install the optional RetroDECK starter pack" \ + "Game Downloader" "Install ROM Hacks, Homebrew or Ports" ) case $choice in @@ -1204,6 +1206,10 @@ configurator_developer_dialog() { configurator_developer_dialog ;; + "Game Downloader" ) + configurator_game_downloader_dialog + ;; + "" ) # No selection made or Back button clicked configurator_welcome_dialog ;; @@ -1355,6 +1361,64 @@ configurator_usb_import_dialog() { } +configurator_game_downloader_dialog() { + choice=$(zenity --list --title="RetroDECK Configurator Utility - Game Downloader" --cancel-label="Back" \ + --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ + --column="Choice" --column="Description" \ + "ROM Hack Downloader" "Install ROM Hacks which are compatible with your ROMs (Right now: Only shows compatible ROMs with Super Mario World (USA) and Super Mario Bros. (World). Can't download.)" \ + "Homebrew Downloader" "Install Homebrew (Not yet functional)" \ + "Ports Downloader" "Install Ports (Not yet functional)" ) + + case $choice in + + "ROM Hack Downloader" ) + configurator_romhack_downloader_dialog + ;; + + "Homebrew Downloader" ) + configurator_developer_dialog + ;; + + "Ports Downloader" ) + configurator_developer_dialog + ;; + + "" ) # No selection made or Back button clicked + configurator_welcome_dialog + ;; + + esac +} + +configurator_romhack_downloader_dialog() { + + get_compatible_romhacks # creates compatible_romhack_patches array + + zenity_columns=() + for hack_name in "${compatible_romhack_patches[@]}"; do + + # Get romhack info + sanitized_name="$(echo "$hack_name" | sed -e "s/'/''/g")" + hack_info="$($hacks_db_cmd "SELECT released,retro_achievements,description FROM main WHERE name = '""$sanitized_name""'")" + IFS='|' read -r -a hack_info_array <<< "$hack_info" + + # Add row of hack info + zenity_columns+=("$hack_name") + for info in "${hack_info_array[@]}"; do + zenity_columns+=("$info") + done + done + + choice=$(zenity --list --title="RetroDECK Configurator Utility - Game Downloader: ROM Hacks" --cancel-label="Back" \ + --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ + --column="ROM Hack Name" --column="Released" --column="Retro Achievements" --column="Description" \ + "${zenity_columns[@]}" ) + + echo "$choice" + + configurator_welcome_dialog +} + # START THE CONFIGURATOR configurator_welcome_dialog From c5c7e4694cbd6c9ca094e965134898f68b9967a6 Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Mon, 22 Jan 2024 16:53:17 +0100 Subject: [PATCH 2/9] Pin db setup file to commit --- functions/game_downloader.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh index d85015da6..2de149257 100755 --- a/functions/game_downloader.sh +++ b/functions/game_downloader.sh @@ -4,7 +4,7 @@ game_downloader_setup() { crc32_cmd="python3 /app/libexec/crc32.py" # "hacks" is the general name which includes ROM Hacks, Homebrew and Ports - hacks_repo_url="https://raw.githubusercontent.com/Libretto7/best-romhacks/main" + hacks_repo_url="https://raw.githubusercontent.com/Libretto7/best-romhacks/b6e2163e9707a23b209f2e3dd082fff29fb6e8c5" hacks_db_path="$HOME/.var/app/net.retrodeck.retrodeck/data/hacks_metadata.db" # set up hacks database From 6d1437e5003fe332d1e8f09986eb793da9d5f280 Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Fri, 26 Jan 2024 17:00:29 +0100 Subject: [PATCH 3/9] Fix global.sh --- functions/global.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/functions/global.sh b/functions/global.sh index 954acdda9..cb8f76e39 100644 --- a/functions/global.sh +++ b/functions/global.sh @@ -7,6 +7,7 @@ source /app/libexec/checks.sh source /app/libexec/compression.sh source /app/libexec/dialogs.sh source /app/libexec/functions.sh +source /app/libexec/game_downloader.sh source /app/libexec/multi_user.sh source /app/libexec/patching.sh source /app/libexec/post_update.sh From 60fa87c16bf26cef900dc5505fcc2e9c83d120cf Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Fri, 26 Jan 2024 19:47:19 +0100 Subject: [PATCH 4/9] Use db for data sharing between configurator and game_downloader.sh --- functions/game_downloader.sh | 46 ++++++++---------------------------- tools/configurator.sh | 41 ++++++++++++++++++++++---------- 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh index 2de149257..49b95d326 100755 --- a/functions/game_downloader.sh +++ b/functions/game_downloader.sh @@ -1,57 +1,31 @@ #!/bin/bash -game_downloader_setup() { +hacks_db_setup() { crc32_cmd="python3 /app/libexec/crc32.py" # "hacks" is the general name which includes ROM Hacks, Homebrew and Ports - hacks_repo_url="https://raw.githubusercontent.com/Libretto7/best-romhacks/b6e2163e9707a23b209f2e3dd082fff29fb6e8c5" + hacks_repo_url="https://raw.githubusercontent.com/Libretto7/best-romhacks/main" hacks_db_path="$HOME/.var/app/net.retrodeck.retrodeck/data/hacks_metadata.db" # set up hacks database + rm $hacks_db_path sqlite3 $hacks_db_path < <(curl -sL "$hacks_repo_url"/db_setup.sql) + sqlite3 $hacks_db_path < <(echo "ALTER TABLE bases ADD COLUMN local_path;") declare -g hacks_db_cmd="sqlite3 $hacks_db_path" } -collect_base_rom_crc32s() { +check_romhacks_compatibility() { # Register all crc32 checksums of potential base ROMs and their paths into the dictionary "base_roms" - declare -gA base_roms + for rom_path in ${roms_folder}/*/*; do + if [[ "$(basename "$rom_path")" != "systeminfo.txt" ]]; then - for rom in ${roms_folder}/*/*; do - if [[ "$(basename "$rom")" != "systeminfo.txt" ]]; then - crc32="$($crc32_cmd "$rom")" - base_roms["$crc32"]="$rom" - fi - done -} - -build_patches_array() { - # Set up array that contains the names of patches compatible with available base ROMs - - declare -ga compatible_romhack_patches=() - - for base_crc32 in "${!base_roms[@]}"; do - - current_base_compatible_patches="$($hacks_db_cmd "SELECT name FROM main WHERE base_crc32 = '""$base_crc32""'")" + crc32="$($crc32_cmd "$rom_path")" + sanitized_path="$(echo "$rom_path" | sed -e "s/'/''/g")" - if [[ ! -z "$(printf "$current_base_compatible_patches")" ]]; then # if there are compatible patches for this base - # Add available patches to array - - # TODO: Remove redundancy within this line. Puts the patches names separated by newlines into an array - IFS='|' read -r -a array_of_compatible_patches <<< $(echo "$current_base_compatible_patches" | tr '\n' '|') - - for patch in "${array_of_compatible_patches[@]}"; do - compatible_romhack_patches+=("$patch") - done + $hacks_db_cmd < <(echo "UPDATE bases SET local_path = '""$sanitized_path""' WHERE crc32 = '""$crc32""'") fi done } -get_compatible_romhacks() { - # Provide global array "compatible_romhack_patches" which contains names of available, compatible romhack patches - - game_downloader_setup - collect_base_rom_crc32s - build_patches_array -} diff --git a/tools/configurator.sh b/tools/configurator.sh index 470343bf8..a2d25e32c 100644 --- a/tools/configurator.sh +++ b/tools/configurator.sh @@ -91,6 +91,7 @@ source /app/libexec/global.sh # - Version-specific changelogs # - RetroDECK Credits # - Add to Steam +# - ROM Hack Downloader # - Developer Options (Hidden) # - Change Multi-user mode # - Change Update channel @@ -109,6 +110,7 @@ configurator_welcome_dialog() { "RetroDECK: Troubleshooting" "Backup data, perform BIOS / multi-disc file checks checks and emulator resets" \ "RetroDECK: About" "Show additional information about RetroDECK" \ "Sync with Steam" "Sync with Steam all the favorites games" \ + "ROM Hack Downloader" "Install ROM Hacks which are compatible with your ROMs" \ "Developer Options" "Welcome to the DANGER ZONE") else welcome_menu_options=("Presets & Settings" "Here you find various presets, tweaks and settings to customize your RetroDECK experience" \ @@ -150,6 +152,10 @@ configurator_welcome_dialog() { configurator_add_steam ;; + "ROM Hack Downloader" ) + configurator_romhack_downloader_dialog + ;; + "Developer Options" ) configurator_generic_dialog "RetroDECK Configurator - Developer Options" "The following features and options are potentially VERY DANGEROUS for your RetroDECK install!\n\nThey should be considered the bleeding-edge of upcoming RetroDECK features, and never used when you have important saves/states/roms that are not backed up!\n\nYOU HAVE BEEN WARNED!" configurator_developer_dialog @@ -1392,26 +1398,35 @@ configurator_game_downloader_dialog() { configurator_romhack_downloader_dialog() { - get_compatible_romhacks # creates compatible_romhack_patches array + hacks_db_setup + check_romhacks_compatibility # add paths of available base roms to db + + available_bases_crc32s="$($hacks_db_cmd "SELECT crc32 FROM bases WHERE local_path NOT NULL;")" zenity_columns=() - for hack_name in "${compatible_romhack_patches[@]}"; do - # Get romhack info - sanitized_name="$(echo "$hack_name" | sed -e "s/'/''/g")" - hack_info="$($hacks_db_cmd "SELECT released,retro_achievements,description FROM main WHERE name = '""$sanitized_name""'")" - IFS='|' read -r -a hack_info_array <<< "$hack_info" + while IFS= read -r base_crc32; do - # Add row of hack info - zenity_columns+=("$hack_name") - for info in "${hack_info_array[@]}"; do - zenity_columns+=("$info") - done - done + # Get info of the available hacks for this base crc32 + info_of_hacks_compatible_with_base="$($hacks_db_cmd "SELECT name,released,retro_achievements,description FROM rhacks WHERE base_crc32 = '""$base_crc32""'")" + + while IFS= read -r single_hack_info; do + + # Turn db output into array + IFS='|' read -r -a single_hack_info_array <<< "$single_hack_info" + + # Add row of hack info to zenity choices + for info in "${single_hack_info_array[@]}"; do + zenity_columns+=("$info") + done + + done <<< "$info_of_hacks_compatible_with_base" + + done <<< "$available_bases_crc32s" choice=$(zenity --list --title="RetroDECK Configurator Utility - Game Downloader: ROM Hacks" --cancel-label="Back" \ --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ - --column="ROM Hack Name" --column="Released" --column="Retro Achievements" --column="Description" \ + --column="ROM Hack Name" --column="Released" --column="RetroAchievements" --column="Description" \ "${zenity_columns[@]}" ) echo "$choice" From 9377502a9fd95c3789a5f4f8e2243d220a666064 Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Sat, 27 Jan 2024 00:37:01 +0100 Subject: [PATCH 5/9] Patches can now get downloaded --- functions/game_downloader.sh | 29 ++++++++++++++++++++++++++--- tools/configurator.sh | 3 +++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh index 49b95d326..16c79cc13 100755 --- a/functions/game_downloader.sh +++ b/functions/game_downloader.sh @@ -15,17 +15,40 @@ hacks_db_setup() { declare -g hacks_db_cmd="sqlite3 $hacks_db_path" } +db_sanitize() { + echo "$(echo "$1" | sed -e "s/'/''/g")" +} + check_romhacks_compatibility() { - # Register all crc32 checksums of potential base ROMs and their paths into the dictionary "base_roms" + # Add paths of locally available base roms to db for rom_path in ${roms_folder}/*/*; do if [[ "$(basename "$rom_path")" != "systeminfo.txt" ]]; then crc32="$($crc32_cmd "$rom_path")" - sanitized_path="$(echo "$rom_path" | sed -e "s/'/''/g")" - $hacks_db_cmd < <(echo "UPDATE bases SET local_path = '""$sanitized_path""' WHERE crc32 = '""$crc32""'") + $hacks_db_cmd < <(echo "UPDATE bases SET local_path = '""$(db_sanitize "$rom_path")""' WHERE crc32 = '""$crc32""'") fi done } +install_romhack() { + # $1: name of romhack + + set -exo pipefail + + hack_name="$1" + infos=$($hacks_db_cmd "SELECT bases.system,bases.name,bases.local_path \ + FROM bases JOIN rhacks ON bases.crc32 = rhacks.base_crc32 \ + WHERE rhacks.name = '""$(db_sanitize "$1")""'") + + IFS='|' read -r system base_name base_local_path <<< $infos + + # download patchfile + wget -q "https://github.com/Libretto7/best-romhacks/raw/main/rhacks/$system/$base_name/$hack_name/patch.tar.xz" -O "/tmp/patch.tar.xz" + + patchfile_name=$(tar -xvf "/tmp/patch.tar.xz" --directory="$roms_folder/$system") + echo "$patchfile_name" + + flips="flatpak-spawn --host flatpak run com.github.Alcaro.Flips" +} diff --git a/tools/configurator.sh b/tools/configurator.sh index a2d25e32c..e9775850f 100644 --- a/tools/configurator.sh +++ b/tools/configurator.sh @@ -103,6 +103,8 @@ source /app/libexec/global.sh # DIALOG TREE FUNCTIONS configurator_welcome_dialog() { + configurator_romhack_downloader_dialog + if [[ $developer_options == "true" ]]; then welcome_menu_options=("Presets & Settings" "Here you find various presets, tweaks and settings to customize your RetroDECK experience" \ "Open Emulator" "Launch and configure each emulators settings (for advanced users)" \ @@ -1430,6 +1432,7 @@ configurator_romhack_downloader_dialog() { "${zenity_columns[@]}" ) echo "$choice" + install_romhack "$choice" && echo "success" configurator_welcome_dialog } From 50ee06784d097c318f2d843ebd35e6a830df67b8 Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Sat, 27 Jan 2024 15:32:42 +0100 Subject: [PATCH 6/9] Romhacks are now fully installable --- functions/game_downloader.sh | 29 +++++++++++++------------ tools/configurator.sh | 41 ++++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh index 16c79cc13..10c2eb60b 100755 --- a/functions/game_downloader.sh +++ b/functions/game_downloader.sh @@ -4,15 +4,12 @@ hacks_db_setup() { crc32_cmd="python3 /app/libexec/crc32.py" # "hacks" is the general name which includes ROM Hacks, Homebrew and Ports - hacks_repo_url="https://raw.githubusercontent.com/Libretto7/best-romhacks/main" hacks_db_path="$HOME/.var/app/net.retrodeck.retrodeck/data/hacks_metadata.db" - # set up hacks database - rm $hacks_db_path - sqlite3 $hacks_db_path < <(curl -sL "$hacks_repo_url"/db_setup.sql) - sqlite3 $hacks_db_path < <(echo "ALTER TABLE bases ADD COLUMN local_path;") - + # Set up hacks database declare -g hacks_db_cmd="sqlite3 $hacks_db_path" + $hacks_db_cmd < <(curl -sL "https://raw.githubusercontent.com/Libretto7/best-romhacks/main/db_setup.sql") + $hacks_db_cmd "ALTER TABLE bases ADD COLUMN local_path;" } db_sanitize() { @@ -35,8 +32,6 @@ check_romhacks_compatibility() { install_romhack() { # $1: name of romhack - set -exo pipefail - hack_name="$1" infos=$($hacks_db_cmd "SELECT bases.system,bases.name,bases.local_path \ FROM bases JOIN rhacks ON bases.crc32 = rhacks.base_crc32 \ @@ -44,11 +39,19 @@ install_romhack() { IFS='|' read -r system base_name base_local_path <<< $infos - # download patchfile - wget -q "https://github.com/Libretto7/best-romhacks/raw/main/rhacks/$system/$base_name/$hack_name/patch.tar.xz" -O "/tmp/patch.tar.xz" + # Download patchfile + wget -q "https://github.com/Libretto7/best-romhacks/raw/main/rhacks/$system/$base_name/$hack_name/patch.tar.xz" \ + -O "/tmp/patch.tar.xz" + # Extract patchfile patchfile_name=$(tar -xvf "/tmp/patch.tar.xz" --directory="$roms_folder/$system") - echo "$patchfile_name" - - flips="flatpak-spawn --host flatpak run com.github.Alcaro.Flips" + + # Create the hack + base_name="$(basename "$base_local_path")" + ext="$(echo "${base_name##*.}")" + flatpak-spawn --host flatpak run com.github.Alcaro.Flips \ + --apply "$roms_folder/$system/$patchfile_name" "$base_local_path" "$roms_folder/$system/$hack_name.$ext" >/dev/null + + # Cleanup + rm "$roms_folder/$system/$patchfile_name" } diff --git a/tools/configurator.sh b/tools/configurator.sh index e9775850f..09bd28f78 100644 --- a/tools/configurator.sh +++ b/tools/configurator.sh @@ -103,8 +103,6 @@ source /app/libexec/global.sh # DIALOG TREE FUNCTIONS configurator_welcome_dialog() { - configurator_romhack_downloader_dialog - if [[ $developer_options == "true" ]]; then welcome_menu_options=("Presets & Settings" "Here you find various presets, tweaks and settings to customize your RetroDECK experience" \ "Open Emulator" "Launch and configure each emulators settings (for advanced users)" \ @@ -155,6 +153,7 @@ configurator_welcome_dialog() { ;; "ROM Hack Downloader" ) + configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "In order to download ROM Hacks you need to have the ROMs the hacks are based on already available. Your base ROMs need to be compatible with the hacks, otherwise those hacks will not be shown.\n\nRight now, your base ROMs need to be uncompressed for this to work.\n\nThe compatible ROM Hacks will now be listed." configurator_romhack_downloader_dialog ;; @@ -1373,13 +1372,14 @@ configurator_game_downloader_dialog() { choice=$(zenity --list --title="RetroDECK Configurator Utility - Game Downloader" --cancel-label="Back" \ --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ --column="Choice" --column="Description" \ - "ROM Hack Downloader" "Install ROM Hacks which are compatible with your ROMs (Right now: Only shows compatible ROMs with Super Mario World (USA) and Super Mario Bros. (World). Can't download.)" \ + "ROM Hack Downloader" "Install ROM Hacks which are compatible with your ROMs" \ "Homebrew Downloader" "Install Homebrew (Not yet functional)" \ "Ports Downloader" "Install Ports (Not yet functional)" ) case $choice in "ROM Hack Downloader" ) + configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "In order to download ROM Hacks you need to have the ROMs the hacks are based on already available. Your base ROMs need to be compatible with the hacks, otherwise those hacks will not be shown.\n\nRight now, your base ROMs need to be uncompressed for this to work.\n\nThe compatible ROM Hacks will now be listed." configurator_romhack_downloader_dialog ;; @@ -1399,18 +1399,18 @@ configurator_game_downloader_dialog() { } configurator_romhack_downloader_dialog() { - hacks_db_setup check_romhacks_compatibility # add paths of available base roms to db available_bases_crc32s="$($hacks_db_cmd "SELECT crc32 FROM bases WHERE local_path NOT NULL;")" zenity_columns=() - while IFS= read -r base_crc32; do # Get info of the available hacks for this base crc32 - info_of_hacks_compatible_with_base="$($hacks_db_cmd "SELECT name,released,retro_achievements,description FROM rhacks WHERE base_crc32 = '""$base_crc32""'")" + info_of_hacks_compatible_with_base="$($hacks_db_cmd "SELECT rhacks.name,bases.system,rhacks.released,rhacks.retro_achievements,rhacks.description \ + FROM bases JOIN rhacks ON bases.crc32 = rhacks.base_crc32 + WHERE bases.crc32 = '""$base_crc32""'")" while IFS= read -r single_hack_info; do @@ -1426,15 +1426,30 @@ configurator_romhack_downloader_dialog() { done <<< "$available_bases_crc32s" - choice=$(zenity --list --title="RetroDECK Configurator Utility - Game Downloader: ROM Hacks" --cancel-label="Back" \ - --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ - --column="ROM Hack Name" --column="Released" --column="RetroAchievements" --column="Description" \ - "${zenity_columns[@]}" ) + if [[ ${#zenity_columns[@]} != 0 ]]; then # Compatible base ROMs found + + choice=$(zenity --list --title="RetroDECK Configurator Utility - ROM Hack Downloader" --cancel-label="Back" \ + --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ + --column="ROM Hack Name" --column="System" --column="Released" --column="RetroAchievements" --column="Description" \ + "${zenity_columns[@]}" ) - echo "$choice" - install_romhack "$choice" && echo "success" + if [[ -z "$choice" ]]; then # no selection or back button + configurator_welcome_dialog + else + install_romhack "$choice" + rc=$? + if [[ $rc == "0" ]]; then + configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "$choice was installed successfully!" + else + configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "Something went wrong :(" + fi - configurator_welcome_dialog + configurator_romhack_downloader_dialog + fi + else # No compatible base ROMs + configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "You have no uncompressed ROMs which are compatible with the available patches." + configurator_welcome_dialog + fi } # START THE CONFIGURATOR From 63df0fa9570658d83d235487b89d6aa111794d71 Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Sat, 27 Jan 2024 15:38:15 +0100 Subject: [PATCH 7/9] Remove blank lines --- tools/configurator.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/configurator.sh b/tools/configurator.sh index 09bd28f78..cc1688c3b 100644 --- a/tools/configurator.sh +++ b/tools/configurator.sh @@ -1423,11 +1423,9 @@ configurator_romhack_downloader_dialog() { done done <<< "$info_of_hacks_compatible_with_base" - done <<< "$available_bases_crc32s" if [[ ${#zenity_columns[@]} != 0 ]]; then # Compatible base ROMs found - choice=$(zenity --list --title="RetroDECK Configurator Utility - ROM Hack Downloader" --cancel-label="Back" \ --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ --column="ROM Hack Name" --column="System" --column="Released" --column="RetroAchievements" --column="Description" \ From 9b504c9284fb9ef9c7f19dcb05884e09ae8e6139 Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Sat, 27 Jan 2024 23:37:30 +0100 Subject: [PATCH 8/9] Add flips module --- functions/game_downloader.sh | 3 +-- net.retrodeck.retrodeck.yml | 12 +++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh index 10c2eb60b..ce137e9a6 100755 --- a/functions/game_downloader.sh +++ b/functions/game_downloader.sh @@ -49,8 +49,7 @@ install_romhack() { # Create the hack base_name="$(basename "$base_local_path")" ext="$(echo "${base_name##*.}")" - flatpak-spawn --host flatpak run com.github.Alcaro.Flips \ - --apply "$roms_folder/$system/$patchfile_name" "$base_local_path" "$roms_folder/$system/$hack_name.$ext" >/dev/null + flips --apply "$roms_folder/$system/$patchfile_name" "$base_local_path" "$roms_folder/$system/$hack_name.$ext" >/dev/null # Cleanup rm "$roms_folder/$system/$patchfile_name" diff --git a/net.retrodeck.retrodeck.yml b/net.retrodeck.retrodeck.yml index 62c2b8431..75b7ffa69 100644 --- a/net.retrodeck.retrodeck.yml +++ b/net.retrodeck.retrodeck.yml @@ -470,6 +470,16 @@ modules: commit: b33d965f227fe971fd590cb022f608521b506ef3 - rd-submodules/boilr/cargo-lock.json + - name: flips + buildsystem: simple + build-commands: + - sh make.sh --cflags=-DFLATPAK + - make install PREFIX=/app + sources: + - type: git + url: https://github.com/Alcaro/Flips.git + commit: 96df78fd733ebc56d64bcfcaee7d127bfd6643d6 + # RetroArch - START # https://github.com/flathub/org.libretro.RetroArch @@ -1403,4 +1413,4 @@ modules: sources: - type: git url: https://github.com/XargonWan/RetroDECK.git - branch: THISBRANCH \ No newline at end of file + branch: THISBRANCH From 1d47d12cc50f30ef304361bf99ab6dca134be85c Mon Sep 17 00:00:00 2001 From: Libretto <> Date: Thu, 9 May 2024 14:59:52 +0200 Subject: [PATCH 9/9] ROM Hack Downloader 1.0 --- functions/crc32.py | 11 --- functions/game_downloader.sh | 56 ------------- functions/global.sh | 2 +- functions/romhack_downloader/db_setup.sql | 55 +++++++++++++ .../romhack_downloader/download_patch.py | 34 ++++++++ functions/romhack_downloader/main.py | 70 ++++++++++++++++ functions/romhack_downloader/scan_roms.py | 42 ++++++++++ functions/romhack_downloader_wrapper.sh | 9 +++ net.retrodeck.retrodeck.yml | 3 + .../python3-pip/python3-modules.json | 79 +++++++++++++++++++ tools/configurator.sh | 24 +++--- 11 files changed, 305 insertions(+), 80 deletions(-) delete mode 100644 functions/crc32.py delete mode 100755 functions/game_downloader.sh create mode 100644 functions/romhack_downloader/db_setup.sql create mode 100644 functions/romhack_downloader/download_patch.py create mode 100644 functions/romhack_downloader/main.py create mode 100644 functions/romhack_downloader/scan_roms.py create mode 100644 functions/romhack_downloader_wrapper.sh create mode 100644 rd-submodules/python3-pip/python3-modules.json diff --git a/functions/crc32.py b/functions/crc32.py deleted file mode 100644 index 4dc8bf46c..000000000 --- a/functions/crc32.py +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env python -import os, sys -import zlib - -def crc32(fileName): - prev = 0 - for eachLine in open(fileName,"rb"): - prev = zlib.crc32(eachLine, prev) - return "%X"%(prev & 0xFFFFFFFF) - -print(crc32(sys.argv[1]).lower()) diff --git a/functions/game_downloader.sh b/functions/game_downloader.sh deleted file mode 100755 index ce137e9a6..000000000 --- a/functions/game_downloader.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -hacks_db_setup() { - crc32_cmd="python3 /app/libexec/crc32.py" - - # "hacks" is the general name which includes ROM Hacks, Homebrew and Ports - hacks_db_path="$HOME/.var/app/net.retrodeck.retrodeck/data/hacks_metadata.db" - - # Set up hacks database - declare -g hacks_db_cmd="sqlite3 $hacks_db_path" - $hacks_db_cmd < <(curl -sL "https://raw.githubusercontent.com/Libretto7/best-romhacks/main/db_setup.sql") - $hacks_db_cmd "ALTER TABLE bases ADD COLUMN local_path;" -} - -db_sanitize() { - echo "$(echo "$1" | sed -e "s/'/''/g")" -} - -check_romhacks_compatibility() { - # Add paths of locally available base roms to db - - for rom_path in ${roms_folder}/*/*; do - if [[ "$(basename "$rom_path")" != "systeminfo.txt" ]]; then - - crc32="$($crc32_cmd "$rom_path")" - - $hacks_db_cmd < <(echo "UPDATE bases SET local_path = '""$(db_sanitize "$rom_path")""' WHERE crc32 = '""$crc32""'") - fi - done -} - -install_romhack() { - # $1: name of romhack - - hack_name="$1" - infos=$($hacks_db_cmd "SELECT bases.system,bases.name,bases.local_path \ - FROM bases JOIN rhacks ON bases.crc32 = rhacks.base_crc32 \ - WHERE rhacks.name = '""$(db_sanitize "$1")""'") - - IFS='|' read -r system base_name base_local_path <<< $infos - - # Download patchfile - wget -q "https://github.com/Libretto7/best-romhacks/raw/main/rhacks/$system/$base_name/$hack_name/patch.tar.xz" \ - -O "/tmp/patch.tar.xz" - - # Extract patchfile - patchfile_name=$(tar -xvf "/tmp/patch.tar.xz" --directory="$roms_folder/$system") - - # Create the hack - base_name="$(basename "$base_local_path")" - ext="$(echo "${base_name##*.}")" - flips --apply "$roms_folder/$system/$patchfile_name" "$base_local_path" "$roms_folder/$system/$hack_name.$ext" >/dev/null - - # Cleanup - rm "$roms_folder/$system/$patchfile_name" -} diff --git a/functions/global.sh b/functions/global.sh index d9d67121d..60a7d8537 100644 --- a/functions/global.sh +++ b/functions/global.sh @@ -7,7 +7,7 @@ source /app/libexec/checks.sh source /app/libexec/compression.sh source /app/libexec/dialogs.sh source /app/libexec/functions.sh -source /app/libexec/game_downloader.sh +source /app/libexec/romhack_downloader_wrapper.sh source /app/libexec/multi_user.sh source /app/libexec/patching.sh source /app/libexec/post_update.sh diff --git a/functions/romhack_downloader/db_setup.sql b/functions/romhack_downloader/db_setup.sql new file mode 100644 index 000000000..7def7fdfc --- /dev/null +++ b/functions/romhack_downloader/db_setup.sql @@ -0,0 +1,55 @@ +.nullvalue NULL + +DROP TABLE IF EXISTS base; +DROP TABLE IF EXISTS rhack; + +CREATE TABLE base ( + system TEXT NOT NULL, -- e.g. 'nes' or 'n64' + name TEXT NOT NULL, -- full name, e.g. "Super Mario Bros." + region TEXT NOT NULL, -- 'U' (USA), 'E' (Europe), 'J' (Japan) or 'W' (World) + version TEXT NOT NULL, -- normally '1.0'; revision 1 is '1.1' etc. + hash TEXT NOT NULL PRIMARY KEY, -- crc32 + local_path TEXT +); + +CREATE TABLE rhack ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + base_hash TEXT NOT NULL, + name TEXT NOT NULL, + author TEXT NOT NULL, + type TEXT, -- e.g. 'English translation'; put NULL when original hack + released TEXT, -- 'YYYY-MM-DD'; if e.g. only year and month is available do 'YYYY-MM' + version TEXT NOT NULL, -- e.g. '1.0' + retro_achievements TEXT NOT NULL, -- 'yes' or 'no' + url TEXT, -- direct download link; always prefer patches provided by RetroAchievements, if available + archive_path TEXT, -- path of the patch file inside the archive, e.g. 'patches/v1.bps' + description TEXT, -- place the whole text on a single line, no line break + FOREIGN KEY (base_hash) REFERENCES base (hash) +); + +----------------------------------------------------------- +--- ROM Hacks +----------------------------------------------------------- + +-- Base ROMs. Order these alphabetically; left-most element is most important for ordering, then next to left-most etc. +INSERT INTO base (system, name, region, version, hash) VALUES +('gba', 'Tomato Adventure', 'J', '1.0', 'e37ca939'), +('n64', 'Super Mario 64', 'U', '1.0', '3ce60709'), +('n64', 'The Legend of Zelda - Ocarina of Time', 'U', '1.2', 'cd16c529'), +('nes', 'Super Mario Bros.', 'W', '1.0', '393a432f'), +('snes', 'Super Mario World', 'U', '1.0', 'b19ed489') +; + +-- ROM Hacks. Follow ordering of base table above, so group by system first, then name of base game etc. +INSERT INTO rhack (base_hash, name, type, version, author, released, retro_achievements, url, archive_path, description) VALUES +-- Super Mario 64 +('3ce60709', 'Super Mario 64 (U)', 'Randomizer', '1.1.2', 'Arthurtilly', NULL, 'yes', 'https://github.com/RetroAchievements/RAPatches/raw/main/N64/Hacks/Super%20Mario%2064/10509-SM64-Randomizer.zip', 'SM64 - Randomizer (v1.1.2) (Arthurtilly).bps', NULL), +('3ce60709', 'Super Mario Bros. 64', NULL, '1.1', 'Kaze Emanuar', '2018-12-21', 'yes', 'https://github.com/RetroAchievements/RAPatches/raw/main/N64/Hacks/Super%20Mario%2064/13831-SM64-SMB64.7z', 'SM64 - Super Mario Bros. 64 (Kaze Emanuar).bps', 'Super Mario Bros. 64 allows you to play through 30 classic NES Super Mario Bros recreated in the Mario 64 game engine. You get infinite lives to play through the game, but are given a ‘Par’ for each level, referring to the amount of lives an average player should lose per level, and you earn points for losing as few lives as possible. There are four playable characters (Mario, Luigi, Wario and Luigi), each of which has their own unique jump height which can make the game harder or easier (we’d recommend Wario or Luigi for your first playthrough).'), +-- Super Mario Bros. +('393a432f', 'Super Mario Unlimited Deluxe', NULL, '2.4', 'frantik', '2021-03-26', 'yes', 'https://github.com/RetroAchievements/RAPatches/raw/main/NES/Hacks/Super%20Mario%20Bros/9904-SMB1-UnlimitedDeluxe.zip', 'SMB1 - Super Mario Unlimited - Deluxe (v2.4) (frantik).ips', 'Super Mario Unlimited Deluxe is a traditional-style Mario hack with difficulty ramping up from beginner to expert. It is based on the Super Mario Bros engine, but has been completely reworked into a whole new adventure.'), +-- Super Mario World +('b19ed489', 'New Super Mario World 2: Around The World', NULL, '1.3', 'Pink Gold Peach', '2019-12-10', 'yes', 'https://github.com/RetroAchievements/RAPatches/raw/main/SNES/Hacks/Super%20Mario%20World/16121-NSMW2AroundtheWorld.zip', 'SMW - New Super Mario World 2 - Around the World (v1.3) (Pink Gold Peach).bps', 'The sequel to NSMW1 The 12 Magic Orbs, this hack features 16 different worlds and 90+ unique levels filled with challenge and secrets. The hack uses a lot of ASM like custom sprites, blocks, uberASM effects and other stuff like that. Aesthetically it has a choconilla style with most of the graphics being from the original SMW with some new custom graphics.'), +('b19ed489', 'Yoshi''s Strange Quest', NULL, '1.3', 'Yoshifanatic', '2015-03-07', 'no', 'https://github.com/RetroAchievements/RAPatches/raw/main/SNES/Hacks/Super%20Mario%20World/8366-YoshisStrangeQuest.zip', 'SMW - Yoshi''s Strange Quest (v1.3) (Yoshifanatic).bps', 'This is the sequel to Mario''s Strange Quest. Picking up where Mario''s Strange Quest left off, it turns out that the part where Yoshi''s eggs hatched at the end of MSQ didn''t actually happen. What really happened after Mario beat Bowser, rescued Yoshi''s eggs, and saved the princess was that Yoshi and his sleepy friend decided to move to a new land so that he can protect his eggs from Bowser before they really hatched. So, both Yoshis do so and they find themselves in the land of Weirdonia. However, it seems that Bowser apparently insists on stealing Yoshi''s eggs, since Yoshi''s eggs were stolen again while Yoshi was out shopping. Since Mario isn''t around to help this time, Yoshi goes on a quest by himself to retrieve his eggs. However, just like Mario''s Strange Quest, this isn''t your ordinary quest. The land of Weirdonia is a strange land filled with bizarre gimmicks, weird themes, and possibly jelly filled donuts and pizza. Expect the unexpected during Yoshi''s journey.'), +-- Tomato Adventure +('e37ca939', 'Tomato Adventure (J)', 'English translation', '1.1.1', 'Unknown W. Brackets', '2021-06-17', 'yes', 'https://github.com/RetroAchievements/RAPatches/raw/main/GBA/Translation/English/9802-TomatoAdv-EnglishTranslation.zip', 'Tomato Adventure (Japan) (En) (v1.1.1) (Unknown W. Brackets).bps', NULL) +; diff --git a/functions/romhack_downloader/download_patch.py b/functions/romhack_downloader/download_patch.py new file mode 100644 index 000000000..46b982e79 --- /dev/null +++ b/functions/romhack_downloader/download_patch.py @@ -0,0 +1,34 @@ +# Copyright 2024 Libretto +# SPDX-License-Identifier: GPL-3.0-or-later + +import os, pathlib, requests +from pyunpack import Archive +from urllib.parse import urlparse + + +# return absolute path of patch +def get_patch_from_archive(archive_path, location_in_archive): + os.system("rm -rf /tmp/extract_patch") + extract_dir = "/tmp/extract_patch" + os.makedirs(extract_dir, exist_ok=True) + + Archive(archive_path).extractall(extract_dir) + return os.path.join(extract_dir, location_in_archive) + + +def directly_download(url): + file_extension = ''.join(pathlib.Path(url).suffixes) + archive_path = f"/tmp/patch_archive{file_extension}" + + request = requests.get(url) + with open(archive_path, 'wb') as file: + file.write(request.content) + return archive_path + + +# "main" function of this module +def download_patch(url, location_in_archive): + match urlparse(url).netloc: # domain + case _: # direct download possible + archive_path = directly_download(url) + return get_patch_from_archive(archive_path, location_in_archive) diff --git a/functions/romhack_downloader/main.py b/functions/romhack_downloader/main.py new file mode 100644 index 000000000..70b497005 --- /dev/null +++ b/functions/romhack_downloader/main.py @@ -0,0 +1,70 @@ +# Copyright 2024 Libretto +# SPDX-License-Identifier: GPL-3.0-or-later + +import argparse, os, pathlib, sqlite3 + +from scan_roms import scan_avail_base_roms +from download_patch import download_patch + +def parse_arguments(): + parser = argparse.ArgumentParser() + parser.add_argument('-f', '--fetch-compatible-hacks', action='store_const', const=True) + parser.add_argument('-i', '--install') + parser.add_argument('-r', '--roms-folder', required=True) + return parser.parse_args() + + +def reset_db(db): + with open('db_setup.sql', 'r') as file: + db.executescript(file.read()) + + +def construct_rhack_path(roms_folder, system, rhack_name, base_path, rhack_version, rhack_type): + rhack_dir = os.path.join(roms_folder, system, 'ROM Hacks') + os.makedirs(rhack_dir, exist_ok=True) + + rhack_extension = pathlib.Path(base_path).suffix + if rhack_type: + rhack_filename = f"{rhack_name}[{rhack_type} v{rhack_version}]{rhack_extension}" + else: + rhack_filename = f"{rhack_name}[v{rhack_version}]{rhack_extension}" + + rhack_path = os.path.join(rhack_dir, rhack_filename) + print(f"Path of the ROM Hack: {rhack_path}") + return rhack_path + + +def install_rhack(db, id, roms_folder): + db.execute(( + "SELECT rhack.url, base.local_path, base.system, rhack.name, rhack.archive_path, rhack.version, rhack.type " + "FROM base JOIN rhack ON base.hash = rhack.base_hash " + f"WHERE rhack.id = {id}" + )) + url, base_path, system, rhack_name, archive_path, rhack_version, rhack_type = db.fetchone() + + rhack_path = construct_rhack_path(roms_folder, system, rhack_name, base_path, rhack_version, rhack_type) + + patch_path = download_patch(url, archive_path) + if patch_path: os.system(f'flatpak run com.github.Alcaro.Flips --apply "{patch_path}" "{base_path}" "{rhack_path}"') + + # cleanup + os.system("rm -rf /tmp/patch_archive* /tmp/extract_patch") + + +def main(): + db_connection = sqlite3.connect('romhacks.db') + db = db_connection.cursor() + + args = parse_arguments() + + if args.fetch_compatible_hacks: + reset_db(db) + scan_avail_base_roms(db, args.roms_folder) + + if args.install: + install_rhack(db, args.install, args.roms_folder) + + db_connection.close() + + +main() diff --git a/functions/romhack_downloader/scan_roms.py b/functions/romhack_downloader/scan_roms.py new file mode 100644 index 000000000..f9878d60d --- /dev/null +++ b/functions/romhack_downloader/scan_roms.py @@ -0,0 +1,42 @@ +# Copyright 2024 Libretto +# SPDX-License-Identifier: GPL-3.0-or-later + +import os, zlib + + +def crc32(file): + prev = 0 + for each_line in open(file, 'rb'): + prev = zlib.crc32(each_line, prev) + return ("%X"%(prev & 0xFFFFFFFF)).lower() + + +def add_base_path_to_db(db, path, hash): + sanitized_path = path.replace("'", "''") + db.execute(f"UPDATE base SET local_path = '{sanitized_path}' WHERE hash = '{hash}'") + + +def scan_and_add(db, root_search_path, avail_systems): + for search_dir, avail_dirs, avail_files in os.walk(root_search_path): + + # only look at consoles that appear in our patch db + if os.path.basename(search_dir) in avail_systems: + + for file in avail_files: + if file.endswith('.txt'): continue + + rom_path = os.path.join(search_dir, file) + rom_hash = crc32(rom_path) + + add_base_path_to_db(db, rom_path, rom_hash) + + +# return a list of consoles for which patches are available +def get_avail_systems(db): + db.execute("SELECT DISTINCT system FROM base") + return [tuple[0] for tuple in db.fetchall()] + + +# "main" function of this module +def scan_avail_base_roms(db, search_path): + scan_and_add(db, search_path, get_avail_systems(db)) diff --git a/functions/romhack_downloader_wrapper.sh b/functions/romhack_downloader_wrapper.sh new file mode 100644 index 000000000..a605a1b08 --- /dev/null +++ b/functions/romhack_downloader_wrapper.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +romhack_downloader_wrapper() { + # turn ~ into path + eval expanded_roms_folder="$roms_folder" + + cd /app/libexec/romhack_downloader + python3 main.py --roms-folder "$expanded_roms_folder" "$@" +} diff --git a/net.retrodeck.retrodeck.yml b/net.retrodeck.retrodeck.yml index 9d7a82364..96f979ed1 100644 --- a/net.retrodeck.retrodeck.yml +++ b/net.retrodeck.retrodeck.yml @@ -67,6 +67,9 @@ cleanup: modules: + # pip modules for romhack downloader + - rd-submodules/python3-pip/python3-modules.json + # dependency of: CEMU, CITRA, DOLPHIN - rd-submodules/shared-modules/libusb/libusb.json diff --git a/rd-submodules/python3-pip/python3-modules.json b/rd-submodules/python3-pip/python3-modules.json new file mode 100644 index 000000000..d7ecf8009 --- /dev/null +++ b/rd-submodules/python3-pip/python3-modules.json @@ -0,0 +1,79 @@ +{ + "name": "python3-modules", + "buildsystem": "simple", + "build-commands": [], + "modules": [ + { + "name": "python3-requests", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"requests\" --no-build-isolation" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/ba/06/a07f096c664aeb9f01624f858c3add0a4e913d6c96257acb4fce61e7de14/certifi-2024.2.2-py3-none-any.whl", + "sha256": "dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/63/09/c1bc53dab74b1816a00d8d030de5bf98f724c52c1635e07681d312f20be8/charset-normalizer-3.3.2.tar.gz", + "sha256": "f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/e5/3e/741d8c82801c347547f8a2a06aa57dbb1992be9e948df2ea0eda2c8b79e8/idna-3.7-py3-none-any.whl", + "sha256": "82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/70/8e/0e2d847013cb52cd35b38c009bb167a1a26b2ce6cd6965bf26b47bc0bf44/requests-2.31.0-py3-none-any.whl", + "sha256": "58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/a2/73/a68704750a7679d0b6d3ad7aa8d4da8e14e151ae82e6fee774e6e0d05ec8/urllib3-2.2.1-py3-none-any.whl", + "sha256": "450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d" + } + ] + }, + { + "name": "python3-pyunpack", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"pyunpack\" --no-build-isolation" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/9c/cf/27d1f4b3bae5e566f94fc716e048120128cf603d5163638d22bcd0fc92d8/EasyProcess-1.1-py3-none-any.whl", + "sha256": "82eed523a0a5eb12a81fa4eacd9f342caeb3f900eb4b798740e6696ad07e63f9" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/42/ee/84c8990b08efa0265bd10fc8781ef26e3157715bf0dfa47ee3c056b513d4/entrypoint2-1.1-py2.py3-none-any.whl", + "sha256": "eeb8c327bdb65cdd1668c023a6b110b7e3d1a046fb05e043861ebd9264b3a257" + }, + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/72/20/5a6dcb0d28529ce6efe850755994c80817279eecf08620003775fda3b914/pyunpack-0.3-py2.py3-none-any.whl", + "sha256": "8f517cfc71215f37f74cf3a7668028828c68dc76f4d02e7a69f227ce978d51a3" + } + ] + }, + { + "name": "python3-patool", + "buildsystem": "simple", + "build-commands": [ + "pip3 install --verbose --exists-action=i --no-index --find-links=\"file://${PWD}\" --prefix=${FLATPAK_DEST} \"patool\" --no-build-isolation" + ], + "sources": [ + { + "type": "file", + "url": "https://files.pythonhosted.org/packages/e6/64/e9dd887985305d4cc88b09bcaaaafe5053197e5ebbeba62473f8c3cf6d80/patool-2.2.0-py2.py3-none-any.whl", + "sha256": "21db6cc2fcd77acd37768258d1ad5aa3df0f676331fd80dfb1eb628626bc9155" + } + ] + } + ] +} \ No newline at end of file diff --git a/tools/configurator.sh b/tools/configurator.sh index 889180209..3a6f679d3 100644 --- a/tools/configurator.sh +++ b/tools/configurator.sh @@ -1441,18 +1441,18 @@ configurator_game_downloader_dialog() { } configurator_romhack_downloader_dialog() { - hacks_db_setup - check_romhacks_compatibility # add paths of available base roms to db + romhack_downloader_wrapper --fetch-compatible-hacks + hacks_db_cmd="sqlite3 /app/libexec/romhack_downloader/romhacks.db" - available_bases_crc32s="$($hacks_db_cmd "SELECT crc32 FROM bases WHERE local_path NOT NULL;")" + available_base_hashes="$($hacks_db_cmd "SELECT hash FROM base WHERE local_path NOT NULL;")" zenity_columns=() - while IFS= read -r base_crc32; do + while IFS= read -r base_hash; do - # Get info of the available hacks for this base crc32 - info_of_hacks_compatible_with_base="$($hacks_db_cmd "SELECT rhacks.name,bases.system,rhacks.released,rhacks.retro_achievements,rhacks.description \ - FROM bases JOIN rhacks ON bases.crc32 = rhacks.base_crc32 - WHERE bases.crc32 = '""$base_crc32""'")" + # Get info of the available hacks for this base hash + info_of_hacks_compatible_with_base="$($hacks_db_cmd "SELECT rhack.id,rhack.name,base.system,rhack.released,rhack.retro_achievements,rhack.description \ + FROM base JOIN rhack ON base.hash = rhack.base_hash + WHERE base.hash = '""$base_hash""'")" while IFS= read -r single_hack_info; do @@ -1465,21 +1465,21 @@ configurator_romhack_downloader_dialog() { done done <<< "$info_of_hacks_compatible_with_base" - done <<< "$available_bases_crc32s" + done <<< "$available_base_hashes" if [[ ${#zenity_columns[@]} != 0 ]]; then # Compatible base ROMs found choice=$(zenity --list --title="RetroDECK Configurator Utility - ROM Hack Downloader" --cancel-label="Back" \ --window-icon="/app/share/icons/hicolor/scalable/apps/net.retrodeck.retrodeck.svg" --width=1200 --height=720 \ - --column="ROM Hack Name" --column="System" --column="Released" --column="RetroAchievements" --column="Description" \ + --column="ID" --column="ROM Hack Name" --column="System" --column="Released" --column="RetroAchievements" --column="Description" \ "${zenity_columns[@]}" ) if [[ -z "$choice" ]]; then # no selection or back button configurator_welcome_dialog else - install_romhack "$choice" + romhack_downloader_wrapper --install "$choice" rc=$? if [[ $rc == "0" ]]; then - configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "$choice was installed successfully!" + configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "The hack was installed successfully." else configurator_generic_dialog "RetroDECK Configurator - ROM Hack Downloader" "Something went wrong :(" fi