Created
June 7, 2014 23:29
-
-
Save Slipyx/c701948550b1c246d7d7 to your computer and use it in GitHub Desktop.
Simple utility to extract all files from an Unreal umod file.
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
// slumod | |
// simple utility to extract all files from an Unreal umod file | |
// only tested with UT99 umods | |
// reference: http://wiki.beyondunreal.com/Legacy:UMOD/File_Format | |
// doesn't preserve directories. extracts to same dir as executable | |
// umod file needs to be renamed to pack.umod and placed in same dir | |
// public domain | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <string.h> | |
uint8_t i = 0; | |
FILE* umodFile = NULL; | |
typedef struct | |
{ | |
char filename[64]; | |
uint32_t offs; | |
uint32_t size; | |
uint32_t flags; // Unused | |
} dirEntry_t; | |
dirEntry_t* entries = NULL; | |
uint32_t numEntries = 0; | |
void DumpFile( const char* filename, uint32_t offs, uint32_t size ) { | |
printf( "Dumping %s...\n", filename ); | |
uint8_t* data = (uint8_t*)malloc( size ); | |
fseek( umodFile, offs, SEEK_SET ); | |
fread( data, size, 1, umodFile ); | |
FILE* dumpedFile = fopen( filename, "wb" ); | |
fwrite( data, size, 1, dumpedFile ); | |
fclose( dumpedFile ); | |
free( data ); | |
} | |
int main( int argc, char** argv ) { | |
umodFile = fopen( "pack.umod", "rb" ); | |
if ( umodFile == NULL ) { | |
fprintf( stderr, "Could not open file.\n" ); | |
exit( EXIT_FAILURE ); | |
} | |
// Seek to "header". 20 bytes from end | |
fseek( umodFile, -20, SEEK_END ); // SEEK_END aint portable bro | |
uint32_t HED = ftell( umodFile ); // Beggining of header marker | |
uint32_t magic = 0; | |
fread( &magic, 4, 1, umodFile ); | |
printf( "0x%0x\n", magic ); | |
uint32_t dirOffs = 0; | |
fread( &dirOffs, 4, 1, umodFile ); | |
printf( "Dir offs: 0x%0x\n", dirOffs ); | |
// Seek to dir offs. +1 because first byte isnt really the first filename size | |
fseek( umodFile, dirOffs + 1, SEEK_SET ); | |
//uint32_t EOD = ftell( umodFile ) - 1; // End of data marker | |
// Read entries | |
while ( ftell( umodFile ) < HED ) { | |
numEntries++; | |
entries = (dirEntry_t*)realloc( entries, sizeof(dirEntry_t) * numEntries ); | |
uint8_t fnl = 0; | |
fread( &fnl, 1, 1, umodFile ); | |
fread( entries[numEntries-1].filename, 1, fnl, umodFile ); | |
fread( &entries[numEntries-1].offs, 4, 1, umodFile ); | |
fread( &entries[numEntries-1].size, 4, 1, umodFile ); | |
fread( &entries[numEntries-1].flags, 4, 1, umodFile ); // Silly flags | |
} | |
/*for ( i = 0; i < numEntries; ++i ) { | |
printf( "Filename: %s\n", entries[i].filename ); | |
printf( "Offset: %0x\n", entries[i].offs ); | |
printf( "Size: %d\n", entries[i].size ); | |
}*/ | |
for ( i = 0; i < numEntries; ++i ) { | |
// trim this bitch | |
char* fname = strchr( entries[i].filename, '\\' ) + 1; | |
DumpFile( fname, entries[i].offs, entries[i].size ); | |
} | |
printf( "%d entries.\n", numEntries ); | |
free( entries ); | |
fclose( umodFile ); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment