From e2026b105677254f26489dfd0b596c70e6b56ef0 Mon Sep 17 00:00:00 2001 From: Alcaro Date: Wed, 21 Dec 2016 14:26:36 +0100 Subject: [PATCH] Update UPS handler, wipe some outdated cruft --- flips.cpp | 1 - flips.h | 2 + patch/bps.cpp | 4 ++ patch/libips.h | 36 ----------------- patch/libups.h | 30 -------------- patch/{libups.cppx => ups.cpp} | 74 ++++++++++++++++------------------ 6 files changed, 41 insertions(+), 106 deletions(-) delete mode 100644 patch/libips.h delete mode 100644 patch/libups.h rename patch/{libups.cppx => ups.cpp} (61%) diff --git a/flips.cpp b/flips.cpp index 28281dd..d2d3513 100644 --- a/flips.cpp +++ b/flips.cpp @@ -1,4 +1,3 @@ -#include "arlib.h" #include "flips.h" /* diff --git a/flips.h b/flips.h index 24dd5eb..144e259 100644 --- a/flips.h +++ b/flips.h @@ -1 +1,3 @@ +#include "patch/patch.h" + #define FLIPSVER "2.00" diff --git a/patch/bps.cpp b/patch/bps.cpp index c68409b..54f733c 100644 --- a/patch/bps.cpp +++ b/patch/bps.cpp @@ -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) diff --git a/patch/libips.h b/patch/libips.h deleted file mode 100644 index 5f4132f..0000000 --- a/patch/libips.h +++ /dev/null @@ -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); diff --git a/patch/libups.h b/patch/libups.h deleted file mode 100644 index 64e9614..0000000 --- a/patch/libups.h +++ /dev/null @@ -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); diff --git a/patch/libups.cppx b/patch/ups.cpp similarity index 61% rename from patch/libups.cppx rename to patch/ups.cpp index a1f00f9..01a419c 100644 --- a/patch/libups.cppx +++ b/patch/ups.cpp @@ -1,10 +1,7 @@ -#include "libups.h" - -#include //uint8_t, uint32_t -#include //malloc, realloc, free -#include //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 (outatptr, 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 +}}