[Next] [Previous] [Up] [Top] [Contents] [Index]

1.3 PSYX Calling Conventions

1.3.1 Code resources


Many programmers may be familiar with the general Macintosh programming model, but not with the technical details of how compiled machine code is loaded and executed. We provide here a short description of code resources. This section is somewhat technical, and the information is not necessary for many PSYX programmers.

1.3.1.1 Applications

To understand stand-alone code resources, it is helpful to first look at how full applications are executed.

In a regular application, the executable machine code is stored in resources of type `CODE'. Each `CODE' resource represents a "segment" of the application; the grouping of source files into segments is performed by the programmer through the compiler. (In THINK C, the horizontal lines in a project window divide up the different segments; in MPW C, segment names are indicated using the #pragma segment directive.)

An application is started up by loading `CODE' resource 0 and jumping (i.e. setting the processor's program counter) to the start of the resource data block. The instructions here will automatically load the segment (i.e. `CODE' resource) containing the application's main() function.

Whenever a function in one segment calls a function that is in another, the function call passes through a jump table. This jump table insures that the segment containing the destination function is loaded and locked in memory.

Application globals are stored in a single, separate block of memory. The address of the beginning of this memory is stored in the processor's A5 register, so that all accesses of global variables are computations from the A5 register.

1.3.1.2 Stand-alone code resources

Code resources are smaller pieces of machine code that have to be loaded and executed explicitly by the caller. Code resources are generally stored as resource of some type other than `CODE'; in particular, PsyScope uses `PSYX' for PSYXs.

When you compile a PSYX in Metrowerks Codewarrior, MPW, or THINK C, you have to tell the compiler that you are writing a code resource, and that the resource type is `PSYX'. Then, instead of generating an application, the compiler will generate a file which contains the `PSYX' resource for your code. Other resources used by the PSYX are also copied into the output file, just as with an application.

Code resources are usually made of only one segment, so there is usually no jump table. To call the main() procedure of a PSYX, the caller jumps (JSR) to the beginning of the `PSYX' resource, first placing main()'s arguments on the stack using C calling conventions.

If a code resource has multiple segments, the compiler will automatically insert code for segment jumps, loading extra segments into memory as necessary. The non-main segments are typically given another resource type -- such as `CCOD' -- by the compiler. The `CCOD' is given an ID based on the main resource (`PSYX') ID, so that multiple multi-segment code resources can be placed in the same resource file. (See Inside Macintosh, Volume I, page I-109 for information on numbering owned resources.)

Note: Multi-segment PSYXs must all have unique resource IDs so that the `CCOD's of different PSYXs do not get mixed up. If you need to make a multi-segment PSYX, you should register the resource ID for the PSYX with PsyScope support so that it does not conflict with other PSYXs.

Code resource globals are usually kept within the main resource segment. When compiling a code resource with MPW or THINK C, the compiler inserts glue code at the beginning of the program that sets the A4 register to point to the start of the globals. (Glue code is also added at the end to restore the value of A4.) When compiling with Metrowerks Codewarrior, the main() function of a code resource must explicitly set up and restore the A4 register. To do this, use the macros EnterCodeResource() and ExitCodeResource(), provided in the header file <A4Stuff.h>.

Usually, you will not need to worry about the A4/A5 distinction -- the compiler will usually be able to make globals work automatically. However, if your PSYX installs an interrupt routine or passes a pointer to a filter procedure into a toolbox function, you will have to perform extra A4 maintenance.

PsyScope handles all message sending, so you do not need to worry about exactly how PSYXs are loaded and called. For PSYXs compiled using MPW or THINK C, PsyScope also takes care of setting and restoring the A4 register (so that the compiler's glue code is not actually necessary). In fact, PsyScope creates some special glue itself when it gets a function pointer from a PSYX message table (see "1.3.3 Message tables"); the glue insures that A4 is correct even when jumping to a function other than main().

When compiling using Metrowerks Codewarrior, PsyScope is unable to automatically set up the A4 register, without first being given the proper A4 value by the PSYXs. Thus for versions of PsyScope after and including 1.1b4, the parameters of the pInitialize message allow the PSYX to pass back the current value of A4. Once this has been done, PsyScope will set up A4 automatically for any other message that's called in the PSYX, whether they're handled in main() or through a message table. See "1.4 Standard Messages" for specifics on the pInitialize message.

Note: The PSYXs Manager's A4 glue code is only used for PSYX messages. Other routines called from PsyScope or the system, such as update procedures for asynchronous DCODs must still set up and restore A4 themselves.

If a PSYX uses a non-modal window, it should set the A4 information when it registers the window with the Event Handler. See "Chapter 12. Windows in PsyScope" and specifically "12.2 Window Callback Record".

1.3.1.1 - Applications
1.3.1.2 - Stand-alone code resources

PSYX Programmer's Manual - 24 AUG 95
[Next] [Previous] [Up] [Top] [Contents] [Index]

Generated with CERN WebMaker