-
-
Save kergoth/4b14262be5788738476da442396be1e1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# NES Flips Wrapper by Europia79 | |
########################################## | |
# README # | |
########################################## | |
# (1) This script requires Linux, Mac, or Git-for-Windows: | |
# https://gitforwindows.org/ | |
# https://git-scm.com/download/win | |
# (2) This script also requires Floating IPS (flips) v1.31: | |
# https://github.com/Alcaro/Flips | |
# https://www.romhacking.net/utilities/1040/ | |
# https://www.smwcentral.net/?a=details&id=11474&p=section | |
# (3) Add the flips directory to your PATH environment variable: | |
# https://gist.github.com/nex3/c395b2f8fd4b02068be37c961301caa7 | |
# (4) Alternatively, if you cannot change your PATH environment, then | |
# you can instead, copy flips to your ~/Git/usr/bin/ folder. | |
########################################## | |
# CONSTANTS1 # | |
########################################## | |
# add line numbers in debug mode (bash set -x ./nes.sh): | |
PS4='+ \e[0;33m${LINENO}\e[0m::' | |
# echo "${D2B[$(( x & 0x80 ))]}" | |
D2B=({0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}{0..1}) | |
# 7z??'.="37 7A BC AF 27 1C" | |
CMAGIC_7Z="377ABCAF271C" | |
# PK..="50 4B 03 04" | |
CMAGIC_ZIP="504B0304" | |
# BPS1="42 50 53 31" | |
PMAGIC_BPS="42505331" | |
# UPS1="55 50 53 31" | |
PMAGIC_UPS="55505331" | |
# XDELTA="D6 C3 C4 00" | |
PMAGIC_XDELTA="D6C3C400" | |
# NINJA2="4E 49 4E 4A 41 32" | |
PMAGIC_RUP="4E494E4A4132" | |
# NES.="4E 45 53 1A" | |
RMAGIC_NES="4E45531A" | |
# FDS.="46 44 53 1A" | |
RMAGIC_FDS="4644531A" | |
# UNIF="55 4E 49 46" | |
RMAGIC_UNF="554E4946" | |
global_args=("$@") | |
declare -i arg_count_nes_cli=0 | |
declare -a CLEANUP_FILES=() | |
# grep -n "^function " nes.sh | sed 's/^/# /g' | sed 's/:function /::/g' | sed 's/() {/()::/g' | |
########################################## | |
# FUNCTION MENU: (Ctl+G) # | |
########################################## | |
# 138::pause():: | |
# 143::close():: | |
# 152::close_now():: | |
# 158::close_delay():: | |
# 163::pipeout():: | |
# 168::die():: | |
# 172::die_now():: | |
# 177::die_delay():: | |
# 182::cleanupValidation():: | |
# 189::cleanup():: | |
# 195::onExit():: | |
# 205::displayFunctionMenu():: | |
# 209::displayVersion():: | |
# 222::displayHelp():: | |
# 276::displayCompressionSupport():: | |
# 286::displayPatchSupport():: | |
# 295::displayRomSupport():: | |
# 314::showAllFileTypes():: | |
# 336::ERROR_INVALID_FILE_FOR():: | |
# 349::ERROR_INVALID_BPS():: | |
# 353::ERROR_INVALID_NES():: | |
# 357::ERROR_INVALID_FDS():: | |
# 360::get_bytesize():: | |
# 363::is_16bytes():: | |
# 366::has_rom_header():: | |
# 369::is_rom_header():: | |
# 373::get_magic_num():: | |
# 376::has_zip_magic():: | |
# 379::has_bps_magic():: | |
# 382::has_nes_magic():: | |
# 385::has_fds_magic():: | |
# 388::has_unf_magic():: | |
# 391::has_tmp_ext():: | |
# 394::has_bps_ext():: | |
# 397::has_nes_ext():: | |
# 400::has_fds_ext():: | |
# 403::has_unf_ext():: | |
# 406::is_zip():: | |
# 409::is_bps():: | |
# 413::is_nes():: | |
# 416::is_fds():: | |
# 419::is_unf():: | |
# 422::extract_bps_crc32():: | |
# 425::extract_ups_crc32():: | |
# 428::extract_zip_crc32():: | |
# 431::calculate_crc32():: | |
# 434::get_crc32():: | |
# 443::get_nes_hashes():: | |
# 451::get_nes_hash():: | |
# 456::get_hash():: | |
# 459::get_all_hashes():: | |
# 468::parseInput():: | |
# 481::parseFullpath():: | |
# 506::getFile():: | |
# 513::getDirectory():: | |
# 520::getBase():: | |
# 527::getExtention():: | |
# 534::getFileTypeExt():: | |
# 581::isFileType():: | |
# 596::getFileType():: | |
# 610::encode_header():: | |
# 646::decode_header():: | |
# 677::get_bps_header():: | |
# 684::get_nes_header_hex():: | |
# 696::get_nes_header_binary():: | |
# 702::get_header():: | |
# 715::save_romheader_tofile():: | |
# 744::get_temp_no_header():: | |
# 764::echo_bps_header():: | |
# 780::print_bps_header():: | |
# 784::echo_manifest():: | |
# 797::print_manifest():: | |
# 800::has_manifest():: | |
# 803::save_manifest():: | |
# 815::insert_manifest():: | |
# 820::insert_header():: | |
# 823::insert_from():: | |
# 828::insert():: | |
# 839::apply_patch():: | |
# 878::create_patch():: | |
# 911::windows_fix():: | |
# 933::getFileType_ReturnValues_Comment():: | |
# 988::FILETYPE_CONSTANTS():: | |
# 1094::require_args():: | |
# 1097::onStartupClientsideValidation():: | |
########################################## | |
# CONTROL FUNCTIONS # | |
########################################## | |
# PAUSE | |
function pause() { | |
read -rsn1 -p "Press any key to continue..." | |
echo "" | |
} | |
# CLOSE | |
function close() { | |
if [ $# -eq 0 ] | |
then | |
close_now $? | |
else | |
close_now $1 | |
fi | |
} | |
# CLOSE_NOW | |
function close_now() { | |
local status=0 | |
if [ -n "$1" ] && (( $1 + 0 > 0 )); then status=$1; fi | |
exit $status | |
} | |
# CLOSE_DELAY | |
function close_delay() { | |
pause | |
close $1 | |
} | |
# PIPEOUT | |
function pipeout() { | |
printf "%s" $* | |
close 0 | |
} | |
# DIE | |
function die() { | |
die_now "$1" | |
} | |
# DIE_NOW | |
function die_now() { | |
printf "Aborted: %s\n" "$"; echo "" | |
close 1 | |
} | |
# DIE_DELAY | |
function die_delay() { | |
printf "Aborted: %s\n" "$1"; echo "" | |
pause | |
close 1 | |
} | |
function cleanupValidation() { | |
printf "\e[1;36m" | |
find . -type f -name "*.tmp" -printf "WARNING: Not removed: %p\n" | |
find . -type f -name "header*" -printf "WARNING: Not removed: %p\n" | |
printf "\e[0m" | |
} | |
# Remove specific files before dying onError/onExit. | |
function cleanup() { | |
for cfile in "$@" | |
do | |
rm -vf -- "${cfile}" | |
done | |
} | |
function onExit() { | |
printf "\e[1;33m%s\e[1;31m\n" "onExit() cleanup..." >&2 | |
cleanup "${CLEANUP_FILES[@]}" | |
printf "\e[1;33m%s\e[0m\n" "...done." >&2 | |
cleanupValidation | |
} >&2 | |
trap onExit EXIT | |
########################################## | |
# DISPLAY METHODS # | |
########################################## | |
function displayFunctionMenu() { | |
grep -n "^function " nes.sh | sed 's/^/# /g' | sed 's/:function /::/g' | sed 's/() {/()::/g' | |
} | |
# displayVersion | |
function displayVersion() { | |
cat << VERSION_EOF | |
Flips NES Wrapper: (nes.sh): by Europia79 | |
./nes.sh revision: r1.31 | |
for | |
----flips version: v1.31 | |
You have Floating IPS (flips) version: | |
VERSION_EOF | |
flips --version | |
} | |
# displayHelp | |
function displayHelp() { | |
cat << HELP_EOF | |
Allows the use of a BPS manifest to save & restore NES headers: | |
Which allows patches to automatically & seemlessly work with ANY NES ROM. | |
Usage: | |
./nes.sh [options] [--] <parameters> | |
Options: | |
-a, --apply apply patch (w/ automatic NES header detection) | |
-c, --create create patch (w/ automatic NES header detection) | |
-d, --has-header | |
-e, --echo-header echo entire BPS Header in DEBUG format | |
-f, --echo-manifest echo only BPS manifest metadata as Hex | |
-g, --get-filetype print filetype for given File | |
-i, --is-filetype compare filetype for File with given type | |
-j, --get-alltypes print all supported filetypes for Patches, ROMs, & Compression | |
-n, --insert-manifest insert manifest (as header) into a ROM | |
-p, --print-manifest print manifest from patch file | |
-q, --has-manifest | |
-r, --print-header decode & print BPS patch file header | |
-s, --save-manifest save manifest to file [header.nes] | |
-t, --get-temp given Rom.nes, creates Rom.tmp without a header | |
-x, --get-hash extract CRC32 from .bps OR calculate for file | |
-z, --get-all-hashes prints all hash info for every every file given | |
-h, --help display this help | |
-u, --menu display all functions & methods | |
-v, --version display the version | |
Example: Create Patch: | |
./nes.sh -c Baserom.nes Hack.nes Patch.bps | |
--Detects NES Header & saves it into the Patch.bps manifest. | |
Example: Apply Patch: | |
./nes.sh -a Patch.bps Baserom.nes Hack.nes | |
--Automatically detects manifest in Patch.bps. | |
--Automatically & temporarily removes header from Baserom.nes (if necessary). | |
--Automatically applies header (from manifest) to Hack.nes. | |
Other Examples: | |
./nes.sh -e Patch.bps | |
./nes.sh -p Patch.bps | |
./nes.sh -s Patch.bps <header.nes> | |
./nes.sh -i 'Baserom.ext' nes && echo true || echo false | |
Warning: | |
FileType 'nes' refers specifically to Headered NES ROMs (iNes1/iNes2). | |
FileType 'nes' does not refer to '.unh' or '.unf': See option -j for more info. | |
HELP_EOF | |
} | |
# DISPLAY FORMAT | |
dformat=".%-10s %s\n" | |
# DISPLAY COMPRESSION SUPPORT | |
function displayCompressionSupport() { | |
local -a keys=( $( echo ${!qFILE_TYPE_COM[@]} | tr ' ' $'\n' | sort ) ) | |
for key in "${keys[@]}" | |
do | |
local value="${qFILE_TYPE_COM[$key]}" | |
# shellcheck disable=SC2059 | |
printf "$dformat" "$key" "$value" | |
done | |
} | |
# DISPLAY PATCH SUPPORT | |
function displayPatchSupport() { | |
local -a keys=( $( echo ${!qFILE_TYPE_DIF[@]} | tr ' ' $'\n' | sort ) ) | |
for key in "${keys[@]}" | |
do | |
local value="${qFILE_TYPE_DIF[$key]}" | |
printf "$dformat" "$key" "$value" | |
done | |
} | |
# DISPLAY ROM SUPPORT | |
function displayRomSupport() { | |
local -a keys=( $( echo ${!qFILE_TYPE_ROM[@]} | tr ' ' $'\n' | sort ) ) | |
for key in "${keys[@]}" | |
do | |
local value="${qFILE_TYPE_ROM[$key]}" | |
if [[ $value = "declare -a"* ]] | |
then | |
eval "$value" | |
for k in "${!array[@]}" | |
do | |
local v="${array[$k]}" | |
printf "$dformat" "$key" "$v" | |
done | |
else | |
printf "$dformat" "$key" "$value" | |
fi | |
done | |
} | |
# DISPLAY ALL SUPPORTED FILETYPES | |
function showAllFileTypes() { | |
cat << TABLE_HEADER | |
########################################## | |
# -g, --get-filetype # | |
########################################## | |
#----------------------------------------- | |
file: type: | |
TABLE_HEADER | |
cat << COM_SUPPORT | |
#------------COMPRESSED-FILES------------- | |
COM_SUPPORT | |
displayCompressionSupport | |
cat << DIF_SUPPORT | |
#--------------PATCH-FILES---------------- | |
DIF_SUPPORT | |
displayPatchSupport | |
cat << ROM_SUPPORT | |
#----------------ROM-FILES---------------- | |
ROM_SUPPORT | |
displayRomSupport | |
} | |
# ERROR_INVALID_FILE_FOR "calling_function" "${filename}" "${actual_header}" "${expected_header}" ".ext" | |
function ERROR_INVALID_FILE_FOR() { | |
cat << FILETYPE_ERROR | |
'$1():' Invalid $5 file with unknown header: | |
---------Filename: $2 | |
------File Header: $3 | |
--Expected Header: $4 | |
FILETYPE_ERROR | |
} | |
########################################## | |
# FILE METHODS # | |
########################################## | |
# ERROR_INVALID_BPS "calling_function" "${bps_file}" "${bps_header}" | |
function ERROR_INVALID_BPS() { | |
ERROR_INVALID_FILE_FOR "$1" "$2" "$3" "${PMAGIC_BPS}" ".bps" | |
} | |
# ERROR_INVALID_NES "calling_function" "${nes_file}" "${nes_header}" | |
function ERROR_INVALID_NES() { | |
ERROR_INVALID_FILE_FOR "$1" "$2" "$3" "${RMAGIC_NES}" ".nes" | |
} | |
# ERROR_INVALID_FDS "calling_function" "${fds_file}" "${fds_header}" | |
function ERROR_INVALID_FDS() { | |
ERROR_INVALID_FILE_FOR "$1" "$2" "$3" "${RMAGIC_FDS}" ".fds" | |
} | |
function get_bytesize() { | |
wc -c < "$1" | |
} | |
function is_16bytes() { | |
(( $(get_bytesize "$1")+0 == 16 )) | |
} | |
function has_rom_header() { | |
has_nes_magic "$1" || has_fds_magic "$1" | |
} | |
function is_rom_header() { | |
has_rom_header "$1" && is_16bytes "$1" | |
} | |
# return_val=$(get_magic_num "${file1}") | |
function get_magic_num() { | |
xxd -p -l 4 "$1" | tr '[:lower:]' '[:upper:]' | |
} | |
function has_zip_magic() { | |
[[ ${CMAGIC_ZIP} = $(get_magic_num "$1") ]] | |
} | |
function has_bps_magic() { | |
[[ ${PMAGIC_BPS} = $(get_magic_num "$1") ]] | |
} | |
function has_nes_magic() { | |
[[ ${RMAGIC_NES} = $(get_magic_num "$1") ]] | |
} | |
function has_fds_magic() { | |
[[ ${RMAGIC_FDS} = $(get_magic_num "$1") ]] | |
} | |
function has_unf_magic() { | |
[[ ${RMAGIC_UNF} = $(get_magic_num "$1") ]] | |
} | |
function has_tmp_ext() { | |
[[ "tmp" = $(getExtention "$1") ]] | |
} | |
function has_bps_ext() { | |
[[ "bps" = $(getExtention "$1") ]] | |
} | |
function has_nes_ext() { | |
[[ "nes" = $(getExtention "$1") ]] | |
} | |
function has_fds_ext() { | |
[[ "fds" = $(getExtention "$1") ]] | |
} | |
function has_unf_ext() { | |
[[ "unf" = $(getExtention "$1") ]] | |
} | |
function is_zip() { | |
has_zip_magic "$1" | |
} | |
function is_bps() { | |
has_bps_magic "$1" | |
} | |
# Only worry about .nes roms that are actually HEADERED. | |
function is_nes() { | |
has_nes_magic "$1" | |
} | |
function is_fds() { | |
has_fds_magic "$1" | |
} | |
function is_unf() { | |
has_unf_magic "$1" | |
} | |
function extract_bps_crc32() { | |
tail -c12 "$1" | xxd -ps -l 4 | |
} | |
function extract_ups_crc32() { | |
tail -c12 "$1" | xxd -ps -l 4 | |
} | |
function extract_zip_crc32() { | |
xxd -ps -s 14 -l 4 "$1" | |
} | |
function calculate_crc32() { | |
cat "$1" | gzip -1 -c | tail -c8 | xxd -ps -l 4 | |
} | |
function get_crc32() { | |
magic_num=$(get_magic_num "$1") | |
case ${magic_num} in | |
${PMAGIC_BPS}) extract_bps_crc32 "$1";; | |
${PMAGIC_UPS}) extract_ups_crc32 "$1";; | |
${CMAGIC_ZIP}) extract_zip_crc32 "$1";; | |
*) calculate_crc32 "$1";; | |
esac | |
} | |
function get_nes_hashes() { | |
local -a hashes=() | |
hashes[0]=$(calculate_crc32 "$1") | |
temp=$(get_temp_no_header "$1") | |
hashes[1]=$(calculate_crc32 "${temp}") | |
rm -f -- "${temp}" | |
declare -p hashes | |
} | |
function get_nes_hash() { | |
local return_val=$(get_nes_hashes "$1") | |
eval "${return_val}" | |
echo "${hashes[1]}" | |
} | |
function get_hash() { | |
get_crc32 "$1" | |
} | |
function get_all_hashes() { | |
local -n hash_array=$1 | |
for i in "${!files[@]}" | |
do | |
local hash=$(get_hash "${files[$i]}") | |
hash_array[$i]="${hash}" | |
done | |
} | |
# Null Check for function arguments: $* $1 $2 etc. | |
function parseInput() { | |
local PARSED_INPUT="" | |
if [ -n "$1" ] | |
then | |
PARSED_INPUT="$1" | |
else | |
die "$(basename $0): function argument cannot be NULL" | |
fi | |
echo "${PARSED_INPUT}" | |
} | |
# $(parseFullpath _RETURN_VAR "${__INPUT_VAL}") | |
# _RETURN_VAR: $1 = A named reference to the array used to store the return values. | |
# __INPUT_VAL: $2 = the input string. | |
function parseFullpath() { | |
local -n returnvar=$1 | |
local input_path=$(parseInput "$2") | |
# Convert backslashes on \Windows\ to foward slashes: /Windows/ | |
local FULLPATH="${input_path//\\//}" | |
# [0] Strip longest match of */ from start | |
local file="${FULLPATH##*/}" | |
# [1] Substring from 0 thru pos of filename | |
local dir="${FULLPATH:0:${#FULLPATH} - ${#file}}" | |
[ -z "${dir}" ] && dir="." | |
# [2] Strip shortest match of . plus at least one non-dot char from end | |
local base="${file%.[^.]*}" | |
# [3] If we have an extension and no base, it's really the base | |
local ext="${file:${#base} + 1}" | |
if [ -z "${base}" ] && [ -n "${ext}" ] | |
then | |
base=".${ext}" | |
ext="" | |
fi | |
returnvar[0]="${file}" | |
returnvar[1]="${dir}" | |
returnvar[2]="${base}" | |
returnvar[3]="${ext}" | |
} | |
# gets the entire Filename including extention. | |
function getFile() { | |
local -a path_array=() | |
local file_input=$(parseInput "$1") | |
parseFullpath path_array "${file_input}" | |
echo "${path_array[0]}" | |
} | |
# gets the Directory, or, "." if none. | |
function getDirectory() { | |
local -a path_array=() | |
local dir_input=$(parseInput "$1") | |
parseFullpath path_array "${dir_input}" | |
echo "${path_array[1]}" | |
} | |
# get only the base Filename without the extention. | |
function getBase() { | |
local -a path_array=() | |
local base_input=$(parseInput "$1") | |
parseFullpath path_array "${base_input}" | |
echo "${path_array[2]}" | |
} | |
# gets the Extention without the period. | |
function getExtention() { | |
local -a path_array=() | |
local ext_input=$(parseInput "$1") | |
parseFullpath path_array "${ext_input}" | |
echo "${path_array[3]}" | |
} | |
# Requires a File parameter, but allows a String arg for Testing purposes. | |
function getFileTypeExt() { | |
local T="" | |
if [ -f "$1" ] | |
then | |
T=$(getFileType "$1") | |
else | |
T="$1" | |
fi | |
local extension="" | |
if [[ $T = data ]] | |
then | |
extension=$(getExtention "$1") | |
echo "${extension}" | |
return 0 | |
fi | |
for key in "${!qFILE_TYPE[@]}" | |
do | |
local val="${qFILE_TYPE[$key]}" | |
if [[ ${val} = "declare -a"* ]] | |
then | |
# re-construct array Object: | |
eval "${qFILE_TYPE[$key]}" | |
for k in "${!array[@]}" | |
do | |
val="${array[$k]}" | |
if [[ $T = ${val}* ]] | |
then | |
extension="$key" | |
echo "$extension" | |
return 0 | |
fi | |
done | |
else | |
if [[ $T = ${val}* ]] | |
then | |
extension="$key" | |
echo "$extension" | |
return 0 | |
fi | |
fi | |
done | |
extension=$(getExtention "$1") | |
echo "$extension" | |
} | |
# Remember, type 'nes' specifically refers to an NES ROM with a header !!! | |
# $(isFileType "$1" bps) && echo "BPS=true" || echo "BPS=false" | |
# $(isFileType "$2" nes) && echo "NES=true" || echo "NES=false" | |
function isFileType() { | |
local T1=$(getFileType "$1") | |
local T2="${qFILE_TYPE[$2]}" | |
[[ ${T1} = ${T2}* ]] && return | |
if [[ ${T2} = "declare -a"* ]] | |
then | |
eval "${T2}" | |
for element in "${array[@]}" | |
do | |
[[ ${T1} = ${element}* ]] && return | |
done | |
fi | |
false | |
} | |
# Fully qualified FileType with extraneous information: | |
function getFileType() { | |
if [ ! -f "$1" ]; then die "getFileTypeOf() requires a File argument: Not: $1"; fi | |
file -b "$1" | |
} | |
########################################## | |
# NES/BPS METHODS # | |
########################################## | |
# ------------------------------------------------------------- | |
# encoded_message=$(encode_header $1 $2 $3) | |
# $1=${source_size} | |
# $2=${target_size} | |
# $3=${mf_size} | |
# printf "${encoded_message}" | xxd -r -p > bps_header.bin | |
# ------------------------------------------------------------- | |
function encode_header() { | |
local string_data="${PMAGIC_BPS}" | |
declare -a encode_array | |
read -a encode_array <<< $* | |
for value in "${encode_array[@]}" | |
do | |
local -i data=${value} | |
while true | |
do | |
local -i x=$(( ${data} & 0x7f )) | |
let "data >>= 7" | |
if [ ${data} = 0 ] | |
then | |
local -i bits=$((0x80 | ${x})) | |
string_data="${string_data}"$(printf '%02X' "${bits}") | |
break | |
fi | |
string_data="${string_data}"$(printf '%02X' "${x}") | |
let "data -= 1" | |
done | |
done | |
printf "${string_data}" | |
# printf "${string_data}" | xxd -r -p > bps_header.bin | |
} | |
# ------------------------------------------------------------- | |
# decoded_message=$(decode_header "${patch_file}") | |
# declare -a header_array | |
# read -a header_array <<< ${decoded_message} | |
# magic_num=${header_array[0]} | |
# source_size=${header_array[1]} | |
# target_size=${header_array[2]} | |
# mf_size=${header_array[3]} | |
# mf_index=${header_array[4]} | |
# metadata=$(xxd -p -s ${mf_index} -l ${mf_size} ${patch_file}) | |
# printf "${metadata}" | xxd -r -p > header.nes | |
# ------------------------------------------------------------- | |
function decode_header() { | |
local -a decoded=() | |
local bps_file=$1 | |
local -i index=4 | |
local bps_header=$(get_magic_num "${bps_file}") | |
if [[ ${PMAGIC_BPS} != ${bps_header} ]] | |
then | |
die $(ERROR_INVALID_BPS "decode_heaer" "${bps_file}" "${bps_header}") | |
fi | |
decoded[0]="${PMAGIC_BPS}" | |
for return_var in {1..3} | |
do | |
local -i data=0 | |
local -i shifter=1 | |
while true | |
do | |
local -i x=0x$(xxd -p -s ${index} -l 1 "${bps_file}") | |
index+=1 | |
data+=$((( x & 0x7f ) * ${shifter} )) | |
if [ $((x & 0x80)) != 0 ]; then break; fi | |
shifter=$(( ${shifter} << 7 )) | |
data=$(( ${data} + ${shifter} )) | |
done | |
decoded[${return_var}]=${data} | |
done | |
decoded[4]=${index} | |
echo "${decoded[*]}" | |
} | |
# return_message=$(get_bps_header "${bps_file}") | |
# declare -a header_array | |
# read -a header_array <<< ${return_message} | |
function get_bps_header() { | |
decoded_message=$(decode_header "$1") | |
declare -a bps_header_array | |
read -a bps_header_array <<< ${decoded_message} | |
echo "${bps_header_array[*]}" | |
} | |
# return_val=$(get_nes_header_hex "${romfile_patchfile}") | |
function get_nes_header_hex() { | |
if is_bps "$1" && has_manifest "$1" | |
then | |
echo_manifest "$1" | |
return | |
elif has_rom_header "$1" | |
then | |
xxd -p -l 16 "$1" | |
return | |
fi | |
echo "" | |
} | |
function get_nes_header_binary() { | |
get_nes_header_hex "$1" | xxd -r -p | |
} | |
# return_message=$(get_header "${rom_or_patch_file}") | |
# declare -a header_array | |
# read -a header_array <<< ${return_message} | |
function get_header() { | |
magic_num=$(get_magic_num "$1") | |
if is_bps "$1" | |
then | |
get_bps_header "$1" | |
elif has_rom_header "$1" | |
then | |
get_nes_header_hex "$1" | |
else | |
echo "" | |
fi | |
} | |
# INPUT: .bps .nes .fds | |
function save_romheader_tofile() { | |
if [ -z "$1" ]; then echo ""; return; fi | |
local temp="" | |
if (( $# >= 2 )) | |
then | |
tmp="$2" | |
else | |
temp="header.tmp" | |
fi | |
get_nes_header_binary "$1" > "${temp}" | |
local rom_header_file="" | |
if has_tmp_ext "${temp}" | |
then | |
if is_nes "${temp}" | |
then | |
rom_header_file=$(getBase "${temp}")".nes" | |
elif is_fds "${temp}" | |
then | |
rom_header_file=$(getBase "${temp}")".fds" | |
else | |
rom_header_file="${temp}" | |
fi | |
else | |
rom_header_file="${temp}" | |
fi | |
mv -f -- "${temp}" "${rom_header_file}" | |
echo "${rom_header_file}" | |
} | |
# temp_file=$(get_temp_no_header "${nes_rom}") | |
function get_temp_no_header() { | |
local temp="" | |
if [ -z "$1" ]; then die "get_temp_no_header(): Method Failure !!! Bad arg: $1"; fi | |
if [ -f "$1" ] | |
then | |
temp=$(getBase "$1") | |
temp+=".tmp" | |
if has_rom_header "$1" | |
then | |
xxd -p -s 16 "$1" | xxd -r -p > "${temp}" | |
else | |
cp -f -- "$1" "${temp}" | |
fi | |
else | |
temp=$(getBase "$1")".tmp" | |
touch "${temp}" | |
fi | |
echo ${temp} | |
} | |
# Implementation for print_bps_header() | |
function echo_bps_header() { | |
decoded_message=$(get_bps_header "$1") | |
declare -a bps_hdr | |
read -a bps_hdr <<< ${decoded_message} | |
echo "File: $1" | |
local -i mf_index=${bps_hdr[4]} | |
local -i mf_len=${bps_hdr[3]} | |
local -i hdr_len=$(( mf_index + mf_len )) | |
xxd -l 0x$hdr_len "$1" | |
echo "0)----magic-number: ${bps_hdr[0]}" | |
echo "1)-----source-size: ${bps_hdr[1]}" | |
echo "2)-----target-size: ${bps_hdr[2]}" | |
echo "3)---manifest-size: ${bps_hdr[3]}" | |
echo "4)--manifest-index: ${bps_hdr[4]}" | |
} | |
# ALIAS for echo_bps_header() | |
function print_bps_header() { | |
echo_bps_header "$1" | |
} | |
# As String Hex output: | |
function echo_manifest() { | |
metadata=""; | |
decoded_message=$(get_bps_header "$1") | |
declare -a header_array | |
read -a header_array <<< ${decoded_message} | |
magic_num="${header_array[0]}" | |
source_size=${header_array[1]} | |
target_size=${header_array[2]} | |
mf_size=${header_array[3]} | |
mf_index=${header_array[4]} | |
if (( mf_size > 0 )) | |
then | |
metadata=$(xxd -p -s ${mf_index} -l ${mf_size} "$1") | |
fi | |
printf "${metadata}" | |
} | |
# As Binary Output: | |
function print_manifest() { | |
echo_manifest "$1" | xxd -r -p | |
} | |
function has_manifest() { | |
[[ -n $(echo_manifest "$1") ]] && true || false | |
} | |
function save_manifest() { | |
local manifest_file="$1" | |
local header_file="" | |
if (( $# >= 2 )) | |
then | |
header_file="$2" | |
save_romheader_tofile "$1" "$2" | |
else | |
header_file=$(save_romheader_tofile "$1") | |
fi | |
echo "${header_file}" | |
} | |
function insert_manifest() { | |
header_file=$(save_manifest "$1") | |
CLEANUP_FILES+=("${header_file}") | |
insert_header "${header_file}" "$2" | |
} | |
function insert_header() { | |
cat <(xxd -p "$1") <(xxd -p "$2") | xxd -r -p > "$3" | |
} | |
function insert_from() { | |
hdr=$(save_romheader_tofile "$1") | |
CLEANUP_FILES+=("${hdr}") | |
insert_header "${hdr}" "$2" | |
} | |
function insert() { | |
# Check if $2 has a header already | |
if is_bps "$1" && has_manifest "$1"; then insert_manifest "$1" "$2" "$3"; return; fi | |
if is_rom_header "$1"; then insert_header "$1" "$2" "$3"; return; fi | |
if has_rom_header "$1"; then insert_from "$1" "$2" "$3"; return; fi | |
die "function insert() requires a bps manifest OR nes header file." | |
} | |
########################################## | |
# FLIPS WRAPPER METHODS # | |
########################################## | |
# flips -a --manifest=header.nes 'Hack.bps' 'Base.tmp' 'Hack.tmp' | |
function apply_patch() { | |
if ! is_bps "$1"; then die "apply_patch() requires a .bps patch file: Not $1"; fi | |
local patch="$1" | |
local baserom="$2" | |
local basetmp=$(get_temp_no_header "$2") | |
CLEANUP_FILES+=("${basetmp}") | |
local hack="" | |
if (( $# >= 3 )) | |
then | |
hack="$3" | |
else | |
hack=$(getBase "${patch}") | |
if has_manifest "${patch}" | |
then | |
if get_nes_header_binary "${patch}" | is_nes | |
then | |
hack="${hack}.nes" | |
elif get_nes_header_binary "${patch}" | is_fds | |
then | |
hack="${hack}.fds" | |
else | |
hack="${hack}."$(getExtention "${baserom}") | |
fi | |
else | |
hack="${hack}."$(getExtention "${baserom}") | |
fi | |
fi | |
hacktmp=$(get_temp_no_header "$hack") | |
CLEANUP_FILES+=("${hacktmp}") | |
local header="header.tmp" | |
flips -a --manifest="${header}" "${patch}" "${basetmp}" "${hacktmp}" | |
[ -f "header.nes" ] && CLEANUP_FILES+=("header.tmp") | |
if [ ! -f "${hacktmp}" ]; then die "apply_patch() failed on $*"; fi | |
if [ ! -f "header.tmp" ]; then header=$(save_manifest "${patch}"); fi | |
if [ ! -f "header.tmp" ]; then die "apply_patch(): insert() failed: header.nes does not exist!"; fi | |
CLEANUP_FILES+=("${header}") | |
insert "${header}" "${hacktmp}" "${hack}" | |
} | |
# flips -c --manifest=header.nes 'Base.tmp' 'Hack.tmp' 'Hack.bps' | |
function create_patch() { | |
local baserom="$1" | |
local romhack="$2" | |
local patchname="" | |
if (( $# >= 3 )) | |
then | |
patchname="$3" | |
else | |
patchname=$(getBase "${romhack}")".bps" | |
fi | |
if ! has_bps_ext "${patchname}"; then die "create_patch() failed: Requires .bps file: Not ${patchname}"; fi | |
local header=$(save_romheader_tofile "${romhack}") | |
CLEANUP_FILES+=("${header}") | |
local basetmp=$(get_temp_no_header "${baserom}") | |
CLEANUP_FILES+=("${basetmp}") | |
local hacktmp=$(get_temp_no_header "${romhack}") | |
CLEANUP_FILES+=("${hacktmp}") | |
if [ -n "${header}" ] && [ -f "${header}" ] | |
then | |
flips -c --manifest="${header}" "${basetmp}" "${hacktmp}" "${patchname}" | |
else | |
flips -c "${basetmp}" "${hacktmp}" "${patchname}" | |
fi | |
} | |
########################################## | |
# WINDOWS BUG FIX # | |
########################################## | |
# Fixes a BUG on Windows: | |
# Where Drag N Drop changes the working directory to | |
# C:\Windows\system32 | |
# /c/Windows/system32 | |
# This functions attempts to change it back based on the input of DragNdrop: | |
# changes=$(windows_fix) | |
function windows_fix() { | |
echo "windows_fix()" | |
local THIS_DIR=$(pwd) | |
for arg in "${global_args[@]}" | |
do | |
if [ "/c/Windows/system32" = "${THIS_DIR}" ] | |
then | |
local temp=$(getDirectory "${arg}") | |
if [ -n "${arg}" ] && [ -n "${temp}" ] && [ -d "${temp}" ] | |
then | |
echo "CHANGING DIRECTORY TO..." | |
echo "${temp}" | |
THIS_DIR="${temp}" | |
cd "${THIS_DIR}" | |
pwd | |
return 1 | |
fi | |
fi | |
done | |
return 0 | |
} | |
# Comment: do-nothing. | |
function getFileType_ReturnValues_Comment() { | |
true | |
} | |
########################################## | |
# getFileType() return values # | |
########################################## | |
#----------------------------------------- | |
# input: Output | |
#-----------COMPRESSED-FILES-------------- | |
# .7z 7-zip archive data, version 0.4 | |
# .zip Zip archive data, at least v2.0 to extract, compression method=deflate | |
#-----------PATCH-FILES------------------- | |
# .aps | |
# .bps BPS patch file | |
# .ebp IPS patch file | |
# .ips IPS patch file | |
# .ppf Playstation Patch File version 3.0, PPF 3.0 patch, Imagetype BIN (any), Blockcheck disabled, Undo data not available, description: FFT: WotL - Valeria 2.2 (PSP USA) | |
# .rup data | |
# .ups UPS patch file | |
# .xdelta VCDIFF binary diff | |
#-----------ROM-FILES--------------------- | |
# .pce data | |
# .nes NES ROM image (iNES): 8x16k PRG, 0x8k CHR [H-mirror] [SRAM] | |
# .fds Famicom Disk System disk image: FMC-ARM, mfr FFFFFFA4 (Rev.00) (2 sides) | |
# .unh data | |
# .unf NES ROM image (UNIF v7 format) | |
# .bs data | |
# .st Sufami Turbo ROM image: "\276\260\327\2", ID 010003, series index 1 [FastROM] | |
# .sfc data | |
# .n64 Nintendo 64 ROM image (32-bit byteswapped) | |
# .v64 Nintendo 64 ROM image (V64) | |
# .z64 Nintendo 64 ROM image: "SUPER MARIO 64 " (NSME, Rev.00) | |
# .iso Nintendo GameCube disc image: "The Legend of Zelda Twilight Princess" (GZ2E01, Rev.00) | |
# .iso Nintendo Wii disc image: "SPORTS PACK for REVOLUTION" (RSPE01, Rev.01) | |
# .wbfs Nintendo Wii disc image (WBFS format): "SPORTS PACK for REVOLUTION" (RSPE01, Rev.01) | |
# .gb Game Boy ROM image: "ZELDA" (Rev.02) [MBC1+RAM+BATT], ROM: 4Mbit, RAM: 64Kbit | |
# .gbc Game Boy ROM image: "PM_CRYSTAL" (Rev.01) [CGB ONLY] [MBC3+TIMER+RAM+BATT], ROM: 16Mbit, RAM: 256Kbit | |
# .gba Game Boy Advance ROM image: "POKEMON RUBY" (AXVE01, Rev.02) | |
# .nds Nintendo DS ROM image: "CASTLEVANIA1" (ACVPA4, Rev.00) (decrypted) | |
# .gg Sega Game Gear ROM image: 2408 (Rev.01) (256 KB) | |
# .sms Sega Master System ROM image: 7076 (Rev.00) (256 KB) | |
# .32x Sega 32X ROM image: "DOOM " (GM MK-84506-00, (C)SEGA 1994.OCT) | |
# .68k Sega Mega Drive / Genesis ROM image: "\377\377\377\377" (\377\377\377\3, \377\377\377\377) | |
# .bin Sega Mega Drive / Genesis ROM image: "SONIC THE " (GM 00001051-02, (C)SEGA 1992.SEP) | |
# .gen Sega Mega Drive / Genesis ROM image: "NHL HOCKEY " (GM T-50236 -00, (C)T-50 1991.MAY) | |
# .md Sega Mega Drive / Genesis ROM image: "EA HOCKEY " (GM T-50236 -50, (C)T-50 1991.JUN) | |
# .smd Sega Mega Drive / Genesis ROM image (SMD format): 64x16k blocks, last in series or standalone | |
# .img Sega Mega CD disc image: "SOULSTAR " (GM T-115035-00, (C)T-1151994.NOV), 2352-byte sectors | |
# .iso Sega Mega CD disc image: "SOULSTAR " (GM T-115035-00, (C)T-1151994.NOV), 2048-byte sectors | |
# .bin Sega Saturn disc image: "AREA 51 " (T-9705H , V1.000) (2352-byte sectors) | |
# .bin Sega Dreamcast disc image: "CRAZY TAXI " (MK-51035 , V1.004) (2352-byte sectors) | |
# .iso UDF filesystem data (version 1.5) 'FINAL_FANTASY_X' | |
########################################## | |
# CONSTANTS2 # | |
########################################## | |
function FILETYPE_CONSTANTS() { | |
true | |
} | |
declare -A qFILE_TYPE | |
declare -A qFILE_TYPE_COM | |
declare -A qFILE_TYPE_DIF | |
declare -A qFILE_TYPE_ROM | |
qFILE_TYPE_COM["7z"]="7-zip archive" | |
qFILE_TYPE_COM[zip]="Zip archive" | |
qFILE_TYPE_DIF[aps]="UNKNOWN: NOT SUPPORTED" | |
qFILE_TYPE_DIF[bps]="BPS patch file" | |
qFILE_TYPE_DIF[ebp]="IPS patch file" | |
qFILE_TYPE_DIF[ips]="IPS patch file" | |
qFILE_TYPE_DIF[ppf]="Playstation Patch File" | |
qFILE_TYPE_DIF[rup]="data" | |
qFILE_TYPE_DIF[ups]="UPS patch file" | |
qFILE_TYPE_DIF[xdelta]="VCDIFF binary diff" | |
qFILE_TYPE_ROM[pce]="data" | |
qFILE_TYPE_ROM[nes]="NES ROM image (iNES)" | |
qFILE_TYPE_ROM[fds]="Famicom Disk System disk image:" | |
qFILE_TYPE_ROM[unh]="data" | |
qFILE_TYPE_ROM[unf]="NES ROM image (UNIF" | |
qFILE_TYPE_ROM[bs]="data" | |
qFILE_TYPE_ROM[st]="Sufami Turbo ROM image:" | |
qFILE_TYPE_ROM[sfc]="data" | |
qFILE_TYPE_ROM[n64]="Nintendo 64 ROM image (32-bit byteswapped)" | |
qFILE_TYPE_ROM[v64]="Nintendo 64 ROM image (V64)" | |
qFILE_TYPE_ROM[z64]="Nintendo 64 ROM image:" | |
qFILE_TYPE_ROM[wbfs]="Nintendo Wii disc image (WBFS format):" | |
qFILE_TYPE_ROM[gb]="Game Boy ROM image:" | |
qFILE_TYPE_ROM[gbc]="Game Boy ROM image:" | |
qFILE_TYPE_ROM[gba]="Game Boy Advance ROM image:" | |
qFILE_TYPE_ROM[nds]="Nintendo DS ROM image:" | |
qFILE_TYPE_ROM[gg]="Sega Game Gear ROM image:" | |
qFILE_TYPE_ROM[sms]="Sega Master System ROM image:" | |
qFILE_TYPE_ROM["32x"]="Sega 32X ROM image:" | |
qFILE_TYPE_ROM["68k"]="Sega Mega Drive / Genesis ROM image:" | |
qFILE_TYPE_ROM[gen]="Sega Mega Drive / Genesis ROM image:" | |
qFILE_TYPE_ROM[md]="Sega Mega Drive / Genesis ROM image:" | |
qFILE_TYPE_ROM[smd]="Sega Mega Drive / Genesis ROM image (SMD format):" | |
qFILE_TYPE_ROM[img]="Sega Mega CD disc image:" | |
declare -a array=("Sega Mega Drive / Genesis ROM image:" "Sega Saturn disc image:" "Sega Dreamcast disc image:") | |
qFILE_TYPE_ROM[bin]=$(declare -p array) | |
declare -a array=("Nintendo GameCube disc image:" "Nintendo Wii disc image:" "Sega Mega CD disc image:" "UDF filesystem data") | |
qFILE_TYPE_ROM[iso]=$(declare -p array) | |
array=() | |
# re-populate array Object: | |
# if [ "declare -a" = "${qFILE_TYPE[$key]::10}" ]; then eval "${qFILE_TYPE[$key]}"; fi | |
# or | |
# if [[ $value = "declare -a"* ]]; then eval "$value"; ...; fi | |
for key in "${!qFILE_TYPE_COM[@]}" | |
do | |
qFILE_TYPE[$key]="${qFILE_TYPE_COM[$key]}" | |
done | |
for key in "${!qFILE_TYPE_DIF[@]}" | |
do | |
qFILE_TYPE[$key]="${qFILE_TYPE_DIF[$key]}" | |
done | |
for key in "${!qFILE_TYPE_ROM[@]}" | |
do | |
qFILE_TYPE[$key]="${qFILE_TYPE_ROM[$key]}" | |
done | |
declare -a test_values | |
test_values+=("7-zip archive data, version 0.4") | |
test_values+=("Zip archive data, at least v2.0 to extract, compression method=deflate") | |
test_values+=("BPS patch file") | |
test_values+=("IPS patch file") | |
test_values+=("IPS patch file") | |
test_values+=("Playstation Patch File version 3.0, PPF 3.0 patch, Imagetype BIN (any), Blockcheck disabled, Undo data not available, description: FFT: WotL - Valeria 2.2 (PSP USA)") | |
test_values+=("data") | |
test_values+=("UPS patch file") | |
test_values+=("VCDIFF binary diff") | |
test_values+=("data") | |
test_values+=("NES ROM image (iNES): 8x16k PRG, 0x8k CHR [H-mirror] [SRAM]") | |
test_values+=("Famicom Disk System disk image: FMC-ARM, mfr FFFFFFA4 (Rev.00) (2 sides)") | |
test_values+=("data") | |
test_values+=("NES ROM image (UNIF v7 format)") | |
test_values+=("data") | |
test_values+=("Sufami Turbo ROM image: \"\276\260\327\2\", ID 010003, series index 1 [FastROM]") | |
test_values+=("data") | |
test_values+=("Nintendo 64 ROM image (32-bit byteswapped)") | |
test_values+=("Nintendo 64 ROM image (V64)") | |
test_values+=("Nintendo 64 ROM image: \"SUPER MARIO 64 \" (NSME, Rev.00)") | |
test_values+=("Nintendo GameCube disc image: \"The Legend of Zelda Twilight Princess\" (GZ2E01, Rev.00)") | |
test_values+=("Nintendo Wii disc image: \"SPORTS PACK for REVOLUTION\" (RSPE01, Rev.01)") | |
test_values+=("Nintendo Wii disc image (WBFS format): \"SPORTS PACK for REVOLUTION\" (RSPE01, Rev.01)") | |
test_values+=("Game Boy ROM image: \"ZELDA\" (Rev.02) [MBC1+RAM+BATT], ROM: 4Mbit, RAM: 64Kbit") | |
test_values+=("Game Boy ROM image: \"PM_CRYSTAL\" (Rev.01) [CGB ONLY] [MBC3+TIMER+RAM+BATT], ROM: 16Mbit, RAM: 256Kbit") | |
test_values+=("Game Boy Advance ROM image: \"POKEMON RUBY\" (AXVE01, Rev.02)") | |
test_values+=("Nintendo DS ROM image: \"CASTLEVANIA1\" (ACVPA4, Rev.00) (decrypted)") | |
test_values+=("Sega Game Gear ROM image: 2408 (Rev.01) (256 KB)") | |
test_values+=("Sega Master System ROM image: 7076 (Rev.00) (256 KB)") | |
test_values+=("Sega 32X ROM image: \"DOOM \" (GM MK-84506-00, (C)SEGA 1994.OCT)") | |
test_values+=("Sega Mega Drive / Genesis ROM image: \"\377\377\377\377\" (\377\377\377\3, \377\377\377\377)") | |
test_values+=("Sega Mega Drive / Genesis ROM image: \"SONIC THE \" (GM 00001051-02, (C)SEGA 1992.SEP)") | |
test_values+=("Sega Mega Drive / Genesis ROM image: \"NHL HOCKEY \" (GM T-50236 -00, (C)T-50 1991.MAY)") | |
test_values+=("Sega Mega Drive / Genesis ROM image: \"EA HOCKEY \" (GM T-50236 -50, (C)T-50 1991.JUN)") | |
test_values+=("Sega Mega Drive / Genesis ROM image (SMD format): 64x16k blocks, last in series or standalone") | |
test_values+=("Sega Mega CD disc image: \"SOULSTAR \" (GM T-115035-00, (C)T-1151994.NOV), 2352-byte sectors") | |
test_values+=("Sega Mega CD disc image: \"SOULSTAR \" (GM T-115035-00, (C)T-1151994.NOV), 2048-byte sectors") | |
test_values+=("Sega Saturn disc image: \"AREA 51 \" (T-9705H , V1.000) (2352-byte sectors)") | |
test_values+=("Sega Dreamcast disc image: \"CRAZY TAXI \" (MK-51035 , V1.004) (2352-byte sectors)") | |
test_values+=("UDF filesystem data (version 1.5) 'FINAL_FANTASY_X'") | |
########################################## | |
# CLIENT-SIDE METHODS # | |
########################################## | |
function require_args() { | |
if [ $arg_count_nes_cli -le $(( $1 - 1 )) ]; then die "Not enough command line arguments (${arg_count_nes_cli}): ${operation}() requires $1"; fi | |
} | |
function onStartupClientsideValidation() { | |
# command -v xxd | |
true | |
} | |
########################################## | |
# START # | |
########################################## | |
onStartupClientsideValidation | |
#declare -i return_value=$(test_zero) | |
#echo "return_value=${return_value}" | |
HACK_DIR="_romhacks" | |
BASE_DIR="_baseroms" | |
operation="" | |
files=() | |
while [[ $# -gt 0 ]] | |
do | |
case $1 in | |
-a|--apply) | |
operation="apply" | |
shift | |
;; | |
-c|--create) | |
operation="create" | |
shift | |
;; | |
-e|--echo-header) | |
operation="echo-header" | |
shift | |
;; | |
-f|--echo-manifest) | |
operation="echo-manifest" | |
shift | |
;; | |
-g|--get-filetype) | |
operation="get-filetype" | |
shift | |
;; | |
-i|--is-filetype) | |
operation="is-filetype" | |
shift | |
;; | |
-j|--get-alltypes) | |
showAllFileTypes | |
pipeout | |
shift | |
;; | |
-n|--insert-manifest) | |
operation="insert-manifest" | |
shift | |
;; | |
-p|--print-manifest) | |
operation="print-manifest" | |
shift | |
;; | |
-r|--print-header) | |
operation="print-header" | |
shift | |
;; | |
-s|--save-manifest) | |
operation="save-manifest" | |
shift | |
;; | |
-t|--get-temp) | |
operation="get-temp" | |
shift | |
;; | |
-x|--get-hash) | |
operation="get-hash" | |
shift | |
;; | |
-z|--get-all-hashes) | |
operation="get-all-hashes" | |
shift | |
;; | |
-h|--help) displayHelp; close;; | |
-u|--menu) displayFunctionMenu; close;; | |
-v|--version) displayVersion; close;; | |
-*|--*) displayHelp; die "Unknown option $1";; | |
*) files+=("$1"); shift;; | |
esac | |
done | |
set -- "${files[@]}" | |
arg_count_nes_cli=$# | |
########################################## | |
# TEST & DEBUG # | |
########################################## | |
# ... tests here ... | |
require_args 1 | |
case ${operation} in | |
echo-header) echo_bps_header "$1"; close;; | |
echo-manifest) echo_manifest "$1"; close;; | |
get-filetype) getFileType "$1"; close;; | |
print-manifest) print_manifest "$1"; close;; | |
print-header) print_bps_header "$1"; close;; | |
get-temp) get_temp_no_header "$1"; close;; | |
get-hash) get_hash "$1"; close;; | |
get-all-hashes) get_all_hashes; close;; | |
esac | |
#-------------------------------------------- | |
require_args 2 | |
if [[ "${operation}" = "save-manifest" ]] | |
then | |
save_manifest "$1" "$2" | |
close | |
elif [[ "${operation}" = "insert-manifest" ]] | |
then | |
insert_manifest "$1" "$2" | |
close | |
elif [[ ${operation} = "is-filetype" ]] | |
then | |
isFileType "$1" $2 | |
close | |
fi | |
#-------------------------------------------- | |
require_args 3 | |
if [[ "${operation}" = "create" ]] | |
then | |
create_patch "$1" "$2" "$3" | |
close | |
elif [[ "${operation}" = "apply" ]] | |
then | |
apply_patch "$1" "$2" "$3" | |
close | |
fi | |
#-------------------------------------------- | |
########################################## | |
# END # | |
########################################## | |
close |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment