#include #include #include #include #include #define UMOD_MAGIC 0x9FE3C5A3 typedef struct { uint32_t sig, dir, size, ver, crc; } umodfoot_t; typedef struct { char *fname; uint32_t ofs, len, flags; } umoddir_t; // CRC has to be done in this very specific way or shit will go wrong // I totally did not take this from leaked Unreal Engine source code uint32_t crctable[256]; void crcinit( void ) { for( uint32_t i=0; i<256; i++ ) for ( uint32_t c=(i<<24), j=8; j; j-- ) crctable[i] = c = (c&0x80000000)?((c<<1)^0x04C11DB7):(c<<1); } uint32_t crc( const void *s, size_t l, uint32_t crc ) { uint8_t *d = (uint8_t*)s; crc = ~crc; for ( size_t i=0; i>24)^d[i]]; return ~crc; } // fuck you tim sweeney (or whoever else is responsible for this crime) int32_t readindex( FILE *f ) { uint8_t byte[5] = {0}; fread(&byte[0],1,1,f); if ( !byte[0] ) return 0; if ( byte[0]&0x40 ) { for ( int i=1; i<5; i++ ) { fread(&byte[i],1,1,f); if ( !(byte[i]&0x80) ) break; } } int32_t tf = byte[0]&0x3f; tf |= (int32_t)(byte[1]&0x7f)<<6; tf |= (int32_t)(byte[2]&0x7f)<<13; tf |= (int32_t)(byte[3]&0x7f)<<20; tf |= (int32_t)(byte[4]&0x7f)<<27; if ( byte[0]&0x80 ) tf *= -1; return tf; } int main( int argc, char **argv ) { if ( argc < 2 ) { fprintf(stderr,"usage: umodextract \n"); return 1; } FILE *f = fopen(argv[1],"rb"); fseek(f,-20,SEEK_END); umodfoot_t feet; fread(&feet,1,20,f); if ( feet.sig != UMOD_MAGIC ) { fclose(f); return 2; } //printf("sig: %08X\ndir: &%u\nsize: %u bytes\nver: %u\ncrc: %08X\n", // feet.sig,feet.dir,feet.size,feet.ver,feet.crc); // CRC verification void *dat = malloc(feet.size-20); fseek(f,0,SEEK_SET); fread(dat,1,feet.size-20,f); crcinit(); uint32_t thiscrc = crc(dat,feet.size-20,0); free(dat); if ( thiscrc != feet.crc ) { fprintf(stderr,"CRC mismatch! %08X != %08X\n",thiscrc,feet.crc); fclose(f); return 4; } fseek(f,feet.dir,SEEK_SET); int32_t ndir = readindex(f); //printf("ndir: %d\n",ndir); umoddir_t *dir = calloc(ndir,sizeof(umoddir_t)); for ( int32_t i=0; i