Generalising the MSU1 pack reader lost a property the original had. Its
find_entry() tested the compression method as part of matching, so an
entry it could not decode simply did not match and the scan continued.
zip_find_*() matched on name alone, so the first hit could be an entry
using some other method: the caller got an index, zip_file_open()
refused it, and there was no way to tell that a usable entry existed
further down the directory.
Reproduced with a pack holding an lzma "a-1.pcm" ahead of a deflated
"b-1.pcm": snes9x2010 plays the track, this core reported status 0x0a
(AudioError) and stayed silent. The same shape applies to ROM loading
and to patches inside a zip.
Make lookup skip undecodable entries, so a match is always readable,
and apply the same rule when loadzip picks the largest entry.
Verified: the mixed-method pack now plays and matches 2010 exactly. A
zip whose only ROM entry is lzma still fails the load cleanly rather
than crashing; one where an lzma entry precedes a deflated copy loads
the deflated one. The stored, deflated, decoy and program.rom
selection cases and the MSU1 loose/stored/deflated matrix are
unchanged.
unzip/ was minizip plus a zlib dependency, pulled in for three things:
loading a ROM out of a .zip, reading a patch out of the same zip, and
the unzStream wrapper that fed those patches to the patch readers. The
MSU1 pack support added recently already had to read zip entries and
did it with rinflate, libretro-common's cleanroom RFC 1951 decoder, so
the tree carried two zip readers and a compression library it no longer
needed.
Generalise the pack reader into zipfile.c: a zip_archive holds the
central directory, entries are found by name, extension or suffix, and
a zip_file reads one entry by offset. Stored entries seek for free;
deflated entries restart the inflate on a backward seek, which is what
minizip did too. msu1_pack.c is gone, msu1.c uses the general reader,
and the patch paths read an entry into memory and hand ReadIPSPatch or
ReadBPSPatch a memStream, which retires unzStream entirely.
Deleted: unzip/ (6 files), -lz from every platform, SYSTEM_ZIP, and
the minizip includes in memmap.cpp, stream.cpp, stream.h and
conffile.h. The binary no longer links libz.
Zip support was previously gated behind UNZIP_SUPPORT and only enabled
for the unix and win platform sets, because the vendored library was
only built there. The new reader is a core source with no external
dependency, so the gate is gone and zip content works everywhere -
including Android and the console targets, which silently answered
"This binary was not created with Zip support" until now.
Verified against generated archives: a 4 MB ROM loads bit-identically
from a loose file, a stored zip and a deflated zip (identical video and
audio hashes over 900 frames of scripted input). Each of the three
entry-selection rules is exercised - largest entry, program.rom, and
the ".1" multi-part extension - plus an archive with a decoy entry. An
IPS patch inside a zip applies from both stored and deflated archives.
MSU1 loose, stored-pack and deflated-pack playback is unchanged, and
the input, peripheral and preemptive-frames suites still pass.
minizip-ng dynamically includes
zlib-ng.h or zlib.h depending on
what was included prior
snes9x.h includes zlib.h
which needs to happen first or the
minizip include tries to include zlib-ng.h by default
resulting in an error because you can't
include both in a single translation unit
(cherry picked from commit 7967d5222d4f1478845a2cf2d661dd670a3e7b82)
* Call `unzClose(file)` outside of the assert clause. In Release mode,
any statement in an assert clause is not called, causing a memory leak.
If the file does not close successfully, `assert(FAIL)` is called.