Revision: 759
Author:
blue...@gmail.com
Date: Fri Nov 21 05:08:38 2014 UTC
Log: Add support for little-endian GSL files.
Endianness is auto-detected for all operations other than creation, where
big endian is assumed unless you specify otherwise.
https://code.google.com/p/sylverant/source/detail?r=759
Modified:
/trunk/pso_tools/pso_artool/Makefile
/trunk/pso_tools/pso_artool/artool.c
/trunk/pso_tools/pso_artool/gsl.c
=======================================
--- /trunk/pso_tools/pso_artool/Makefile Wed Nov 19 19:43:59 2014 UTC
+++ /trunk/pso_tools/pso_artool/Makefile Fri Nov 21 05:08:38 2014 UTC
@@ -3,7 +3,7 @@
all: pso_artool
-pso_artool:
+pso_artool: artool.c afs.c gsl.c
$(CC) -o pso_artool artool.c afs.c gsl.c
.PHONY: clean
=======================================
--- /trunk/pso_tools/pso_artool/artool.c Wed Nov 19 19:43:59 2014 UTC
+++ /trunk/pso_tools/pso_artool/artool.c Fri Nov 21 05:08:38 2014 UTC
@@ -24,10 +24,13 @@
/* Available archive types. */
#define ARCHIVE_TYPE_NONE -1
#define ARCHIVE_TYPE_AFS 0
-#define ARCHIVE_TYPE_GSLBE 1
+#define ARCHIVE_TYPE_GSL 1
#define ARCHIVE_TYPE_COUNT 2
+#define GSL_BIG 0
+#define GSL_LITTLE 1
+
/* Archive manipulation functions. These should probably go in a header,
but I'm
feeling lazy at the moment. */
int print_afs_files(const char *fn);
@@ -43,6 +46,7 @@
int add_to_gsl(const char *fn, const char *files[], uint32_t count);
int update_gsl(const char *fn, const char *file, const char *path);
int delete_from_gsl(const char *fn, const char *files[], uint32_t cnt);
+void gsl_set_endianness(int e);
/* This looks ugly, but whatever. */
struct {
@@ -85,8 +89,8 @@
static void print_help(const char *bin) {
printf("Usage:\n"
" %s type operation [operation aguments]\n"
- "Where type is one of --afs or --gsl. Available operations
and\n"
- "their arguments are shown below:\n"
+ "Where type is one of --afs, --gsl, --gsl-little, or
--gsl-big.\n"
+ "Available operations and their arguments are shown below:\n"
"To list the files in an archive:\n"
" -t archive\n"
"To extract an archive:\n"
@@ -107,7 +111,15 @@
printf("As AFS archives do not store filenames, any files specified in
an\n"
"AFS archive are specified by index within the archive (for the
-u\n"
"and --delete operations). For other archive formats, you
should\n"
- "specify the file names within the archive for these
operations.\n");
+ "specify the file names within the archive for these
operations.\n"
+ "\n");
+ printf("GSL archives are supported in both big- and little-endian
forms.\n"
+ "If the endianness is not specified (by way of the --gsl-big
or\n"
+ "--gsl-little types), then it will be auto-detected for all\n"
+ "operations other than archive creation (big-endian is assumed
if\n"
+ "endianness is not specified for archive creation). You should
use\n"
+ "big-endian mode for PSOGC files and little-endian mode for
any\n"
+ "other versions of the game.\n");
}
/* Parse any command-line arguments passed in. */
@@ -120,12 +132,23 @@
exit(EXIT_FAILURE);
}
- if(!strcmp(argv[1], "--afs"))
+ if(!strcmp(argv[1], "--afs")) {
t = ARCHIVE_TYPE_AFS;
- else if(!strcmp(argv[1], "--gsl"))
- t = ARCHIVE_TYPE_GSLBE;
- else
+ }
+ else if(!strcmp(argv[1], "--gsl")) {
+ t = ARCHIVE_TYPE_GSL;
+ }
+ else if(!strcmp(argv[1], "--gsl-little")) {
+ t = ARCHIVE_TYPE_GSL;
+ gsl_set_endianness(GSL_LITTLE);
+ }
+ else if(!strcmp(argv[1], "--gsl-big")) {
+ t = ARCHIVE_TYPE_GSL;
+ gsl_set_endianness(GSL_BIG);
+ }
+ else {
i = 1;
+ }
if(!strcmp(argv[i], "--version")) {
print_program_info();
=======================================
--- /trunk/pso_tools/pso_artool/gsl.c Wed Nov 19 19:43:59 2014 UTC
+++ /trunk/pso_tools/pso_artool/gsl.c Fri Nov 21 05:08:38 2014 UTC
@@ -33,8 +33,14 @@
#include <libgen.h>
#endif
+#define GSL_AUTO -1
+#define GSL_BIG 0
+#define GSL_LITTLE 1
+
static uint8_t xbuf[512];
+static int endianness = GSL_AUTO;
+
struct delete_cxt {
FILE *fp;
uint32_t item_count;
@@ -137,11 +143,30 @@
char filename[33];
int rv = 0;
uint32_t offset, size, i;
- long next;
+ long next, total;
/* Open up the file */
if(!(fp = open_gsl(fn)))
return -1;
+
+ /* Figure out the length of the file. */
+ if(fseek(fp, 0, SEEK_END)) {
+ printf("Seek error: %s\n", strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+
+ if((total = ftell(fp)) < 0) {
+ printf("Cannot determine length of file: %s\n", strerror(errno));
+ fclose(fp);
+ return -1;
+ }
+
+ if(fseek(fp, 0, SEEK_SET)) {
+ printf("Seek error: %s\n", strerror(errno));
+ fclose(fp);
+ return -1;
+ }
/* Read in each file in the archive, writing each one out. */
for(i = 0; ; ++i) {
@@ -167,7 +192,33 @@
goto out;
}
- offset = (buf[3]) | (buf[2] << 8) | (buf[1] << 16) | (buf[0] <<
24);
+ /* If the user hasn't specified the endianness, then try to guess.
*/
+ if(endianness == GSL_AUTO) {
+ /* Guess big endian first. */
+ offset = (buf[3]) | (buf[2] << 8) | (buf[1] << 16) | (buf[0]
<< 24);
+ endianness = GSL_BIG;
+
+ /* If the offset of the file is outside of the archive length,
the
+ we probably guessed wrong, try as little endian. */
+ if(offset > (uint32_t)total || offset * 2048 >
(uint32_t)total) {
+ offset = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) |
+ (buf[0]);
+ endianness = GSL_LITTLE;
+
+ if(offset * 2048 > (uint32_t)total) {
+ printf("GSL file looks corrupt. Cowardly refusing to
even "
+ "attempt further operation.\n");
+ rv = -9;
+ goto out;
+ }
+ }
+ }
+ else if(endianness == GSL_BIG) {
+ offset = (buf[3]) | (buf[2] << 8) | (buf[1] << 16) | (buf[0]
<< 24);
+ }
+ else {
+ offset = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) |
(buf[0]);
+ }
/* Figure out the size of the next file. */
if(fread(buf, 1, 4, fp) != 4) {
@@ -176,7 +227,12 @@
goto out;
}
- size = (buf[3]) | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24);
+ if(endianness == GSL_BIG) {
+ size = (buf[3]) | (buf[2] << 8) | (buf[1] << 16) | (buf[0] <<
24);
+ }
+ else {
+ size = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) |
(buf[0]);
+ }
/* Seek over the blank padding space. */
if(fseek(fp, 8, SEEK_CUR)) {
@@ -290,14 +346,27 @@
/* Write the file's information into the file table. */
wposp = wpos >> 11;
- buf[0] = (uint8_t)(wposp >> 24);
- buf[1] = (uint8_t)(wposp >> 16);
- buf[2] = (uint8_t)(wposp >> 8);
- buf[3] = (uint8_t)(wposp);
- buf[4] = (uint8_t)(size >> 24);
- buf[5] = (uint8_t)(size >> 16);
- buf[6] = (uint8_t)(size >> 8);
- buf[7] = (uint8_t)(size);
+ if(endianness == GSL_BIG) {
+ buf[0] = (uint8_t)(wposp >> 24);
+ buf[1] = (uint8_t)(wposp >> 16);
+ buf[2] = (uint8_t)(wposp >> 8);
+ buf[3] = (uint8_t)(wposp);
+ buf[4] = (uint8_t)(size >> 24);
+ buf[5] = (uint8_t)(size >> 16);
+ buf[6] = (uint8_t)(size >> 8);
+ buf[7] = (uint8_t)(size);
+ }
+ else {
+ buf[0] = (uint8_t)(wposp);
+ buf[1] = (uint8_t)(wposp >> 8);
+ buf[2] = (uint8_t)(wposp >> 16);
+ buf[3] = (uint8_t)(wposp >> 24);
+ buf[4] = (uint8_t)(size);
+ buf[5] = (uint8_t)(size >> 8);
+ buf[6] = (uint8_t)(size >> 16);
+ buf[7] = (uint8_t)(size >> 24);
+ }
+
buf[8] = 0;
buf[9] = 0;
buf[10] = 0;
@@ -398,14 +467,27 @@
strncpy((char *)buf, fn, 32);
/* Fill in the header data for the file. */
- buf[32] = (uint8_t)(wposp >> 24);
- buf[33] = (uint8_t)(wposp >> 16);
- buf[34] = (uint8_t)(wposp >> 8);
- buf[35] = (uint8_t)(wposp);
- buf[36] = (uint8_t)(sz >> 24);
- buf[37] = (uint8_t)(sz >> 16);
- buf[38] = (uint8_t)(sz >> 8);
- buf[39] = (uint8_t)(sz);
+ if(endianness == GSL_BIG) {
+ buf[32] = (uint8_t)(wposp >> 24);
+ buf[33] = (uint8_t)(wposp >> 16);
+ buf[34] = (uint8_t)(wposp >> 8);
+ buf[35] = (uint8_t)(wposp);
+ buf[36] = (uint8_t)(sz >> 24);
+ buf[37] = (uint8_t)(sz >> 16);
+ buf[38] = (uint8_t)(sz >> 8);
+ buf[39] = (uint8_t)(sz);
+ }
+ else {
+ buf[32] = (uint8_t)(wposp);
+ buf[33] = (uint8_t)(wposp >> 8);
+ buf[34] = (uint8_t)(wposp >> 16);
+ buf[35] = (uint8_t)(wposp >> 24);
+ buf[36] = (uint8_t)(sz);
+ buf[37] = (uint8_t)(sz >> 8);
+ buf[38] = (uint8_t)(sz >> 16);
+ buf[39] = (uint8_t)(sz >> 24);
+ }
+
buf[40] = 0;
buf[41] = 0;
buf[42] = 0;
@@ -458,14 +540,27 @@
strncpy((char *)buf, fn, 32);
/* Fill in the header data for the file. */
- buf[32] = (uint8_t)(wposp >> 24);
- buf[33] = (uint8_t)(wposp >> 16);
- buf[34] = (uint8_t)(wposp >> 8);
- buf[35] = (uint8_t)(wposp);
- buf[36] = (uint8_t)(sz >> 24);
- buf[37] = (uint8_t)(sz >> 16);
- buf[38] = (uint8_t)(sz >> 8);
- buf[39] = (uint8_t)(sz);
+ if(endianness == GSL_BIG) {
+ buf[32] = (uint8_t)(wposp >> 24);
+ buf[33] = (uint8_t)(wposp >> 16);
+ buf[34] = (uint8_t)(wposp >> 8);
+ buf[35] = (uint8_t)(wposp);
+ buf[36] = (uint8_t)(sz >> 24);
+ buf[37] = (uint8_t)(sz >> 16);
+ buf[38] = (uint8_t)(sz >> 8);
+ buf[39] = (uint8_t)(sz);
+ }
+ else {
+ buf[32] = (uint8_t)(wposp);
+ buf[33] = (uint8_t)(wposp >> 8);
+ buf[34] = (uint8_t)(wposp >> 16);
+ buf[35] = (uint8_t)(wposp >> 24);
+ buf[36] = (uint8_t)(sz);
+ buf[37] = (uint8_t)(sz >> 8);
+ buf[38] = (uint8_t)(sz >> 16);
+ buf[39] = (uint8_t)(sz >> 24);
+ }
+
buf[40] = 0;
buf[41] = 0;
buf[42] = 0;
@@ -529,14 +624,27 @@
strncpy((char *)buf, fn, 32);
/* Fill in the header data for the file. */
- buf[32] = (uint8_t)(wposp >> 24);
- buf[33] = (uint8_t)(wposp >> 16);
- buf[34] = (uint8_t)(wposp >> 8);
- buf[35] = (uint8_t)(wposp);
- buf[36] = (uint8_t)(sz >> 24);
- buf[37] = (uint8_t)(sz >> 16);
- buf[38] = (uint8_t)(sz >> 8);
- buf[39] = (uint8_t)(sz);
+ if(endianness == GSL_BIG) {
+ buf[32] = (uint8_t)(wposp >> 24);
+ buf[33] = (uint8_t)(wposp >> 16);
+ buf[34] = (uint8_t)(wposp >> 8);
+ buf[35] = (uint8_t)(wposp);
+ buf[36] = (uint8_t)(sz >> 24);
+ buf[37] = (uint8_t)(sz >> 16);
+ buf[38] = (uint8_t)(sz >> 8);
+ buf[39] = (uint8_t)(sz);
+ }
+ else {
+ buf[32] = (uint8_t)(wposp);
+ buf[33] = (uint8_t)(wposp >> 8);
+ buf[34] = (uint8_t)(wposp >> 16);
+ buf[35] = (uint8_t)(wposp >> 24);
+ buf[36] = (uint8_t)(sz);
+ buf[37] = (uint8_t)(sz >> 8);
+ buf[38] = (uint8_t)(sz >> 16);
+ buf[39] = (uint8_t)(sz >> 24);
+ }
+
buf[40] = 0;
buf[41] = 0;
buf[42] = 0;
@@ -584,6 +692,11 @@
mode_t mask;
#endif
+ /* If the user hasn't specified the endianness of the file he or she is
+ creating, then assume big endian. */
+ if(endianness == GSL_AUTO)
+ endianness = GSL_BIG;
+
/* Figure out the size of the header. Sega's files seem (to me) to
have no
rhyme or reason to how long the header is. I just round it up to
the next
multiple of 2048. */
@@ -894,3 +1007,7 @@
int extract_gsl(const char *fn) {
return scan_gsl(fn, &extract_file, (void *)fn);
}
+
+void gsl_set_endianness(int e) {
+ endianness = e;
+}