PPC Data Fork Tool
Volume Number: 12
Issue Number: 12
Column Tag: Toolbox Techniques
Leave the Data (Fork) Alone!
A developer utility to restructure fat/PowerPC applications
By Roger Smith
Note: Source code files accompanying article are located on MacTech CD-ROM or
source code disks.
Warning!
This article may change your life forever. Okay, maybe that’s a bit dramatic, but
hopefully by the time you finish reading it, you will have discarded all previous
knowledge on how to structure fat binaries. The utility MoveData that we will examine
shortly, grew out of a need to create a fat application which stored data in its data fork.
It turns out that the default model of native applications storing code in the data fork,
is merely a default. Apple designed the Power Macintosh runtime architecture with
sufficient flexibility to allow you to locate code fragments just about anywhere you
could imagine. Bottom line, MoveData might actually save you significant amounts of
development effort!
Outline
There is a certain category of applications that allow a user to create
self-running and self-contained documents. For example, a graphic artist might use a
multimedia presentation program to create an informative self-running presentation
to give to end users without the full package. A file compression program might create
an archive that when run, automatically un-archives its contents to fill your hard
drive. In addition to these documents being self-running, where appropriate, it should
also be possible to re-open, edit and re-save them with a minimal amount of hassle.
How many times have you just peeked inside a self-extracting archive and manually
extracted 1 or 2 files without un-archiving the entire contents? It would be great if
these self-running documents ran native on 68K and PPC machines.
Most applications create documents where the stored information is in the data
fork of the files. These applications generally use a subset of the File Manager routines
for manipulating this data. Under the 68K model, this approach lends itself easily to
design a self-running document. In this instance, a stripped down version of your
application checks on startup to see if its data fork is empty. If it is not [empty] it
assumes that it is a self running document and proceeds to load and handle the data in
the data fork. The function checkforSelfContained() (see Listing 4) shows how to do
this, making use of some Process Manager routines to obtain an FSSpec for the current
application. It then uses this FSSpec as a basis for the subsequent calls to the File
Manager to open and process the “Data” in the data fork of the application.
Developing on Power Macintosh.
The above approach breaks under the default PowerPC model since the application
would ultimately try to load itself as data, (recall that by default the code for a
PowerPC application resides in the data fork). If your application were attempting to
interpret sound data, it could lead to some rather interesting “industrial” music. The
exercise of creating a top musical hit using this approach is left as an exercise to the
readers. (Hint: start with a Microsoft application!) What is a developer supposed to
do?
CFRG Resource
Apple defined ‘cfrg’ resource (code fragment), which was introduced with the
Power Macintosh, as the key to understanding the MoveData utility. Using ResEdit to
edit this resource is tedious at best, as you will have to roll your own template to
handle a resource that contains fields that vary in size. Using Resorcerer™ makes
editing and changing this resource a simple task.
.
Figure 1. Application resource list in Resourcer.
Open the ‘cfrg’ editor by double clicking on the ‘cfrg’ resource.
Figure 2. The ‘cfrg’ resource editor in Resourcer.
Normally the various fields are filled in at link time, and you need not
worry about them. The two fields that form the heart of the MoveData
utility are the usage field and where does fragment start. I have defined a C structure
called codeFragRecord (located in the file DSGlobals.h) that mirrors this layout.
codeFragRecord
Listing 1. Structure definition to mimic the ‘cfrg’ layout illustrated in Figure 2.
typedef struct fragDescriptors
{
long CodeType;
long UpdateLevel;
long CurrentVersion;
long OldestDefVersion;
long AppStackSize;
short AppLibDirectory;
Byte TypeOfFrag;
Byte LocationOfFrag;
long OffsetToFrag;
long LengthOfFrag;
long Reserved1;
long Reserved2;
Str255 Fragname;
}fragDescriptors;
typedef struct fragDescriptors fragDescriptors;
typedef fragDescriptors FragArray[1];
typedef struct codeFragRecord
{
long Reserved1;
long Reserved2;
long Version;
long Reserved3;
long Reserved4;
long Reserved5;
long Reserved6;
long NumberofFrags;
FragArray fragArray; // array[0..0] of fragDescriptors;
}codeFragRecord;
typedef struct codeFragRecord *codeFragRecPtr, **codeFragRecHandle;
Problem Identified
Given the task of designing a fat application that stores its data in its own data
fork, you could take one of the following approaches.
(1) Write additional code to handle the case of loading and saving documents.
This code would need to calculate offsets to move the file’s mark to skip over the
code fragment.
(2) Compile your PowerPC application as a code resource. Write additional
code compiled in the 68K version of your application that checks the environment
on startup. If running on a PowerPC, load and execute the PowerPC resource
(often referred to as an accelerated resource).
(3) Not to write code, instead tell the Code Fragment Manager to look in a
particular resource to find the code it should load and execute.
Going back to the ‘cfrg’ editor in Resorcerer™ for a moment, we see that the
usage field allows us to pick one of three options for our code fragment. If generating an
application, this field is set by your development environment to indicate that the
fragment is an application. Internally, the code fragment manager uses this to
determine how to prepare a particular fragment and load it into memory. Refer to
Inside Macintosh, PowerPC System Software if you need additional information.
Figure 3. The usage field popup in the ‘cfrg’ resource.
More importantly the where does fragment start field allows you to change from
the default location in the data fork.