Skip to content

Instantly share code, notes, and snippets.

@dvessel
Last active November 23, 2022 21:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dvessel/8466f69be77caa8a687ad18fb8aa5e06 to your computer and use it in GitHub Desktop.
Save dvessel/8466f69be77caa8a687ad18fb8aa5e06 to your computer and use it in GitHub Desktop.
Command line launcher for Dolphin emulator. (MacOS)
[{
"flag": "--game",
"description": "Hooks into existing flag. Hides the GUI when starting with a game.",
"options": [
"--batch"
]
}, {
"flag": "--metal",
"description": "Metal graphics backend",
"options": [
"--config=Dolphin.Core.GFXBackend=Metal"
]
}, {
"flag": "--vulkan",
"description": "Vulkan graphics backend",
"options": [
"--config=Dolphin.Core.GFXBackend=Vulkan"
]
}, {
"flag": "--gfx-software",
"description": "Software graphics backend",
"options": [
"--config=Dolphin.Core.GFXBackend=Software Renderer"
]
}, {
"flag": "--sc",
"description": "Enable single core.",
"options": [
"--config=Dolphin.Core.CPUThread=False"
]
}, {
"flag": "--dc",
"description": "Enable dual core. This is prone to errors.",
"options": [
"--config=Dolphin.Core.CPUThread=True"
]
}, {
"flag": "--speedup",
"description": "105% faster emulation. Added for SoulCalibur II because I felt like it.",
"options": [
"--config=Dolphin.Core.EmulationSpeed=1.05"
]
}, {
"flag": "--rtc-12:34",
"description": "Testing for F-Zero intro track.",
"options": [
"--config=Dolphin.Core.CustomRTCValue=0x386d4b78",
"--config=Dolphin.Core.EnableCustomRTC=True"
]
}, {
"flag": "--aspect-auto",
"description": "Auto aspect ratio.",
"options": [
"--config=Graphics.Settings.AspectRatio=0"
]
}, {
"flag": "--4:3",
"description": "Force 4:3 aspect ratio.",
"options": [
"--config=Graphics.Settings.AspectRatio=2"
]
}, {
"flag": "--16:9",
"description": "Force 16:9 aspect ratio.",
"options": [
"--config=Graphics.Settings.AspectRatio=1"
]
}, {
"flag": "--hybrid-ubershaders",
"description": "Use exclusive ubershaders.",
"options": [
"--config=Graphics.Settings.ShaderCompilationMode=2"
]
}, {
"flag": "--exclusive-ubershaders",
"description": "Use exclusive ubershaders.",
"options": [
"--config=Graphics.Settings.ShaderCompilationMode=1"
]
}, {
"flag": "--default-textures",
"description": "Use default textures. Disables texture loading.",
"options": [
"--config=Graphics.Settings.HiresTextures=False"
]
}, {
"flag": "--load-textures",
"description": "Load custom textures.",
"options": [
"--config=Graphics.Settings.HiresTextures=True"
]
}, {
"flag": "--dump-textures",
"description": "Enable texture dumping. Triggers dump management when GAMEID.sh exists.",
"options": [
"--config=Graphics.Settings.DumpTextures=True",
"--config=Graphics.Settings.TexturePNGCompressionLevel=0",
"--config=Graphics.Settings.HiresTextures=False"
]
}, {
"flag": "--with-mipmaps",
"description": "Enable texture dumping. Triggers dump management when GAMEID.sh exists.",
"options": [
"--config=Graphics.Enhancements.ArbitraryMipmapDetection=False",
"--config=Graphics.Settings.DumpMipTextures=True"
]
}, {
"flag": "--with-arbitrary-mipmaps",
"description": "Enable texture dumping. Triggers dump management when GAMEID.sh exists.",
"options": [
"--config=Graphics.Enhancements.ArbitraryMipmapDetection=True",
"--config=Graphics.Settings.DumpMipTextures=True"
]
}, {
"flag": "--dsp-hle",
"description": "DSP audio high level emulation (fast).",
"options": [
"--config=Dolphin.Core.DSPHLE=True"
]
}, {
"flag": "--dsp-lle",
"description": "DSP audio low level emulation (recompiler - slow).",
"options": [
"--config=Dolphin.Core.DSPHLE=False",
"--config=Dolphin.Core.DPL2Decoder=False",
"--config=Dolphin.DSP.EnableJIT=True"
]
}, {
"flag": "--dolby",
"description": "Enable Dolby Pro Logic II decoder (recompiler - slow).",
"options": [
"--config=Dolphin.Core.DSPHLE=False",
"--config=Dolphin.Core.DPL2Decoder=True",
"--config=Dolphin.DSP.EnableJIT=True"
]
}, {
"flag": "--uncap-render",
"description": "Used for testing render performance.",
"options": [
"--config=Graphics.Settings.LogRenderTimeToFile=True",
"--config=Graphics.Settings.ShowFPS=True",
"--config=Dolphin.Core.EmulationSpeed=0",
"--config=Dolphin.DSP.Backend=No Audio Output",
"--config=Dolphin.General.ShowFrameCount=True",
"--config=Dolphin.Movie.PauseMovie=True"
]
}, {
"flag": "--log-notice",
"description": "",
"options": [
"--config=Logger.Options.Verbosity=1",
"--config=Logger.Options.WriteToConsole=True"
]
}, {
"flag": "--log-error",
"description": "",
"options": [
"--config=Logger.Options.Verbosity=2",
"--config=Logger.Options.WriteToConsole=True"
]
}, {
"flag": "--log-warning",
"description": "",
"options": [
"--config=Logger.Options.Verbosity=3",
"--config=Logger.Options.WriteToConsole=True"
]
}, {
"flag": "--log-info",
"description": "",
"options": [
"--config=Logger.Options.Verbosity=4",
"--config=Logger.Options.WriteToConsole=True"
]
}, {
"flag": "--log-disabled",
"description": "Disable all logging.",
"options": [
"--config=Logger.Logs.ActionReplay=False",
"--config=Logger.Logs.AI=False",
"--config=Logger.Logs.Audio=False",
"--config=Logger.Logs.BOOT=False",
"--config=Logger.Logs.COMMON=False",
"--config=Logger.Logs.CONSOLE=False",
"--config=Logger.Logs.CORE=False",
"--config=Logger.Logs.CP=False",
"--config=Logger.Logs.DIO=False",
"--config=Logger.Logs.DSP=False",
"--config=Logger.Logs.DSPHLE=False",
"--config=Logger.Logs.DSPLLE=False",
"--config=Logger.Logs.DSPMails=False",
"--config=Logger.Logs.DVD=False",
"--config=Logger.Logs.EXI=False",
"--config=Logger.Logs.FileMon=False",
"--config=Logger.Logs.GDB_STUB=False",
"--config=Logger.Logs.GP=False",
"--config=Logger.Logs.HLE=False",
"--config=Logger.Logs.Host GPU=False",
"--config=Logger.Logs.IOS=False",
"--config=Logger.Logs.IOS_DI=False",
"--config=Logger.Logs.IOS_ES=False",
"--config=Logger.Logs.IOS_FS=False",
"--config=Logger.Logs.IOS_NET=False",
"--config=Logger.Logs.IOS_SD=False",
"--config=Logger.Logs.IOS_SSL=False",
"--config=Logger.Logs.IOS_STM=False",
"--config=Logger.Logs.IOS_USB=False",
"--config=Logger.Logs.IOS_WC24=False",
"--config=Logger.Logs.IOS_WFS=False",
"--config=Logger.Logs.IOS_WIIMOTE=False",
"--config=Logger.Logs.JIT=False",
"--config=Logger.Logs.MASTER=False",
"--config=Logger.Logs.MemCard Manager=False",
"--config=Logger.Logs.MI=False",
"--config=Logger.Logs.NETPLAY=False",
"--config=Logger.Logs.OSREPORT=False",
"--config=Logger.Logs.PAD=False",
"--config=Logger.Logs.PE=False",
"--config=Logger.Logs.PI=False",
"--config=Logger.Logs.PowerPC=False",
"--config=Logger.Logs.SI=False",
"--config=Logger.Logs.SP1=False",
"--config=Logger.Logs.SYMBOLS=False",
"--config=Logger.Logs.VI=False",
"--config=Logger.Logs.Video=False",
"--config=Logger.Logs.WII_IPC=False",
"--config=Logger.Logs.Wiimote=False",
"--config=Logger.Logs.FRAMEDUMP=False",
"--config=Logger.Logs.OSREPORT_HLE=False",
"--config=Logger.Logs.CI=False",
"--config=Logger.Logs.HSP=False"
]
}]
#!/bin/zsh
# Default function to run Dolphin.
#
# @optional --binary|-i [search]
# @optional --game|-g [search]
# If a search only has a single result, it will automatically be accepted.
# @optional --latest [search]
# Will selected the latest binary no matter how many results.
# @optional --force
# Overrides any settings within a game.ini file. --game is required.
# @optional --show-args
# Shows the arguments that would be passed to Dolphin without running it.
function run {
local blatest=${argv[( $argv[(i)--latest] + 1 )]##-*}
local bsearch=${argv[( $argv[(i)--binary|-i] + 1 )]##-*}
local gsearch=${argv[( $argv[(i)--game|-g] + 1 )]##-*}
local cl=(
--latest $blatest --binary -i $bsearch --game -g $gsearch --show-args --force --dump-textures
)
declare -g usr_dir
usr_dir=${${argv[$argv[(i)--user=*]]##--user=}:-${argv[( $argv[(i)-u] + 1 )]##-*}}
usr_dir=${usr_dir:-~/Library/Application\ Support/Dolphin}
if [[ $argv[(I)(--binary|-i)] -gt 0 ]]; then
i.active_app --query=$bsearch --select-1
else
i.active_app --filter=$blatest
fi
if [[ $argv[(I)(--game|-g)] -gt 0 ]]; then
i.active_rom --query=$gsearch --select-1 --header=$active_ver
argv+=--exec=$active_rom
fi
local shortcuts=$usr_dir/Config/cli-shortcuts.json
if [[ -f $shortcuts ]]; then
local sc=( `jq -r '.[] | .flag' $shortcuts` )
for f in $argv; if [[ $sc[(I)$f] -gt 0 ]]; then
for i in {0..$((
`jq -j --arg f $f '.[] | select(.flag == $f) .options | length' $shortcuts` - 1
))}; argv+=(
"`jq -r --arg f $f --argjson i $i '.[] | select(.flag == $f) .options[$i]' $shortcuts`"
)
fi
fi
if [[ $argv[(I)--show-args] -gt 0 ]]; then
printf "%q " $active_bin ${${@:|cl}:|sc}; echo; exit
fi
if [[ $argv[(I)--force] -gt 0 ]]; then
i.force-config ${${@:|cl}:|sc}
fi
if [[ $argv[(I)--dump-textures] -gt 0 ]]; then
i.preprocess-dumped-textures --scratch-size 128
fi
export MVK_CONFIG_LOG_LEVEL=2
$active_bin ${${@:|cl}:|sc}
}
# Find and select Dolphin. (Requires Spotlight.)
#
# @global $active_ver $active_app $active_bin
# Dolphin version, path to app bundle and internal command line executable.
function i.active_app {
[[ -z $active_app ]] || return
local apps active_info
while read -r p; do v=''
for k in CFBundleShortVersionString CFBundleLongVersionString
v+="`plutil -extract $k raw $p/Contents/Info.plist` "
apps+="$v[1,20]\t$p\t$p/Contents/MacOS/Dolphin\n"
done < <( mdfind "kMDItemCFBundleIdentifier==org.dolphin-emu.dolphin" )
active_info=`printf $apps | sort -Vr | fzf -d "\t" --with-nth=1,2 --tiebreak=begin $@ | head -n 1`
if [[ -z $active_info ]]; then
echo "Dolphin not selected. Exiting." >&2; exit 1
fi
declare -g active_ver active_app active_bin
active_ver=`printf $active_info | cut -f1`
active_app=`printf $active_info | cut -f2`
active_bin=`printf $active_info | cut -f3`
}
# Invokes rom selection.
#
# @global $active_rom $active_rid
# Full rom path and the 6 character rom id.
function i.active_rom {
[[ -z $active_rom ]] || return
local ext=${argv[( $argv[(i)--format|-f] + 1 )]:-iso|gcz|wia|rvz|nkit}
local cl=( --format -f $ext )
local roms
for i in {1..`i.config -c Dolphin.General.ISOPaths`}
while read -r r; do
[[ `file -b $r` =~ ([0-9A-Z]{6}),.*\)$ ]] && g=$match[1] || g=??????
roms+="$r\t$g\t$r:t:r\n"
done < <( find -E $(i.config -c Dolphin.General.ISOPath$((--i))) -regex ".+\.($ext)" 2>/dev/null )
if [[ -z $roms ]]; then
echo "No results for $ext." >&2; exit 1
fi
local rom_info=`printf $roms | sort -t $'\t' -k3 | fzf -d "\t" --with-nth=3 --tiebreak=begin ${@:|cl}`
if [[ -z $rom_info ]]; then
echo Canceled.; exit
fi
declare -g active_rom active_rid
active_rom=`printf $rom_info | cut -f1`
active_rid=`printf $rom_info | cut -f2`
}
# Reads configuration data from ini files.
#
# @required --config|-c [System.Section.Key]
# Example: `Dolphin.Core.Foo` would look for the key `Foo` under the `Core`
# section within Dolphin.ini system config file.
# @optional --path|-p [path/to/GAMEID.ini]
# Set a GAMEID.ini path to load. `System` Is ignored from --config when set.
# @return string
function i.config {
if [[ $argv[(I)(--path|-p)] -gt 0 ]]; then
if [[ $argv[( $argv[(i)--config|-c] + 1 )] =~ ([[:alnum:].]+) ]]; then
local key=$match[1] ini=$argv[( $argv[(i)--path|-p] + 1 )]
fi
else
if [[ $argv[( $argv[(i)--config|-c] + 1 )] =~ ([[:alnum:]]+)\.([[:alnum:].]+) ]]; then
local key=$match[2] ini=$usr_dir/Config/${match[1]:/Graphics/GFX}.ini
fi
fi
if [[ -z $match ]]; then
echo "Invalid setting: $argv[( $argv[(i)--config|-c] + 1 )]" >&2; exit 1
elif [[ ! -f $ini ]]; then
echo "Config file '$ini' not found." >&2; exit 1
fi
while read -r l; do
[[ $l =~ ^\\[(.+)\\] ]] && s=$match[1] && continue
[[ $l =~ (^[[:alnum:]]+)\ *=\ *([[:print:]]+) ]] &&
[[ $s.$match[1] == $key ]] && printf $match[2] && break
done < <( grep "\S" $ini )
}
# Overrides game.ini options with command line options.
#
function i.force-config {
[[ -n $active_rid && -n $active_app ]] || return
local -a keys vals
local -a inipaths=(
$usr_dir/GameSettings/$active_rid.ini
$usr_dir/GameSettings/$active_rid[1,3].ini
$active_app/Contents/Resources/Sys/GameSettings/$active_rid[1,3].ini
)
local ini=$inipaths[1]
for c in $argv; [[ $c =~ --config=([[:alnum:].]+)=(.+) ]] &&
keys+=$match[1] vals+=$match[2]
for k in $keys; for p in $inipaths; do v=
if [[ -f $p ]]; then
v=`i.config --config $k --path $p ||
i.config -c ${${${k/#Dolphin.Core/Core}/#Dolphin.DSP/DSP}/#Graphics./Video_} -p $p`
fi
# Why does -n go through with empty values? `! -z $v` catches it.
test ! -z $v || continue
if [[ $v != $vals[$keys[(i)$k]] && $k =~ ([[:alnum:]]+\.[[:alnum:]]+)\.([[:alnum:]]+) ]]; then
echo "\n\n\n# temporary override:\n# $p\n# $k = $v" >> $ini.tmp
echo "[$match[1]]\n$match[2] = $vals[$keys[(i)$k]]" >> $ini.tmp
fi
break
done
if [[ -f $ini.tmp ]]; then
declare -g forced_ini=$ini
test ! -f $ini && cp $ini.tmp $ini ||
mv $ini $ini.bak && cat $ini.bak $ini.tmp > $ini
rm $ini.tmp
fi
}
# Uses a RAM disk for scratch space.
#
# @optional --scratch-size [size]
# Size in MB. Defaults to 128.
function i.preprocess-dumped-textures {
[[ -n $active_rid && -f $usr_dir/Dump/Textures/$active_rid.sh ]] || return 1
local size=${argv[( $argv[(i)--scratch-size] + 1 )]:-128}
local gid=$active_rid
local dump=$usr_dir/Dump/Textures/$gid.base
local load=$usr_dir/Load/Textures/$gid
# Move `GAMEID` dump folder to `GAMEID.base` and merge them if they both exist.
if [[ ! -h $dump:r && -d $dump:r ]]; then
if [[ -d $dump ]]; then
fd '^tex1_.+\.png$' $dump:r -X mv {} $dump
test "`fd -tf -1 . $dump:r`" &&
mv $dump:r $dump:r.backup || rm -rf $dump:r
else
mv $dump:r $dump
fi
fi
if [[ ! -d /Volumes/$gid ]]; then
diskutil partitionDisk $(hdiutil attach -nomount ram://$((2048*$size))) 1 GPTFormat APFS $gid 100%
echo "Preparing scratch space. Please wait..."
TIMEFMT=$'Finished in %*E seconds.'
time fd '^tex1_.+\.png$' $dump -X touch /Volumes/$gid/{/}
fi
ln -fhs /Volumes/$gid $dump:r
echo Ready...
source $usr_dir/Dump/Textures/$active_rid.sh &
}
# Collect accessible function list. Omit [i.]nternal functions.
fnl=(${(k)functions:#i.*})
# Clean up!
function TRAPINT {
exit
}
function TRAPEXIT {
# i.force-config
if [[ -n $forced_ini ]]; then
test -f $forced_ini.bak &&
mv -f $forced_ini.bak $forced_ini ||
rm $forced_ini
fi
# i.dump-textures
if [[ -n $active_rid && -h $usr_dir/Dump/Textures/$active_rid ]]; then
test $active_rid.base != `readlink $usr_dir/Dump/Textures/$active_rid` &&
ln -fhs $active_rid.base $usr_dir/Dump/Textures/$active_rid
test -d /Volumes/$active_rid &&
hdiutil eject /Volumes/$active_rid
fi
pkill -g 0
}
# First argument calls the function. Defaults to "run" if invalid or not given.
${fnl[$fnl[(Ie)$1]]:-run} ${@:|fnl}
#!/bin/zsh
# Metroid Prime 2
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
review_dir="$dump/- review"
mkdir -p $ignore_dir $linked_dir $review_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_(64[02]x4[45][80]_[0-9a-f]{16}_2|.+_4)\.png$ ]]; then
rm $p
echo "\033[9;37m$p:t deleted. \033[0m"
elif [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_((128|256|512)x(16|32|64|128|256)|512x512)_[a-f0-9]{16}_14\.png$ ]]; then
magick $p $review_dir/$p:t; rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;35m$p:t review. \033[0m"
elif [[ $p:t =~ ^tex1_(320x(184|224)|640x(368|448))_.+_1\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t FMV ignored. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# Dynamic textures.
# - tex1_*_4.png
# - tex1_642x450_*_2.png
# - tex1_640x448_*_2.png
# Light maps (blocky and often colored purple).
# Do not ignore mipmapped textures with the same dimensions.
# * tex1_128x16_*14
# * tex1_128x32_*_14
# * tex1_128x64_*_14
# * tex1_128x128_*_14
# * tex1_128x256_*_14
# - tex1_256x16_*14
# - tex1_256x32_*_14
# - tex1_256x64_*_14
# * tex1_256x128_*_14
# * tex1_256x256_*_14
# - tex1_512x16_*_14
# - tex1_512x32_*_14
# - tex1_512x64_*_14
# - tex1_512x128_*_14
# - tex1_512x256_*_14
# - tex1_512x512_*_14
# Conflicts:
# * tex1_128x16_0b98ebcd2b1ad927_14.png
# * tex1_128x32_cb5effa8501a2ab5_14.png
# * tex1_128x32_dbfe3ff0180733f6_14.png
# * tex1_128x32_ee91b518387f08f8_14.png
# * tex1_128x64_b763ef3aaba26ee9_14.png
# * tex1_128x64_e378bac5ef1d4edc_14.png
# * tex1_128x128_1693de7a151c7c61_14.png
# * tex1_128x128_322a99c689b04f92_14.png
# * tex1_128x128_7268110735ee7ba2_14.png
# * tex1_128x128_d319a67781ff8e2a_14.png
# * tex1_128x128_d5f7fdcc2ce2547f_14.png
# * tex1_128x256_d2a1257e4932232a_14.png
# * tex1_256x128_73ef9096d5f45287_14.png
# * tex1_256x256_9d9a206e08f07ec0_14.png
# * tex1_256x256_9f93901bed9b388d_14.png
# FMV
# - tex1_320x184_*_1
# - tex1_320x224_*_1
# - tex1_640x368_*_1
# - tex1_640x448_*_1
#!/bin/zsh
# Resident Evil
# preliminary
ignore_dir="$dump/- ignore"
mkdir -p $ignore_dir
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_(256x168_.+_6)\.png$ ]]; then
rm $p
echo "\033[9;37m$p:t deleted. \033[0m"
elif [[ $p:t =~ ^tex1_(512x336_.+_1|256x168_.+_3)\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t FMV ignore. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# Dynamic
# - tex1_256x168_*_6.png
# FMV
# - tex1_512x336_*_1.png
# - tex1_256x168_*_3.png
#!/bin/zsh
# Paper Mario - The Thousand-Year Door
# preliminary
linked_dir="$dump/- linked"
mkdir -p $ignore_dir $linked_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
#!/bin/zsh
# F-ZERO GX
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
mkdir -p $ignore_dir $linked_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_(16x16_.+_[12]|4x128_.+_3|320x224_.+_5)\.png$ ]]; then
rm $p
echo "\033[9;37m$p:t deleted. \033[0m"
elif [[ $p:t =~ ^tex1_((.x.+|.+x.)|(12|16|20|24|32)x(12|16|20|24|28|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_(320x168_.+_3|640x336_.+_1)\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t FMV ignored. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# Dynamically generated in intro logo and ship select.
# - tex1_16x16_*_1.png
# - tex1_16x16_*_2.png
# - tex1_4x128_*_3.png
# Copy EBF to texture for end credits.
# - tex1_320x224_*_5.png
# FMV
# - tex1_320x168_*_3.png
# - tex1_640x336_*_1.png
#!/bin/zsh
# IKARUGA
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
mkdir -p $ignore_dir $linked_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_(640x368|640x448)_.+_6\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m $p:t FMV ignore. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# FMV
# - tex1_640x368_*_6.png
# - tex1_640x448_*_6.png
#!/bin/zsh
# Mario Kart - Double Dash!!
# preliminary
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
mkdir -p $ignore_dir $linked_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_(304x224|608x448)_.+_1\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t FMV ignored. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# FMV
# - tex1_304x224_*_1.png
# - tex1_608x448_*_1.png
#!/bin/zsh
# Metroid Prime
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
review_dir="$dump/- review"
mkdir -p $ignore_dir $linked_dir $review_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_(64[02]x4[45][80]_[0-9a-f]{16}_2|.+_4)\.png$ ]]; then
rm $p
echo "\033[9;37m$p:t deleted. \033[0m"
elif [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_((256)x(16|32|64|128|256|512)|512x256)_[a-f0-9]{16}_14\.png$ ]]; then
magick $p $review_dir/$p:t; rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;35m$p:t review. \033[0m"
elif [[ $p:t =~ ^tex1_(320x240|640x480)_.+_1\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t FMV ignored. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# Dynamic textures.
# - tex1_*_4.png
# - tex1_642x450_*_2.png
# - tex1_640x448_*_2.png
# Light maps (blocky and often colored purple).
# Do not ignore mipmapped textures with these dimensions.
# - tex1_256x16_*14
# * tex1_256x32_*_14
# - tex1_256x64_*_14
# - tex1_256x128_*_14
# * tex1_256x256_*_14
# - tex1_256x512_*_14
# - tex1_512x256_*_14
# Conflicts:
# * tex1_256x32_d1994fd7bf879660_14.png
# * tex1_256x256_4a7e1590e1d34e91_14.png
# * tex1_256x256_9d9a206e08f07ec0_14.png
# * tex1_256x256_9f93901bed9b388d_14.png
# FMV
# - tex1_320x240_*_1
# - tex1_640x480_*_1
#!/bin/zsh
# SOULCALIBUR 2
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
mkdir -p $ignore_dir $linked_dir $load
ln -sf $linked_dir $load
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_(640x368|640x448)_.+_6\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t FMV ignored. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# FMV
# tex1_640x368_*_6.png
# tex1_640x448_*_6.png
#!/bin/zsh
# VIEWTIFUL JOE
# preliminary
ignore_dir="$dump/- ignore"
linked_dir="$dump/- linked"
mkdir -p $ignore_dir $linked_dir $load
ln -sf $linked_dir $load
# film grain and debris. do not process.
link_list=(
tex1_128x128_4891aa7c35419451_14.png
tex1_14x14_7156df3a049d5496_29a9a9b57a4d576f_8.png
tex1_14x16_511802597f7ff346_43febf0e1ce975a4_8.png
tex1_14x36_694f90bbc6c02bb8_63034f9aba923882_8.png
tex1_24x82_14af3816255d439b_3bd492a0f640f537_8.png
tex1_28x30_d3af9ae5c344aa15_cea3a438545a0ef5_8.png
tex1_44x44_8425324d5a4f63b0_d7ca7f8403f817a6_8.png
)
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_((.x.+|.+x.)|(16|32)x(16|32))_.+\.png$ || $link_list[(I)$p:t] > 0 ]]; then
magick $p $linked_dir/$p:t; rm $p
touch $p
echo "\033[0;37m$p:t linked. \033[0m"
elif [[ $p:t =~ ^tex1_(16x16|64x64)_.+_3\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m$p:t Unknown ignored. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t; rm $p
touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# Unknown, just gray
# tex1_16x16_*_3.png
# tex1_64x64_*_3.png
#!/bin/zsh
# The Legend of Zelda Twilight Princess
# preliminary
ignore_dir="$dump/- ignore"
review_dir="$dump/- review"
mkdir -p $ignore_dir $review_dir
while read -r p; do
[[ -s $p ]] || continue
if [[ $p:t =~ ^tex1_(304x224|608x448)_.+_1\.png$ ]]; then
rm $p
touch $p $ignore_dir/$p:t
echo "\033[0;37m $p:t FMV ignore. \033[0m"
elif [[ $p:t =~ ^tex1_.+\.png$ ]]; then
magick $p $dump/$p:t
rm $p; touch $p
echo "$p:t ready."
fi
done< <( fswatch --event Created /Volumes/$gid )
# FMV
# - tex1_304x224_*_1.png
# - tex1_608x448_*_1.png
@dvessel
Copy link
Author

dvessel commented May 27, 2022

Requires fzf, fd, jq, fswatch and imagemagick. Install with brew install fzf fd jq fswatch imagemagick

  • fzf for searching and selecting Dolphin.app and games.
  • fd for searching and setting up the scratch space for texture dumping.
  • jq for processing the shortcuts within the cli-shortcuts.json file.
  • fswatch used for monitoring and managing texture dumps.
  • imagemagick for compressing dumps. I’m running a compiled version of Dolphin with configurable png compression for texture dumps which greatly improves performance. see pull request #10792

Installation:

  • Throw dolphin into a bin path and run chmod +x dolphin.
  • Move the cli-shortcuts.json file into ~/Library/Application Support/Dolphin/Config and edit as you wish.
  • Move all the GAMEID.sh into ~/Library/Application Support/Dolphin/Dump/Textures and run with --dump-textures.

Made while using MacOS Monterey (zsh 5.8.1) with no consideration of other systems. YMMV

This will eventually be thrown into a personal homebrew tap so it’s easier to install

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment