Skip to content

Instantly share code, notes, and snippets.

@Slipyx
Created June 7, 2014 23:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Slipyx/c701948550b1c246d7d7 to your computer and use it in GitHub Desktop.
Save Slipyx/c701948550b1c246d7d7 to your computer and use it in GitHub Desktop.
Simple utility to extract all files from an Unreal umod file.
// 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