Files
libretroadmin d580522058 Patch: the loaded patches, the pnach parser and the loaders in C
The patch store was a std::vector<IniPatch> exported to Counters and
VMManager, each walking it for the places it wanted; a 'bytes'
payload was a std::vector<u8> inside each patch; the dynamic patches
were copies of the game database's vectors; the parser split lines
into std::vector<std::string_view>; the loaders took std::string and
went through std::string buffers, std::optional and FileSystem's
std::vector of results.

Now:
- The patches are a plain array in Patch.cpp, read through
  LoadedPatchCount/LoadedPatch, and applied by ApplyLoadedPatches with
  a mask of places, in load order as before. A payload is a malloc'd
  run with its length, freed by ForgetLoadedPatches, and only
  allocated once the line has passed every check.
- The dynamic patches' entries are copied into one array of their
  own, a pattern run then a replacement run per patch, so a reload of
  the game database cannot leave them dangling.
- The parser splits into five (pointer, length) fields on the stack,
  with the stripping and empty-field rules SplitString had, and the
  command table takes the same.
- LoadPatchesFromZip and LoadPatchesFromDir take C strings. The zip
  member is inflated into a malloc'd buffer. The folder is walked with
  retro_opendir directly, with FindFiles's filter (files, hidden ones
  included, "*.pnach", sizable) and its order, and each file is read
  with filestream_read_file, which terminates it. The "not found"
  message no longer has a newline in the middle of the path.

tests/patch gains a lane that links Patch.cpp against the real
libretro-common directory, file and inflate code: pnach files for the
CRC in either case and with suffixes beside another CRC's, a .txt, a
hidden file, a directory named like a pnach and an empty folder; and
archives written by Python's zipfile with the member deflated, stored
under an upper-case name, only under a subfolder, and behind a
comment, plus every truncation and every one-byte corruption of one.
It fails if the CRC match turns case-sensitive.
2026-11-03 22:29:43 +01:00

78 lines
3.9 KiB
Bash
Executable File

