Skip to content

Instantly share code, notes, and snippets.

@simontime
Created December 29, 2018 16:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save simontime/9ba59ab1045f204519643666a2f8b56e to your computer and use it in GitHub Desktop.
Save simontime/9ba59ab1045f204519643666a2f8b56e to your computer and use it in GitHub Desktop.
Monster Hunter Generations Ultimate ARC extractor
#define _CRT_SECURE_NO_WARNINGS
#define ZLIB_WINAPI
#include <direct.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <zlib.h>
#define BUFFERSIZE 0x10000000
typedef struct {
char magic[4];
short unk1;
short count;
int unk2;
} header;
typedef struct {
char name[0x40];
int unk1;
int size;
int unk2;
int offset;
} fileEntry;
// Source: https://stackoverflow.com/questions/4901842/in-memory-decompression-with-zlib
int decompress(const void *src, int srcLen, void *dst, int dstLen) {
z_stream strm = { 0 };
strm.total_in = strm.avail_in = srcLen;
strm.total_out = strm.avail_out = dstLen;
strm.next_in = (Bytef *)src;
strm.next_out = (Bytef *)dst;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
int err = -1;
int ret = -1;
err = inflateInit2(&strm, (15 + 32));
if (err == Z_OK) {
err = inflate(&strm, Z_FINISH);
if (err == Z_STREAM_END) {
ret = strm.total_out;
}
else {
inflateEnd(&strm);
return err;
}
}
else {
inflateEnd(&strm);
return err;
}
inflateEnd(&strm);
return ret;
}
int rmakedir(const char *dir) {
char tmp[256];
char *p = NULL;
struct stat sb;
size_t len = strnlen(dir, 256);
memcpy(tmp, dir, len);
tmp[len] = '\0';
if (tmp[len - 1] == '\\')
tmp[len - 1] = '\0';
for (p = tmp + 1; *p; p++) {
if (*p == '\\') {
*p = 0;
if (stat(tmp, &sb))
if (_mkdir(tmp) < 0)
return -1;
*p = '\\';
}
}
if (stat(tmp, &sb))
if (_mkdir(tmp) < 0)
return -1;
return 0;
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "Usage: %s file.arc", argv[0]);
return 1;
}
FILE *in = fopen(argv[1], "rb");
header hdr;
fread(&hdr, sizeof(hdr), 1, in);
fileEntry *entries = malloc(sizeof(fileEntry) * hdr.count);
fread(entries, sizeof(fileEntry), hdr.count, in);
for (int i = 0; i < hdr.count; i++) {
char *name = calloc(0x40, 1),
*dirname = calloc(0x40, 1);
strcpy(name, entries[i].name);
char *fnm = strrchr(name, '\\');
if (fnm) {
strncpy(dirname, name, (int)(fnm - name));
rmakedir(dirname);
}
printf("Saving %s...\n", name);
FILE *out = fopen(name, "wb");
char *buf = malloc(entries[i].size),
*comp = malloc(BUFFERSIZE);
fseek(in, entries[i].offset, 0);
fread(buf, 1, entries[i].size, in);
int sz = decompress(buf, entries[i].size, comp, BUFFERSIZE);
fwrite(comp, 1, sz, out);
fclose(out);
free(buf);
free(comp);
}
puts("\nDone!");
fclose(in);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment