Rez 101
by: Tim Swihart


So, you've heard how great resources are and how much easier they can 
make software development.  You're eager to find out what resources can do 
for you, then suddenly, it hits you - you're not even sure what resources 
ARE!

Even the best sample source code fails if the reader doesn't understand the 
concepts BEHIND that source.  Why were certain tool calls used?  How did the 
author decide which calls to use (there are roughly a thousand tool calls to 
choose from)?  Why did the author use certain resource types and not 
others?  Where do you go to learn more about all of this?


Step Right Up!

I'll tackle answering those questions and others like them in this file and in 
others to follow.  Along the way, I'll point out other sources of more detailed 
information (to help you learn faster), I'll mention trade offs between doing 
things one way or doing them another, I'll cover various development tools 
that help make resources easier, and I'll try to do it all at a level that just 
about anyone can understand.

In GEnie's A2Pro library and in America Online's ADV library are a series of 
source code samples that I wrote showing how to use resources in IIGS 
applications.  This file is intended to explain Part 1 of the APW C-based Rez 
tutorial that I've uploaded to those libraries (if you don't have those files 
handy, then you should get them, it'll make this file more valuable).  Later 
files will detail Part 2, Part 2.5, Part 3, etc of the resource tutorial files.  That 
way, you have one detailed explanation for each part of the sample source.

Future versions of this detailed explanation will ONLY explain the things that 
are NEW to whatever part they're supposed to "match".  That means that the 
detailed explanation for Part 2 won't contain this background information 
and it won't talk about starting up the tools (Part 1 will do that).  You should 
be prepared to read each of the files in this series in order to understand all 
of what's involved in using resources in your own applications.


The Problem:

All Apple IIGS programs that use the Toolbox need to use certain data 
structures like menu bars, window templates, icons, strings, etc.  The original 
way to handle these within an application was to hard code it inside the 
source files to the applications themselves.  If you wanted to rename a 
menu, change the title of a window, make a window bigger or smaller, etc, 
then you had to edit your source, compile it, link it, run it, and repeat until 
you achieved the desired affect.

What if you wanted to do a French version of your application?  You had to 
go back into your source code to try it all out, you had to once again use trial 
and error to get your controls to line up (their sizes would change no doubt if 
the text within them changed to a new language).

This "edit/compile/link/run/repeat" method was usually VERY time 
consuming.  Linking large applications can be very time consuming, 
recompiling source code over and over is also very time consuming, but 
there just weren't any other ways to do it.

Changing the user interface to your applications was a nightmare.  Many 
developers just didn't bother to fix "holes" in their user interface because 
they were tired of recompiling just for minor tweaks.

What if there was a special place you could store the templates for all of 
these structures?  What if there was a special place you could put all of the 
text strings that your applications use?  What if there was a faster way to 
create things like windows, menus, etc?  What if it were possible to make 
sweeping changes to the user interfaces within seconds - without "breaking" 
your application?

What if we defined a special part of the file to contain nothing more than the 
collection of these structures and their contents?  How would your 
application be able to tell one structure from another?  How would you 
access these structures?  How would you create them?


Enter Resources:

Since the introduction of Apple IIGS System Disk v.5.0.2, there IS a special 
place for keeping all of these "things" that need to be tweaked, converted to 
foreign languages, embellished, etc.  This special place is known as the 
"resource fork" of a file.

