home *** CD-ROM | disk | FTP | other *** search
- /* Welcome to Gordon Fecyk's very first real C program.
-
- This is a Macintosh resource file unpacker with special
- searches and routines for FOND, FONT, and NFNT resources.
-
- Both pure resource files and MacBinary files will unpack
- as I've put enough smarts in this thing to know the difference.
-
- Coming one of these days: font charset remapping and actual conversion.
- */
-
- #include <stdio.h>
- #include <proto/exec.h>
-
- /* This program is the product of learning two different styles of
- C programming and trying to mix them. Kids, don't try this
- at home. */
-
- /* Some defines for resource types */
- #define FOND 0x464F4E44
- #define FONT 0x464F4E54
- #define NFNT 0x4E464E54
- /* These let me cheat; I can read resource */
- /* types as ULONGs instead of chars! */
-
- /* My prototypes: */
-
- void RemoveSpaces(char *charString);
- char *freadline(FILE *sourceFile);
- long ReadInt(FILE *filePointer, int numBytes);
-
- int main(int argc, char *argv[])
-
- {
- ULONG resDOffset,resMOffset,resDLength,resMLength,resOffset;
- ULONG resType,resTOrder[3];
- UWORD numRTType[3],refLOffsets[3],numRTypes,resTLOffset,resNLOffset,test;
- WORD resID,resNLength,numFonts,fontSize,fontType;
- char resName[24];
- /* All documented in Inside Macintosh I */
-
- char *fileName;
- FILE *resFile;
- char resData,outName[30],inName[30],fontName[30],;
- FILE *outFile,*fondList;
- ULONG resLength,index,index2,resDPosition=0,resStart=0;
-
- if (argc!=2)
- {
- printf("Usage: %s SuitcaseName[.mbin]\n\n",argv[0]);
- printf("The Suitcase file must be created from Font/DA Mover V3.8\n");
- printf("or better, and be a pure resource file or a MacBinary file.\n");
- SafeExit();
- }
-
- fileName=argv[1]; /* Passed through CLI/Shell */
-
- resFile=fopen(fileName,"r"); /* No BPTRs here! */
-
- if(resFile==0)
- {
- printf("%s not found.\n",fileName);
- printf("Usage: %s SuitcaseName[.mbin]\n",argv[0]);
- SafeExit();
- }
-
- resDOffset=ReadInt(resFile,4);
- if (resDOffset!=256)
- {
- fseek(resFile,128,0);
- resDOffset=ReadInt(resFile,4); /* That's better */
- resStart=128;
- if (resDOffset!=256) /* Check one more time */
- {
- printf("%s is not a font suitcase file!\n",fileName);
- fclose(resFile);
- SafeExit();
- }
- }
- resMOffset=ReadInt(resFile,4);
- resDLength=ReadInt(resFile,4);
- resMLength=ReadInt(resFile,4);
-
- fseek(resFile,resStart+resDOffset,0); /* Jump to resDOffset */
-
- /* This will extract the individual resources and name them.
- Empty resources (resLength=0) are ignored. */
-
- mkdir("T:ResFiles","w");
- while(resDPosition < resDLength)
- {
- resLength=ReadInt(resFile,4);
- if (resLength!=0)
- {
- sprintf(outName,"T:ResFiles/RES%ld",resDPosition);
- outFile=fopen(outName,"w");
- for (index=0;index < resLength;index++)
- {
- resData=fgetc(resFile);
- fputc(resData,outFile);
- }
- fclose(outFile);
- }
- resDPosition=resDPosition+resLength+4;
- }
-
- /* With extraction out of the way, time to parse the resource map. */
-
- fseek(resFile,resStart+resMOffset+24,0);
-
- resTLOffset=ReadInt(resFile,2);
- resNLOffset=ReadInt(resFile,2);
- resStart=ftell(resFile); /* Start of Res type list */
- numRTypes=ReadInt(resFile,2);
-
- index2=0;
- for (index=0;index<=numRTypes;index++)
- {
- resType=ReadInt(resFile,4);
- switch(resType)
- {
- case FONT:
- case NFNT:
- case FOND:
- resTOrder[index2]=resType;
- numRTType[index2]=ReadInt(resFile,2);
- refLOffsets[index2]=ReadInt(resFile,2);
- index2++;
- break;
-
- default:
- fseek(resFile,4,1);
- break;
- }
- }
-
- /* Where the font manager resources are is now saved. */
- /* Next, we rename the files in T:ResFiles by resource type and ID. */
-
- for (index=0;index<3;index++)
- {
- fseek(resFile,resStart+refLOffsets[index],0);
- for (index2=0;index2<=numRTType[index];index2++)
- {
- resID=ReadInt(resFile,2);
- resNLOffset=ReadInt(resFile,2);
- fseek(resFile,1,1);
- resOffset=ReadInt(resFile,3); /* That's why I like my own int reader! */
- fseek(resFile,4,1);
-
- sprintf(inName,"T:ResFiles/RES%ld",resOffset);
-
- switch(resTOrder[index])
- {
- case FOND:
- sprintf(outName,"T:ResFiles/Fond %ld",resNLOffset);
- break;
-
- case FONT:
- case NFNT:
- sprintf(outName,"T:ResFiles/Font %ld",resID);
- break;
- }
- rename(inName,outName);
- }
- }
-
- /* Wicked... On to the name list... Only FONDs are named here, but this
- could be altered. A rename only occurs if the name offset matches the
- name offset in a FOND filename. Fortunately, C programs don't croak if a
- rename() fails. This makes this part easy to code. */
-
- resStart=ftell(resFile); /* Start of res name list */
- fondList=fopen("T:ResFiles/FondNameList.txt","w");
-
- while (!feof(resFile))
- {
- resNLOffset=ftell(resFile)-resStart;
- resNLength=ReadInt(resFile,1); /* My ReadInt is great! */
- fread(resName,1,resNLength,resFile);
- resName[resNLength]=0; /* Let's not forget that null */
- sprintf(inName,"T:ResFiles/Fond %ld",resNLOffset);
- RemoveSpaces(resName);
- sprintf(outName,"T:ResFiles/%s",resName);
- test=rename(inName,outName);
- if (test==0)
- fprintf(fondList,"%s\n",resName);
- }
-
- fclose(resFile);
- fclose(fondList);
-
- /* Now to interpret the FONDs and determine which ones are what. */
-
- fondList=fopen("T:ResFiles/FondNameList.txt","r");
- mkdir("T:UnpackedFonts","w");
-
- strcpy(fontName,freadline(fondList));
- while (!feof(fondList))
- {
- strcpy(resName,"T:ResFiles/");
- strcat(resName,fontName);
- resFile=fopen(resName,"r");
- fseek(resFile,52,0);
- numFonts=ReadInt(resFile,2);
- for (index=0;index<=numFonts;index++)
- {
- fontSize=ReadInt(resFile,2);
- fontType=ReadInt(resFile,2);
- resID=ReadInt(resFile,2);
- if (fontType==0)
- {
- sprintf(inName,"T:ResFiles/Font %d",resID);
- sprintf(outName,"T:UnpackedFonts/%s.%d",fontName,fontSize);
- rename(inName,outName);
- }
- }
- fclose(resFile);
- sprintf(inName,"T:ResFiles/%s",fontName);
- remove(inName);
- strcpy(fontName,freadline(fondList));
- }
- fclose(fondList);
- remove("T:ResFiles/FondNameList.txt");
- rmdir("T:ResFiles");
-
- /* All cleaning up is done, time to quit. */
-
- SafeExit();
- };
-
-
- /* Simple safe exit routine */
-
- SafeExit()
-
- {
- exit(0);
- };
-
- void RemoveSpaces(char *charString)
-
- /* This'll go through a string (typically a font name) and strip
- the spaces from it. The original string is affected by this,
- and the string length will be shorter or the same length. */
-
- {
-
- int index,charOffset,strLength;
-
- strLength=strlen(charString);
- charOffset=0;
- for (index=0;index<strLength;index++)
- {
- if (charString[index]==32)
- {
- charOffset++;
- index++;
- }
-
- charString[index-charOffset]=charString[index];
- }
- charString[strLength-charOffset]=0;
- return;
- };
-
- #include "ReadInt.c"
- #include "freadline.c" /* Borrowed from ConvertAFM */
-