Update_RetroDriven.sh 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. #!/bin/bash
  2. # This program is free software: you can redistribute it and/or modify
  3. # it under the terms of the GNU General Public License as published by
  4. # the Free Software Foundation, either version 3 of the License, or
  5. # (at your option) any later version.
  6. # This program is distributed in the hope that it will be useful,
  7. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. # GNU General Public License for more details.
  10. # You should have received a copy of the GNU General Public License
  11. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. # Copyright 2018-2019 Alessandro "Locutus73" Miele
  13. # You can download the latest version of this script from:
  14. # https://github.com/MiSTer-devel/Updater_script_MiSTer
  15. # RetroDriven v1.0 - Changed Script as needed
  16. #========= USER OPTIONS =========
  17. #Base directory for all script’s tasks, "/media/fat" for SD root, "/media/usb0" for USB drive root.
  18. BASE_PATH="/media/fat"
  19. #Directories where all core categories will be downloaded.
  20. declare -A CORE_CATEGORY_PATHS
  21. CORE_CATEGORY_PATHS["arcade-cores"]="$BASE_PATH/_RetroDriven"
  22. #Specifies if old files (cores, main MiSTer executable, menu, SD-Installer, etc.) will be deleted as part of an update.
  23. DELETE_OLD_FILES="true"
  24. #Specifies what to do with new cores not installed locally:
  25. #true for downloading new cores in the standard directories (see CORE_CATEGORY_PATHS),
  26. #false for not downloading new cores at all,
  27. #a string value, i.e. "NewCores", for downloading new cores in the "NewCores" subdirectory.
  28. DOWNLOAD_NEW_CORES="true"
  29. #Specifies if the "Arcade-" prefix will be removed in local arcade cores.
  30. REMOVE_ARCADE_PREFIX="true"
  31. #A space separated list of filters for the online repositories;
  32. #each filter can be part of the repository name or a whole core category,
  33. #i.e. “C64 Minimig NES SNES arcade-cores” if you want the script to check only
  34. #for C64, Minimig, NES, SNES, and all arcade cores repositories making the whole
  35. #update process quicker;
  36. #if you use this option probably you want DOWNLOAD_NEW_CORES="true" so that you
  37. #can use this filter in order to setup a brand new empty SD with only the cores
  38. #you need, otherwise cores in the filter, but not on the SD won't be downloaded.
  39. REPOSITORIES_FILTER=""
  40. #Specifies if the cheats will be downloaded/updated from https://gamehacking.org/
  41. #"true" for checking for updates each time, "false" for disabling the function,
  42. #"once" for downloading cheats just once if not on the SD card (no further updating).
  43. UPDATE_CHEATS="false"
  44. #EXPERIMENTAL: specifies if the Kernel, the Linux filesystem and the bootloader will be updated; use it at your own risk!
  45. UPDATE_LINUX="false"
  46. #EXPERIMENTAL: specifies if the update process must be done with parallel processing; use it at your own risk!
  47. PARALLEL_UPDATE="false"
  48. #Specifies an optional URL with a text file containing a curated list of "good" cores.
  49. #If a core is specified there, it will be preferred over the latest "bleeding edge" core in its repository.
  50. #The text file can be something simple as "Genesis_20190712.rbf SNES_20190703.rbf".
  51. GOOD_CORES_URL=""
  52. #Specifies if the core directory (i.e. /media/fat/Amiga for Minimig core, /media/fat/SNES for SNES core) has to be created
  53. #the first time the core is downloaded.
  54. CREATE_CORES_DIRECTORIES="false"
  55. #========= ADVANCED OPTIONS =========
  56. #ALLOW_INSECURE_SSL="true" will check if SSL certificate verification (see https://curl.haxx.se/docs/sslcerts.html )
  57. #is working (CA certificates installed) and when it's working it will use this feature for safe curl HTTPS downloads,
  58. #otherwise it will use --insecure option for disabling SSL certificate verification.
  59. #If CA certificates aren't installed it's advised to install them (i.e. using security_fixes.sh).
  60. #ALLOW_INSECURE_SSL="false" will never use --insecure option and if CA certificates aren't installed
  61. #any download will fail.
  62. ALLOW_INSECURE_SSL="true"
  63. CURL_RETRY="--connect-timeout 15 --max-time 120 --retry 3 --retry-delay 5"
  64. SCRIPTS_PATH="Scripts"
  65. OLD_SCRIPTS_PATH="#Scripts"
  66. WORK_PATH="/media/fat/$SCRIPTS_PATH/.mister_updater"
  67. #Uncomment this if you want the script to sync the system date and time with a NTP server
  68. #NTP_SERVER="0.pool.ntp.org"
  69. AUTOREBOOT="false"
  70. REBOOT_PAUSE=0
  71. TEMP_PATH="/tmp"
  72. TO_BE_DELETED_EXTENSION="to_be_deleted"
  73. sleep 2
  74. echo
  75. echo "RetroDriven Core Updater - A Festivus for the rest of us!"
  76. echo
  77. #========= CODE STARTS HERE =========
  78. ORIGINAL_SCRIPT_PATH="$0"
  79. if [ "$ORIGINAL_SCRIPT_PATH" == "bash" ]
  80. then
  81. ORIGINAL_SCRIPT_PATH=$(ps | grep "^ *$PPID " | grep -o "[^ ]*$")
  82. fi
  83. INI_PATH=${ORIGINAL_SCRIPT_PATH%.*}.ini
  84. if [ -f $INI_PATH ]
  85. then
  86. eval "$(cat $INI_PATH | tr -d '\r')"
  87. fi
  88. if [ -d "${BASE_PATH}/${OLD_SCRIPTS_PATH}" ] && [ ! -d "${BASE_PATH}/${SCRIPTS_PATH}" ]
  89. then
  90. mv "${BASE_PATH}/${OLD_SCRIPTS_PATH}" "${BASE_PATH}/${SCRIPTS_PATH}"
  91. echo "Moved"
  92. echo "${BASE_PATH}/${OLD_SCRIPTS_PATH}"
  93. echo "to"
  94. echo "${BASE_PATH}/${SCRIPTS_PATH}"
  95. echo "please relaunch the script."
  96. exit 3
  97. fi
  98. SSL_SECURITY_OPTION=""
  99. curl $CURL_RETRY -q https://github.com &>/dev/null
  100. case $? in
  101. 0)
  102. ;;
  103. 60)
  104. if [ "$ALLOW_INSECURE_SSL" == "true" ]
  105. then
  106. SSL_SECURITY_OPTION="--insecure"
  107. else
  108. echo "CA certificates need"
  109. echo "to be fixed for"
  110. echo "using SSL certificate"
  111. echo "verification."
  112. echo "Please fix them i.e."
  113. echo "using security_fixes.sh"
  114. exit 2
  115. fi
  116. ;;
  117. *)
  118. echo "No Internet connection"
  119. exit 1
  120. ;;
  121. esac
  122. ## sync with a public time server
  123. if [[ -n "${NTP_SERVER}" ]] ; then
  124. echo "Syncing date and time with"
  125. echo "${NTP_SERVER}"
  126. # (-b) force time reset, (-s) write output to syslog, (-u) use
  127. # unprivileged port for outgoing packets to workaround firewalls
  128. ntpdate -b -s -u "${NTP_SERVER}"
  129. echo
  130. fi
  131. mkdir -p "${CORE_CATEGORY_PATHS[@]}"
  132. declare -A NEW_CORE_CATEGORY_PATHS
  133. if [ "$DOWNLOAD_NEW_CORES" != "true" ] && [ "$DOWNLOAD_NEW_CORES" != "false" ] && [ "$DOWNLOAD_NEW_CORES" != "" ]
  134. then
  135. for idx in "${!CORE_CATEGORY_PATHS[@]}"; do
  136. NEW_CORE_CATEGORY_PATHS[$idx]=$(echo ${CORE_CATEGORY_PATHS[$idx]} | sed "s/$(echo $BASE_PATH | sed 's/\//\\\//g')/$(echo $BASE_PATH | sed 's/\//\\\//g')\/$DOWNLOAD_NEW_CORES/g")
  137. done
  138. mkdir -p "${NEW_CORE_CATEGORY_PATHS[@]}"
  139. fi
  140. CORE_URLS=$(curl $CURL_RETRY $SSL_SECURITY_OPTION -sLf "https://github.com/RetroDriven/Mister/wiki" | grep -io '\(https://github.com/RetroDriven/MiSTer_UnofficialCores/tree/master/Arcade_Cores/[a-zA-Z0-9./_-]*\)\|\(user-content-[a-z-]*\)')
  141. CORE_CATEGORY="-"
  142. SD_INSTALLER_PATH=""
  143. REBOOT_NEEDED="false"
  144. CORE_CATEGORIES_FILTER=""
  145. GOOD_CORES=""
  146. if [ "$GOOD_CORES_URL" != "" ]
  147. then
  148. GOOD_CORES=$(curl $CURL_RETRY $SSL_SECURITY_OPTION -sLf "$GOOD_CORES_URL")
  149. fi
  150. function checkCoreURL {
  151. echo "Checking $(echo $CORE_URL | sed 's/.*\///g' | sed 's/_MiSTer//gI')"
  152. [ "${SSH_CLIENT}" != "" ] && echo "URL: $CORE_URL"
  153. if echo "$CORE_URL" | grep -q "SD-Installer"
  154. then
  155. RELEASES_URL="$CORE_URL"
  156. else
  157. RELEASES_URL=https://github.com$(curl $CURL_RETRY $SSL_SECURITY_OPTION -sLf "$CORE_URL" | grep -o '/RetroDriven/[a-zA-Z0-9./_-]*/tree/master/[a-zA-Z0-9./_-]*/releases' | head -n1)
  158. fi
  159. RELEASE_URLS=$(curl $CURL_RETRY $SSL_SECURITY_OPTION -sLf "$RELEASES_URL" | grep -o '/RetroDriven/[a-zA-Z0-9./_-]*_[0-9]\{8\}[a-zA-Z]\?\(\.rbf\|\.rar\)\?')
  160. MAX_VERSION=""
  161. MAX_RELEASE_URL=""
  162. GOOD_CORE_VERSION=""
  163. for RELEASE_URL in $RELEASE_URLS; do
  164. if echo "$RELEASE_URL" | grep -q "SharpMZ"
  165. then
  166. RELEASE_URL=$(echo "$RELEASE_URL" | grep '\.rbf$')
  167. fi
  168. if echo "$RELEASE_URL" | grep -q "Atari800"
  169. then
  170. if [ "$CORE_CATEGORY" == "cores" ]
  171. then
  172. RELEASE_URL=$(echo "$RELEASE_URL" | grep '800_[0-9]\{8\}[a-zA-Z]\?\.rbf$')
  173. else
  174. RELEASE_URL=$(echo "$RELEASE_URL" | grep '5200_[0-9]\{8\}[a-zA-Z]\?\.rbf$')
  175. fi
  176. fi
  177. CURRENT_VERSION=$(echo "$RELEASE_URL" | grep -o '[0-9]\{8\}[a-zA-Z]\?')
  178. if [ "$GOOD_CORES" != "" ]
  179. then
  180. GOOD_CORE_VERSION=$(echo "$GOOD_CORES" | grep -wo "$(echo "$RELEASE_URL" | sed 's/.*\///g')" | grep -o '[0-9]\{8\}[a-zA-Z]\?')
  181. if [ "$GOOD_CORE_VERSION" != "" ]
  182. then
  183. MAX_VERSION=$CURRENT_VERSION
  184. MAX_RELEASE_URL=$RELEASE_URL
  185. break
  186. fi
  187. fi
  188. if [[ "$CURRENT_VERSION" > "$MAX_VERSION" ]]
  189. then
  190. MAX_VERSION=$CURRENT_VERSION
  191. MAX_RELEASE_URL=$RELEASE_URL
  192. fi
  193. done
  194. FILE_NAME=$(echo "$MAX_RELEASE_URL" | sed 's/.*\///g')
  195. if [ "$CORE_CATEGORY" == "arcade-cores" ] && [ $REMOVE_ARCADE_PREFIX == "true" ]
  196. then
  197. FILE_NAME=$(echo "$FILE_NAME" | sed 's/Arcade-//gI')
  198. fi
  199. BASE_FILE_NAME=$(echo "$FILE_NAME" | sed 's/_[0-9]\{8\}.*//g')
  200. CURRENT_DIRS="${CORE_CATEGORY_PATHS[$CORE_CATEGORY]}"
  201. if [ "${NEW_CORE_CATEGORY_PATHS[$CORE_CATEGORY]}" != "" ]
  202. then
  203. CURRENT_DIRS=("$CURRENT_DIRS" "${NEW_CORE_CATEGORY_PATHS[$CORE_CATEGORY]}")
  204. fi
  205. if [ "$CURRENT_DIRS" == "" ]
  206. then
  207. CURRENT_DIRS=("$BASE_PATH")
  208. fi
  209. if [ "$BASE_FILE_NAME" == "MiSTer" ] || [ "$BASE_FILE_NAME" == "menu" ] || { echo "$CORE_URL" | grep -q "SD-Installer"; }
  210. then
  211. mkdir -p "$WORK_PATH"
  212. CURRENT_DIRS=("$WORK_PATH")
  213. fi
  214. CURRENT_LOCAL_VERSION=""
  215. MAX_LOCAL_VERSION=""
  216. for CURRENT_DIR in "${CURRENT_DIRS[@]}"
  217. do
  218. for CURRENT_FILE in "$CURRENT_DIR/$BASE_FILE_NAME"*
  219. do
  220. if [ -f "$CURRENT_FILE" ]
  221. then
  222. if echo "$CURRENT_FILE" | grep -q "$BASE_FILE_NAME\_[0-9]\{8\}[a-zA-Z]\?\(\.rbf\|\.rar\)\?$"
  223. then
  224. CURRENT_LOCAL_VERSION=$(echo "$CURRENT_FILE" | grep -o '[0-9]\{8\}[a-zA-Z]\?')
  225. if [ "$GOOD_CORE_VERSION" != "" ]
  226. then
  227. if [ "$CURRENT_LOCAL_VERSION" == "$GOOD_CORE_VERSION" ]
  228. then
  229. MAX_LOCAL_VERSION=$CURRENT_LOCAL_VERSION
  230. else
  231. if [ "$MAX_LOCAL_VERSION" == "" ]
  232. then
  233. MAX_LOCAL_VERSION="00000000"
  234. fi
  235. if [ $DELETE_OLD_FILES == "true" ]
  236. then
  237. mv "${CURRENT_FILE}" "${CURRENT_FILE}.${TO_BE_DELETED_EXTENSION}" > /dev/null 2>&1
  238. fi
  239. fi
  240. else
  241. if [[ "$CURRENT_LOCAL_VERSION" > "$MAX_LOCAL_VERSION" ]]
  242. then
  243. MAX_LOCAL_VERSION=$CURRENT_LOCAL_VERSION
  244. fi
  245. if [[ "$MAX_VERSION" > "$CURRENT_LOCAL_VERSION" ]] && [ $DELETE_OLD_FILES == "true" ]
  246. then
  247. # echo "Moving $(echo ${CURRENT_FILE} | sed 's/.*\///g')"
  248. mv "${CURRENT_FILE}" "${CURRENT_FILE}.${TO_BE_DELETED_EXTENSION}" > /dev/null 2>&1
  249. fi
  250. fi
  251. fi
  252. fi
  253. done
  254. if [ "$MAX_LOCAL_VERSION" != "" ]
  255. then
  256. break
  257. fi
  258. done
  259. if [[ "$MAX_VERSION" > "$MAX_LOCAL_VERSION" ]]
  260. then
  261. if [ "$DOWNLOAD_NEW_CORES" != "false" ] || [ "$MAX_LOCAL_VERSION" != "" ] || [ "$BASE_FILE_NAME" == "MiSTer" ] || [ "$BASE_FILE_NAME" == "menu" ] || { echo "$CORE_URL" | grep -q "SD-Installer"; }
  262. then
  263. echo "Downloading $FILE_NAME"
  264. [ "${SSH_CLIENT}" != "" ] && echo "URL: https://github.com$MAX_RELEASE_URL?raw=true"
  265. if curl $CURL_RETRY $SSL_SECURITY_OPTION -L "https://github.com$MAX_RELEASE_URL?raw=true" -o "$CURRENT_DIR/$FILE_NAME"
  266. then
  267. if [ ${DELETE_OLD_FILES} == "true" ]
  268. then
  269. echo "Deleting old ${BASE_FILE_NAME} files"
  270. rm "${CURRENT_DIR}/${BASE_FILE_NAME}"*.${TO_BE_DELETED_EXTENSION} > /dev/null 2>&1
  271. fi
  272. if [ $BASE_FILE_NAME == "MiSTer" ] || [ $BASE_FILE_NAME == "menu" ]
  273. then
  274. DESTINATION_FILE=$(echo "$MAX_RELEASE_URL" | sed 's/.*\///g' | sed 's/_[0-9]\{8\}[a-zA-Z]\{0,1\}//g')
  275. echo "Moving $DESTINATION_FILE"
  276. rm "/media/fat/$DESTINATION_FILE" > /dev/null 2>&1
  277. mv "$CURRENT_DIR/$FILE_NAME" "/media/fat/$DESTINATION_FILE"
  278. touch "$CURRENT_DIR/$FILE_NAME"
  279. REBOOT_NEEDED="true"
  280. fi
  281. if echo "$CORE_URL" | grep -q "SD-Installer"
  282. then
  283. SD_INSTALLER_PATH="$CURRENT_DIR/$FILE_NAME"
  284. fi
  285. if [ "$CORE_CATEGORY" == "arcade-cores" ]
  286. then
  287. OLD_IFS="$IFS"
  288. IFS="|"
  289. for ARCADE_ALT_PATH in $ARCADE_ALT_PATHS
  290. do
  291. for ARCADE_ALT_DIR in "$ARCADE_ALT_PATH/_$BASE_FILE_NAME"*
  292. do
  293. if [ -d "$ARCADE_ALT_DIR" ]
  294. then
  295. echo "Updating $(echo $ARCADE_ALT_DIR | sed 's/.*\///g')"
  296. if [ $DELETE_OLD_FILES == "true" ]
  297. then
  298. for ARCADE_HACK_CORE in "$ARCADE_ALT_DIR/"*.rbf
  299. do
  300. if [ -f "$ARCADE_HACK_CORE" ] && { echo "$ARCADE_HACK_CORE" | grep -q "$BASE_FILE_NAME\_[0-9]\{8\}[a-zA-Z]\?\.rbf$"; }
  301. then
  302. rm "$ARCADE_HACK_CORE" > /dev/null 2>&1
  303. fi
  304. done
  305. fi
  306. cp "$CURRENT_DIR/$FILE_NAME" "$ARCADE_ALT_DIR/"
  307. fi
  308. done
  309. done
  310. IFS="$OLD_IFS"
  311. fi
  312. else
  313. echo "${FILE_NAME} download failed"
  314. rm "${CURRENT_DIR}/${FILE_NAME}" > /dev/null 2>&1
  315. if [ ${DELETE_OLD_FILES} == "true" ]
  316. then
  317. echo "Restoring old ${BASE_FILE_NAME} files"
  318. for FILE_TO_BE_RESTORED in "${CURRENT_DIR}/${BASE_FILE_NAME}"*.${TO_BE_DELETED_EXTENSION}
  319. do
  320. mv "${FILE_TO_BE_RESTORED}" "${FILE_TO_BE_RESTORED%.${TO_BE_DELETED_EXTENSION}}" > /dev/null 2>&1
  321. done
  322. fi
  323. fi
  324. sync
  325. else
  326. echo "New core: $FILE_NAME"
  327. fi
  328. else
  329. echo "No Updates Available"
  330. fi
  331. echo ""
  332. }
  333. for CORE_URL in $CORE_URLS; do
  334. if [[ $CORE_URL == https://* ]]
  335. then
  336. if [ "$REPOSITORIES_FILTER" == "" ] || { echo "$CORE_URL" | grep -qi "$REPOSITORIES_FILTER"; } || { echo "$CORE_CATEGORY" | grep -qi "$CORE_CATEGORIES_FILTER"; }
  337. then
  338. if echo "$CORE_URL" | grep -qE "(SD-Installer)|(/Main_MiSTer$)|(/Menu_MiSTer$)"
  339. then
  340. checkCoreURL
  341. else
  342. [ "$PARALLEL_UPDATE" == "true" ] && { echo "$(checkCoreURL)"$'\n' & } || checkCoreURL
  343. fi
  344. fi
  345. else
  346. CORE_CATEGORY=$(echo "$CORE_URL" | sed 's/user-content-//g')
  347. if [ "$CORE_CATEGORY" == "" ]
  348. then
  349. CORE_CATEGORY="-"
  350. fi
  351. if [ "$CORE_CATEGORY" == "computer-cores" ]
  352. then
  353. CORE_CATEGORY="cores"
  354. fi
  355. fi
  356. done
  357. wait
  358. echo "Done!"
  359. if [ $REBOOT_NEEDED == "true" ]
  360. then
  361. if [ $AUTOREBOOT == "true" ]
  362. then
  363. echo "Rebooting in $REBOOT_PAUSE seconds"
  364. sleep $REBOOT_PAUSE
  365. reboot now
  366. else
  367. echo "You should reboot"
  368. fi
  369. fi
  370. exit 0