Created
July 29, 2012 05:02
-
-
Save kikuchan/3196179 to your computer and use it in GitHub Desktop.
unpacker for multi game scripter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
uint8_t read_uint8(FILE *fp) | |
{ | |
int ch = fgetc(fp); | |
uint8_t ret = 0; | |
if (ch == EOF) return 0; /* XXX */ | |
return ch ^ 'R'; | |
} | |
uint16_t read_uint16(FILE *fp) | |
{ | |
uint16_t ret = 0; | |
ret |= read_uint8(fp) << 0; | |
ret |= read_uint8(fp) << 8; | |
} | |
uint32_t read_uint32(FILE *fp) | |
{ | |
uint32_t ret = 0; | |
ret |= read_uint8(fp) << 0; | |
ret |= read_uint8(fp) << 8; | |
ret |= read_uint8(fp) << 16; | |
ret |= read_uint8(fp) << 24; | |
return ret; | |
} | |
size_t read_block(FILE *fp, char *buf, size_t len) | |
{ | |
int i; | |
for (i = 0; i < len; i++) { | |
buf[i] = read_uint8(fp); | |
if (feof(fp)) break; | |
} | |
return len; | |
} | |
char *progname = "mgs-unpack"; | |
void usage() | |
{ | |
fprintf(stderr, "Usage: %s <l|x> <filename>\n", progname); | |
exit(0); | |
} | |
struct _pack_dirent { | |
uint32_t len; | |
char filename[16]; | |
} *entries; | |
int main(int argc, char *argv[]) | |
{ | |
FILE *fp = stdin; | |
unsigned short num = 0; | |
int i; | |
int flag_extract = 0; | |
progname = argv[0]; | |
if (argc < 3) { | |
usage(); | |
} | |
if (!strcmp(argv[1], "l")) { | |
} else if (!strcmp(argv[1], "x")) { | |
flag_extract = 1; | |
} else { | |
usage(); | |
} | |
if (!!strcmp(argv[2], "-")) fp = fopen(argv[2], "rb"); | |
if (fp == NULL) { | |
fprintf(stderr, "Can't open the file; %s\n", argv[2]); | |
return -1; | |
} | |
num = read_uint16(fp); | |
if (num == (0x5a4d ^ 0x5252)) { | |
fseek(fp, 217792, SEEK_SET); | |
num = read_uint16(fp); | |
} | |
printf("Entries; %d\n", num); | |
if (num > 0x100) { | |
fprintf(stderr, "Too many file? num = %d\n", num); | |
exit(0); | |
} | |
entries = malloc(sizeof(struct _pack_dirent) * num); | |
if (entries == NULL) { | |
perror("malloc"); | |
exit(0); | |
} | |
for (i = 0; i < num; i++) { | |
struct _pack_dirent *ent = &entries[i]; | |
ent->len = read_uint32(fp); | |
read_block(fp, ent->filename, 16); | |
printf("%-16s %d bytes\n", ent->filename, ent->len); | |
} | |
if (!flag_extract) return 0; | |
for (i = 0; i < num; i++) { | |
struct _pack_dirent *ent = &entries[i]; | |
uint32_t remain = ent->len; | |
char buf[1024]; | |
FILE *fpw; | |
fpw = fopen(ent->filename, "w+b"); | |
if (fpw == NULL) { | |
fprintf(stderr, "Can't open the file for writing\n"); | |
return -1; | |
} | |
while (remain > 0) { | |
int reqlen = remain < sizeof(buf) ? remain : sizeof(buf); | |
int len = read_block(fp, buf, reqlen); | |
if (len < reqlen) { | |
fprintf(stderr, "Premature EOF is detected\n"); | |
return -1; | |
} | |
fwrite(buf, 1, len, fpw); | |
remain -= reqlen; | |
} | |
fclose(fpw); | |
} | |
if (fp != stdin) fclose(fp); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment