summaryrefslogtreecommitdiff
path: root/tools/asmdiff/ntruncompbw.c
diff options
context:
space:
mode:
authorThomas <doodrabbit@hotmail.com>2021-12-17 20:57:03 -0500
committerGitHub <noreply@github.com>2021-12-17 20:57:03 -0500
commitaf67eaffa7ab1a347a6f0e59ed7f1e107749d15a (patch)
treeb9f90f7b047b3dc5a411dbf65117bf07b237a37d /tools/asmdiff/ntruncompbw.c
parent3ab18655ca1311019212b3a2a9dbe32e5fbee55d (diff)
parent44cd7753b5dde323d1e8274b2dc8a5599729e83f (diff)
Merge pull request #463 from PikalaxALT/pikalax_workHEADmaster
Real-match math_util.c
Diffstat (limited to 'tools/asmdiff/ntruncompbw.c')
-rw-r--r--tools/asmdiff/ntruncompbw.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/tools/asmdiff/ntruncompbw.c b/tools/asmdiff/ntruncompbw.c
new file mode 100644
index 00000000..e97db925
--- /dev/null
+++ b/tools/asmdiff/ntruncompbw.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+static inline uint32_t READ32(const unsigned char * ptr)
+{
+ return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+}
+
+static uint32_t MIi_UncompressBackwards(unsigned char ** out_p, size_t compsize)
+{
+ unsigned char * out = *out_p;
+
+ // Read the pointer to the end of the compressed image
+ uint8_t * endptr = out + compsize - 8;
+ uint32_t size = READ32(endptr);
+ uint32_t offset = READ32(endptr + 4);
+ out = realloc(out, compsize + offset);
+ if (out == NULL)
+ return -1u;
+ endptr = out + compsize;
+ uint8_t * dest_p = endptr + offset;
+ uint8_t * end = endptr - ((uint8_t)(size >> 24));
+ uint8_t * start = endptr - (size & ~0xFF000000);
+ while (end > start) {
+ uint8_t r5 = *--end;
+ for (int i = 0; i < 8; i++) {
+ if ((r5 & 0x80) == 0)
+ *--dest_p = *--end;
+ else {
+ int ip = *--end;
+ int r7 = *--end;
+
+
+ r7 = ((r7 | (ip << 8)) & ~0xF000) + 2;
+ ip += 0x20;
+ while (ip >= 0) {
+ dest_p[-1] = dest_p[r7];
+ dest_p--;
+ ip -= 0x10;
+ }
+ }
+ if (end <= start)
+ break;
+ r5 <<= 1;
+ }
+ }
+ *out_p = out;
+ return compsize + offset;
+}
+
+int main(int argc, char ** argv)
+{
+ if (argc < 4) {
+ fprintf(stderr, "usage: %s FILE VMA END\n\ninsufficient arguments\n", argv[0]);
+ return 1;
+ }
+ char * infname = argv[1];
+ uint32_t vma = strtoul(argv[2], NULL, 0);
+ uint32_t end = strtoul(argv[3], NULL, 0);
+ if (end == 0) {
+ fprintf(stderr, "compressed size is 0, no action taken\n");
+ return 0;
+ }
+ FILE * infile = fopen(infname, "r+b");
+ if (infile == NULL) {
+ fclose(infile);
+ fprintf(stderr, "unable to open file %s for reading\n", infname);
+ return 1;
+ }
+ fseek(infile, 0, SEEK_END);
+ long infsize = ftell(infile);
+ fseek(infile, 0, SEEK_SET);
+ if (infsize != end - vma) {
+ fclose(infile);
+ fprintf(stderr, "compressed size does not match file size, I am cowardly doing nothing\n");
+ return 0;
+ }
+ unsigned char * inbuf = malloc(infsize);
+ if (inbuf == NULL) {
+ fclose(infile);
+ fprintf(stderr, "error: malloc(%d)\n", (int)infsize);
+ return 1;
+ }
+ if (fread(inbuf, 1, infsize, infile) != infsize) {
+ fclose(infile);
+ free(inbuf);
+ fprintf(stderr, "error reading from %s\n", infname);
+ return 1;
+ }
+ uint32_t outsize = MIi_UncompressBackwards(&inbuf, end - vma);
+ if (outsize == -1u) {
+ fclose(infile);
+ fprintf(stderr, "fatal error reallocating for decompression\n");
+ return 1;
+ }
+ fseek(infile, 0, SEEK_SET);
+ if (fwrite(inbuf, 1, outsize, infile) != outsize) {
+ fclose(infile);
+ free(inbuf);
+ fprintf(stderr, "error writing back to %s\n", infname);
+ return 1;
+ }
+ fclose(infile);
+ free(inbuf);
+ return 0;
+}