#!/bin/sh
# Every patch line in the game database, through the real parser.
set -e
DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
ROOT=$(CDPATH= cd -- "$DIR/../.." && pwd)
# SANFLAGS is what CI passes; SANITIZER is the run-all.sh shorthand.
SANFLAGS=${SANFLAGS:-}
[ -n "${SANITIZER:-}" ] && SANFLAGS="$SANFLAGS -fsanitize=$SANITIZER"
echo "== game database patch lines vs the real parser =="
${CXX:-c++} -std=c++17 -O1 -w $SANFLAGS -I "$ROOT" -I "$ROOT/pcsx2" \
-I "$ROOT/common" -I "$ROOT/common/include" -I "$ROOT/3rdparty/include" \
-I "$ROOT/libretro/libretro-common/include" \
-o "$DIR/patch_dbparse" "$DIR/dbparse.cpp" \
"$ROOT/pcsx2/Patch.cpp" "$ROOT/pcsx2/FormatString.cpp" \
"$ROOT/libretro/libretro-common/file/file_path.c" "$ROOT/libretro/libretro-common/string/stdstring.c" "$ROOT/libretro/libretro-common/compat/compat_strl.c" "$ROOT/libretro/libretro-common/encodings/encoding_utf.c" "$ROOT/libretro/libretro-common/time/rtime.c"
"$DIR/patch_dbparse" "$ROOT/bin/resources/GameIndex.yaml"
echo "== game database entries vs the real parser =="
LC="$ROOT/libretro/libretro-common"
${CXX:-c++} -std=c++17 -O1 -w $SANFLAGS -I "$ROOT" -I "$ROOT/pcsx2" \
-I "$ROOT/common" -I "$ROOT/common/include" -I "$ROOT/3rdparty/include" \
-I "$LC/include" \
-c -o "$DIR/dbload.o" "$DIR/dbload.cpp"
for f in GameDatabase Pcsx2Config FormatString; do
${CXX:-c++} -std=c++17 -O1 -w $SANFLAGS -I "$ROOT" -I "$ROOT/pcsx2" \
-I "$ROOT/common" -I "$ROOT/common/include" -I "$ROOT/3rdparty/include" \
-I "$LC/include" -c -o "$DIR/dbload_$f.o" "$ROOT/pcsx2/$f.cpp"
done
# libretro-common is C: built by the C compiler, as in the core. Through
# the C++ driver its TSan annotations get C++ linkage and do not link.
LCOBJS=""
for f in rthreads/retro_eventcount rthreads/retro_procbarrier \
rthreads/retro_asym_eventcount formats/yaml/ryaml rthreads/rthreads \
file/file_path string/rstrtod string/stdstring compat/fopen_utf8 \
compat/compat_strl encodings/encoding_utf time/rtime; do
o="$DIR/dbload_lc_$(echo "$f" | tr / _).o"
${CC:-cc} -O1 -w $SANFLAGS -I "$LC/include" -c -o "$o" "$LC/$f.c"
LCOBJS="$LCOBJS $o"
done
${CXX:-c++} $SANFLAGS -o "$DIR/patch_dbload" "$DIR/dbload.o" \
"$DIR/dbload_GameDatabase.o" "$DIR/dbload_Pcsx2Config.o" \
"$DIR/dbload_FormatString.o" $LCOBJS -lpthread
"$DIR/patch_dbload" "$ROOT/bin/resources/GameIndex.yaml"
echo "== the core's built-in game patches, every serial and hint =="
${CC:-cc} -std=c89 -O1 -Wall -Wdeclaration-after-statement $SANFLAGS \
-I "$LC/include" -c "$DIR/ingame.c" -o "$DIR/ingame.o"
${CXX:-c++} -std=c++17 -O1 -w $SANFLAGS -I "$ROOT" -I "$ROOT/pcsx2" \
-I "$ROOT/common" -I "$ROOT/common/include" -I "$ROOT/3rdparty/include" \
-I "$LC/include" \
-o "$DIR/patch_ingame" "$DIR/ingame.o" "$DIR/ingame_glue.cpp" "$ROOT/libretro/patches.cpp" \
"$ROOT/pcsx2/Patch.cpp" "$ROOT/pcsx2/FormatString.cpp" \
"$LC/file/file_path.c" "$LC/string/stdstring.c" "$LC/compat/compat_strl.c" \
"$LC/encodings/encoding_utf.c" "$LC/time/rtime.c"
rm -f "$DIR/ingame.o"
"$DIR/patch_ingame" "$ROOT/libretro/patches.cpp"
echo "== pnach files and archives through the real file code =="
ZDIR=$(mktemp -d /tmp/pnachzips.XXXXXX)
python3 -I "$DIR/mkzips.py" "$ZDIR"
PLOBJS=""
for f in file/retro_dirent vfs/vfs_implementation compat/compat_fnmatch \
file/file_path file/file_path_io streams/file_stream encodings/encoding_deflate \
encodings/encoding_crc32 features/features_cpu string/rstrtod \
string/stdstring compat/compat_strl encodings/encoding_utf time/rtime compat/fopen_utf8; do
o="$DIR/pnachload_lc_$(echo "$f" | tr / _).o"
${CC:-cc} -O1 -w $SANFLAGS -I "$LC/include" -c -o "$o" "$LC/$f.c"
PLOBJS="$PLOBJS $o"
done
${CXX:-c++} -std=c++17 -O1 -w $SANFLAGS -I "$ROOT" -I "$ROOT/pcsx2" \
-I "$ROOT/common" -I "$ROOT/common/include" -I "$ROOT/3rdparty/include" \
-I "$LC/include" \
-o "$DIR/patch_pnachload" "$DIR/pnachload.cpp" "$ROOT/pcsx2/Patch.cpp" $PLOBJS
"$DIR/patch_pnachload" "$ZDIR"
rm -f "${ZDIR:?}"/*.zip
rmdir "${ZDIR:?}"