mirror of
https://github.com/Alcaro/Flips.git
synced 2026-04-08 18:36:26 -05:00
Update UPS handler, wipe some outdated cruft
This commit is contained in:
parent
0e31df85fd
commit
e2026b1056
|
|
@ -197,6 +197,8 @@ result apply(const file& patch_, const file& source_, file& target_, bool accept
|
|||
|
||||
target_.write(out->v());
|
||||
free(out->ptr);
|
||||
patch_.unmap(patch.v());
|
||||
source_.unmap(in.v());
|
||||
return error;
|
||||
#undef read8
|
||||
#undef decodeto
|
||||
|
|
@ -205,6 +207,8 @@ result apply(const file& patch_, const file& source_, file& target_, bool accept
|
|||
|
||||
exit:
|
||||
free(out->ptr);
|
||||
patch_.unmap(patch.v());
|
||||
source_.unmap(in.v());
|
||||
out->len=0;
|
||||
out->ptr=NULL;
|
||||
if (metadata)
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
#include "global.h"
|
||||
|
||||
enum ipserror {
|
||||
ips_ok,//Patch applied or created successfully.
|
||||
|
||||
ips_notthis,//The patch is most likely not intended for this ROM.
|
||||
ips_thisout,//You most likely applied the patch on the output ROM.
|
||||
ips_scrambled,//The patch is technically valid, but seems scrambled or malformed.
|
||||
ips_invalid,//The patch is invalid.
|
||||
|
||||
ips_16MB,//One or both files is bigger than 16MB. The IPS format doesn't support that. The created
|
||||
//patch contains only the differences to that point.
|
||||
ips_identical,//The input buffers are identical.
|
||||
|
||||
ips_shut_up_gcc//This one isn't used, it's just to kill a stray comma warning.
|
||||
};
|
||||
|
||||
//Applies the IPS patch in [patch, patchlen] to [in, inlen] and stores it to [out, outlen]. Send the
|
||||
// return value in out to ips_free when you're done with it.
|
||||
enum ipserror ips_apply(struct mem patch, struct mem in, struct mem * out);
|
||||
|
||||
//Creates an IPS patch that converts source to target and stores it to patch.
|
||||
enum ipserror ips_create(struct mem source, struct mem target, struct mem * patch);
|
||||
|
||||
//Frees the memory returned in the output parameters of the above. Do not call it twice on the same
|
||||
// input, nor on anything you got from anywhere else. ips_free is guaranteed to be equivalent to
|
||||
// calling stdlib.h's free() on mem.ptr.
|
||||
void ips_free(struct mem mem);
|
||||
|
||||
//ips_study allows you to detect most patching errors without applying it to a ROM, or even a ROM to
|
||||
// apply it to. ips_apply calls ips_study and ips_apply_study, so if you call ips_study yourself,
|
||||
// it's recommended to call ips_apply_study to not redo the calculation. ips_free is still
|
||||
// required.
|
||||
struct ipsstudy;
|
||||
enum ipserror ips_study(struct mem patch, struct ipsstudy * study);
|
||||
enum ipserror ips_apply_study(struct mem patch, struct ipsstudy * study, struct mem in, struct mem * out);
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#include "global.h"
|
||||
|
||||
//Several of those are unused, but remain there so the remaining ones match bpserror.
|
||||
enum upserror {
|
||||
ups_ok,//Patch applied or created successfully.
|
||||
|
||||
ups_unused1, //bps_to_output
|
||||
ups_not_this,//This is not the intended input file for this patch.
|
||||
ups_broken, //This is not a UPS patch, or it's malformed somehow.
|
||||
ups_unused2, //bps_io
|
||||
|
||||
ups_identical,//The input files are identical.
|
||||
ups_too_big, //Somehow, you're asking for something a size_t can't represent.
|
||||
ups_unused3, //bps_out_of_mem
|
||||
ups_unused4, //bps_canceled
|
||||
|
||||
ups_shut_up_gcc//This one isn't used, it's just to kill a stray comma warning.
|
||||
};
|
||||
|
||||
//Applies the UPS patch in [patch, patchlen] to [in, inlen] and stores it to [out, outlen]. Send the
|
||||
// return value in out to ups_free when you're done with it.
|
||||
enum upserror ups_apply(struct mem patch, struct mem in, struct mem * out);
|
||||
|
||||
//Creates an UPS patch that converts source to target and stores it to patch. (Not implemented.)
|
||||
enum upserror ups_create(struct mem source, struct mem target, struct mem * patch);
|
||||
|
||||
//Frees the memory returned in the output parameters of the above. Do not call it twice on the same
|
||||
// input, nor on anything you got from anywhere else. ups_free is guaranteed to be equivalent to
|
||||
// calling stdlib.h's free() on mem.ptr.
|
||||
void ups_free(struct mem mem);
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
#include "libups.h"
|
||||
|
||||
#include <stdint.h>//uint8_t, uint32_t
|
||||
#include <stdlib.h>//malloc, realloc, free
|
||||
#include <string.h>//memcpy, memset
|
||||
#include "arlib/crc32.h"
|
||||
#include "patch.h"
|
||||
|
||||
namespace patch { namespace ups {
|
||||
//TODO: HEAVY cleanups needed here
|
||||
static uint32_t read32(uint8_t * ptr)
|
||||
{
|
||||
uint32_t out;
|
||||
|
|
@ -16,14 +13,19 @@ static uint32_t read32(uint8_t * ptr)
|
|||
}
|
||||
|
||||
#define error(which) do { error=which; goto exit; } while(0)
|
||||
#define assert_sum(a,b) do { if (SIZE_MAX-(a)<(b)) error(ups_too_big); } while(0)
|
||||
#define assert_shift(a,b) do { if (SIZE_MAX>>(b)<(a)) error(ups_too_big); } while(0)
|
||||
enum upserror ups_apply(struct mem patch, struct mem in, struct mem * out)
|
||||
#define assert_sum(a,b) do { if (SIZE_MAX-(a)<(b)) error(e_too_big); } while(0)
|
||||
#define assert_shift(a,b) do { if (SIZE_MAX>>(b)<(a)) error(e_too_big); } while(0)
|
||||
result apply(const file& patch_, const file& source_, file& target_)
|
||||
{
|
||||
enum upserror error;
|
||||
if (patch_.size()<4+2+12) return e_broken;
|
||||
|
||||
struct mem patch = patch_.read();
|
||||
struct mem in = source_.read();
|
||||
struct mem out_;
|
||||
struct mem * out = &out_;
|
||||
result error;
|
||||
out->len=0;
|
||||
out->ptr=NULL;
|
||||
if (patch.len<4+2+12) return ups_broken;
|
||||
|
||||
if (true)
|
||||
{
|
||||
|
|
@ -54,10 +56,10 @@ enum upserror ups_apply(struct mem patch, struct mem in, struct mem * out)
|
|||
uint8_t * patchat=patch.ptr;
|
||||
uint8_t * patchend=patch.ptr+patch.len-12;
|
||||
|
||||
if (readpatch8()!='U') error(ups_broken);
|
||||
if (readpatch8()!='P') error(ups_broken);
|
||||
if (readpatch8()!='S') error(ups_broken);
|
||||
if (readpatch8()!='1') error(ups_broken);
|
||||
if (readpatch8()!='U') error(e_broken);
|
||||
if (readpatch8()!='P') error(e_broken);
|
||||
if (readpatch8()!='S') error(e_broken);
|
||||
if (readpatch8()!='1') error(e_broken);
|
||||
|
||||
size_t inlen;
|
||||
size_t outlen;
|
||||
|
|
@ -70,7 +72,7 @@ enum upserror ups_apply(struct mem patch, struct mem in, struct mem * out)
|
|||
outlen=tmp;
|
||||
backwards=true;
|
||||
}
|
||||
if (inlen!=in.len) error(ups_not_this);
|
||||
if (inlen!=in.len) error(e_not_this);
|
||||
|
||||
out->len=outlen;
|
||||
out->ptr=(uint8_t*)malloc(outlen);
|
||||
|
|
@ -107,7 +109,7 @@ enum upserror ups_apply(struct mem patch, struct mem in, struct mem * out)
|
|||
}
|
||||
while (tmp);
|
||||
}
|
||||
if (patchat!=patchend) error(ups_broken);
|
||||
if (patchat!=patchend) error(e_broken);
|
||||
while (outat<outend) writeout8(0);
|
||||
while (inat<inend) (void)readin8();
|
||||
|
||||
|
|
@ -115,53 +117,47 @@ enum upserror ups_apply(struct mem patch, struct mem in, struct mem * out)
|
|||
uint32_t crc_out_expected=read32(patchat+4);
|
||||
uint32_t crc_patch_expected=read32(patchat+8);
|
||||
|
||||
uint32_t crc_in=crc32(in.ptr, in.len);
|
||||
uint32_t crc_out=crc32(out->ptr, out->len);
|
||||
uint32_t crc_patch=crc32(patch.ptr, patch.len-4);
|
||||
uint32_t crc_in=crc32(in.v());
|
||||
uint32_t crc_out=crc32(out->v());
|
||||
uint32_t crc_patch=crc32(patch.v().slice(0, patch.len-4));
|
||||
|
||||
if (inlen==outlen)
|
||||
{
|
||||
if ((crc_in!=crc_in_expected || crc_out!=crc_out_expected) && (crc_in!=crc_out_expected || crc_out!=crc_in_expected)) error(ups_not_this);
|
||||
if ((crc_in!=crc_in_expected || crc_out!=crc_out_expected) && (crc_in!=crc_out_expected || crc_out!=crc_in_expected)) error(e_not_this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!backwards)
|
||||
{
|
||||
if (crc_in!=crc_in_expected) error(ups_not_this);
|
||||
if (crc_out!=crc_out_expected) error(ups_not_this);
|
||||
if (crc_in!=crc_in_expected) error(e_not_this);
|
||||
if (crc_out!=crc_out_expected) error(e_not_this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (crc_in!=crc_out_expected) error(ups_not_this);
|
||||
if (crc_out!=crc_in_expected) error(ups_not_this);
|
||||
if (crc_in!=crc_out_expected) error(e_not_this);
|
||||
if (crc_out!=crc_in_expected) error(e_not_this);
|
||||
}
|
||||
}
|
||||
if (crc_patch!=crc_patch_expected) error(ups_broken);
|
||||
return ups_ok;
|
||||
if (crc_patch!=crc_patch_expected) error(e_broken);
|
||||
|
||||
target_.write(out->v());
|
||||
free(out->ptr);
|
||||
free(patch.ptr);
|
||||
return e_ok;
|
||||
#undef read8
|
||||
#undef decodeto
|
||||
#undef write8
|
||||
}
|
||||
|
||||
exit:
|
||||
free(patch.ptr);
|
||||
free(out->ptr);
|
||||
out->len=0;
|
||||
out->ptr=NULL;
|
||||
return error;
|
||||
}
|
||||
|
||||
enum upserror ups_create(struct mem sourcemem, struct mem targetmem, struct mem * patchmem)
|
||||
{
|
||||
patchmem->ptr=NULL;
|
||||
patchmem->len=0;
|
||||
return ups_broken;//unimplemented, just pick a random error
|
||||
}
|
||||
|
||||
void ups_free(struct mem mem)
|
||||
{
|
||||
free(mem.ptr);
|
||||
}
|
||||
|
||||
#if 0
|
||||
//Sorry, no undocumented features here. The only thing that can change an UPS patch is swapping the two sizes and checksums, and I don't create anyways.
|
||||
#endif
|
||||
}}
|
||||
Loading…
Reference in New Issue
Block a user