Skip to content

Instantly share code, notes, and snippets.

@hezi
Created July 22, 2020 17:26
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 hezi/c572f89beaed0cf11aca5f6403c43cc1 to your computer and use it in GitHub Desktop.
Save hezi/c572f89beaed0cf11aca5f6403c43cc1 to your computer and use it in GitHub Desktop.
#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, &lt);
// SetFileTime(_get_osfhandle(_fileno(fl)), &lt, &lt, &lt);
// }
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