/* extract text, meshes, textures, palettes and sounds from 1995 packages. TODO: extract animseq and meshmap data for meshes */ #include #include #include #include #include #include #include #include #include #include #define NAMES_MARK "[REFERENCED NAMES]" #define IMPORT_MARK "[IMPORTED RESOURCES]" #define EXPORT_MARK "[EXPORTED RESOURCES]" #define DATA_MARK "[EXPORTED RESOURCE DATA]" #define HEADER_MARK "[EXPORTED RESOURCE HEADERS]" #define TABLE_MARK "[EXPORTED RESOURCE TABLE]" #define TRAILER_MARK "[SUMMARY]" #define RES_FILE_TAG "Unreal Resource\0" enum EResourceType { RES_None = 0, // No resource. RES_Buffer = 1, // A large binary object holding misc saveable data. RES_Array = 3, // An array of resources. RES_TextBuffer = 4, // A text buffer. RES_Texture = 5, // Texture or compound texture. RES_Font = 6, // Font for use in game. RES_Palette = 7, // A palette. RES_Script = 9, // Script. RES_Class = 10, // An actor class. RES_ActorList = 11, // An array of actors. RES_Sound = 12, // Sound effect. RES_Mesh = 14, // Animated mesh. RES_Vectors = 16, // 32-bit floating point vector list. RES_BspNodes = 17, // Bsp node list. RES_BspSurfs = 18, // Bsp polygon list. RES_LightMesh = 19, // Bsp polygon lighting mesh. RES_Polys = 20, // Editor polygon list. RES_Model = 21, // Model or level map. RES_Level = 22, // A game level. RES_Camera = 25, // A rendering camera on this machine. RES_Player = 28, // A remote player logged into the local server. RES_VertPool = 29, // A vertex pool corresponding to a Bsp and FPoints/FVectors table. RES_Ambient = 30, // An ambient sound definition. RES_TransBuffer = 31, // Transaction tracking buffer. RES_MeshMap = 32, // MeshMap. RES_Bounds = 33, // Bounding structure. RES_Terrain = 34, // Terrain. RES_Enum = 35, // Enumeration (array of FName's). }; typedef struct { uint16_t version, nexports, nimports, nnames; uint32_t onames, oimports, oheaders, oexports; uint8_t pad[32]; char tag[16]; } __attribute__((packed)) resourcefiletrailer_t; typedef struct { char name[16]; uint16_t unused; } __attribute__((packed)) nameentry_t; typedef struct { char name[16]; uint16_t index; uint8_t type, unknown; uint8_t pad1[6]; uint16_t headersize; uint8_t pad2[10]; uint32_t dataofs, datasize; uint8_t pad3[8]; } __attribute__((packed)) resnamefileentry_t; typedef struct { uint8_t r, g, b, x; } __attribute__((packed)) color_t; // global stuff FILE *f; resourcefiletrailer_t tail; nameentry_t *names; resnamefileentry_t *imports; resnamefileentry_t *exports; size_t *eheaders; int writepng( const char *filename, unsigned char *fdata, int fw, int fh, png_color *fpal, int fpalsiz ) { if ( !filename ) return 0; png_structp pngp; png_infop infp; FILE *pf; if ( !(pf = fopen(filename,"wb")) ) return 0; pngp = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); if ( !pngp ) { fclose(pf); return 0; } infp = png_create_info_struct(pngp); if ( !infp ) { fclose(pf); png_destroy_write_struct(&pngp,0); return 0; } if ( setjmp(png_jmpbuf(pngp)) ) { png_destroy_write_struct(&pngp,&infp); fclose(pf); return 0; } png_init_io(pngp,pf); if ( fpal ) { png_set_IHDR(pngp,infp,fw,fh,8,PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_set_PLTE(pngp,infp,fpal,fpalsiz); unsigned char t = 0; png_set_tRNS(pngp,infp,&t,1,0); png_write_info(pngp,infp); for ( int i=0; i\n"); return 0; } f = fopen(argv[1],"rb"); if ( !f ) { fprintf(stderr,"Cannot open %s: %s\n",argv[1],strerror(errno)); return 1; } fseek(f,-sizeof(resourcefiletrailer_t),SEEK_END); fread(&tail,sizeof(resourcefiletrailer_t),1,f); if ( strncmp(tail.tag,RES_FILE_TAG,16) ) { fprintf(stderr,"Not a valid Unreal Resource file.\n"); fclose(f); return 1; } if ( tail.version != 1 ) { fprintf(stderr,"Unreal Resource version %04x not supported.\n", tail.version); fclose(f); return 1; } printf("%s - %u names, %u imports, %u exports\n",argv[1],tail.nnames, tail.nimports,tail.nexports); names = calloc(tail.nnames,sizeof(nameentry_t)); imports = calloc(tail.nimports,sizeof(resnamefileentry_t)); exports = calloc(tail.nexports,sizeof(resnamefileentry_t)); eheaders = calloc(tail.nexports,sizeof(size_t)); fseek(f,tail.onames,SEEK_SET); fread(names,sizeof(nameentry_t),tail.nnames,f); fseek(f,tail.oimports,SEEK_SET); fread(imports,sizeof(resnamefileentry_t),tail.nimports,f); fseek(f,tail.oexports,SEEK_SET); fread(exports,sizeof(resnamefileentry_t),tail.nexports,f); fseek(f,tail.oheaders,SEEK_SET); for ( int i=0; i