1577 lines
34 KiB
Bash
1577 lines
34 KiB
Bash
#!/bin/bash
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
# NDS2RM: NDS Simple Rom Manager
|
|
#
|
|
# (C) 2009 Arnaud G. Gibert
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
# $RCSfile: nds2rm,v $
|
|
# $Revision: 1.16 $
|
|
# $Name: $
|
|
# $Date: 2009/04/12 01:20:14 $
|
|
# $Author: agibert $
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
# This file is part of NDS2RM
|
|
#
|
|
# NDS2RM is free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public Licence as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# NDS2RM is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU Lesser General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with NDS2RM; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
# System Constants
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
STATS_FILE="stats.txt"
|
|
|
|
TMP_DIR=$(mktemp -d)
|
|
|
|
NDS_VERSION="$Name: $"
|
|
|
|
# Region Table
|
|
reg_tab[0]="E"; # Europe
|
|
reg_tab[1]="U"; # USA
|
|
reg_tab[2]="G"; # Germany
|
|
reg_tab[3]="C"; # China
|
|
reg_tab[4]="S"; # Spain
|
|
reg_tab[5]="F"; # France
|
|
reg_tab[6]="I"; # Italy
|
|
reg_tab[7]="J"; # Japan
|
|
reg_tab[8]="Nl"; # Nederland
|
|
reg_tab[9]="En"; # England
|
|
reg_tab[10]="Dn"; # Denmark
|
|
reg_tab[11]="Fi"; # Finland
|
|
reg_tab[12]="No"; # Norway
|
|
reg_tab[13]="Pl"; # Poland
|
|
reg_tab[14]="Pr"; # Portugal
|
|
reg_tab[15]="Sw"; # Sweden
|
|
reg_tab[16]="UE"; # USA and Europe
|
|
reg_tab[17]="JUE"; # Japan, USA and Europe
|
|
reg_tab[18]="JU"; # Japan and USA
|
|
reg_tab[19]="Au"; # Australia
|
|
reg_tab[20]="nK"; # North Korea
|
|
reg_tab[21]="Br"; # Brazil
|
|
reg_tab[22]="K"; # South Korea
|
|
reg_tab[23]="EB"; # Europe and Brazil
|
|
reg_tab[24]="EUB"; # Europe, USA and Brazil
|
|
reg_tab[25]="UB"; # USA and Brazil
|
|
reg_tab[26]="R"; # Russia
|
|
reg_tab[27]="R"; # Russia
|
|
reg_tab[28]="Gr"; # Greece
|
|
|
|
# Language Table
|
|
lang_tab[1]="Fr"; # French
|
|
lang_tab[2]="En"; # English
|
|
lang_tab[4]="Zh"; # Chinese
|
|
lang_tab[8]="da"; # Danish
|
|
lang_tab[16]="Nl"; # Dutch
|
|
lang_tab[32]="Fi"; # Finnish
|
|
lang_tab[64]="De"; # German
|
|
lang_tab[128]="It"; # Italian
|
|
lang_tab[256]="Ja"; # Japanese
|
|
lang_tab[512]="Nn"; # Norwegian
|
|
lang_tab[1024]="Pl"; # Polish
|
|
lang_tab[2048]="Pt"; # Portuguese
|
|
lang_tab[4096]="Es"; # Spanish
|
|
lang_tab[8192]="Sv"; # Swedish
|
|
lang_tab[16384]="En"; # English
|
|
lang_tab[32768]="Pt"; # Portuguese
|
|
lang_tab[65536]="Ko"; # Korean
|
|
lang_tab[131072]="Ru"; # Russian
|
|
lang_tab[262144]="El"; # Greek
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Print Version
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function version_print()
|
|
{
|
|
echo ${NDS_VERSION} | sed -e 's/.*: //' -e 's/-/ /' -e 's/_/\./g' -e 's/\$$//'
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Prin Help
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function help_print()
|
|
{
|
|
echo "Path options:"
|
|
echo "-i | --repo_in <path>: input repository path (default: ${nds_repository_in})"
|
|
echo "-o | --repo_out <path>: output repository path (default: ${nds_repository_out})"
|
|
echo ""
|
|
echo "Mode selection"
|
|
echo "-C | --correct: corect output repository"
|
|
echo "-T | --test: test input repository (default mode)"
|
|
echo "-D | --dsrom: dsrom.lst will be dumped"
|
|
echo "-h | --help: print this help and exit"
|
|
echo "-V | --version: print the version and exit"
|
|
echo ""
|
|
echo "Global options"
|
|
echo "-m | --max <id>: maximum rom id to load from dat file (default: ${max_idx})"
|
|
echo "-v | --verbose: switch on verbosity"
|
|
echo "-c | --compressor <c>: set archive compressor (zip, rar or 7z) (default: ${compressor})"
|
|
echo ""
|
|
echo "Test and Correct Mode options:"
|
|
echo "-j | --jobs <jobs>: nuber of parallel jobs to run (default: ${job_nb})"
|
|
echo "-r | --rebuild: don't trust archive file name (test & correct mode)"
|
|
echo " rebuild archives (correct mode)"
|
|
echo "-n | --renum: try to renumber archives"
|
|
echo " --list_ok: list roms with ok status"
|
|
echo " --list_ko: list roms with ko status"
|
|
echo " --list_miss: list missing roms"
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Parse Args
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function args_parse()
|
|
{
|
|
nds_repository_in="/opt/public/nds"
|
|
nds_repository_out="/opt/public/nds"
|
|
mode="test"
|
|
verbose="no"
|
|
max_idx=9999
|
|
compressor="7z"
|
|
job_nb=1
|
|
rebuild="no"
|
|
renum="no"
|
|
lok="no"
|
|
lko="no"
|
|
lmiss="no"
|
|
|
|
|
|
tmp_args=$(getopt -o i:o:CTDhVm:vc:j:rn --long repo_in,repo_out,correct,test,dsrom,help,version,max:,verbose,compressor:,jobs:,rebuild,renum,list_ok,list_ko,list_miss -n 'nds_simple_rom_mng' -- "$@")
|
|
|
|
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
|
|
|
|
# Note the quotes around `$TEMP': they are essential!
|
|
eval set -- "${tmp_args}"
|
|
|
|
while true ; do
|
|
case "$1" in
|
|
# Path options
|
|
-i|--repo_in) shift; nds_repository_in="$1"; shift;;
|
|
-o|--repo_out) shift; nds_repository_out="$1"; shift;;
|
|
|
|
# Mode switches
|
|
-C|--correct) mode="correct"; shift;;
|
|
-T|--test) mode="test"; shift;;
|
|
-D|--dsrom) mode="dsrom"; shift;;
|
|
-h|--help) mode="exit"; help_print; shift;;
|
|
-V|--version) mode="exit"; version_print; shift;;
|
|
|
|
# Global options
|
|
-m|--max) shift; max_idx="$1"; shift;;
|
|
-v|--verbose) verbose="yes"; shift;;
|
|
-c|--compressor) shift; compressor="$1"; shift;;
|
|
|
|
# T & C options
|
|
-j|--jobs) shift; job_nb="$1"; shift;;
|
|
-r|--rebuild) rebuild="yes"; shift;;
|
|
-n|--renum) renum="yes"; shift;;
|
|
--list_ok) lok="yes"; shift;;
|
|
--list_ko) lko="yes"; shift;;
|
|
--list_miss) lmiss="yes"; shift;;
|
|
|
|
#
|
|
--) shift; break;;
|
|
*) echo "args_parse internal error [$1] !"; exit 1;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Setup Environment
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function env_setup()
|
|
{
|
|
if [[ ${nds_repository_in} == ${nds_repository_out} ]]
|
|
then
|
|
in_place=yes
|
|
else
|
|
in_place=no
|
|
fi
|
|
|
|
# Path Config
|
|
nds_roms_in=${nds_repository_in}/roms
|
|
nds_roms_out=${nds_repository_out}/roms
|
|
nds_xml=${nds_repository_in}/misc/dsrom.xml
|
|
|
|
if [[ ! -f ${nds_xml} ]]
|
|
then
|
|
echo "error: dsrom.xml not found !" 1>&2
|
|
exit 1
|
|
fi
|
|
|
|
case "${compressor}"
|
|
in
|
|
(zip)
|
|
csfx=zip
|
|
;;
|
|
|
|
(rar)
|
|
csfx=rar
|
|
;;
|
|
|
|
(7z)
|
|
csfx=7z
|
|
;;
|
|
|
|
(*)
|
|
echo "Error: unsuported compressor: ${compressor} !"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
rrfnfs_regex=".... - .* \(.*:.*\) \[..\] \{........} <....>[-]*[0-9]*\.${csfx}$"
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Print Counter
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function count_print
|
|
{
|
|
idx=${1}
|
|
|
|
|
|
printf "%4d" ${idx} 1>&2
|
|
|
|
if [[ "${verbose}" == "yes" ]]
|
|
then
|
|
echo 1>&2
|
|
else
|
|
printf "\r" 1>&2
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Convert Language to Lang
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function lang_conv
|
|
{
|
|
lang_ptr=${1}
|
|
language=${2}
|
|
|
|
|
|
i=0
|
|
langue=""
|
|
|
|
while [[ ${i} -le 20 ]]
|
|
do
|
|
bit=$(( 2 ** i ))
|
|
if [[ $(( ${language} & ${bit} )) != 0 ]]
|
|
then
|
|
if [[ "${langue}" != "" ]]
|
|
then
|
|
langue="${langue}-"
|
|
fi
|
|
|
|
langue="${langue}${lang_tab[${bit}]}"
|
|
fi
|
|
|
|
i=$(( ${i} + 1 ))
|
|
done
|
|
|
|
eval ${lang_ptr}=${langue}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Load XML File
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function xml_load()
|
|
{
|
|
echo "loading dsrom.xml..." 1>&2
|
|
|
|
loaded_cnt=0
|
|
IFS='>'
|
|
|
|
while read line
|
|
do
|
|
if [[ "${line}" != "" ]]
|
|
then
|
|
set ${line}
|
|
|
|
tag=${1/*</}
|
|
value=${2/<*/}
|
|
|
|
case "${tag}" in
|
|
("releaseNumber")
|
|
rn=${value}
|
|
;;
|
|
|
|
("title")
|
|
title=${value}
|
|
title=${title//&/&}
|
|
title=${title//</<}
|
|
title=${title//>/>}
|
|
;;
|
|
|
|
("saveType")
|
|
save_type=${value}
|
|
;;
|
|
|
|
("location")
|
|
location=${value}
|
|
;;
|
|
|
|
("language")
|
|
language=${value}
|
|
lang_conv "lang" "${language}"
|
|
;;
|
|
|
|
("romCRC extension=\".nds\"")
|
|
crc=${value}
|
|
;;
|
|
|
|
("comment")
|
|
id=${value}
|
|
;;
|
|
|
|
("/game")
|
|
|
|
idx=${id/*(0)/}
|
|
|
|
if [[ "${idx}" != "xxxx" ]]
|
|
then
|
|
|
|
count_print ${idx}
|
|
|
|
dat_rn[${idx}]="${rn}"
|
|
dat_id[${idx}]="${id}"
|
|
dat_title[${idx}]="${title}"
|
|
dat_region[${idx}]="${reg_tab[${location}]}"
|
|
dat_lang[${idx}]="${lang}"
|
|
dat_save_type[${idx}]="${save_type}"
|
|
dat_crc[${idx}]="${crc}"
|
|
|
|
dat_fp[${idx}]="????"
|
|
dat_status[${idx}]="?"
|
|
dat_dup[${idx}]="0"
|
|
|
|
loaded_cnt=$((${loaded_cnt} + 1))
|
|
|
|
if [[ ${loaded_cnt} -ge ${max_idx} ]]
|
|
then
|
|
echo "max rom id reached: skipping loading !" 1>&2
|
|
break;
|
|
fi
|
|
fi
|
|
;;
|
|
esac
|
|
fi
|
|
done < ${nds_xml}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Initialize Job Control
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function job_init()
|
|
{
|
|
job_id=0
|
|
|
|
while [[ ${job_id} -lt ${job_nb} ]]
|
|
do
|
|
job_pid[${job_id}]="0"
|
|
job_dir[${job_id}]="${TMP_DIR}/nds2rom-$$-${job_id}"
|
|
|
|
mkdir "${job_dir[${job_id}]}"
|
|
> "${job_dir[${job_id}]}/${STATS_FILE}"
|
|
|
|
job_id=$((${job_id} + 1))
|
|
done
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# DeInitialize Job Control
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function job_deinit()
|
|
{
|
|
job_id=0
|
|
|
|
while [[ ${job_id} -lt ${job_nb} ]]
|
|
do
|
|
rm -R "${job_dir[${job_id}]}"
|
|
|
|
job_id=$((${job_id} + 1))
|
|
done
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Switch Job
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function job_switch()
|
|
{
|
|
job_id=$((${job_id} + 1))
|
|
|
|
if [[ ${job_id} -ge ${job_nb} ]]
|
|
then
|
|
job_id=0
|
|
fi
|
|
|
|
cd "${job_dir[${job_id}]}"
|
|
|
|
if [[ "${job_pid[${job_id}]}" != "0" ]]
|
|
then
|
|
wait "${job_pid[${job_id}]}"
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Lookup CRC
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function crc_lookup()
|
|
{
|
|
idx_ptr=${1}
|
|
crc=${2}
|
|
|
|
|
|
i=1
|
|
|
|
while [[ ( ${i} -le ${loaded_cnt} ) && ( ${dat_crc[${i}]} != ${crc} ) ]]
|
|
do
|
|
i=$(( ${i} + 1 ))
|
|
done
|
|
|
|
if [[ ${i} -le ${loaded_cnt} ]]
|
|
then
|
|
eval ${idx_ptr}=${i}
|
|
else
|
|
eval ${idx_ptr}=""
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Verbose Print
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function print_verbose()
|
|
{
|
|
text=${1}
|
|
|
|
|
|
if [[ "${verbose}" == "yes" ]]
|
|
then
|
|
echo "${text}" 1>&2
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Dump Rom List
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function rom_list_dump()
|
|
{
|
|
status=${1}
|
|
|
|
|
|
i=1
|
|
while [[ ${i} -le ${loaded_cnt} ]]
|
|
do
|
|
if [[ ${dat_status[${i}]} == "${status}" ]]
|
|
then
|
|
echo "${dat_id[${i}]} - ${dat_title[${i}]} (${dat_region[${i}]}:${dat_lang[${i}]}) {${dat_crc[${i}]}} <${dat_fp[${i}]}>"
|
|
fi
|
|
|
|
i=$(( ${i} + 1 ))
|
|
done
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Get Save Type Mask
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function mask_get()
|
|
{
|
|
save_type=${1}
|
|
|
|
|
|
case "${save_type}"
|
|
in
|
|
("None") echo "000000000";;
|
|
("Eeprom - 4 kbit") echo "100000000";;
|
|
("Eeprom - 64 kbit") echo "200000000";;
|
|
("Eeprom - 512 kbit") echo "500000000";;
|
|
("Flash - 2 Mbit") echo "300000000";;
|
|
("Flash - 4 Mbit") echo "400000000";;
|
|
("Flash - 64 Mbit") echo "600000000";;
|
|
("TBC") echo "F00000000";;
|
|
esac
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Dump DSROM List
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function dsrom_dump()
|
|
{
|
|
echo "dumping ds rom list..." 1>&2
|
|
|
|
i=1
|
|
|
|
while [[ ${i} -le ${loaded_cnt} ]]
|
|
do
|
|
if [[ "${dat_status[${i}]}" != "?" ]]
|
|
then
|
|
mask=$(mask_get "${dat_save_type[${i}]}")
|
|
|
|
echo "${dat_id[${i}]} ${dat_fp[${i}]}-0 $mask ${dat_title[${i}]} (${dat_region[${i}]}:${dat_lang[${i}]}) [${dat_status[${i}]}] {${dat_crc[${i}]}}"
|
|
fi
|
|
|
|
i=$(( ${i} + 1 ))
|
|
done
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Dump OK ROMs
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function ok_dump()
|
|
{
|
|
echo "OK ROMs List:"
|
|
|
|
rom_list_dump "OK"
|
|
|
|
echo
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Dump KO Roms
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function ko_dump()
|
|
{
|
|
echo "KO ROMs List:"
|
|
|
|
rom_list_dump "KO"
|
|
|
|
echo
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Dump Missing ROMs
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function missing_dump()
|
|
{
|
|
echo "Missing ROMs List:"
|
|
|
|
rom_list_dump "?"
|
|
|
|
echo
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Make Arc FileName
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_mkfn()
|
|
{
|
|
file_name_ptr=${1}
|
|
id=${2}
|
|
title=${3}
|
|
reg=${4}
|
|
lang=${5}
|
|
crc=${6}
|
|
fp=${7}
|
|
status=${8}
|
|
dup_id=${9}
|
|
|
|
|
|
file_prefix="${id} - ${title} (${reg}:${lang}) [${status}] {${crc}} <${fp}>"
|
|
|
|
if [[ ${dup_id} == "" ]]
|
|
then
|
|
dup_name=""
|
|
else
|
|
dup_name="-${dup_id}"
|
|
fi
|
|
|
|
eval ${file_name_ptr}=\"${file_prefix}${dup_name}${file_suffix}\"
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Build Arc
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_build()
|
|
{
|
|
file_name=${1}
|
|
rom=${2}
|
|
file=${3}
|
|
mode=${4}
|
|
idx=${5}
|
|
|
|
|
|
if [[ "${mode}" == "correct" ]]
|
|
then
|
|
if [[ ${in_place} == "yes" ]]
|
|
then
|
|
print_verbose "removing ${file}"
|
|
|
|
\rm -f "${nds_roms_in}/${file}"
|
|
fi
|
|
|
|
case "${compressor}"
|
|
in
|
|
(zip)
|
|
print_verbose "zipping ${rom} into ${file_name}"
|
|
|
|
zip -m9 "${nds_roms_out}/${file_name}" "${rom}" >/dev/null 2>&1
|
|
;;
|
|
|
|
(rar)
|
|
print_verbose "raring ${rom} into ${file_name}"
|
|
|
|
rar m -m5 "${nds_roms_out}/${file_name}" "${rom}" >/dev/null 2>&1
|
|
;;
|
|
|
|
(7z)
|
|
print_verbose "7zipping ${rom} into ${file_name}"
|
|
|
|
7z a -t7z -m0=lzma -mx=9 -mfb=64 -md=32m -ms=on -bd "${nds_roms_out}/${file_name}" "${rom}" >/dev/null 2>&1
|
|
\rm -f "${rom}"
|
|
;;
|
|
|
|
|
|
(*)
|
|
echo "arc_build internal error [$compressor] !" 1>&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
else
|
|
print_verbose "removing ${rom}"
|
|
|
|
\rm -f "${rom}"
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Rename Arc
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_rename()
|
|
{
|
|
file_name=${1}
|
|
file=${2}
|
|
action=${3}
|
|
mode=${4}
|
|
|
|
|
|
if [[ "${mode}" == "correct" ]]
|
|
then
|
|
# if [[ ${action} != "keep_status" ]]
|
|
# then
|
|
if [[ ${in_place} == "yes" ]]
|
|
then
|
|
print_verbose "moving ${file} to ${file_name}"
|
|
|
|
mv "${nds_roms_in}/${file}" "${nds_roms_out}/${file_name}"
|
|
else
|
|
print_verbose "copying ${file} to ${file_name}"
|
|
|
|
cp "${nds_roms_in}/${file}" "${nds_roms_out}/${file_name}"
|
|
fi
|
|
# fi
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Move Duplicate
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_mv()
|
|
{
|
|
file_name_trg=${1}
|
|
file_name_src=${2}
|
|
mode=${3}
|
|
|
|
|
|
if [[ "${mode}" == "correct" ]]
|
|
then
|
|
print_verbose "moving ${file_name_src} to ${file_name_trg}"
|
|
|
|
mv "${file_name_src}" "${file_name_trg}"
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Extract ROM
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function rom_extract()
|
|
{
|
|
rom=$1
|
|
file=$2
|
|
|
|
|
|
case "${file}"
|
|
in
|
|
(*.nds)
|
|
print_verbose "copying ${file} to ${rom}"
|
|
|
|
cp "${nds_roms_in}/${file}" "${rom}"
|
|
;;
|
|
|
|
(*.rar)
|
|
print_verbose "extracting ${rom} from ${file}"
|
|
|
|
unrar p -inul "${nds_roms_in}/${file}" > "${rom}"
|
|
;;
|
|
|
|
(*.7z)
|
|
print_verbose "extracting ${rom} from ${file}"
|
|
|
|
7z x -so "${nds_roms_in}/${file}" > "${rom}" 2>/dev/null
|
|
;;
|
|
|
|
(*.zip)
|
|
print_verbose "extracting ${rom} from ${file}"
|
|
|
|
unzip -p "${nds_roms_in}/${file}" > "${rom}"
|
|
;;
|
|
|
|
(*)
|
|
echo "rom_extract internal error [$1] !" 1>&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Remove .tmp suffix
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function tmp_mv()
|
|
{
|
|
echo "removing .tmp suffix..." 1>&2
|
|
|
|
IFS=' '
|
|
mv_cnt=0
|
|
|
|
for file_src in ${nds_roms_out}/*.tmp
|
|
do
|
|
if [[ "${file_src}" != "${nds_roms_out}/*.tmp" ]]
|
|
then
|
|
file_trg=${file_src/.${csfx}.tmp/.${csfx}}
|
|
|
|
print_verbose "move ${file_src} to ${file_trg}"
|
|
|
|
mv "${file_src}" "${file_trg}"
|
|
|
|
mv_cnt=$((${mv_cnt} + 1))
|
|
|
|
printf "moved: %4d\r" "${mv_cnt}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Identify Arc
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_ident()
|
|
{
|
|
arc_type_ptr=${1}
|
|
extract_ptr=${2}
|
|
file=${3}
|
|
|
|
|
|
|
|
# Type of archive ?
|
|
|
|
if [[ ${file} =~ ${rrfnfs_regex} ]]
|
|
then
|
|
eval ${arc_type_ptr}="rx3"
|
|
else
|
|
eval ${arc_type_ptr}="unknown"
|
|
fi
|
|
|
|
|
|
# Extract ROM if needed
|
|
|
|
if [[ ( "${arc_type}" != "rx3" ) || ( "${rebuild}" == "yes" ) ]]
|
|
then
|
|
eval ${extract_ptr}="yes"
|
|
else
|
|
eval ${extract_ptr}="no"
|
|
fi
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Proceed Arc
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_proceed()
|
|
{
|
|
file=${1}
|
|
arc_type=${2}
|
|
extract=${3}
|
|
found_cnt=${4}
|
|
|
|
|
|
set ${file:0:4}
|
|
|
|
id=$1
|
|
idx=${id/*(0)/}
|
|
|
|
if [[ ${idx} -gt ${loaded_cnt} ]]
|
|
then
|
|
echo "max rom id reached: skipping processing !" 1>&2
|
|
break;
|
|
fi
|
|
|
|
# Get info from dat
|
|
|
|
title=${dat_title[${idx}]}
|
|
reg=${dat_region[${idx}]}
|
|
lang=${dat_lang[${idx}]}
|
|
crc=${dat_crc[${idx}]}
|
|
|
|
|
|
# Extract ROM if needed
|
|
|
|
if [[ "${extract}" == "yes" ]]
|
|
then
|
|
rom="${id} - ${title} (${reg}:${lang}).nds"
|
|
|
|
rom_extract "${rom}" "${file}"
|
|
|
|
crc2=$(check -n <"${rom}" 2>&1 | sed -e 's/,.*//' -e 's/.*= //' | tr [:lower:] [:upper:])
|
|
fp=$(dd skip=12 count=4 bs=1 <"${rom}" 2>/dev/null)
|
|
else
|
|
crc2=${file/*\{/}; crc2=${crc2/\}*/}
|
|
fp=${file/*\} \</}; fp=${fp/\>*/}
|
|
fi
|
|
|
|
|
|
# Extract info
|
|
|
|
if [[ "${arc_type}" == "rx3" ]]
|
|
then
|
|
status=${file/* \[/}; status=${status/\] {*/}
|
|
|
|
if [[ "${crc}" != "${crc2}" ]]
|
|
then
|
|
if [[ "${status}" == "OK" ]]
|
|
then
|
|
action="change_status"
|
|
status="KO"
|
|
else
|
|
action="keep_status"
|
|
fi
|
|
else
|
|
if [[ "${status}" == "OK" ]]
|
|
then
|
|
action="keep_status"
|
|
else
|
|
action="change_status"
|
|
status="OK"
|
|
fi
|
|
fi
|
|
else
|
|
action="set_status"
|
|
|
|
if [[ "${crc}" != "${crc2}" ]]
|
|
then
|
|
status="KO"
|
|
else
|
|
status="OK"
|
|
fi
|
|
fi
|
|
|
|
|
|
|
|
# Try to Renumber if KO
|
|
renumed="no"
|
|
|
|
if [[ ( ${status} == "KO" ) && ( "${renum}" == "yes" ) ]]
|
|
then
|
|
crc_lookup "idx2" "${crc2}"
|
|
|
|
if [[ "${idx2}" != "" ]]
|
|
then
|
|
idx=${idx2}
|
|
id=${dat_id[${idx}]}
|
|
title=${dat_title[${idx}]}
|
|
reg=${dat_region[${idx}]}
|
|
lang=${dat_lang[${idx}]}
|
|
crc=${dat_crc[${idx}]}
|
|
status2="OK"
|
|
|
|
# Rename the ROM file
|
|
rom2="${id} - ${title} (${reg}:${lang}) [${status2}].nds"
|
|
|
|
print_verbose "moving ${rom} to ${rom2}"
|
|
|
|
mv "${rom}" "${rom2}"
|
|
rom=${rom2}
|
|
|
|
if [[ "${arc_type}" == "rx3" ]]
|
|
then
|
|
status=${file/* \[/}; status=${status/\] {*/}
|
|
|
|
if [[ "${status}" == "${status2}" ]]
|
|
then
|
|
action="keep_status"
|
|
else
|
|
action="change_status"
|
|
status=${status2}
|
|
fi
|
|
else
|
|
action="set_status"
|
|
status=${status2}
|
|
fi
|
|
|
|
renumed="yes"
|
|
fi
|
|
fi
|
|
|
|
# Rename ROM if needed
|
|
|
|
if [[ ( "${renumed}" != "yes") && ( ( "${arc_type}" != "rx3" ) || ( "${rebuild}" == "yes" ) ) ]]
|
|
then
|
|
rom2="${id} - ${title} (${reg}:${lang}) [${status}].nds"
|
|
|
|
print_verbose "moving ${rom} to ${rom2}"
|
|
|
|
mv "${rom}" "${rom2}"
|
|
rom=${rom2}
|
|
fi
|
|
|
|
|
|
|
|
# Make File Name
|
|
|
|
arc_mkfn "file_name" "${id}" "${title}" "${reg}" "${lang}" "${crc2}" "${fp}" "${status}" "${found_cnt}"
|
|
|
|
|
|
|
|
# Make / Rename Archive
|
|
|
|
if [[ ( "${arc_type}" != "rx3" ) || ( ${rebuild} == "yes" ) ]]
|
|
then
|
|
arc_build "${file_name}" "${rom}" "${file}" "${mode}" "${idx}"
|
|
else
|
|
arc_rename "${file_name}" "${file}" "${action}" "${mode}"
|
|
fi
|
|
|
|
|
|
|
|
# Updates Stats
|
|
|
|
echo "${renumed}" "${action}" "${status}" >>"${STATS_FILE}"
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Manage Archives
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function arc_mng()
|
|
{
|
|
# Initialize Job Control
|
|
job_init
|
|
|
|
echo "processing rom repository..." 1>&2
|
|
|
|
IFS=' '
|
|
found_cnt=0
|
|
|
|
tmp_file=$(mktemp)
|
|
|
|
ls ${nds_roms_in} > ${tmp_file}
|
|
|
|
while read file
|
|
do
|
|
arc_ident "arc_type" "extract" "${file}"
|
|
|
|
if [[ "${extract}" == "no" ]]
|
|
then
|
|
arc_proceed "${file}" "${arc_type}" "${extract}" "${found_cnt}"
|
|
else
|
|
job_switch "${job_id}"
|
|
|
|
arc_proceed "${file}" "${arc_type}" "${extract}" "${found_cnt}" &
|
|
|
|
job_pid[${job_id}]=$!
|
|
fi
|
|
|
|
|
|
# Update stats
|
|
found_cnt=$((${found_cnt} + 1))
|
|
|
|
count_print ${found_cnt}
|
|
|
|
done < ${tmp_file}
|
|
|
|
\rm -f ${tmp_file}
|
|
|
|
# Wait all Jobs
|
|
|
|
wait
|
|
|
|
# Collect Stats"
|
|
cd "${TMP_DIR}"
|
|
|
|
cat *"/${STATS_FILE}" >> "${STATS_FILE}"
|
|
|
|
# DeInitialize Job Control
|
|
job_deinit
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Manage Arc Suffix
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function suffix_mng()
|
|
{
|
|
echo "managing duplicate archives..." 1>&2
|
|
|
|
IFS=' '
|
|
found_cnt=0
|
|
ok_cnt=0
|
|
ok_dup_cnt=0
|
|
ko_cnt=0
|
|
ko_dup_cnt=0
|
|
dup_cnt=0
|
|
ignored_cnt=0
|
|
|
|
idx_old=0
|
|
status_old=""
|
|
|
|
tmp_file=$(mktemp)
|
|
|
|
ls ${nds_roms_out} > ${tmp_file}
|
|
|
|
while read file
|
|
do
|
|
set ${file:0:4}
|
|
|
|
id=$1
|
|
idx=${id/*(0)/}
|
|
|
|
if [[ ${idx} -gt ${loaded_cnt} ]]
|
|
then
|
|
ignored_cnt=$((${ignored_cnt} + 1))
|
|
else
|
|
status=${file/* \[/}; status=${status/\] \{*/}
|
|
crc=${file/*\] \{/}; crc=${crc/\} \<*/}
|
|
fp=${file/*\} \</}; fp=${fp/\>-*/}
|
|
|
|
dat_dup[${idx}]="${dup_id}"
|
|
|
|
# Test if file is a new idx or different status
|
|
|
|
if [[ ( ${idx} != ${idx_old} ) || ( "${status}" != "${status_old}" ) ]]
|
|
then
|
|
# Non duplicate rom
|
|
|
|
idx_old=${idx}
|
|
status_old=${status}
|
|
dup_id=0
|
|
file_name="${file/) \[*/}) [${status}] {${crc}} <${fp}>.${csfx}"
|
|
|
|
dat_fp[${idx}]="${fp}"
|
|
dat_status[${idx}]="${status}"
|
|
|
|
if [[ "${status}" == "KO" ]]
|
|
then
|
|
ko_cnt=$((${ko_cnt} + 1))
|
|
fi
|
|
else
|
|
# Duplicate rom
|
|
|
|
dup_id=$((${dup_id} + 1))
|
|
file_name="${file/) \[*/}) [${status}] {${crc}} <${fp}>-${dup_id}.${csfx}"
|
|
|
|
dup_cnt=$((${dup_cnt} + 1))
|
|
|
|
if [[ "${status}" == "OK" ]]
|
|
then
|
|
ok_dup_cnt=$((${ok_dup_cnt} + 1))
|
|
else
|
|
ko_dup_cnt=$((${ko_dup_cnt} + 1))
|
|
fi
|
|
fi
|
|
|
|
print_verbose "moving ${file} to ${file_name}"
|
|
arc_mv "${nds_roms_out}/${file_name}" "${nds_roms_out}/${file}" "${mode}"
|
|
fi
|
|
|
|
found_cnt=$((${found_cnt} + 1))
|
|
|
|
count_print ${found_cnt}
|
|
done < ${tmp_file}
|
|
|
|
\rm -f ${tmp_file}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Update Statistics
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function stats_update()
|
|
{
|
|
renumed=${1}
|
|
action=${2}
|
|
status=${3}
|
|
mode=${4}
|
|
|
|
|
|
if [[ "${renumed}" == "yes" ]]
|
|
then
|
|
renum_cnt=$((${renum_cnt} + 1))
|
|
fi
|
|
|
|
case ${action} in
|
|
("set_status")
|
|
if [[ ${status} == "OK" ]]
|
|
then
|
|
ss_ok_cnt=$((${ss_ok_cnt} + 1))
|
|
else
|
|
ss_ko_cnt=$((${ss_ko_cnt} + 1))
|
|
fi
|
|
;;
|
|
|
|
("change_status")
|
|
if [[ ${status} == "OK" ]]
|
|
then
|
|
cs_ok_cnt=$((${cs_ok_cnt} + 1))
|
|
else
|
|
cs_ko_cnt=$((${cs_ko_cnt} + 1))
|
|
fi
|
|
;;
|
|
|
|
("keep_status")
|
|
if [[ ${status} == "OK" ]]
|
|
then
|
|
ks_ok_cnt=$((${ks_ok_cnt} + 1))
|
|
else
|
|
ks_ko_cnt=$((${ks_ko_cnt} + 1))
|
|
fi
|
|
;;
|
|
|
|
*)
|
|
echo "stats_update internal error [$1] !" 1>&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Proceed Stats
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function stats_proceed()
|
|
{
|
|
ss_ok_cnt=0
|
|
ss_ko_cnt=0
|
|
cs_ok_cnt=0
|
|
cs_ko_cnt=0
|
|
ks_ok_cnt=0
|
|
ks_ko_cnt=0
|
|
renum_cnt=0
|
|
ko_not_ok_cnt=0
|
|
ok_total_count=0
|
|
ko_total_count=0
|
|
proceeded_cnt=0
|
|
missing_cnt=0
|
|
|
|
|
|
# Summarize stats files
|
|
|
|
while read file
|
|
do
|
|
set ${file}
|
|
|
|
renumed=${1}
|
|
action=${2}
|
|
status=${3}
|
|
|
|
stats_update "${renumed}" "${action}" "${status}"
|
|
done < "${STATS_FILE}"
|
|
|
|
\rm -f "${STATS_FILE}"
|
|
|
|
# Compute ok, ko_nok and missing count
|
|
|
|
i=1
|
|
|
|
while [[ ${i} -le ${loaded_cnt} ]]
|
|
do
|
|
case ${dat_status[${i}]}
|
|
in
|
|
("OK")
|
|
ok_cnt=$((${ok_cnt} + 1))
|
|
;;
|
|
|
|
("KO")
|
|
ko_nok_cnt=$((${ko_nok_cnt} + 1))
|
|
;;
|
|
|
|
("?")
|
|
missing_cnt=$((${missing_cnt} + 1))
|
|
;;
|
|
esac
|
|
|
|
i=$(( ${i} + 1 ))
|
|
done
|
|
|
|
found_cnt=$((${ok_cnt} + ${ko_cnt} + ${dup_cnt} + ${ignored_cnt}))
|
|
proceeded_cnt=$((${found_cnt} - ${ignored_cnt}))
|
|
ok_total_cnt=$((${ok_cnt} + ${ok_dup_cnt}))
|
|
ko_total_cnt=$((${ko_cnt} + ${ko_dup_cnt}))
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Print Stats
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function stats_print()
|
|
{
|
|
echo "run statistics:" 1>&2
|
|
|
|
printf "%4d roms set to OK\n" ${ss_ok_cnt} 1>&2
|
|
printf "%4d roms changed to OK\n" ${cs_ok_cnt} 1>&2
|
|
printf "%4d roms kept to OK\n" ${ks_ok_cnt} 1>&2
|
|
|
|
echo 1>&2
|
|
|
|
printf "%4d roms set to KO\n" ${ss_ko_cnt} 1>&2
|
|
printf "%4d roms changed to KO\n" ${cs_ko_cnt} 1>&2
|
|
printf "%4d roms kept to KO\n" ${ks_ko_cnt} 1>&2
|
|
|
|
echo 1>&2
|
|
|
|
printf "%4d roms are renumbered\n" ${renum_cnt} 1>&2
|
|
|
|
echo 1>&2
|
|
echo "global statistics:" 1>&2
|
|
|
|
printf "%4d roms are in dsrom.dat\n" ${loaded_cnt} 1>&2
|
|
printf "%4d roms are found\n" ${found_cnt} 1>&2
|
|
printf "%4d roms are ignored\n" ${ignored_cnt} 1>&2
|
|
printf "%4d roms are proceeded\n" ${proceeded_cnt} 1>&2
|
|
printf "%4d roms are duplicated\n" ${dup_cnt} 1>&2
|
|
echo 1>&2
|
|
printf "%4d total roms are OK\n" ${ok_total_cnt} 1>&2
|
|
printf "%4d roms are dup OK\n" ${ok_dup_cnt} 1>&2
|
|
printf "%4d roms are OK\n" ${ok_cnt} 1>&2
|
|
echo 1>&2
|
|
printf "%4d total roms are KO\n" ${ko_total_cnt} 1>&2
|
|
printf "%4d roms are dup KO\n" ${ko_dup_cnt} 1>&2
|
|
printf "%4d roms are KO\n" ${ko_cnt} 1>&2
|
|
printf "%4d roms are KO not OK\n" ${ko_nok_cnt} 1>&2
|
|
echo 1>&2
|
|
printf "%4d roms are missing\n" ${missing_cnt} 1>&2
|
|
}
|
|
|
|
|
|
|
|
|
|
# FingerPrint Scan
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function fp_scan()
|
|
{
|
|
echo "scanning rom repository..." 1>&2
|
|
|
|
IFS=' '
|
|
found_cnt=0
|
|
|
|
tmp_file=$(mktemp)
|
|
|
|
ls ${nds_roms_in} > ${tmp_file}
|
|
|
|
while read file
|
|
do
|
|
set ${file:0:4}
|
|
|
|
id=$1
|
|
idx=${id/*(0)/}
|
|
|
|
if [[ ${idx} -gt ${loaded_cnt} ]]
|
|
then
|
|
break;
|
|
fi
|
|
|
|
# Get info from dat
|
|
|
|
title=${dat_title[${idx}]}
|
|
reg=${dat_region[${idx}]}
|
|
lang=${dat_lang[${idx}]}
|
|
crc=${dat_crc[${idx}]}
|
|
|
|
# Type of archive ?
|
|
|
|
if [[ ${file} =~ ${rrfnfs_regex} ]]
|
|
then
|
|
fp=${file/*\} \</}; fp=${fp/\>*/}
|
|
status=${file/* \[/}; status=${status/\] \{*/}
|
|
|
|
if [[ ( "${dat_fp[${idx}]}" == "????" ) || ( ( "${dat_status[${idx}]}" == "KO" ) && ( "${status}" == "OK" ) ) ]]
|
|
then
|
|
dat_fp[${idx}]=${fp}
|
|
dat_status[${idx}]=${status}
|
|
else
|
|
if [[ "${dat_fp[${idx}]}" != "${fp}" ]]
|
|
then
|
|
echo "Skipping: (${idx}): [${dat_fp[${idx}]}]:[${dat_status[${idx}]}] ==> [${fp}]:[${status}] !!!" 1>&2
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
found_cnt=$((${found_cnt} + 1))
|
|
|
|
count_print ${found_cnt}
|
|
done < ${tmp_file}
|
|
|
|
\rm -f ${tmp_file}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# DSROM Mode
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function dsrom_mode()
|
|
{
|
|
# Scan repository for fp
|
|
fp_scan
|
|
|
|
# Dump it !
|
|
dsrom_dump
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Test and Correct Mode
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function test_correct_mode()
|
|
{
|
|
if [[ ${in_place} == "yes" ]]
|
|
then
|
|
file_suffix=".${csfx}.tmp"
|
|
else
|
|
file_suffix=".${csfx}"
|
|
fi
|
|
|
|
# Remove .tmp suffix
|
|
tmp_mv
|
|
|
|
# Process Archives
|
|
arc_mng
|
|
|
|
# Suffix Management
|
|
suffix_mng
|
|
|
|
echo " " 1>&2
|
|
|
|
# Dump ROMs List
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
if [[ ${lok} == "yes" ]]
|
|
then
|
|
ok_dump
|
|
fi
|
|
|
|
if [[ ${lko} == "yes" ]]
|
|
then
|
|
ko_dump
|
|
fi
|
|
|
|
if [[ ${lmiss} == "yes" ]]
|
|
then
|
|
missing_dump
|
|
fi
|
|
|
|
|
|
|
|
# Collect and Proceed Stats
|
|
stats_proceed
|
|
|
|
# Print statistics
|
|
stats_print
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# Main
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
cd ${TMP_DIR}
|
|
|
|
shopt -s extglob
|
|
|
|
args_parse "$@"
|
|
|
|
if [[ ${mode} == "exit" ]]
|
|
then
|
|
exit 0
|
|
fi
|
|
|
|
env_setup
|
|
|
|
case "${mode}"
|
|
in
|
|
(dsrom):
|
|
echo "mode: [${mode}] repository: [${nds_repository_in}] max idx: (${max_idx}) compressor: [${compressor}]" 1>&2
|
|
;;
|
|
|
|
(test|correct):
|
|
echo "mode: [${mode}] repository in: [${nds_repository_in}] repository out: [${nds_repository_out}]" 1>&2
|
|
echo "max idx: (${max_idx}) compressor: [${compressor}] rebuild: [${rebuild}] renum: [${renum}] jobs: (${job_nb})" 1>&2
|
|
;;
|
|
esac
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
xml_load
|
|
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
if [[ "${mode}" == "dsrom" ]]
|
|
then
|
|
dsrom_mode
|
|
|
|
else
|
|
test_correct_mode
|
|
fi
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
# Final Cleanup
|
|
|
|
cd /tmp
|
|
|
|
rmdir ${TMP_DIR}
|
|
|
|
exit 0
|
|
|