@@ -154,16 +154,16 @@ int write_file(const char *path, const uint8_t *data, size_t size) {
154154 }
155155
156156 fclose (f );
157- return 0 ;
157+ return EXIT_SUCCESS ;
158158}
159159
160160// check if extension needs reversing
161161int is_invertible (const char * ext ) {
162162 const char * invertible [] = { "RGCN" , "RLCN" , "RECN" , "RNAN" , "RCSN" , "RTFN" };
163163 for (size_t i = 0 ; i < sizeof (invertible )/sizeof (invertible [0 ]); ++ i ) {
164- if (strcasecmp (ext , invertible [i ]) == 0 ) return 1 ;
164+ if (strcasecmp (ext , invertible [i ]) == 0 ) return EXIT_FAILURE ;
165165 }
166- return 0 ;
166+ return EXIT_SUCCESS ;
167167}
168168
169169// reverse string in place
@@ -207,19 +207,19 @@ const char *try_get_extension(
207207
208208// extract files from acf archive
209209int extract_acf (const char * path ) {
210- if (!path ) return 1 ;
210+ if (!path ) return EXIT_FAILURE ;
211211
212212 size_t fileSize ;
213213 uint8_t * fileData = read_file (path , & fileSize );
214214 if (!fileData ) {
215215 fprintf (stderr , "Can't read %s\n" , path );
216- return 1 ;
216+ return EXIT_FAILURE ;
217217 }
218218
219219 if (fileSize < sizeof (ACFHeader )) {
220220 fprintf (stderr , "%s: too small to be an ACF\n" , path );
221221 free (fileData );
222- return 1 ;
222+ return EXIT_FAILURE ;
223223 }
224224
225225 // read header
@@ -229,14 +229,14 @@ int extract_acf(const char *path) {
229229 if (memcmp (hdr .magic , "acf" , 3 ) != 0 ) {
230230 fprintf (stderr , "%s doesn't have an 'acf\\0' header\n" , path );
231231 free (fileData );
232- return 1 ;
232+ return EXIT_FAILURE ;
233233 }
234234
235235 size_t fatOffset = hdr .headerSize ;
236236 if (hdr .numFiles * sizeof (FATEntry ) > fileSize - fatOffset ) {
237237 fprintf (stderr , "%s: FAT table exceeds file size\n" , path );
238238 free (fileData );
239- return 1 ;
239+ return EXIT_FAILURE ;
240240 }
241241
242242 FATEntry * entries = (FATEntry * )(fileData + fatOffset );
@@ -255,13 +255,16 @@ int extract_acf(const char *path) {
255255 if (!mf ) {
256256 fprintf (stderr , "Cannot create metadata file\n" );
257257 free (fileData );
258- return 1 ;
258+ return EXIT_FAILURE ;
259259 }
260260
261261 char extBuf [16 ];
262262 for (uint32_t i = 0 ; i < hdr .numFiles ; ++ i ) {
263263 FATEntry e = entries [i ];
264- if (e .relativeOffset == 0xFFFFFFFFu ) continue ;
264+ if (e .relativeOffset == 0xFFFFFFFFu ) { // unused entry
265+ fprintf (mf , "%04u -1\n" , i );
266+ continue ;
267+ }
265268
266269 size_t dataOffset = (size_t )hdr .dataStart + (size_t )e .relativeOffset ;
267270 if (dataOffset >= fileSize ) {
@@ -285,7 +288,7 @@ int extract_acf(const char *path) {
285288 fprintf (stderr , "OOME\n" );
286289 free (fileData );
287290 fclose (mf );
288- return 1 ;
291+ return EXIT_FAILURE ;
289292 }
290293 memcpy (outBuf , src , outSize );
291294 } else {
@@ -298,7 +301,7 @@ int extract_acf(const char *path) {
298301 fprintf (stderr , "OOME\n" );
299302 free (fileData );
300303 fclose (mf );
301- return 1 ;
304+ return EXIT_FAILURE ;
302305 }
303306 memcpy (outBuf , src , outSize );
304307 }
@@ -325,7 +328,7 @@ int extract_acf(const char *path) {
325328 printf ("\n" );
326329 fclose (mf );
327330 free (fileData );
328- return 0 ;
331+ return EXIT_SUCCESS ;
329332}
330333
331334// process all acf archives in a directory
@@ -374,69 +377,86 @@ void process_directory(const char *directory) {
374377
375378// build an acf archive from a directory
376379int build_acf (const char * directory ) {
377- if (!directory ) return 1 ;
380+ if (!directory ) return EXIT_FAILURE ;
378381
379382 // read metadata from filelist.txt
380383 char metafile [512 ];
381384 snprintf (metafile , sizeof (metafile ), "%s/filelist.txt" , directory );
382385 FILE * mf = fopen (metafile , "r" );
383386 char * * files = NULL ;
384- uint32_t * compressFlags = NULL ;
387+ int * compressFlags = NULL ; // use int to hold -1 for unused entries
385388 size_t numFiles = 0 ;
386389
387390 if (mf ) {
388391 char line [1024 ];
389392 while (fgets (line , sizeof (line ), mf )) {
390393 if (line [0 ] == '#' || strlen (line ) < 3 ) continue ;
391394
392- char fname [512 ];
393- unsigned int comp ;
394- if (sscanf (line , "%s %u" , fname , & comp ) == 2 ) {
395- char * * tmpFiles = realloc (files , (numFiles + 1 ) * sizeof (char * ));
395+ char id [32 ];
396+ int flag ;
397+ if (sscanf (line , "%31s %d" , id , & flag ) != 2 ) continue ;
398+
399+ // determine the index from the ID
400+ int index = atoi (id );
401+ if ((size_t )(index + 1 ) > numFiles ) {
402+ // expand arrays if needed
403+ char * * tmpFiles = realloc (files , (index + 1 ) * sizeof (char * ));
396404 if (!tmpFiles ) {
397- for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
405+ for (size_t j = 0 ; j < numFiles ; j ++ ) free (files [j ]);
398406 free (files );
399407 free (compressFlags );
400408 fclose (mf );
401409 fprintf (stderr , "Memory allocation failed\n" );
402- return 1 ;
410+ return EXIT_FAILURE ;
403411 }
404412 files = tmpFiles ;
405413
406- uint32_t * tmpFlags = realloc (compressFlags , (numFiles + 1 ) * sizeof (uint32_t ));
414+ int * tmpFlags = realloc (compressFlags , (index + 1 ) * sizeof (int ));
407415 if (!tmpFlags ) {
408- for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
416+ for (size_t j = 0 ; j < numFiles ; j ++ ) free (files [j ]);
409417 free (files );
410418 free (compressFlags );
411419 fclose (mf );
412420 fprintf (stderr , "Memory allocation failed\n" );
413- return 1 ;
421+ return EXIT_FAILURE ;
414422 }
415423 compressFlags = tmpFlags ;
416424
417- size_t pathlen = strlen (directory ) + strlen (fname ) + 2 ;
418- files [numFiles ] = malloc (pathlen );
419- if (!files [numFiles ]) {
420- for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
425+ // initialize new entries
426+ for (size_t j = numFiles ; j <= (size_t )index ; j ++ ) {
427+ files [j ] = NULL ;
428+ compressFlags [j ] = -1 ; // default to unused
429+ }
430+
431+ numFiles = index + 1 ;
432+ }
433+
434+ // store file path if not unused
435+ if (flag == -1 ) {
436+ files [index ] = NULL ; // mark unused
437+ compressFlags [index ] = -1 ;
438+ } else {
439+ size_t pathlen = strlen (directory ) + strlen (id ) + 8 ; // allow for extension
440+ files [index ] = malloc (pathlen );
441+ if (!files [index ]) {
442+ for (size_t j = 0 ; j < numFiles ; j ++ ) free (files [j ]);
421443 free (files );
422444 free (compressFlags );
423445 fclose (mf );
424446 fprintf (stderr , "Memory allocation failed\n" );
425- return 1 ;
447+ return EXIT_FAILURE ;
426448 }
427-
428- snprintf (files [numFiles ], pathlen , "%s/%s" , directory , fname );
429- compressFlags [numFiles ] = comp ;
430- numFiles ++ ;
449+ snprintf (files [index ], pathlen , "%s/%s" , directory , id );
450+ compressFlags [index ] = flag ;
431451 }
432452 }
433453 fclose (mf );
434454 } else {
435455 fprintf (stderr , "Metadata file not found in %s\n" , directory );
436- return 1 ;
456+ return EXIT_FAILURE ;
437457 }
438458
439- if (numFiles == 0 ) { fprintf (stderr , "No files to pack\n" ); return 1 ; }
459+ if (numFiles == 0 ) { fprintf (stderr , "No files to pack\n" ); return EXIT_FAILURE ; }
440460
441461 // create output acf archive
442462 char outname [512 ];
@@ -447,7 +467,7 @@ int build_acf(const char *directory) {
447467 for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
448468 free (files );
449469 free (compressFlags );
450- return 1 ;
470+ return EXIT_FAILURE ;
451471 }
452472
453473 // initialize header
@@ -468,7 +488,7 @@ int build_acf(const char *directory) {
468488 for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
469489 free (files );
470490 free (compressFlags );
471- return 1 ;
491+ return EXIT_FAILURE ;
472492 }
473493
474494 memcpy (headerBuf , & hdr , sizeof (hdr ));
@@ -483,19 +503,31 @@ int build_acf(const char *directory) {
483503 for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
484504 free (files );
485505 free (compressFlags );
486- return 1 ;
506+ return EXIT_FAILURE ;
507+ }
508+
509+ // initialize FAT to unused
510+ for (size_t i = 0 ; i < numFiles ; i ++ ) {
511+ fat [i ].relativeOffset = 0xFFFFFFFFu ;
512+ fat [i ].inputSize = 0 ;
513+ fat [i ].outputSize = 0 ;
487514 }
488515
489516 fwrite (fat , sizeof (FATEntry ), numFiles , out );
490517
491518 // write files
492519 size_t offset = 0 ;
493-
494520 for (size_t i = 0 ; i < numFiles ; i ++ ) {
521+ // skip unused entries
522+ if (compressFlags [i ] == -1 || files [i ] == NULL ) {
523+ fat [i ].relativeOffset = 0xFFFFFFFFu ;
524+ fat [i ].inputSize = 0 ;
525+ fat [i ].outputSize = 0 ;
526+ continue ;
527+ }
495528
496529 size_t sz = 0 ;
497530 uint8_t * buf = read_file (files [i ], & sz );
498-
499531 if (!buf ) {
500532 fprintf (stderr , "Skipping %s\n" , files [i ]);
501533 fat [i ].relativeOffset = 0xFFFFFFFFu ;
@@ -505,18 +537,15 @@ int build_acf(const char *directory) {
505537 }
506538
507539 int doCompress = compressFlags [i ];
508- if (i == 0 ) {
509- doCompress = 0 ; // fat[0] is always raw
510- }
511- fat [i ].relativeOffset = (uint32_t )offset ;
540+ if (i == 0 ) doCompress = 0 ; // first file always raw
512541
513- if ( doCompress ) {
542+ fat [ i ]. relativeOffset = ( uint32_t ) offset ;
514543
544+ if (doCompress ) {
515545 size_t compSize = 0 ;
516546 uint8_t * comp = lz10_compress (buf , sz , & compSize );
517547
518548 size_t paddedComp = pad_size (compSize , 4 );
519-
520549 fwrite (comp , 1 , compSize , out );
521550
522551 // padding
@@ -527,20 +556,17 @@ int build_acf(const char *directory) {
527556 fat [i ].outputSize = (uint32_t )pad_size (sz , 4 );
528557
529558 offset += paddedComp ;
530- }
531-
532- if (!doCompress ) {
559+ free (comp );
560+ } else {
533561 size_t padded = pad_size (sz , 4 );
534-
535- fat [i ].outputSize = (uint32_t )padded ;
536- fat [i ].inputSize = 0 ;
537-
538562 fwrite (buf , 1 , sz , out );
539563
540564 // padding
541565 for (size_t p = sz ; p < padded ; p ++ )
542566 fputc (0x00 , out );
543567
568+ fat [i ].inputSize = 0 ;
569+ fat [i ].outputSize = (uint32_t )padded ;
544570 offset += padded ;
545571 }
546572
@@ -556,21 +582,8 @@ int build_acf(const char *directory) {
556582
557583 // update header and fat table
558584 hdr .dataStart = (uint32_t )(hdr .headerSize + numFiles * sizeof (FATEntry ));
559- headerBuf = calloc (1 , hdr .headerSize );
560- if (!headerBuf ) {
561- fprintf (stderr , "Memory allocation failed\n" );
562- fclose (out );
563- free (fat );
564- for (size_t i = 0 ; i < numFiles ; i ++ ) free (files [i ]);
565- free (files );
566- free (compressFlags );
567- return 1 ;
568- }
569-
570- memcpy (headerBuf , & hdr , sizeof (hdr ));
571585 fseek (out , 0 , SEEK_SET );
572586 fwrite (& hdr , 1 , sizeof (hdr ), out );
573- free (headerBuf );
574587
575588 fseek (out , hdr .headerSize , SEEK_SET );
576589 fwrite (fat , sizeof (FATEntry ), numFiles , out );
@@ -586,7 +599,7 @@ int build_acf(const char *directory) {
586599 printf ("Built %s with %zu files. headerSize=0x%X dataStart=0x%X\n" ,
587600 outname , numFiles , (unsigned )hdr .headerSize , (unsigned )hdr .dataStart );
588601
589- return 0 ;
602+ return EXIT_SUCCESS ;
590603}
591604
592605int main (int argc , char * * argv ) {
@@ -596,7 +609,7 @@ int main(int argc, char **argv) {
596609 printf ("Usage:\n" );
597610 printf (" %s -x|--extract <in.acf|indir>\n" , argv [0 ]);
598611 printf (" %s -b|--build <indir>\n" , argv [0 ]);
599- return 0 ;
612+ return EXIT_SUCCESS ;
600613 }
601614
602615 const char * mode = argv [1 ];
@@ -606,7 +619,7 @@ int main(int argc, char **argv) {
606619 struct stat st ;
607620 if (stat (path , & st ) != 0 ) {
608621 fprintf (stderr , "Invalid path: %s\n" , path );
609- return 1 ;
622+ return EXIT_FAILURE ;
610623 }
611624
612625 if (S_ISDIR (st .st_mode )) { // directory
@@ -620,16 +633,16 @@ int main(int argc, char **argv) {
620633 struct stat st ;
621634 if (stat (path , & st ) != 0 || !S_ISDIR (st .st_mode )) {
622635 fprintf (stderr , "Invalid path: %s\n" , path );
623- return 1 ;
636+ return EXIT_FAILURE ;
624637 }
625638
626639 printf ("Building ACF from directory: %s\n" , path );
627640 build_acf (path );
628641 }
629642 else {
630643 fprintf (stderr , "Unknown mode %s\n" , mode );
631- return 1 ;
644+ return EXIT_FAILURE ;
632645 }
633646
634- return 0 ;
647+ return EXIT_SUCCESS ;
635648}
0 commit comments