| /* rezrov.c | |
| * Extracts resources from a blorb file | |
| * Written by Felix Gr�tzmacher and placed into the public domain */ | |
| /* The following might need changing on your machine */ | |
| typedef unsigned int UI32; | |
| /* Define this if you're compiling for an Intel machine */ | |
| typedef struct { | |
| char usage[4]; | |
| UI32 num; | |
| UI32 start; | |
| } RES_T; | |
| void extract(RES_T res, FILE *blb); | |
| void endian_transform(UI32 *p); | |
| unsigned num_ext = 0; | |
| int main(int argc, char *argv[]) { | |
| FILE *blb; | |
| UI32 num_res=0; | |
| RES_T res[MAX_RES]; | |
| UI32 i; | |
| if(argc<2) { | |
| fprintf(stderr, "Usage: %s <filename>\n", argv[0]); | |
| exit(1); | |
| } | |
| if(!(blb=fopen(argv[1],"rb"))) { | |
| perror(argv[1]); | |
| exit(2); | |
| } | |
| fseek(blb, 20, SEEK_SET); | |
| if(fread(&num_res, 4, 1, blb)!=1) { | |
| if(feof(blb)) | |
| fputs("End of file while reading resource index.\n", stderr); | |
| else perror("Error getting number of resources"); | |
| exit(3); | |
| } | |
| endian_transform(&num_res); | |
| if(num_res>MAX_RES) | |
| num_res=MAX_RES; | |
| if(fread(res, sizeof(RES_T), num_res, blb)!=num_res) { | |
| if(feof(blb)) | |
| fputs("End of file while reading resource index.\n", stderr); | |
| else perror("Error reading resource index"); | |
| exit(3); | |
| } | |
| for(i=0; i<num_res; i++) | |
| if(!strncmp(res[i].usage, "Snd ", 4) || !strncmp(res[i].usage, "Pict ", 4) || !strncmp(res[i].usage, "Exec", 4)) | |
| extract(res[i], blb); | |
| /* Our work is done */ | |
| fclose(blb); | |
| printf("Successfully captured %u resources!\n", num_ext); | |
| return 0; | |
| } | |
| void extract(RES_T res, FILE *blb) { | |
| char type[4]; | |
| UI32 len; | |
| char fname[16]; /* max 10 digits + ".xxxx" + '\0' */ | |
| FILE *out; | |
| UI32 i; | |
| int c; | |
| int tmp; | |
| const char *ext; | |
| endian_transform(&(res.start)); | |
| endian_transform(&(res.num)); | |
| fseek(blb, res.start, SEEK_SET); | |
| if(fread((void *)type, 1, 4, blb)!=4) { | |
| if(feof(blb)) | |
| fputs("End of file while reading resource type.\n", stderr); | |
| else perror("Error reading resource type"); | |
| exit(3); | |
| } | |
| switch(*type) { | |
| case 'M': | |
| ext = ".mod"; | |
| break; | |
| case 'F': | |
| ext = ".aiff"; | |
| break; | |
| case 'P': | |
| ext = ".png"; | |
| break; | |
| case 'Z': | |
| ext = ".z"; | |
| break; | |
| case 'G': | |
| ext = ".ulx"; | |
| break; | |
| default: | |
| return; /* skip resources of unknown type */ | |
| } | |
| if(fread(&len, 4, 1, blb)!=1) { | |
| if(feof(blb)) | |
| fputs("End of file while reading resource length.\n", stderr); | |
| else perror("Error reading resource length"); | |
| exit(3); | |
| } | |
| tmp=len; | |
| endian_transform(&len); | |
| sprintf(fname, "%u", res.num); | |
| strcat(fname, ext); | |
| if(!(out=fopen(fname, "wb"))) { | |
| perror(fname); | |
| exit(4); | |
| } | |
| /* If this is an aiff, write "FORM" and len to output */ | |
| if(*type=='F') { | |
| if(fwrite(type, 1, 4, out)!=4) { | |
| perror("Error writing lead-in FORM tag"); | |
| exit(4); | |
| } | |
| if(fwrite(&len, 4, 1, out)!=1) { | |
| perror("Error writing lead-in form length"); | |
| exit(4); | |
| } | |
| } | |
| /* Copy the data */ | |
| for(i=0; i<len; i++) { | |
| if((c=getc(blb))==EOF) { | |
| if(ferror(blb)) | |
| perror("Error reading resource data"); | |
| else fputs("End of file while reading resource data.\n", stderr); | |
| exit(3); | |
| } | |
| if(putc(c, out)==EOF) { | |
| perror(fname); | |
| exit(4); | |
| } | |
| } | |
| fclose(out); | |
| num_ext++; | |
| } | |
| void endian_transform(UI32 *p) { | |
| UI32 r = *p; | |
| r = (r>>24) | ((r>>8)&0x0000ff00) | ((r<<8)&0x00ff0000) | (r<<24); | |
| *p=r; | |
| } | |
Xet Storage Details
- Size:
- 3.54 kB
- Xet hash:
- 9d5fa46fa495b62708f5a5c24ce9c9dc56cc2b76bb4c3deb86c99b266d9b7e6a
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.