Refactor patch handling.

This commit is contained in:
Themaister 2012-03-17 01:10:57 +01:00
parent cd0973d213
commit 56e5c9fcec
3 changed files with 63 additions and 105 deletions

77
file.c
View File

@ -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
View File

@ -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
View File

@ -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);