I found a couple of use cases where we [may] want to reparse a RetroArch .cht
file. The first is if you edit/delete/rearrange a bunch of stuff but the format is correct and you just want to re-number everything.
Renumber .cht
file contents:
perl -pe '++$a if /cheat\d+_desc/ ; s/(?<=cheat)\d+/$a/ ; s/(?<=cheat)(\d+)/$1-1/e' 'cheat.cht' | perl -0777 -pe 's/(?<=^cheats = )\d+(?=.*(?s).*cheat(\d+)(?-s))/$1+1/e' | perl -00pe0 > 'newcheat.cht'
It’s a trick that sets a counter variable each time cheat#_desc
is encountered, then it looks for that #
everytime it’s preceded by cheat
and replaces it. The counter increments to 1, at the start, so we have to do the whole thing again while subracting 1 (since the first cheat is numbered 0
).
After that, we ‘slurp’ the whole input file, matching cheats = #
to the very last #
in the file, and add 1. Finally, we strip extra EOL CR,LF, etc, out. It’s a nasty, dirty, misuse of Perl and Regex in a single line.
Here’s another one for ‘Nintendo DS’ cheats that have a ‘fake’ Category. This category is defined as a cheat#_desc
not followed immediately by cheat#_code
. Mario Kart DS (U).cht is a great example of this. Anyway, this bit of Perl will strip out the category names while combining them with the real cheat descriptions.
Merge DS categories and renumber .cht
file contents:
perl -0777 -pe 's/(cheat(\d+)_)desc(?=.*\n(?!cheat\2_code))/\1cat/gi' 'cheat.txt' | perl -pe '$cat = $1 if s/^cheat\d+_cat = \"(.*)\".*\n// ; s/(^cheat\d+_desc = \")/$1$cat, / ; ++$a if /cheat\d+_desc/ ; s/(?<=cheat)\d+/$a/ ; s/(?<=cheat)(\d+)/$1-1/e' | perl -0777 -pe 's/(?<=^cheats = )\d+(?=.*(?s).*cheat(\d+)(?-s))/$1+1/e' | perl -00pe0 > 'newcheat.txt'
This code rewrites cheat#_desc
not immediately followed by cheat#_code
as cheat#_cat
. The text of these is added to the cheat#_desc
, for each virtual category, while removing the category itself. Then we just renumber everything as in the first piece of code.