Each structure within your application COULD (they don't HAVE to) now be 
placed in another portion of your application (the resource fork).  The 
Resource Manager takes care of keeping track of where within the file your 
structure lives and loads it into memory for you when you need it.  Each of 
these individual structures living in the resource fork are called "resources".  
So, the simple definition of a resource is data that is needed for your 
application.

Individual resources are kept track of by the Resource Manager because 
EVERY resource has a specific "type" and a specific "ID" (you assign the ID, 
what you're trying to use the resource for defines the type).  Apple defined 
the most commonly used types and published the definitions for those types 
in Apple IIGS Toolbox Reference Manual, Volume 3 (available as I type this 
in beta form from APDA and soon to be available in "final" form from 
Addison-Wesley at better bookstores and [of course] at APDA).

For the sake of those of you who don't have Toolbox Reference Volume 3, I'll 
BRIEFLY describe each type of resource when ever it gets added to the 
resource tutorial application.  I will not go into tons of detail (Volume 3 is 
over a thousand pages and I'm not going to paraphrase that much!).  If you 
need more information or explanation that I've provided, then you should 
either post a specific question either in A2Pro or ADV or get Volume 3 and 
read what Apple says (it's a great book to have <hint, hint>).


How Do Resources Get Used?

If you need a specific resource in memory, you can tell the Resource 
Manager to load it by making the tool call "LoadResource".  It's fairly rare 
that you have to use LoadResource yourself!!!  Why?  Because most of the 
standard resource types are loaded for you when you make specific calls to 
OTHER tool sets (such as the Window Manager or the Menu Manager)!  The 
resource sample source code (up through Part 3.2) does NOT use 
LoadResource - it's simply not needed.

System Disk 5.0 introduced a number of new tool calls to several toolbox 
Managers so that these Manager could support resources.  You create a 
window the old way by calling "NewWindow".  You create a window using 
resources by calling "NewWindow2" (notice the "2" on the end of the call).  
Using the old way, you would add menus to your application by calling 
NewMenuBar and then adding the menus one by one by calling InsertMenu 
on each of them (ugh!  sounds like a lot of work).  Using resources, you can 
install a menu bar, its menus, and all of the items within those menus with 
ONE call - NewMenuBar2.  (ahhh, much easier!)

So, the answer to "How do I use resources?" is simply create the resources 
your application will need and let the toolbox use them for you.  You simply 
pass references to the resources to the toolbox and the computer takes it 
from there.


What's A Reference?:

Before we go any further, let's look at a new data type that we need to 
understand.  The new tool calls can your resources for the information they 
need or they can use structures that you already have in memory (or that 
you hard coded within your application).  These calls can accept either a 
handle to the data structure you want to use, a pointer to the data structure, 
or the ID of the resource you want to use.  This handle/point/resource ID is 
referred to as a "reference".  In other words, a reference is the way that the 
toolbox gets to the actual data structure.

How does the toolbox know whether you've passed a pointer, a handle, or a 
resource ID?  Simple, YOU tell the toolbox what you're passing, every time 
you pass it!  Each tool call that accepts a reference also REQUIRES that you 
tell it what kind of reference you've passed!

The bits that describe the type of reference passed is called a "reference 
descriptor" or simply a "refDesc".  Toolbox Volume 3 has more details and 
explains the bit patterns used for the different types of reference 
descriptors.  Since I'm trying to teach you about resources, all of the 
resource-related tool calls I've used have resource ID's as their reference.


Tools to Help:

There are several ways to create resources.  The first tool that was available 
to developers is a "resource compiler" from Apple named "Rez".  Rez takes 
text descriptions of resources and converts them into actual resources (which 
is why it's called a "compiler").  Since Rez takes text files as input, it's very 
easy to upload resources TODAY to share with others - you simply upload 
the text description and the downloaders compile it to create the actual 
resources (this gets around the problem of current file packer's not being 
able to cope with FILES that have resources).  You can also put the resources 
themselves on a disk and pack the disk for uploading, but when sending 
sample source code, the text version is often faster (because you only pack 
the files, not the whole disk).  Also, the text-based descriptions of resources 
help newer developers unravel the structure of resources.

Creating things like windows filled with controls by typing in text 
descriptions is often cumbersome.  That's where desktop applications like 
SSSi's "GeneSys" comes in handy.  GeneSys (and competing programs not yet 
released) let you "draw" your window, menus, controls, etc on the desktop 
(so you can see what they look like immediately) and GeneSys creates either 
the Rez source for you or creates the resources directly.

Rez can do things no other tool can do yet - such as combining several 
resource forks into one, easily supporting custom resources types, reading 
data files and saving them as resources (so you can move sampled sounds, 
pictures, etc into resources easily).  So, Rez should be in every developer's 
arsenal of tools!

The package of tools that Rez comes in includes a resource decompiler (called 
DeRez).  DeRez allows you to convert existing resources back into text 
descriptions.  If you use a different tool to create your resources directly, 
then you can convert those resources to text using DeRez.  Why would you 
want to do this?  Several reasons, this protects you from anything that 
trashes your resource fork (if your resources get trampled, simply use Rez to 
recompile them - this is called "Rez-urrecting your resource fork").  You can 
also do this as an easier way to "archive" your application's source code.

Many tasks require a more visually oriented tools (such as GeneSys) to get 
the job done quickly.  So having BOTH Rez and a desktop tool like GeneSys 
should be seriously considered!  If you decide to not have both, then 
consider again.  It's that important.

The resource tutorials that I've uploaded, and the descriptions like this file 
all assume that you have Rez.  If you don't have Rez then you can get it by 
calling either Developer Tools Express or APDA (if you don't belong to APDA, 
then call Developer Tools Express).  Both APDA and Developer Tools Express 
use the same phone number (1-800-282-2732 from U.S., 1-800-637-0029 
from Canada, and 408-562-3910 from International).  Tell them you want to 
order part number A0240LL/A (price is fifty dollars).  This package includes 
a collection of tools for use with the APW and ORCA shells that are used 
throughout this tutorial series.


Every App Has To...:

Every Apple IIGS application that wants to use the Toolbox has to start up 
the individual tool sets that the application expects to use.  The application 
also has to start up any tool sets that are needed by the tool set the app 
wants to use (you many not care about the Memory Manager, bu you can bet 
the other tools do!).  These tools have to be started up in just the right order 
- that order is listed in a tech note, several books, etc, so it is fairly easy to 
find this out.  Some of the tool sets need some memory in bank zero (called 
direct page space) and the starting points of each tool's direct page space has 
to be passed to the tools as they are started up.  Before you can pass this 
direct page space, you have to request it.  

Starting up tools in this way is an ugly process, you have to know the right 
order to start things up in, you have to request direct page space from the 
Memory Manager, and you have to pass this space to the tools as you start 
them up one by one.  It would sure be a LOT easier if we could just make a 
list of what tools we want started up and have the computer figure out how 
much direct page space was needed, get the direct page space for us and 
start the tools for us as well.  That would let us make ONE tool call to start 
ALL of the tools our application needs!

Well, System Disk 5.0 introduced just such a tool call.  It's called 
"StartUpTools" (naturally) and it makes life a LOT easier for us!  Now, to start 
all of the tools your application will need, simply make a list (the format for 
this list is given in Toolbox Reference, Volume 3), and  pass your user ID 
(which you get from the Memory Manager), a reference descriptor (so 
StartUpTools knows whether it's getting a pointer, a handle, or a resource 
ID), a reference to this list.  We're showing how to use resources so the 
reference descriptor we use is "refIsResource" (this is a constant defined in 
the interfaces files by Apple).  The reference we pass is the resource ID of 
the tools list (which lives in the resource fork).


What's in the tools list?:

Earlier in this file, I told you that the type of the resources you use is 
dictated by what you want to do with that resource.  In order to use a tool 
list in a resource to start all of the tools, it has to be of type "rToolStartup".  
This name (rToolStartup) is a constant defined in the Types.Rez interface file.  
In order to create a resource of this type, we create a text file (see the 
"rTutor.Rez" file) that contains a line telling Rez to include (i.e.: read in) the 
standard resource types file (called "Types.Rez") and then we can describe 
the actual resource itself using the syntax that Rez expects to see.

Comments in Rez source files can be in either of two formats.  If you see a 
pair of slashes (i.e.:  //) then that means the rest of that line is treated by 
Rez as a comment and ignored.  If you see a slash followed immediately by 
an asterisk (i.e.:  /*), then that starts a comment - to end that comment, Rez 
has to see an asterisk followed by a slash (i.e.:  */).  This second form can be 
as long as you want it and can span multiple lines.  I'll use either type in my 
Rez source throughout the tutorial, so be sure you remember both of them.

If we strip all of the comments out of the rTutor.Rez file, we're left with the 
"#include Types.Rez" line (which we already discusses) and a funny looking 
structure that starts with "resource rToolStartup (1)".  This funny looking 
structure is how we tell Rez what we want in the various parts of the tool 
startup list.

The word "resource" at the beginning of the line simply tells Rez that we're 
starting the description of a resource and that we'll use a template (from 
Types.Rez this time, but we can also define our own if we'd rather) to 
describe the parts of this resource.  It's possible to create resources by just 
passing Rez a bunch of bytes of data - those types of resources start off with 
"data" instead of "resource".

The next thing on the line we're talking about is "rToolStartup" - this is the 
TYPE of the resource we're about to describe.  Remember, the type is 
dictated by what you want to do with it - we want to start up the tools so we 
HAVE to use the type of "rToolStartup".  The "(1)" is the resource ID we've 
assigned to this tool startup list.  Since all resources are described by BOTH a 
type AND an ID, you can have multiple resources of the same TYPE (because 
they'll all have different ID's) and of the same ID (as long as their types are 
different).

Why did I give this resource an ID of 1?  Why not use 4129?  Or some other 
number?  I like to keep tutorial source simple, so I tend to number resources 
starting from 1 (which I use for the first resource of that type).  I use a 
different numbering system for menus because you have to keep track of 
menu bars, menus, menu items, and the text strings that all of them use.  
The best way to do all of this is to define your own constants and use the 
constants between the parenthesis!  i.e.:  instead of using "1", I should have 
put  "#define firstStartupList 1"  in my Rez source ABOVE the "resource 
rToolStartup..." line.  Then, I could have changed the "resource 
rToolStartup..." line to be:  "resource rToolStartup (firstStartupList)"  Since 
applications tend to have only one startup tools list, this isn't that big of a 
deal, but later on (when we get into menus) you'll see that this technique is 
almost mandatory in order to figure out what's going on.

The curly brace ("{") tells Rez that we're starting the description of the 
rToolStartup list.  The "$C080" that's on the next line is a hex number that 
Rez uses in the first field of the tool startup list.  This field tells the toolbox 
whether your app wants to come up in 320 or 640 mode and allows you to 
set other QuickDraw attributes (if you want to know them all, see Toolbox 
Ref, Volume 3).

A comma separates items within the test that describes the resource.  We 
could cram everything onto one long line and Rez could figure it out.  I like 
to be able to read what I've done (so I can catch errors), so I've manually 
formatted the listing.

Let's think for a minute - how many tools are we going to start up?  Will it 
always be the same number for EVERY application?  How do we tell the 
toolbox that we only want to start up 17 of the tools (there are many more 
than just 17)?  Obviously, we have to tell the toolbox how many items are in 
our list of tools.  That can easily lead to errors if we have to count the 
number of tools our selves and put that number in a list.  Adding a tool and 
forgetting to change the number could cause weird problems.

Fortunately, Rez is smart enough to be able to count for us!  So, instead of 
having to count the number of tools we want to start, we let Rez do it.  (this 
requires some special fields in the template, if you want to know how it's 
done, see the Rez chapter of the APW Tools manual).  Since the template 
takes care of whatever it is that's needed to make this auto-counting happen, 
we only have to open another layer of curly braces and list all of the tools.  
So, the next line of the Rez source is simply another curly brace ("{") and 
then comes the list of tools.

Notice that each line has TWO numbers on it (separated by commas).  The 
first number is the tool set's number (assigned by Apple) and the second 
number is the minimum version of that toolset that our application is willing 
to accept.  "4, $0302" means that we must be able to start at least version 3.2 
of tool set #4 (QuickDraw).  The "$" tells us the numbers after it are hex, the 
lack of any special characters in front of the "4" tell us that it's just a plain 
old decimal number.  For details on how version number are decoded, look in 
the Toolbox Reference Manual (Volume 2 I believe).

Why is the version number important????  As the IIGS's tools have become 
more mature over the years, new calls have been added.  If you start up an 
old version of the tools, the calls you make may NOT have been implemented 
yet!  That means your application will fail in some weird place!  If you check 
the version numbers at startup, you'll know THEN whether or not all of the 
tool calls your application uses are implemented!  Early versions of the Rez 
tutorial allows many of the version numbers to be MUCH lower than they 
should be (i.e.:  it uses version 1.0 for things that should be 2.0 or higher).  
This will be fixed in whatever comes AFTER Part 3.2 (3.2 is already released, 
so there's no way to fix it until the next version is released).

In your applications, be sure you check the version numbers!!!! 

After we've listed all of the tools the tutorial app needs started, we have to 
close the list with a curly brace ("}").  This marks the spot for Rez to stop 
counting (now Rez can fill in the count field for us).  A second curly brace 
("}") is needed to close the complete resource description (remember, we had 
two opening braces, so we HAVE to have two closing braces.  A semicolon is 
added after the last closing brace to tell Rez the resource has been 
completely described.


That's It for The Resource Fork:

Part 1 of the Rez tutorial only includes ONE resource (the list used to start up 
the tools).  Later part of this tutorial will add additional resources (and will 
NOT describe the rToolStartup resource).

Since the resource fork of Part 1 has now been fully described, it's time to 
look at what's needed from within the application itself in order to use the 
rToolStartup resource we just created.


The Application Itself:

At this stage of the game, the application is only supposed to start up the 
tools, indicate that it succeeded and shut the tools back down.  I made the 
application beep three times to indicate success.  If the startup fails, you get 
no beeps.  Either way, the tools are shutdown and the application quits back 
to the launching program.  Your only indications of success are the brief view 
of the desktop and the three beeps.  Don't be surprised if the brief view of 
the desktop does NOT have any menus showing - those don't get added until 
Part 2.  

There are two routines in the APW C source code file that make up Part 1 of 
the Rez tutorial application.  All applications built with C need a routine 
named "main".  The other routine is named "do_init_rom" and that's where 
we actually call StartUpTools.  Since "do_init_rom" is called from within 
"main", we have to put "main" AFTER "do_init_rom", otherwise, the compiler 
will complain that it doesn't know what to do with the call to "do_init_rom" 
because the compiler has NOT yet seen a definition for "do_init_rom".  So, if 
you're not a C fan, but you're studying this source anyways to learn about 
resources, you should now be able to tell what the different routines are for.

"main" has about five lines of meaningful code (I'm ignoring comments and 
braces).  The first one is simply a call to our routine that starts up the tools.  
I put the call to StartUpTools in a separate routine simply to make "main" 
easier to read.  The second line tests the value of a boolean variable to 
determine whether or not the tools were successfully started up.

If the startup was successful, then we make three calls to SysBeep (SysBeep 
is a toolbox routine that simply beeps once each time it's called).  After the 
beeps, we shut down the tools by calling "ShutDownTools".  If the startup 
failed, then we skip the three calls to SysBeep and immediately shut down 
the tools.

ShutDownTools is a toolbox routine and is fully documented in IIGS Toolbox 
Reference Volume 3.  This tool requires two parameters.  The first one is a 
reference descriptor (which I explained earlier).  The second parameter is 
the reference to the "StartStopRecord" that StartUpTools returned to us when 
we called it.  The contents of a StartStopRecord are beyond the scope of this 
explanation (you can survive just fine for now without knowing what they 
are).

Notice that the reference descriptor indicates the the reference we're passing 
to ShutDownTools is a HANDLE.  I said earlier that we'd only be dealing with 
reference descriptors that are resources.  Well, I was wrong.  <grin>  Since 
the StartStopRecord is initialized by calling StartUpTools and is only used 
again by ShutDownTools, I made it a regular variable.

If you examine the contents of the "do_init_rom" routine, you'll see that it 
contains about six lines (ignoring comments and braces) of meaningful code.  
The first line gets our user ID from the Memory Manager.  Under APW C, this 
is actually done for use by the code in the "start.root" file that we have to 
link with, so we can grab the "built in" variable's value and use it here.  
Users of ORCA/C may have to change "_ownerid" to what ever ORCA/C uses 
or replace it with a call to MMStartup (Memory Manager Startup routine).

What?  Start the Memory Manager again?  Won't that fry it if we start it and 
it's already started?  Turns out that MMStartup doesn't actually start the 
Memory Manager, it simply returns the user ID of whatever called it.  So, 
we're safe calling MMStartup as often as we want to.

The next line of code is the call to StartUpTools and it requires the three 
parameters I described much earlier.  StartUpTools returns a reference to 
the StartStopRecord we talked about a little bit ago.  This reference is a 
handle and is need for the ShutDownTools calls right before we quit this 
application.

After we've called StartUpTools, we need to check for errors.  Was our tool 
list correct?  Did we pass all the right parameters to the call?  (remember, 
the resource ID we pass is a LONG, don't forget to pass ALL of that LONG, 
passing only a WORD will cause StartUpTools to fail!).  If the call worked, we 
set the boolean "gPunt" to FALSE.  If there was an error returned by 
StartUpTools, then we set "gPunt" to TRUE.

"gPunt" is a global (that's why it starts with "g" - that's a naming convention 
I use) variable that we'll use in various places within the application later 
on.  Once we've added an event loop (Part 2.5), we'll use gPunt to determine 
when it's time to quit the application.


Th-th-th-that's All Folks!

I've described in pretty intricate detail how Part 1 of the Rez tutorial works.  
I've described what a resource is and given examples of how to use and 
define them.  I've also talked about a couple of tools that are used to create 
resources.  More details on Rez and on GeneSys can be found on both GEnie's 
A2Pro and on America Online (Rez is under ADV and GeneSys is in the SSSi 
section).

If you have further questions, send me email (try the others first), post in 
the appropriate topic/folder, or read the manuals.  Details on the Resource 
Manager and all of the new 5.0 tool calls that support resources are 
documented in Apple IIGS Toolbox Reference, Volume 3.  Rez is documented 
in the manual that comes with "APW Tools & Interfaces".  Enjoy!


Tim S.

