Created
July 22, 2020 17:26
-
-
Save hezi/c572f89beaed0cf11aca5f6403c43cc1 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 <stdlib.h> | |
#include <string.h> | |
// #include <malloc.h> | |
// #include <windows.h> | |
#ifdef GCC32HACK | |
#include "win32gcc.h" | |
#endif | |
#pragma pack(push, 1) | |
/* PCX Library format description taken from PCXLIB.H */ | |
/* Image Library Header */ | |
typedef struct { | |
char id[10]; /* Library ID string */ | |
char copyright[50]; /* Copyright notice */ | |
unsigned short version; /* pcxLib version */ | |
char label[40]; /* Library volume label */ | |
char xtra[20]; /* filler */ | |
} PCXLIBHEADER; | |
/* Image Library Image Header */ | |
typedef struct { | |
char synch; /* Synch byte (always 1) */ | |
char filename[13]; /* Image file name */ | |
unsigned int filesize; /* File size */ | |
unsigned short date; /* File date */ | |
unsigned short time; /* File time */ | |
unsigned short pack; /* Packing type */ | |
char note[40]; /* Image note */ | |
char xtra[20]; /* Extra filler */ | |
} PCXLIBDIR; | |
/* GX Library format description taken from GXLIB.H */ | |
/* Library Header */ | |
typedef struct { | |
unsigned short id; /* Library header id (=0CA01H) */ | |
char copyright[50]; /* Copyright notice */ | |
unsigned short version; /* gxLib version */ | |
char label[40]; /* Library volume label */ | |
unsigned short entries; /* Total image entries */ | |
char reserved[32]; /* Reserved for GX kernel */ | |
} GXLIBHEADER; | |
/* Library File Information */ | |
typedef struct { | |
char pack; /* Packing type */ | |
char filename[13]; /* Image file name */ | |
unsigned int fileoffs; /* File offset (absolute) */ | |
unsigned int filesize; /* File size */ | |
unsigned short date; /* File date */ | |
unsigned short time; /* File time */ | |
} GXFINFO; | |
#pragma pack(pop) | |
/* remove spaces: "MYFILE .EXT" -> "MYFILE.EXT" */ | |
void fixname(char *s) { | |
char *x; | |
/* just in case */ | |
s[12] = 0; | |
/* remove spaces */ | |
for (x = s; *s; s++) { | |
if (*s != ' ') { | |
*x = *s; | |
x++; | |
} | |
} | |
/* cut tail */ | |
*x = 0; | |
} | |
// void fixtime(FILE *fl, unsigned short d, unsigned short t) { | |
// FILETIME ft, lt; | |
// DosDateTimeToFileTime(d, t, &ft); | |
// /* since DOS don't have timezones - convert to local time, | |
// so the files will have the same time if them was repack | |
// back to the library with the pcxLib/gxLib tool */ | |
// FileTimeToLocalFileTime(&ft, <); | |
// SetFileTime(_get_osfhandle(_fileno(fl)), <, <, <); | |
// } | |
int main(int argc, char *argv[]) { | |
FILE *fl, *f; | |
PCXLIBHEADER hpcx; | |
GXLIBHEADER hgx; | |
PCXLIBDIR dpcx; | |
GXFINFO dgx; | |
unsigned int i; | |
void *p; | |
printf("PCX/GX Library unpacker v1.2\n(c) CTPAX-X Team 2010,2015,2016\nhttp://www.CTPAX-X.org/\n\n"); | |
if (argc != 2) { | |
printf("Usage: unpcxgx <filename.ext>\n\n"); | |
return(1); | |
} | |
fl = fopen(argv[1], "rb"); | |
if (!fl) { | |
printf("ERROR: can\'t open \"%s\".\n\n", argv[1]); | |
return(2); | |
} | |
/* read header */ | |
memset(&hpcx, 0, sizeof(hpcx)); | |
memset(&hgx, 0, sizeof(hgx)); | |
fread(&hpcx, sizeof(hpcx), 1, fl); | |
fseek(fl, 0, SEEK_SET); | |
fread(&hgx, sizeof(hgx), 1, fl); | |
/* try to detect library type */ | |
i = 0; | |
if (!strcmp(hpcx.id, "pcxLib")) { i = 1; } | |
if (hgx.id == 0xCA01) { i = 2; } | |
if (!i) { | |
fclose(fl); | |
printf("ERROR: \"%s\" not a PCX/GX Library file.\n\n", argv[1]); | |
return(3); | |
} | |
printf("%s Library format detected\n\n", (i == 1) ? "PCX" : "GX"); | |
/* unpacking */ | |
if (i == 1) { | |
/* PCX Library */ | |
fseek(fl, 0, SEEK_END); | |
i = ftell(fl); | |
fseek(fl, sizeof(hpcx), SEEK_SET); | |
while ((ftell(fl) + sizeof(dpcx)) <= i) { | |
memset(&dpcx, 0, sizeof(dpcx)); | |
fread(&dpcx, sizeof(dpcx), 1, fl); | |
/* something wrong? */ | |
if (dpcx.synch != 1) { break; } | |
printf("%s", dpcx.filename); | |
/* unpack item */ | |
p = malloc(dpcx.filesize); | |
if (p) { | |
fread(p, 1, dpcx.filesize, fl); | |
fixname(dpcx.filename); | |
f = fopen(dpcx.filename, "wb"); | |
if (f) { | |
fwrite(p, 1, dpcx.filesize, f); | |
// fixtime(f, dpcx.date, dpcx.time); | |
fclose(f); | |
} | |
free(p); | |
} | |
printf("\n"); | |
} | |
} else { | |
/* GX Library */ | |
fseek(fl, sizeof(hgx), SEEK_SET); | |
for (; hgx.entries; hgx.entries--) { | |
memset(&dgx, 0, sizeof(dgx)); | |
fread(&dgx, sizeof(dgx), 1, fl); | |
printf("%s", dgx.filename); | |
/* unpack item */ | |
p = malloc(dgx.filesize); | |
if (p) { | |
i = ftell(fl); | |
fseek(fl, dgx.fileoffs, SEEK_SET); | |
fread(p, 1, dgx.filesize, fl); | |
fixname(dgx.filename); | |
f = fopen(dgx.filename, "wb"); | |
if (f) { | |
fwrite(p, 1, dgx.filesize, f); | |
// fixtime(f, dgx.date, dgx.time); | |
fclose(f); | |
} | |
free(p); | |
fseek(fl, i, SEEK_SET); | |
} | |
printf("\n"); | |
} | |
} | |
fclose(fl); | |
printf("\ndone\n\n"); | |
return(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment