RetroArch/tasks/task_patch.c

985 lines
28 KiB
C
Raw Normal View History

2012-04-21 21:13:50 +00:00
/* RetroArch - A frontend for libretro.
2014-01-01 00:50:59 +00:00
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
2016-01-10 03:06:50 +00:00
* Copyright (C) 2011-2016 - Daniel De Matteis
*
2012-04-21 21:13:50 +00:00
* RetroArch is free software: you can redistribute it and/or modify it under the terms
2011-08-17 22:05:56 +00:00
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
2012-04-21 21:13:50 +00:00
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
2011-08-17 22:05:56 +00:00
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
2012-04-21 21:31:57 +00:00
* You should have received a copy of the GNU General Public License along with RetroArch.
2011-08-17 22:05:56 +00:00
* If not, see <http://www.gnu.org/licenses/>.
*/
2014-09-02 03:10:54 +00:00
/* BPS/UPS/IPS implementation from bSNES (nall::).
* Modified for RetroArch. */
2012-03-20 22:08:34 +00:00
2017-01-31 04:33:13 +00:00
/* TODO/FIXME - turn this into actual task */
2012-03-16 22:42:00 +00:00
#include <stdint.h>
2012-03-20 22:08:34 +00:00
#include <string.h>
#include <boolean.h>
#include <compat/msvc.h>
#include <file/file_path.h>
2016-03-20 15:29:14 +00:00
#include <streams/file_stream.h>
#include <string/stdstring.h>
#include <encodings/crc32.h>
2016-09-06 21:52:33 +00:00
2022-12-05 14:10:19 +00:00
#include "../runloop.h"
2017-01-31 04:33:42 +00:00
#include "../msg_hash.h"
#include "../verbosity.h"
#include "../configuration.h"
2011-08-17 22:05:56 +00:00
#ifdef HAVE_XDELTA
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
#include "../deps/xdelta3/xdelta3.h"
#endif
2011-08-17 22:05:56 +00:00
enum bps_mode
{
SOURCE_READ = 0,
TARGET_READ,
SOURCE_COPY,
TARGET_COPY
};
2016-02-25 18:33:46 +00:00
enum patch_error
{
PATCH_UNKNOWN = 0,
PATCH_SUCCESS,
PATCH_PATCH_TOO_SMALL,
PATCH_PATCH_INVALID_HEADER,
PATCH_PATCH_INVALID,
PATCH_SOURCE_TOO_SMALL,
2019-09-01 19:01:48 +00:00
PATCH_TARGET_ALLOC_FAILED,
2016-02-25 18:33:46 +00:00
PATCH_SOURCE_INVALID,
PATCH_TARGET_INVALID,
PATCH_SOURCE_CHECKSUM_INVALID,
PATCH_TARGET_CHECKSUM_INVALID,
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
PATCH_PATCH_CHECKSUM_INVALID,
PATCH_PATCH_UNSUPPORTED
2016-02-25 18:33:46 +00:00
};
2011-08-17 22:05:56 +00:00
struct bps_data
{
2020-08-14 16:58:09 +00:00
const uint8_t *modify_data;
const uint8_t *source_data;
uint8_t *target_data;
2017-05-13 20:21:57 +00:00
size_t modify_length;
size_t source_length;
size_t target_length;
size_t modify_offset;
size_t source_offset;
size_t target_offset;
size_t source_relative_offset;
size_t target_relative_offset;
size_t output_offset;
2020-03-07 18:14:45 +00:00
uint32_t modify_checksum;
uint32_t source_checksum;
uint32_t target_checksum;
2011-08-17 22:05:56 +00:00
};
2016-05-27 15:29:12 +00:00
struct ups_data
{
2020-08-14 16:58:09 +00:00
const uint8_t *patch_data;
const uint8_t *source_data;
uint8_t *target_data;
2017-05-13 20:21:57 +00:00
unsigned patch_length;
unsigned source_length;
unsigned target_length;
unsigned patch_offset;
unsigned source_offset;
unsigned target_offset;
unsigned patch_checksum;
unsigned source_checksum;
unsigned target_checksum;
2016-05-27 15:29:12 +00:00
};
typedef enum patch_error (*patch_func_t)(const uint8_t*, uint64_t,
const uint8_t*, uint64_t, uint8_t**, uint64_t*);
2016-02-07 00:46:20 +00:00
2011-08-17 22:05:56 +00:00
static uint8_t bps_read(struct bps_data *bps)
{
2017-05-14 20:23:05 +00:00
uint8_t data = bps->modify_data[bps->modify_offset++];
bps->modify_checksum = ~(encoding_crc32(
~bps->modify_checksum, &data, 1));
2011-08-17 22:05:56 +00:00
return data;
}
static uint64_t bps_decode(struct bps_data *bps)
{
uint64_t data = 0, shift = 1;
for (;;)
{
2016-01-21 02:35:06 +00:00
uint8_t x = bps_read(bps);
data += (x & 0x7f) * shift;
2011-08-17 22:05:56 +00:00
if (x & 0x80)
break;
2016-01-21 02:35:06 +00:00
shift <<= 7;
data += shift;
2011-08-17 22:05:56 +00:00
}
return data;
}
2016-02-25 18:33:46 +00:00
static enum patch_error bps_apply_patch(
const uint8_t *modify_data, uint64_t modify_length,
const uint8_t *source_data, uint64_t source_length,
uint8_t **target_data, uint64_t *target_length)
2011-08-17 22:05:56 +00:00
{
size_t i;
2017-05-13 20:21:57 +00:00
struct bps_data bps;
2020-01-20 03:44:45 +00:00
uint32_t checksum = 0;
size_t modify_source_size = 0;
size_t modify_target_size = 0;
size_t modify_markup_size = 0;
2016-09-19 02:01:02 +00:00
uint32_t modify_source_checksum = 0;
uint32_t modify_target_checksum = 0;
uint32_t modify_modify_checksum = 0;
2011-08-17 22:05:56 +00:00
if (modify_length < 19)
2012-03-17 00:10:57 +00:00
return PATCH_PATCH_TOO_SMALL;
2011-08-17 22:05:56 +00:00
2017-05-13 20:21:57 +00:00
bps.modify_data = modify_data;
bps.source_data = source_data;
bps.target_data = *target_data;
2017-05-13 20:21:57 +00:00
bps.modify_length = modify_length;
bps.source_length = source_length;
bps.target_length = *target_length;
bps.modify_offset = 0;
bps.source_offset = 0;
bps.target_offset = 0;
bps.modify_checksum = ~0;
bps.source_checksum = 0;
bps.target_checksum = ~0;
bps.source_relative_offset = 0;
bps.target_relative_offset = 0;
bps.output_offset = 0;
if ( (bps_read(&bps) != 'B') ||
2017-05-13 20:21:57 +00:00
(bps_read(&bps) != 'P') ||
(bps_read(&bps) != 'S') ||
2017-05-13 20:21:57 +00:00
(bps_read(&bps) != '1'))
2012-03-17 00:10:57 +00:00
return PATCH_PATCH_INVALID_HEADER;
2011-08-17 22:05:56 +00:00
2016-09-19 02:01:02 +00:00
modify_source_size = bps_decode(&bps);
modify_target_size = bps_decode(&bps);
modify_markup_size = bps_decode(&bps);
2017-05-13 20:21:57 +00:00
for (i = 0; i < modify_markup_size; i++)
2011-08-17 22:05:56 +00:00
bps_read(&bps);
if (modify_source_size > bps.source_length)
2012-03-17 00:10:57 +00:00
return PATCH_SOURCE_TOO_SMALL;
2020-01-20 03:44:45 +00:00
if (modify_target_size > bps.target_length)
{
uint8_t *prov=(uint8_t*)malloc((size_t)modify_target_size);
2020-01-20 03:44:45 +00:00
if (!prov)
2019-09-01 19:01:48 +00:00
return PATCH_TARGET_ALLOC_FAILED;
2020-01-20 03:44:45 +00:00
free(*target_data);
bps.target_data = prov;
*target_data = prov;
bps.target_length = modify_target_size;
}
2011-08-17 22:05:56 +00:00
while (bps.modify_offset < bps.modify_length - 12)
{
size_t length = bps_decode(&bps);
unsigned mode = length & 3;
2011-08-17 22:05:56 +00:00
length = (length >> 2) + 1;
switch (mode)
{
case SOURCE_READ:
while (length--)
2024-05-23 21:49:59 +00:00
{
uint8_t data = bps.source_data[bps.output_offset];
bps.target_data[bps.output_offset++] = data;
bps.target_checksum = ~(encoding_crc32(~bps.target_checksum, &data, 1));
}
2011-08-17 22:05:56 +00:00
break;
case TARGET_READ:
while (length--)
2024-05-23 21:49:59 +00:00
{
uint8_t data = bps_read(&bps);
bps.target_data[bps.output_offset++] = data;
bps.target_checksum = ~(encoding_crc32(~bps.target_checksum, &data, 1));
}
2011-08-17 22:05:56 +00:00
break;
case SOURCE_COPY:
case TARGET_COPY:
{
int offset = (int)bps_decode(&bps);
2011-08-17 22:05:56 +00:00
bool negative = offset & 1;
2015-07-01 22:56:51 +00:00
2011-08-17 22:05:56 +00:00
offset >>= 1;
2015-07-01 22:56:51 +00:00
2011-08-17 22:05:56 +00:00
if (negative)
offset = -offset;
if (mode == SOURCE_COPY)
{
bps.source_offset += offset;
while (length--)
2024-05-23 21:49:59 +00:00
{
uint8_t data = bps.source_data[bps.source_offset++];
bps.target_data[bps.output_offset++] = data;
bps.target_checksum = ~(encoding_crc32(~bps.target_checksum, &data, 1));
}
2011-08-17 22:05:56 +00:00
}
else
{
bps.target_offset += offset;
while (length--)
2024-05-23 21:49:59 +00:00
{
uint8_t data = bps.target_data[bps.target_offset++];
bps.target_data[bps.output_offset++] = data;
bps.target_checksum = ~(encoding_crc32(~bps.target_checksum, &data, 1));
}
2011-08-17 22:05:56 +00:00
break;
}
break;
}
}
}
for (i = 0; i < 32; i += 8)
2011-08-17 22:05:56 +00:00
modify_source_checksum |= bps_read(&bps) << i;
for (i = 0; i < 32; i += 8)
2011-08-17 22:05:56 +00:00
modify_target_checksum |= bps_read(&bps) << i;
checksum = ~bps.modify_checksum;
for (i = 0; i < 32; i += 8)
2011-08-17 22:05:56 +00:00
modify_modify_checksum |= bps_read(&bps) << i;
bps.source_checksum = encoding_crc32(0,
2016-02-07 00:44:54 +00:00
bps.source_data, bps.source_length);
2011-08-17 22:05:56 +00:00
bps.target_checksum = ~bps.target_checksum;
if (bps.source_checksum != modify_source_checksum)
2012-03-17 00:10:57 +00:00
return PATCH_SOURCE_CHECKSUM_INVALID;
2016-09-19 02:01:02 +00:00
2011-08-17 22:05:56 +00:00
if (bps.target_checksum != modify_target_checksum)
2012-03-17 00:10:57 +00:00
return PATCH_TARGET_CHECKSUM_INVALID;
2016-09-19 02:01:02 +00:00
2011-08-17 22:05:56 +00:00
if (checksum != modify_modify_checksum)
2012-03-17 00:10:57 +00:00
return PATCH_PATCH_CHECKSUM_INVALID;
2011-08-17 22:05:56 +00:00
*target_length = modify_target_size;
2012-03-17 00:10:57 +00:00
return PATCH_SUCCESS;
2011-08-17 22:05:56 +00:00
}
static uint8_t ups_patch_read(struct ups_data *data)
2012-03-16 22:42:00 +00:00
{
if (data && data->patch_offset < data->patch_length)
2012-03-16 22:42:00 +00:00
{
uint8_t n = data->patch_data[data->patch_offset++];
data->patch_checksum =
~(encoding_crc32(~data->patch_checksum, &n, 1));
2012-03-16 22:42:00 +00:00
return n;
}
return 0x00;
}
static uint8_t ups_source_read(struct ups_data *data)
2012-03-16 22:42:00 +00:00
{
if (data && data->source_offset < data->source_length)
2012-03-16 22:42:00 +00:00
{
uint8_t n = data->source_data[data->source_offset++];
data->source_checksum =
~(encoding_crc32(~data->source_checksum, &n, 1));
2012-03-16 22:42:00 +00:00
return n;
}
return 0x00;
}
static void ups_target_write(struct ups_data *data, uint8_t n)
2012-03-16 22:42:00 +00:00
{
if (data && data->target_offset < data->target_length)
2012-03-16 22:42:00 +00:00
{
data->target_data[data->target_offset] = n;
data->target_checksum =
~(encoding_crc32(~data->target_checksum, &n, 1));
2012-03-16 22:42:00 +00:00
}
2015-03-12 03:11:12 +00:00
if (data)
data->target_offset++;
2012-03-16 22:42:00 +00:00
}
static uint64_t ups_decode(struct ups_data *data)
2012-03-16 22:42:00 +00:00
{
uint64_t offset = 0, shift = 1;
for (;;)
2012-03-16 22:42:00 +00:00
{
uint8_t x = ups_patch_read(data);
2015-07-01 22:56:51 +00:00
offset += (x & 0x7f) * shift;
if (x & 0x80)
2012-03-16 22:42:00 +00:00
break;
shift <<= 7;
offset += shift;
}
return offset;
}
2016-02-25 18:33:46 +00:00
static enum patch_error ups_apply_patch(
const uint8_t *patchdata, uint64_t patchlength,
const uint8_t *sourcedata, uint64_t sourcelength,
uint8_t **targetdata, uint64_t *targetlength)
2012-03-16 22:42:00 +00:00
{
size_t i;
2017-05-13 20:21:57 +00:00
struct ups_data data;
2016-09-19 02:01:02 +00:00
unsigned source_read_length;
unsigned target_read_length;
2020-03-07 18:14:45 +00:00
uint32_t patch_result_checksum = 0;
uint32_t patch_read_checksum = 0;
uint32_t source_read_checksum = 0;
uint32_t target_read_checksum = 0;
2015-03-12 03:11:12 +00:00
data.patch_data = patchdata;
data.source_data = sourcedata;
data.target_data = *targetdata;
data.patch_length = (unsigned)patchlength;
data.source_length = (unsigned)sourcelength;
data.target_length = (unsigned)*targetlength;
2017-05-13 20:21:57 +00:00
data.patch_offset = 0;
data.source_offset = 0;
data.target_offset = 0;
2015-03-12 03:11:12 +00:00
data.patch_checksum = ~0;
2012-03-16 22:42:00 +00:00
data.source_checksum = ~0;
data.target_checksum = ~0;
if (data.patch_length < 18)
2012-03-17 00:10:57 +00:00
return PATCH_PATCH_INVALID;
2017-05-13 20:21:57 +00:00
if (
(ups_patch_read(&data) != 'U') ||
(ups_patch_read(&data) != 'P') ||
(ups_patch_read(&data) != 'S') ||
(ups_patch_read(&data) != '1')
)
2012-03-17 00:10:57 +00:00
return PATCH_PATCH_INVALID;
2012-03-16 22:42:00 +00:00
source_read_length = (unsigned)ups_decode(&data);
target_read_length = (unsigned)ups_decode(&data);
2012-03-16 22:42:00 +00:00
2017-05-13 20:21:57 +00:00
if ( (data.source_length != source_read_length)
&& (data.source_length != target_read_length))
2012-03-17 00:10:57 +00:00
return PATCH_SOURCE_INVALID;
2017-05-13 20:21:57 +00:00
2014-09-02 03:10:54 +00:00
*targetlength = (data.source_length == source_read_length ?
target_read_length : source_read_length);
2017-05-13 20:21:57 +00:00
2020-01-20 03:44:45 +00:00
if (data.target_length < *targetlength)
{
uint8_t *prov=(uint8_t*)malloc((size_t)*targetlength);
2020-01-20 03:44:45 +00:00
if (!prov)
2019-09-01 19:01:48 +00:00
return PATCH_TARGET_ALLOC_FAILED;
2020-01-20 03:44:45 +00:00
free(*targetdata);
*targetdata = prov;
data.target_data = prov;
}
2017-05-13 20:21:57 +00:00
data.target_length = (unsigned)*targetlength;
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
while (data.patch_offset < data.patch_length - 12)
2012-03-16 22:42:00 +00:00
{
unsigned length = (unsigned)ups_decode(&data);
while (length--)
2012-03-16 22:42:00 +00:00
ups_target_write(&data, ups_source_read(&data));
for (;;)
2012-03-16 22:42:00 +00:00
{
uint8_t patch_xor = ups_patch_read(&data);
ups_target_write(&data, patch_xor ^ ups_source_read(&data));
if (patch_xor == 0)
break;
2012-03-16 22:42:00 +00:00
}
}
while (data.source_offset < data.source_length)
2012-03-16 22:42:00 +00:00
ups_target_write(&data, ups_source_read(&data));
while (data.target_offset < data.target_length)
2012-03-16 22:42:00 +00:00
ups_target_write(&data, ups_source_read(&data));
for (i = 0; i < 4; i++)
2012-03-16 22:42:00 +00:00
source_read_checksum |= ups_patch_read(&data) << (i * 8);
for (i = 0; i < 4; i++)
2012-03-16 22:42:00 +00:00
target_read_checksum |= ups_patch_read(&data) << (i * 8);
patch_result_checksum = ~data.patch_checksum;
data.source_checksum = ~data.source_checksum;
data.target_checksum = ~data.target_checksum;
2012-03-16 22:42:00 +00:00
for (i = 0; i < 4; i++)
2012-03-16 22:42:00 +00:00
patch_read_checksum |= ups_patch_read(&data) << (i * 8);
if (patch_result_checksum != patch_read_checksum)
2012-03-17 00:10:57 +00:00
return PATCH_PATCH_INVALID;
2012-03-16 22:42:00 +00:00
2020-01-20 03:44:45 +00:00
if ( data.source_checksum == source_read_checksum
&& data.source_length == source_read_length)
2012-03-16 22:42:00 +00:00
{
2020-01-20 03:44:45 +00:00
if ( data.target_checksum == target_read_checksum
&& data.target_length == target_read_length)
2012-03-17 00:10:57 +00:00
return PATCH_SUCCESS;
return PATCH_TARGET_INVALID;
}
2014-09-02 03:10:54 +00:00
else if (data.source_checksum == target_read_checksum
2020-01-20 03:44:45 +00:00
&& data.source_length == target_read_length)
2012-03-16 22:42:00 +00:00
{
2020-01-20 03:44:45 +00:00
if ( data.target_checksum == source_read_checksum
&& data.target_length == source_read_length)
2012-03-17 00:10:57 +00:00
return PATCH_SUCCESS;
return PATCH_TARGET_INVALID;
}
return PATCH_SOURCE_INVALID;
2012-03-16 22:42:00 +00:00
}
2019-09-01 19:01:48 +00:00
static enum patch_error ips_alloc_targetdata(
const uint8_t *patchdata, uint64_t patchlen,
uint64_t sourcelength,
uint8_t **targetdata, uint64_t *targetlength)
{
uint8_t *prov_alloc;
uint32_t offset = 5;
2020-01-20 03:44:45 +00:00
*targetlength = sourcelength;
2019-09-01 19:01:48 +00:00
for (;;)
{
uint32_t address;
unsigned length;
if (offset > patchlen - 3)
break;
address = patchdata[offset++] << 16;
address |= patchdata[offset++] << 8;
address |= patchdata[offset++] << 0;
if (address == 0x454f46) /* EOF */
{
if (offset == patchlen)
{
2020-01-20 03:44:45 +00:00
prov_alloc = (uint8_t*)malloc((size_t)*targetlength);
2019-09-01 19:01:48 +00:00
if (!prov_alloc)
return PATCH_TARGET_ALLOC_FAILED;
free(*targetdata);
2020-01-20 03:44:45 +00:00
*targetdata = prov_alloc;
2019-09-01 19:01:48 +00:00
return PATCH_SUCCESS;
}
else if (offset == patchlen - 3)
{
2020-01-20 03:44:45 +00:00
uint32_t size = patchdata[offset++] << 16;
size |= patchdata[offset++] << 8;
size |= patchdata[offset++] << 0;
*targetlength = size;
prov_alloc = (uint8_t*)malloc((size_t)*targetlength);
2019-09-01 19:01:48 +00:00
if (!prov_alloc)
return PATCH_TARGET_ALLOC_FAILED;
free(*targetdata);
2020-01-20 03:44:45 +00:00
*targetdata = prov_alloc;
2019-09-01 19:01:48 +00:00
return PATCH_SUCCESS;
}
}
if (offset > patchlen - 2)
break;
length = patchdata[offset++] << 8;
length |= patchdata[offset++] << 0;
if (length) /* Copy */
{
if (offset > patchlen - length)
break;
while (length--)
{
address++;
offset++;
}
}
else /* RLE */
{
if (offset > patchlen - 3)
break;
length = patchdata[offset++] << 8;
length |= patchdata[offset++] << 0;
if (length == 0) /* Illegal */
break;
while (length--)
address++;
offset++;
}
if (address > *targetlength)
*targetlength = address;
}
return PATCH_PATCH_INVALID;
}
2016-02-25 18:33:46 +00:00
static enum patch_error ips_apply_patch(
const uint8_t *patchdata, uint64_t patchlen,
const uint8_t *sourcedata, uint64_t sourcelength,
2019-09-01 19:01:48 +00:00
uint8_t **targetdata, uint64_t *targetlength)
2012-03-20 22:08:34 +00:00
{
uint32_t offset = 5;
enum patch_error error_patch = PATCH_UNKNOWN;
2020-01-20 03:44:45 +00:00
if ( patchlen < 8 ||
2012-03-20 22:08:34 +00:00
patchdata[0] != 'P' ||
patchdata[1] != 'A' ||
patchdata[2] != 'T' ||
patchdata[3] != 'C' ||
patchdata[4] != 'H')
return PATCH_PATCH_INVALID;
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
2020-01-20 03:44:45 +00:00
if ((error_patch = ips_alloc_targetdata(
patchdata, patchlen, sourcelength,
targetdata, targetlength)) != PATCH_SUCCESS)
2019-09-01 19:01:48 +00:00
return error_patch;
2012-03-20 22:08:34 +00:00
2019-09-01 19:01:48 +00:00
memcpy(*targetdata, sourcedata, (size_t)sourcelength);
2012-03-20 22:08:34 +00:00
for (;;)
{
uint32_t address;
unsigned length;
2012-03-20 22:08:34 +00:00
if (offset > patchlen - 3)
break;
address = patchdata[offset++] << 16;
2012-03-20 22:08:34 +00:00
address |= patchdata[offset++] << 8;
address |= patchdata[offset++] << 0;
2014-09-02 03:10:54 +00:00
if (address == 0x454f46) /* EOF */
2012-03-20 22:08:34 +00:00
{
if (offset == patchlen)
return PATCH_SUCCESS;
2020-01-20 03:44:45 +00:00
if (offset == patchlen - 3)
2012-03-20 22:08:34 +00:00
{
2021-02-09 15:43:40 +00:00
#if 0
2020-01-20 03:44:45 +00:00
uint32_t size = patchdata[offset++] << 16;
size |= patchdata[offset++] << 8;
size |= patchdata[offset++] << 0;
2021-02-09 15:43:40 +00:00
#endif
2012-03-20 22:08:34 +00:00
return PATCH_SUCCESS;
}
}
if (offset > patchlen - 2)
break;
length = patchdata[offset++] << 8;
2012-03-20 22:08:34 +00:00
length |= patchdata[offset++] << 0;
2014-09-02 03:10:54 +00:00
if (length) /* Copy */
2012-03-20 22:08:34 +00:00
{
if (offset > patchlen - length)
break;
while (length--)
2019-09-01 19:01:48 +00:00
(*targetdata)[address++] = patchdata[offset++];
2012-03-20 22:08:34 +00:00
}
2014-09-02 03:10:54 +00:00
else /* RLE */
2012-03-20 22:08:34 +00:00
{
if (offset > patchlen - 3)
break;
length = patchdata[offset++] << 8;
length |= patchdata[offset++] << 0;
2014-09-02 03:10:54 +00:00
if (length == 0) /* Illegal */
2012-03-20 22:08:34 +00:00
break;
while (length--)
2019-09-01 19:01:48 +00:00
(*targetdata)[address++] = patchdata[offset];
2012-03-20 22:08:34 +00:00
offset++;
}
}
return PATCH_PATCH_INVALID;
}
2024-01-25 15:04:11 +00:00
#if defined(HAVE_PATCH) && defined(HAVE_XDELTA)
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
static enum patch_error xdelta_apply_patch(
const uint8_t *patchdata, uint64_t patchlen,
const uint8_t *sourcedata, uint64_t sourcelength,
uint8_t **targetdata, uint64_t *targetlength)
{
int ret;
enum patch_error error_patch = PATCH_SUCCESS;
xd3_stream stream;
xd3_config config;
xd3_source source;
/* Validate the magic number, as given by RFC 3284 section 4.1 */
if (patchlen < 8 ||
patchdata[0] != 0xD6 ||
patchdata[1] != 0xC3 ||
patchdata[2] != 0xC4 ||
patchdata[3] != 0x00)
return PATCH_PATCH_INVALID_HEADER;
xd3_init_config(&config, XD3_SKIP_EMIT);
/* The first pass is just to compute the buffer size,
* no need to emit patched data yet */
if (xd3_config_stream(&stream, &config) != 0)
return PATCH_UNKNOWN;
memset(&source, 0, sizeof(source));
source.blksize = sourcelength;
source.onblk = sourcelength;
source.curblk = sourcedata;
source.curblkno = 0;
xd3_set_source_and_size(&stream, &source, sourcelength);
do
{ /* Make a first pass over the patch, to compute the target size.
* XDelta3 doesn't store the target size in the patch file,
* so we have to either compute it ourselves
* or keep reallocating a buffer as we go.
* I went with the former because it's simpler and fails sooner.
*/
switch (ret = xd3_decode_input(&stream))
{ /* xd3 works like a zlib-styled state machine (stream is the machine) */
case XD3_INPUT: /* When starting the first pass, provide the input */
xd3_avail_input(&stream, patchdata, patchlen);
RARCH_DBG("[xdelta] Provided %lu bytes of input to xd3_stream\n", patchlen);
break;
case XD3_GOTHEADER:
case XD3_WINSTART:
*targetlength += stream.winsize;
RARCH_DBG("[xdelta] Discovered a window of %lu bytes (target filesize is %lu bytes)\n", stream.winsize, *targetlength);
/* xdelta updates the active stream window in the GOTHEADER and WINSTART states */
break;
case XD3_OUTPUT:
xd3_consume_output(&stream); /* Need to call this after every output */
break;
case XD3_INVALID_INPUT:
error_patch = PATCH_PATCH_INVALID;
RARCH_ERR("[xdelta] Invalid input in xd3_stream (%s)\n", xd3_errstring(&stream));
goto cleanup_stream;
case XD3_INTERNAL:
error_patch = PATCH_UNKNOWN;
RARCH_ERR("[xdelta] Internal error in xd3_stream (%s)\n", xd3_errstring(&stream));
goto cleanup_stream;
case XD3_WINFINISH:
RARCH_DBG("[xdelta] Finished processing window #%d\n", stream.current_window);
break;
default:
RARCH_DBG("[xdelta] xd3_decode_input returned %ld (%s; %s)\n", ret, xd3_strerror(ret), stream.msg);
}
} while (stream.avail_in);
2024-07-20 17:42:45 +00:00
*targetdata = (uint8_t*)malloc(*targetlength);
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
switch (ret = xd3_decode_memory(
patchdata, patchlen,
sourcedata, sourcelength,
*targetdata, targetlength, *targetlength, 0))
{
case 0: /* Success */
break;
case ENOSPC:
error_patch = PATCH_TARGET_ALLOC_FAILED;
free(*targetdata);
goto cleanup_stream;
default:
error_patch = PATCH_UNKNOWN;
free(*targetdata);
goto cleanup_stream;
}
cleanup_stream:
xd3_close_stream(&stream);
xd3_free_stream(&stream);
return error_patch;
}
2024-01-25 15:04:11 +00:00
#endif
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
2015-02-19 03:30:53 +00:00
static bool apply_patch_content(uint8_t **buf,
ssize_t *size, const char *patch_desc, const char *patch_path,
patch_func_t func, void *patch_data, int64_t patch_size)
2015-02-19 03:30:53 +00:00
{
settings_t *settings = config_get_ptr();
bool show_notification = settings ?
settings->bools.notification_show_patch_applied : false;
2016-02-25 18:33:46 +00:00
enum patch_error err = PATCH_UNKNOWN;
2015-03-12 03:11:12 +00:00
ssize_t ret_size = *size;
uint8_t *ret_buf = *buf;
2019-09-01 19:01:48 +00:00
uint64_t target_size = 0;
uint8_t *patched_content = NULL;
2015-02-19 03:30:53 +00:00
RARCH_LOG("Found %s file in \"%s\", attempting to patch ...\n",
patch_desc, patch_path);
2020-01-20 03:44:45 +00:00
if ((err = func((const uint8_t*)patch_data, patch_size, ret_buf,
ret_size, &patched_content, &target_size)) == PATCH_SUCCESS)
2015-02-19 03:30:53 +00:00
{
2017-05-13 22:54:58 +00:00
free(ret_buf);
*buf = patched_content;
*size = target_size;
/* Show an OSD message */
if (show_notification)
{
char msg[128];
const char *patch_filename = path_basename_nocompression(patch_path);
snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_APPLYING_PATCH),
patch_filename ? patch_filename :
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_UNKNOWN));
runloop_msg_queue_push(msg, 1, 180, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
2015-02-19 03:30:53 +00:00
}
else
2016-06-30 03:23:22 +00:00
RARCH_ERR("%s %s: %s #%u\n",
2016-06-20 02:01:58 +00:00
msg_hash_to_str(MSG_FAILED_TO_PATCH),
patch_desc,
2016-06-30 03:23:22 +00:00
msg_hash_to_str(MSG_ERROR),
2015-02-19 03:30:53 +00:00
(unsigned)err);
return true;
}
2017-01-23 13:56:09 +00:00
static bool try_bps_patch(bool allow_bps, const char *name_bps,
uint8_t **buf, ssize_t *size)
2015-02-19 03:30:53 +00:00
{
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
if ( allow_bps
2020-01-20 03:44:45 +00:00
&& !string_is_empty(name_bps)
&& path_is_valid(name_bps)
)
{
int64_t patch_size;
bool ret = false;
void *patch_data = NULL;
2017-05-13 22:52:56 +00:00
2020-01-20 03:44:45 +00:00
if (!filestream_read_file(name_bps, &patch_data, &patch_size))
return false;
2017-05-13 22:52:56 +00:00
2020-01-20 03:44:45 +00:00
if (patch_size >= 0)
ret = apply_patch_content(buf, size, "BPS", name_bps,
bps_apply_patch, patch_data, patch_size);
if (patch_data)
free(patch_data);
return ret;
}
2017-05-13 23:04:37 +00:00
2017-01-23 13:56:09 +00:00
return false;
2015-02-19 03:30:53 +00:00
}
2017-01-23 13:56:09 +00:00
static bool try_ups_patch(bool allow_ups, const char *name_ups,
uint8_t **buf, ssize_t *size)
2015-02-19 03:30:53 +00:00
{
2020-01-20 03:44:45 +00:00
if ( allow_ups
&& !string_is_empty(name_ups)
&& path_is_valid(name_ups)
)
{
int64_t patch_size;
bool ret = false;
void *patch_data = NULL;
2017-05-13 22:52:56 +00:00
2020-01-20 03:44:45 +00:00
if (!filestream_read_file(name_ups, &patch_data, &patch_size))
return false;
2017-05-13 22:52:56 +00:00
2020-01-20 03:44:45 +00:00
if (patch_size >= 0)
ret = apply_patch_content(buf, size, "UPS", name_ups,
ups_apply_patch, patch_data, patch_size);
2017-05-13 23:04:37 +00:00
2020-01-20 03:44:45 +00:00
if (patch_data)
free(patch_data);
return ret;
}
2017-01-23 13:56:09 +00:00
return false;
2015-02-19 03:30:53 +00:00
}
2017-01-23 13:56:09 +00:00
static bool try_ips_patch(bool allow_ips,
const char *name_ips, uint8_t **buf, ssize_t *size)
2015-02-19 03:30:53 +00:00
{
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
if ( allow_ips
2020-01-20 03:44:45 +00:00
&& !string_is_empty(name_ips)
&& path_is_valid(name_ips)
)
{
int64_t patch_size;
bool ret = false;
void *patch_data = NULL;
2017-05-13 22:52:56 +00:00
2020-01-20 03:44:45 +00:00
if (!filestream_read_file(name_ips, &patch_data, &patch_size))
return false;
2017-05-13 22:52:56 +00:00
2020-01-20 03:44:45 +00:00
if (patch_size >= 0)
ret = apply_patch_content(buf, size, "IPS", name_ips,
ips_apply_patch, patch_data, patch_size);
2017-05-13 23:04:37 +00:00
2020-01-20 03:44:45 +00:00
if (patch_data)
free(patch_data);
return ret;
}
2017-01-23 13:56:09 +00:00
return false;
2015-02-19 03:30:53 +00:00
}
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
static bool try_xdelta_patch(bool allow_xdelta,
const char *name_xdelta, uint8_t **buf, ssize_t *size)
{
#if defined(HAVE_PATCH) && defined(HAVE_XDELTA)
if ( allow_xdelta
&& !string_is_empty(name_xdelta)
&& path_is_valid(name_xdelta)
)
{
int64_t patch_size;
bool ret = false;
void *patch_data = NULL;
if (!filestream_read_file(name_xdelta, &patch_data, &patch_size))
return false;
if (patch_size >= 0)
ret = apply_patch_content(buf, size, "Xdelta", name_xdelta,
xdelta_apply_patch, patch_data, patch_size);
if (patch_data)
free(patch_data);
return ret;
}
#endif
return false;
}
2015-02-19 03:30:53 +00:00
/**
* patch_content:
* @buf : buffer of the content file.
* @size : size of the content file.
*
* Apply patch to the content file in-memory.
*
**/
bool patch_content(
bool is_ips_pref,
bool is_bps_pref,
bool is_ups_pref,
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
bool is_xdelta_pref,
2017-01-23 13:56:09 +00:00
const char *name_ips,
const char *name_bps,
const char *name_ups,
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
const char *name_xdelta,
2017-01-23 13:56:09 +00:00
uint8_t **buf,
2017-01-31 03:04:45 +00:00
void *data)
2015-02-19 03:30:53 +00:00
{
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
ssize_t *size = (ssize_t*)data;
bool allow_ups = !is_bps_pref && !is_ips_pref && !is_xdelta_pref;
bool allow_ips = !is_ups_pref && !is_bps_pref && !is_xdelta_pref;
bool allow_bps = !is_ups_pref && !is_ips_pref && !is_xdelta_pref;
bool allow_xdelta = !is_bps_pref && !is_ups_pref && !is_ips_pref;
2017-02-21 19:38:02 +00:00
if ( (unsigned)is_ips_pref
+ (unsigned)is_bps_pref
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
+ (unsigned)is_ups_pref
+ (unsigned)is_xdelta_pref > 1)
2015-02-19 03:30:53 +00:00
{
2016-07-01 07:45:04 +00:00
RARCH_WARN("%s\n",
msg_hash_to_str(MSG_SEVERAL_PATCHES_ARE_EXPLICITLY_DEFINED));
return false;
2015-02-19 03:30:53 +00:00
}
/* Attempt to apply first (non-indexed) patch */
if ( try_ips_patch(allow_ips, name_ips, buf, size)
|| try_bps_patch(allow_bps, name_bps, buf, size)
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
|| try_ups_patch(allow_ups, name_ups, buf, size)
|| try_xdelta_patch(allow_xdelta, name_xdelta, buf, size))
2015-02-19 03:30:53 +00:00
{
/* A patch has been found. Now attempt to apply
* any additional 'indexed' patch files */
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
size_t name_ips_len = strlen(name_ips);
size_t name_bps_len = strlen(name_bps);
size_t name_ups_len = strlen(name_ups);
size_t name_xdelta_len = strlen(name_xdelta);
char *name_ips_indexed = (char*)malloc((name_ips_len + 2) * sizeof(char));
char *name_bps_indexed = (char*)malloc((name_bps_len + 2) * sizeof(char));
char *name_ups_indexed = (char*)malloc((name_ups_len + 2) * sizeof(char));
char *name_xdelta_indexed = (char*)malloc((name_xdelta_len + 2) * sizeof(char));
/* First patch already applied -> index
* for subsequent patches starts at 1 */
size_t patch_index = 1;
strlcpy(name_ips_indexed, name_ips, (name_ips_len + 1) * sizeof(char));
strlcpy(name_bps_indexed, name_bps, (name_bps_len + 1) * sizeof(char));
strlcpy(name_ups_indexed, name_ups, (name_ups_len + 1) * sizeof(char));
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
strlcpy(name_xdelta_indexed, name_xdelta, (name_xdelta_len + 1) * sizeof(char));
/* Ensure that we NUL terminate *after* the
* index character */
name_ips_indexed[name_ips_len + 1] = '\0';
name_bps_indexed[name_bps_len + 1] = '\0';
name_ups_indexed[name_ups_len + 1] = '\0';
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
name_xdelta_indexed[name_xdelta_len + 1] = '\0';
/* try to patch "*.ipsX" */
while (patch_index < 10)
{
/* Add index character to end of patch
* file path string
* > Note: This technique only works for
* index values up to 9 (i.e. single
* digit numbers)
* > If we want to support more than 10
* patches in total, will have to replace
* this with an snprintf() implementation
* (which will have significantly higher
* performance overheads) */
char index_char = '0' + patch_index;
name_ips_indexed[name_ips_len] = index_char;
name_bps_indexed[name_bps_len] = index_char;
name_ups_indexed[name_ups_len] = index_char;
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
name_xdelta_indexed[name_xdelta_len] = index_char;
if ( !try_ips_patch(allow_ips, name_ips_indexed, buf, size)
&& !try_bps_patch(allow_bps, name_bps_indexed, buf, size)
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
&& !try_ups_patch(allow_ups, name_ups_indexed, buf, size)
&& !try_xdelta_patch(allow_xdelta, name_xdelta_indexed, buf, size))
break;
patch_index++;
}
free(name_ips_indexed);
free(name_bps_indexed);
free(name_ups_indexed);
XDelta patch support (Take 2) (#15915) * Add xdelta in deps * Include <assert.h> in xdelta3.h - Otherwise the static_assert calls can fail * Build xdelta3 in Makefile.common * Add xdelta support to the softpatching infrastructure - The patching itself isn't fully implemented yet * Adjust how xdelta3.h checks the sizes of some types - Now checks max values instead of relying on autotools * Add some enums that were excluded by the cherry-pick * Remove stray whitespace * Adjust SIZE macros in xdelta3.h - Move them outside the XD3_USE_LARGEFILE64 block - Add more SIZE declarations - Make SIZEOF_UNSIGNED_LONG_LONG contingent on the presence of ULLONG_MAX * Reintegrate xdelta support * Enable support for xdelta's secondary compressors - Necessary for some patches * Fix some format specifiers * Remove unnecessary files from xdelta * Include xdelta3.h with a relative path * Add xdelta3 headers to HEADERS variable * Gate Xdelta support behind HAVE_XDELTA - HAVE_XDELTA is on by default - HAVE_PATCH is still required for HAVE_XDELTA to be meaningful - Support is mostly contingent on the availability of LZMA - Anything modern should be okay - Legacy platforms (e.g. DOS) may need to have Xdelta support disabled - At least until some other solution can be found * Disable HAVE_XDELTA on platforms where the build recently failed - These come from looking at the failed builds on GitHub - These are guesses, and may turn out to be wrong * Fix a potential memory leak - Whoops, looks like I need to call two cleanup functions - xd3_close_stream exists separately from xd3_free_stream * Split the --help printout for --xdelta into its own strlcat call - GCC was complaining about #ifdefs within macro arguments being non-portable * Fix some incorrect printf format specifiers * Modify Xdelta to adhere to C89 - It's mostly using RetroArch's INLINE macro instead of the inline keyword * Slight cleanups * Remove a stray comma that was hindering C89 builds * Add XDelta support to CHANGES.md * Change how the xdelta patch's name is computed - To be in line with other recent refactoring * Fix an incorrect merge - Whoops, this part was from before I figured out how to get the size of a patched file * Explain the song-and-dance behind computing a patched file's size * Define some XDelta3-related constants to 0 on 32-bit platforms * Adjust some Xdelta-related macro definitions - Exclude the encoder, since we're not making patches - Move some #defines to after inclusion of <stdint.h>, to fix undefined behavior - Remove _WIN32_WINNT overrides, since they were for code that we're not using * Fix Xdelta support * Wrap an encoder-only function in `#if XD3_ENCODER`
2023-11-24 04:19:07 +00:00
free(name_xdelta_indexed);
return true;
}
return false;
2015-02-19 03:30:53 +00:00
}