Refactor patch handling.
This commit is contained in:
parent
cd0973d213
commit
56e5c9fcec
77
file.c
77
file.c
|
@ -136,21 +136,17 @@ error:
|
|||
return false;
|
||||
}
|
||||
|
||||
enum patch_type
|
||||
{
|
||||
PATCH_NONE,
|
||||
PATCH_UPS,
|
||||
PATCH_BPS
|
||||
};
|
||||
|
||||
static void patch_rom(uint8_t **buf, ssize_t *size)
|
||||
{
|
||||
uint8_t *ret_buf = *buf;
|
||||
ssize_t ret_size = *size;
|
||||
|
||||
const char *patch_desc = NULL;
|
||||
const char *patch_path = NULL;
|
||||
patch_func_t func = NULL;
|
||||
|
||||
ssize_t patch_size = 0;
|
||||
void *patch_data = NULL;
|
||||
enum patch_type type = PATCH_NONE;
|
||||
bool success = false;
|
||||
|
||||
if (g_extern.ups_pref && g_extern.bps_pref)
|
||||
|
@ -160,28 +156,24 @@ static void patch_rom(uint8_t **buf, ssize_t *size)
|
|||
}
|
||||
|
||||
if (!g_extern.bps_pref && *g_extern.ups_name && (patch_size = read_file(g_extern.ups_name, &patch_data)) >= 0)
|
||||
type = PATCH_UPS;
|
||||
{
|
||||
patch_desc = "UPS";
|
||||
patch_path = g_extern.ups_name;
|
||||
func = ups_apply_patch;
|
||||
}
|
||||
else if (!g_extern.ups_pref && *g_extern.bps_name && (patch_size = read_file(g_extern.bps_name, &patch_data)) >= 0)
|
||||
type = PATCH_BPS;
|
||||
|
||||
if (type == PATCH_NONE)
|
||||
{
|
||||
patch_desc = "BPS";
|
||||
patch_path = g_extern.bps_name;
|
||||
func = bps_apply_patch;
|
||||
}
|
||||
else
|
||||
{
|
||||
SSNES_LOG("Did not find a valid ROM patch.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case PATCH_UPS:
|
||||
SSNES_LOG("Found UPS file in \"%s\", attempting to patch ...\n", g_extern.ups_name);
|
||||
break;
|
||||
case PATCH_BPS:
|
||||
SSNES_LOG("Found BPS file in \"%s\", attempting to patch ...\n", g_extern.bps_name);
|
||||
break;
|
||||
|
||||
default:
|
||||
return; // Should not happen, but.
|
||||
}
|
||||
SSNES_LOG("Found %s file in \"%s\", attempting to patch ...\n", patch_desc, patch_path);
|
||||
|
||||
size_t target_size = ret_size * 4; // Just to be sure ...
|
||||
uint8_t *patched_rom = (uint8_t*)malloc(target_size);
|
||||
|
@ -191,39 +183,14 @@ static void patch_rom(uint8_t **buf, ssize_t *size)
|
|||
goto error;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
patch_error_t err = func((const uint8_t*)patch_data, patch_size, ret_buf, ret_size, patched_rom, &target_size);
|
||||
if (err == PATCH_SUCCESS)
|
||||
{
|
||||
case PATCH_UPS:
|
||||
{
|
||||
ups_error_t err = ups_apply_patch((const uint8_t*)patch_data, patch_size, ret_buf, ret_size, patched_rom, &target_size);
|
||||
if (err == UPS_SUCCESS)
|
||||
{
|
||||
SSNES_LOG("ROM patched successfully (UPS).\n");
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
SSNES_ERR("Failed to patch UPS: Error #%u\n", (unsigned)err);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PATCH_BPS:
|
||||
{
|
||||
bps_error_t err = bps_apply_patch((const uint8_t*)patch_data, patch_size, ret_buf, ret_size, patched_rom, &target_size);
|
||||
if (err == BPS_SUCCESS)
|
||||
{
|
||||
SSNES_LOG("ROM patched successfully (BPS).\n");
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
SSNES_ERR("Failed to patch BPS: Error #%u\n", (unsigned)err);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
SSNES_LOG("ROM patched successfully (%s).\n", patch_desc);
|
||||
success = true;
|
||||
}
|
||||
else
|
||||
SSNES_ERR("Failed to patch %s: Error #%u\n", patch_desc, (unsigned)err);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
|
46
patch.c
46
patch.c
|
@ -70,13 +70,13 @@ static void bps_write(struct bps_data *bps, uint8_t data)
|
|||
bps->target_checksum = crc32_adjust(bps->target_checksum, data);
|
||||
}
|
||||
|
||||
bps_error_t bps_apply_patch(
|
||||
patch_error_t bps_apply_patch(
|
||||
const uint8_t *modify_data, size_t modify_length,
|
||||
const uint8_t *source_data, size_t source_length,
|
||||
uint8_t *target_data, size_t *target_length)
|
||||
{
|
||||
if (modify_length < 19)
|
||||
return BPS_PATCH_TOO_SMALL;
|
||||
return PATCH_PATCH_TOO_SMALL;
|
||||
|
||||
struct bps_data bps = {0};
|
||||
bps.modify_data = modify_data;
|
||||
|
@ -89,7 +89,7 @@ bps_error_t bps_apply_patch(
|
|||
bps.target_checksum = ~0;
|
||||
|
||||
if ((bps_read(&bps) != 'B') || (bps_read(&bps) != 'P') || (bps_read(&bps) != 'S') || (bps_read(&bps) != '1'))
|
||||
return BPS_PATCH_INVALID_HEADER;
|
||||
return PATCH_PATCH_INVALID_HEADER;
|
||||
|
||||
size_t modify_source_size = bps_decode(&bps);
|
||||
size_t modify_target_size = bps_decode(&bps);
|
||||
|
@ -98,9 +98,9 @@ bps_error_t bps_apply_patch(
|
|||
bps_read(&bps);
|
||||
|
||||
if (modify_source_size > bps.source_length)
|
||||
return BPS_SOURCE_TOO_SMALL;
|
||||
return PATCH_SOURCE_TOO_SMALL;
|
||||
if (modify_target_size > bps.target_length)
|
||||
return BPS_TARGET_TOO_SMALL;
|
||||
return PATCH_TARGET_TOO_SMALL;
|
||||
|
||||
while (bps.modify_offset < bps.modify_length - 12)
|
||||
{
|
||||
|
@ -161,15 +161,15 @@ bps_error_t bps_apply_patch(
|
|||
bps.target_checksum = ~bps.target_checksum;
|
||||
|
||||
if (bps.source_checksum != modify_source_checksum)
|
||||
return BPS_SOURCE_CHECKSUM_INVALID;
|
||||
return PATCH_SOURCE_CHECKSUM_INVALID;
|
||||
if (bps.target_checksum != modify_target_checksum)
|
||||
return BPS_TARGET_CHECKSUM_INVALID;
|
||||
return PATCH_TARGET_CHECKSUM_INVALID;
|
||||
if (checksum != modify_modify_checksum)
|
||||
return BPS_PATCH_CHECKSUM_INVALID;
|
||||
return PATCH_PATCH_CHECKSUM_INVALID;
|
||||
|
||||
*target_length = modify_target_size;
|
||||
|
||||
return BPS_SUCCESS;
|
||||
return PATCH_SUCCESS;
|
||||
}
|
||||
|
||||
struct ups_data
|
||||
|
@ -229,7 +229,7 @@ static uint64_t ups_decode(struct ups_data *data)
|
|||
return offset;
|
||||
}
|
||||
|
||||
ups_error_t ups_apply_patch(
|
||||
patch_error_t ups_apply_patch(
|
||||
const uint8_t *patchdata, size_t patchlength,
|
||||
const uint8_t *sourcedata, size_t sourcelength,
|
||||
uint8_t *targetdata, size_t *targetlength)
|
||||
|
@ -246,24 +246,24 @@ ups_error_t ups_apply_patch(
|
|||
data.target_checksum = ~0;
|
||||
|
||||
if (data.patch_length < 18)
|
||||
return UPS_PATCH_INVALID;
|
||||
return PATCH_PATCH_INVALID;
|
||||
if (ups_patch_read(&data) != 'U')
|
||||
return UPS_PATCH_INVALID;
|
||||
return PATCH_PATCH_INVALID;
|
||||
if (ups_patch_read(&data) != 'P')
|
||||
return UPS_PATCH_INVALID;
|
||||
return PATCH_PATCH_INVALID;
|
||||
if (ups_patch_read(&data) != 'S')
|
||||
return UPS_PATCH_INVALID;
|
||||
return PATCH_PATCH_INVALID;
|
||||
if (ups_patch_read(&data) != '1')
|
||||
return UPS_PATCH_INVALID;
|
||||
return PATCH_PATCH_INVALID;
|
||||
|
||||
unsigned source_read_length = ups_decode(&data);
|
||||
unsigned target_read_length = ups_decode(&data);
|
||||
|
||||
if (data.source_length != source_read_length && data.source_length != target_read_length)
|
||||
return UPS_SOURCE_INVALID;
|
||||
return PATCH_SOURCE_INVALID;
|
||||
*targetlength = (data.source_length == source_read_length ? target_read_length : source_read_length);
|
||||
if (data.target_length < *targetlength)
|
||||
return UPS_TARGET_TOO_SMALL;
|
||||
return PATCH_TARGET_TOO_SMALL;
|
||||
data.target_length = *targetlength;
|
||||
|
||||
while (data.patch_offset < data.patch_length - 12)
|
||||
|
@ -298,21 +298,21 @@ ups_error_t ups_apply_patch(
|
|||
patch_read_checksum |= ups_patch_read(&data) << (i * 8);
|
||||
|
||||
if (patch_result_checksum != patch_read_checksum)
|
||||
return UPS_PATCH_INVALID;
|
||||
return PATCH_PATCH_INVALID;
|
||||
|
||||
if (data.source_checksum == source_read_checksum && data.source_length == source_read_length)
|
||||
{
|
||||
if (data.target_checksum == target_read_checksum && data.target_length == target_read_length)
|
||||
return UPS_SUCCESS;
|
||||
return UPS_TARGET_INVALID;
|
||||
return PATCH_SUCCESS;
|
||||
return PATCH_TARGET_INVALID;
|
||||
}
|
||||
else if (data.source_checksum == target_read_checksum && data.source_length == target_read_length)
|
||||
{
|
||||
if (data.target_checksum == source_read_checksum && data.target_length == source_read_length)
|
||||
return UPS_SUCCESS;
|
||||
return UPS_TARGET_INVALID;
|
||||
return PATCH_SUCCESS;
|
||||
return PATCH_TARGET_INVALID;
|
||||
}
|
||||
else
|
||||
return UPS_SOURCE_INVALID;
|
||||
return PATCH_SOURCE_INVALID;
|
||||
}
|
||||
|
||||
|
|
45
patch.h
45
patch.h
|
@ -23,39 +23,30 @@
|
|||
|
||||
// BPS/UPS implementation from bSNES (nall::).
|
||||
|
||||
typedef enum bps_error
|
||||
typedef enum
|
||||
{
|
||||
BPS_UNKNOWN,
|
||||
BPS_SUCCESS,
|
||||
BPS_PATCH_TOO_SMALL,
|
||||
BPS_PATCH_INVALID_HEADER,
|
||||
BPS_SOURCE_TOO_SMALL,
|
||||
BPS_TARGET_TOO_SMALL,
|
||||
BPS_SOURCE_CHECKSUM_INVALID,
|
||||
BPS_TARGET_CHECKSUM_INVALID,
|
||||
BPS_PATCH_CHECKSUM_INVALID
|
||||
} bps_error_t;
|
||||
PATCH_UNKNOWN,
|
||||
PATCH_SUCCESS,
|
||||
PATCH_PATCH_TOO_SMALL,
|
||||
PATCH_PATCH_INVALID_HEADER,
|
||||
PATCH_PATCH_INVALID,
|
||||
PATCH_SOURCE_TOO_SMALL,
|
||||
PATCH_TARGET_TOO_SMALL,
|
||||
PATCH_SOURCE_INVALID,
|
||||
PATCH_TARGET_INVALID,
|
||||
PATCH_SOURCE_CHECKSUM_INVALID,
|
||||
PATCH_TARGET_CHECKSUM_INVALID,
|
||||
PATCH_PATCH_CHECKSUM_INVALID
|
||||
} patch_error_t;
|
||||
|
||||
bps_error_t bps_apply_patch(
|
||||
typedef patch_error_t (*patch_func_t)(const uint8_t*, size_t, const uint8_t*, size_t, uint8_t*, size_t*);
|
||||
|
||||
patch_error_t bps_apply_patch(
|
||||
const uint8_t *patch_data, size_t patch_length,
|
||||
const uint8_t *source_data, size_t source_length,
|
||||
uint8_t *target_data, size_t *target_length);
|
||||
|
||||
|
||||
typedef enum ups_error
|
||||
{
|
||||
UPS_UNKNOWN,
|
||||
UPS_SUCCESS,
|
||||
UPS_PATCH_INVALID,
|
||||
UPS_SOURCE_INVALID,
|
||||
UPS_TARGET_INVALID,
|
||||
UPS_TARGET_TOO_SMALL,
|
||||
UPS_PATCH_CHECKSUM_INVALID,
|
||||
UPS_SOURCE_CHECKSUM_INVALID,
|
||||
UPS_TARGET_CHECKSUM_INVALID
|
||||
} ups_error_t;
|
||||
|
||||
ups_error_t ups_apply_patch(
|
||||
patch_error_t ups_apply_patch(
|
||||
const uint8_t *patch_data, size_t patch_length,
|
||||
const uint8_t *source_data, size_t source_length,
|
||||
uint8_t *target_data, size_t *target_length);
|
||||
|
|
Loading…
Reference in New Issue