Drivers.
Under Mac OS 8, the device driver mechanism has been rearchitected to ensure a
high-throughput and flexible I/O system. Pre-Mac OS 8 'DRVR'-style drivers are
not supported and so need to be rewritten. As we'll discuss below, some
software written as a driver today may be better written as another application
type.
The first step in preparing for Mac OS 8 is determining the migration path your
application will follow. Depending on what type of application you have today,
this could mean a complete rewrite, minor tweaks, or no changes at all.
The most important point along the Mac OS 8 migration path is the first one:
compatibility. Before determining the best way of moving your application
forward, you should ensure that it runs out of the box on Mac OS 8. We'll
discuss compatibility specifics in a later section.
Each System 7 application type has a unique migration path; the sections below
cover the available options.
As shown in Figure 1, a System 7-based user interface application has several
alternatives for migration. The simplest alternative is not to revise the
application at all, or, if needed, do the minimum required to make the
application Mac OS 8 compatible.
Figure 1. The migration path for a user interface application
Another
alternative is to convert the application into an OpenDoc part editor. I'm not
going to go into OpenDoc in this article; if you choose this route, see the
article "The OpenDoc User Experience" in develop Issue 22 for a good overview
of how part editors work from the user's perspective.
If having a single binary for both System 7 and Mac OS 8 is important, the
minimal-adoption option may be appropriate. By migrating to minimal adoption,
you ensure user interface consistency and may be able to take advantage of a
limited number of Mac OS 8 features. For example, more efficient memory
management is possible if you restrict yourself to a subset of the Macintosh
Memory Manager API and don't access Memory Manager heap structures directly.
The most ambitious path for migration is to make the application Mac OS 8
savvy. This will mean that the same binary won't run under both System 7 and
Mac OS 8. If the application is made Mac OS 8 savvy, it can take advantage of
the wide range of preemptive tasking services, efficient event handling, and an
object-oriented version of the Macintosh Toolbox.
The migration path for a real-time application is more straightforward than for
a user interface application (see Figure 2). Either the application can move to
Mac OS 8 without changes or it can take advantage of additional real-time
features provided by Mac OS 8, becoming a Mac OS 8-specific real-time
application. Which path is taken depends on whether the existing application
performs properly under Mac OS 8 without changes. For example, the developer of
an application that was using Time Manager tasks for accuracy-critical timing
would want to consider migrating to take advantage of the improved timing
services of Mac OS 8.
Figure 2. The migration path for real-time applications
As shown in Figure 3, existing OpenDoc part editors will be compatible with Mac
OS 8, but a part editor can be updated to take advantage of new Mac OS 8 APIs
if the developer chooses. Both Mac OS 8-savvy and existing OpenDoc part editors
can work on the same OpenDoc documents without problems.
Figure 3. The migration path for OpenDoc part editors
Faceless background applications (FBAs), also known as background-only
applications, are supported under Mac OS 8, but the natural migration path for
most FBAs leads to the server application type (see Figure 4).
Figure 4. The migration path for faceless background applications
The preemptive nature of servers makes them easier to write than FBAs, since
file system and networking calls can block until completion instead of being
written with asynchronous calls and chained completion routines. More
important, the enhanced reliability of servers makes this transition an easy
decision. One drawback of servers is that they cannot access the cooperative
Toolbox environment, since they're preemptively scheduled.
We'll cover desk accessories and control panels together, since they share many
of the same user interface characteristics. Most user interaction for these
types takes place in a single window, and neither type maintains a full menu
bar. All existing desk accessories and control panels are unsupported under Mac
OS 8 and so need to be rewritten. As shown in Figure 5, the two suggested
replacement application types are utility applications and OpenDoc part editors.
Figure 5. The migration path for desk accessories and control panels
Figure 6 shows the migration path for drivers. On pre-Mac OS 8 systems, drivers
were typically written for a variety of reasons. The most straightforward use
of old-style drivers was to control hardware devices. With Mac OS 8, a newly
designed driver architecture has been provided for these hardware control
drivers.
Figure
6. The migration path for drivers
Another common reason for writing a driver was to get periodic time from the
system, or to present a common interface for other drivers or applications
through the PBControl call. Mac OS 8's server mechanism is a much more capable
solution for these types of products. Servers can get reliable periodic time
through the Mac OS 8 kernel's timing services, and messaging or Apple events
can be used to communicate with other servers or applications.
Certain existing drivers will be compatible with Mac OS 8. Display and
networking drivers developed in strict accordance with the guidelines in
Designing PCI Cards and Drivers for Power Macintosh Computers will work under
Mac OS 8 without modification.
Finally, non-QuickDraw GX printer drivers are not supported under Mac OS 8.
Since the printing mechanism for Mac OS 8 is an improved version of QuickDraw
GX, existing non-GX printer drivers need to be updated to the QuickDraw GX
printer driver model.
Extensions, in the form of both individual INITs and INITs packaged within
control panels, are not supported under Mac OS 8. These extensions, for the
most part, can be divided into two categories: those that need periodic time
from the system and those that operate through global-effect patching. The
former will typically be replaced by servers, while the latter will migrate to
either the built-in extensibility services or the extension library mechanism
(as shown in Figure 7).
Figure
7. The migration path for extensions
For extensions that patch traps such as SystemTask to get periodic time to run
"on the dime" of other applications, the Mac OS 8 server model provides a much
more straightforward mechanism. The only drawback to using servers in this way
is that the cooperative Toolbox environment is not available to preemptive
callers, so an old-style faceless background application may be another
migration alternative.
As mentioned earlier, hooks for extensibility have been designed into the Mac
OS 8 system. For this reason, patching is no longer necessary in most cases.
These built-in extensibility hooks should accommodate most former clients of
patching.
Since we can't forecast every possible way of extending the system, the
extension library and patch library mechanisms have been provided. Through
data-driven means, patches can be installed on a per-application basis to
control behaviors. Super Boomerang, for example, could be rewritten in this
way.
Some items located in the System 7 Extensions folder will continue to work
under Mac OS 8. These include CFM shared libraries, 'appe' background
applications, Communications Toolbox tools, Chooser extensions, and Apple Guide
guide files. Note that no INITs associated with these extension types will be
loaded by Mac OS 8, which could impact compatibility for these products.
Several types of non-INIT Apple extensions are not supported, however, and
soneed to be rewritten. These include sound sifters, inline input methods, and
FSM modules.
By application plug-ins, we're referring to products like Kai's Power Tools for
Photoshop. There shouldn't be any compatibility issues specific to plug-ins
operating in existing applications. There are, however, compelling reasons for
application developers to update the way they present plug-in interfaces.
Figure 8 shows the migration path. For applications that present their plug-in
model in an object-oriented fashion, the System Object Model (SOM) should be
used. Its many advantages include strong type checking, object-oriented
interfaces, and a solution to the fragile base-class problem. For developers
who want to maintain a functional interface, the Code Fragment Manager is the
best option.
Figure
8. The migration path for application plug-ins
There are some potential pitfalls related to plug-in compatibility with Mac OS
8. Although mixing Mac OS 8 APIs with System 7 APIs is permitted, there may be
problems running System 7 plug-ins with Mac OS 8-savvy versions of
applications. For instance, Photoshop could choose to take advantage of new
memory management services provided in Mac OS 8. For the payoff of not having a
fixed-size Memory Manager heap, they promise not to make certain Memory Manager
calls. If a System 7 Photoshop plug-in makes any of these disallowed Memory
Manager calls, Photoshop may not work.
For this reason, we're suggesting that all applications that support a plug-in
model provide isolation for these plug-ins from system calls. If the plug-in
needs to allocate memory, for example, it should call the application to do so,
instead of calling the Memory Manager directly. In this way, plug-ins can take
advantage of new Mac OS 8 features without ever being updated.
Several existing plug-in mechanisms are either not available or not encouraged
for use under Mac OS 8. The Apple Shared Library Manager, as we'll discuss
later, is not available. The Component Manager is available but is not
recommended for use, since the Code Fragment Manager and SOM are now the
preferred mechanisms.
There are quite a few steps you can take to ensure application compatibility
with Mac OS 8. You've heard a lot of these suggestions before, while some are
new. All are important techniques that can save you many hours of debugging.
You'll find that in the Mac OS 8 release, a debugging version of the system has
been provided that will assert via the debugger whenever your application
performs a questionable behavior. Hopefully, if you follow the guidelines in
this article, you won't ever have to see these assertions.
For each suggestion, we'll show a snippet of code or an example of the
technique where appropriate. Each one of these techniques can be put into
action today.
Within Apple, all Macintosh development is now done using the same set of
universal interfaces. These interfaces are periodically released to developers
on the MPW Pro disk and online, and are also available on this issue's CD. Some
third-party tools, such as Metrowerks CodeWarrior, also ship with the latest
interfaces. By using these interfaces, you'll be developing with the same C,
Pascal, and assembly headers as Apple engineers, which ensures that you'll be
up to date with the latest changes from Apple.
Over time, the universal interfaces will have Mac OS 8 features conditionally
added. For example, several compile-time switches will be added to indicate
which calls are available in certain situations.
Mac OS 8 is, at heart, a PowerPC processor-based system. Porting only
performance-critical sections of your application to PowerPC code and leaving
the rest in 680x0 code will begin to become more of a liability than an
advantage under Mac OS 8. New API calls introduced in Mac OS 8 will not have
traps associated with them. They'll be made available only through CFM and
SOM-based interfaces. This means that 680x0 code will not be able to access
these new services. Note, however, that 680x0 applications are still fully
supported under Mac OS 8 for compatibility.
Considering all the changes coming for developers in the Mac OS 8 release, you
may choose to move your application to a well-supported Macintosh framework.
Apple is already working closely with several framework providers, and you may
decide to take advantage of their efforts. One word of caution is that using a
framework doesn't guarantee compatibility. If that framework "breaks the
rules," or if your own application code uses unsupported behaviors, you still
have compatibility concerns.
While getting a variety of applications running on the Mac OS 8 release, we've
found that many developers have obsolete code buried in their applications. For
instance, several developers used the code shown in Listing 1 to check for the
availability of certain system traps. Note the function ToolboxTrapTableSize.
This code checks to see if the application is running on a Macintosh with an
expanded Toolbox trap table -- but this has been the case ever since Color
QuickDraw was introduced. Considering that the applications performing this
check were PowerPC native, this check is overkill and so can be removed.
Listing 1. Obsolete code for checking trap availability
Boolean IsTrapAvailable(short theTrap)
{
TrapType trapType;
Boolean available;
if ((theTrap & 0x0800) > 0)
trapType = ToolTrap;
else
trapType = OSTrap;
if (trapType == ToolTrap) {
theTrap &= 0x07FF;
if (theTrap >= ToolboxTrapTableSize())
theTrap = _Unimplemented;
}
available = NGetTrapAddress(theTrap, trapType)
!= GetToolTrapAddress(_Unimplemented);
return available;
}
short ToolboxTrapTableSize(void)
{
if (GetToolTrapAddress(_InitGraf) == GetToolTrapAddress(0xAA6E))
return 0x0200;
else
return 0x0400;
}
Other
examples of long-obsolete behaviors include using old SFGetFile-style Standard
File calls and relying on HFS working directories to make file system calls. In
other words, you can safely assume that Apple will not introduce a PowerPC
processor-based Macintosh that runs System 6.
Many applications use patching to excess. A well-written PowerPC-native
application should not have to patch any traps. Along the lines of removing old
code, consider removing patches installed simply to work around a long-fixed
bug, at least conditionally.
We found a particularly bad example of application trap patching when bringing
up a major word processing application. The application called the Alert
routine to display an alert to the user. The developers decided that they
wanted a cool 3D button instead of the Macintosh-standard button, so they
patched NewControl and watched for NewControl to be called from NewDialog
(itself called from Alert) with the expected pushButProc procID. When this call
was intercepted, they substituted their 3D button procID, and the alert was
displayed with their button. Of course, they could have simply called the
Dialog Manager and Control Manager themselves, thereby avoiding the trap patch
entirely. There's no law that says you need to call Alert, after all.
We can't stress enough the importance of patch minimization. Relying on side
effects that are undocumented, such as the fact that Alert will end up calling
NewControl, may cause your application to break unexpectedly with any new
system release. We found out about the above example because the Mac OS 8
Dialog Manager used its new modern mechanisms within Alert. To maintain
compatibility with this application, we had to back off from this and revert to
the existing mechanisms. In many key areas, Apple can't innovate as much as
developers would like because of the behaviors of many existing applications.
As has been common for some time with cross-platform development, it's a useful
exercise to separate your application into several distinct parts in
preparation for Mac OS 8. At least two of these parts should be the user
interaction component and the compute engine component. Separating all
Macintosh-specific calls such as disk access and networking into modules may
also be helpful.
Mac OS 8 provides several new facilities to make factoring your application
easier. Tasking and synchronization services provided by the system allow you
to divide computation into several tasks, resulting in greatly improved CPU
usage. Unlike the Thread Manager, Mac OS 8's new tasking services provide
preemptive multitasking. In addition, the Apple event mechanism has been
significantly improved in both performance and functionality. The Apple Event
Manager can be called by both preemptive and cooperative tasks, and is the
preferred method of communication among an application's factored tasks.
The reasons for factoring your application are twofold. First, the separation
will allow you to more easily bridge the gap between your Mac OS 8 source base
and your System 7 source base. You could separate your core functionality (such
as an image processing algorithm) from your user interface code, thereby
allowing you to write a new Mac OS 8-savvy user interaction module. Or, under
Mac OS 8, you could choose to run your image processing module preemptively in
another task. This modularity could make it possible to substitute Mac OS
8-specific file system calls, for example, to achieve better throughput.
The second reason has a more immediate payoff. Factoring your application will
help make it scriptable and recordable with AppleScript. With Mac OS 8, the
event routing mechanism will change from a polling to a delivery mechanism,
with high-level synthetic events being produced from lower-level user actions.
This new model is just a short step from a System 7 AppleScript-recordable
application.
With Mac OS 8, the Macintosh user experience will get a major facelift. Any
number of user-selectable themes can be chosen to alter the appearance of
windows, menus, and controls. Some examples of theme-specific windows are shown
in Figure 9.
Figure
9. Theme-specific windows
As you can see, the appearance of themes can vary greatly. The big
compatibility challenge here is that many developers have lost patience with
Apple in the area of user interface look enhancements, and have implemented
their own unique application appearances already. A user who switches the theme
on his or her Macintosh will expect the appearance of all applications to
change. The new Apple-supplied theme-specific appearances are tied to
Apple-standard Toolbox definition procedures. If an application developer uses
a custom 3D button or checkbox, it will look the same no matter which theme is
selected. Needless to say, this can create combinations no graphic artist would
ever approve of.