The Palm Application Compatibility Environment, or PACE, is a 68K emulator that supports execution of well-behaved 68K-based Palm OS applications on devices that use an ARM processor.
PACE allows the majority of existing 68K-based Palm OS applications to run on devices that use an ARM processor. Users can beam an application from a 68K device to an ARM-based device and run the application. The Palm Application Compatibility Environment helps provide a migration path for developers. The developer can continue to use existing 68K-based tools to build their application.
Design Objectives
The Palm Application Compatibility Environment is designed to allow well-behaved 68K applications to run at 68K speeds or faster on an ARM-based device, with minimum code and memory overhead. A well-behaved application is one that:
- only uses documented Palm OS APIs
- does not access hardware directly
- does not access the display memory directly
- does not access low memory globals
- does not access the fields of Palm OS structures directly
- runs on Palm OS Emulator with a debug Palm OS Garnet ROM without encountering any errors
Performance
Performance of a 68K application varies greatly depending on how much time it spends executing 68K instructions compared to the time it spends calling Palm OS functions.
Code that consists only of 68K instructions, such as a prime number generator, will run slower than an ARM-native version of the same code since the 68K instructions are emulated. For reference, the time it takes to execute emulated 68K instructions on a 70 MHz ARM device is roughly the same as the time it takes to execute the same instructions on a Palm Vx device. Most applications spend a great deal of time inside operating system calls, however, and those calls execute at the full speed of the ARM processor (note that there may be additional overhead for some Palm OS functions, depending on how close the native function's API is to the 68K API). Thus most 68K applications running under PACE will actually run much faster than they would on a device with a 68K processor.
Developer SDK
Because an application that runs under PACE is like any other 68K application, when writing applications to run under PACE you continue to use the tools and headers available for 68K-based Palm OS application development.
Applications are no longer allowed access to many internal, publicly-defined structures (such as the ControlType
structure). To make up for this, some accessor functions were added in Palm OS 4.0, and additional accessor functions were added to the Palm OS glue library shipped with the Palm OS Garnet SDK.
The 68K Palm debugger and other tools which depend on the 68K debugger APIs (such as the Metrowerks debugger) are supported by the Palm Application Compatibility Environment.
API Restrictions
Most well-behaved applications run under the Palm OS Garnet version of PACE with no problems. Due to differences in the underlying operating system in Palm OS Cobalt, however, PACE is somewhat more restricting on Palm OS Cobalt devices. The following sections detail those restrictions.
Deprecated APIs
Very few deprecated APIs (such as CategoryEditV20()
) are supported for native ARM applications. The Palm Application Compatibility Environment still supports these deprecated APIs, unless they are listed in Table 1.1.
Unsupported APIs
A number of Palm OS APIs are not supported by PACE. These are APIs that either are documented as private, are internal-only APIs (yet appear in public header files), or are APIs that developer support has advised developers to not use. A list of unsupported APIs can be found under "Unsupported Palm OS Functions."
Card Number Argument
The native ARM version of Palm OS no longer has the concept of memory cards. For this reason, the card number concept is faked for emulated 68K applications. If an application calls MemNumCards()
, a value of 1 is always returned. If an application calls any function that takes cardNum
as an argument and the value for cardNum
is not zero, an error is returned to the application.
Record Unique IDs
In previous versions of Palm OS, only 24 bits of a record's unique ID were stored in the record header. In Palm OS Cobalt, however, all 32 bits are unique. The function that returns a record's unique ID returns a 32-bit value; to ensure the greatest degree of compatiblity an application should save all 32 bits of the record's unique ID, and not truncate the result to 24 bits.
Effect of Calling an Unsupported or Deprecated Palm OS Function
If a 68K application calls an unsupported or deprecated Palm OS function, an alert is displayed and the application is terminated. The alert contains the message "An error occurred in the application you are using. Note the error code and contact the developer of this application" followed by an error number in parentheses. When the user presses the OK button, the application is forced to exit. The debug version of this error alert has two more numbers displayed (to help you pinpoint the problem) and a Cancel button. If you tap the Cancel button, PACE tries to connect to the 68K Palm Debugger so you can determine why and where the error is occurring.
Unsupported Palm OS Functions
Table 1.1 is a list of Palm OS functions that are not supported by PACE in Palm OS Cobalt. The following are the reasons why these functions are not supported.
- Documented as "System Use Only"
- These functions are documented as "System Use Only" in the Palm OS Programmer's API Reference and thus should never have been called by applications.
- Should have been documented as "system use only"
- These functions were intended for internal PalmSource use only but were documented.
- Obsolete
- These functions are not implemented because they have long been obsolete. Current Palm OS applications should no longer be using them.
- Implemented as a "NOP" function
- Typically, these are functions that should not have been called by applications. Because some applications may call them, however, PACE supports them. However, they do nothing and simply return.
- Rarely-used function
- Functions that are only used internally by Palm OS, by serial drivers, or by OEM extensions. They are not functions that an application would use. PACE does not implement these functions.
- Unimplemented in Palm OS Cobalt
- Functions that were supported by PACE in Palm OS Garnet but are no longer supported by PACE in Palm OS Cobalt. The vast majority of these are intended for system use only, and the remaining few are very rarely used by applications.
Table 1.1 Unsupported Palm OS functions
Accessing the PIM Application Databases
Some 68K applications access the PIM application databases. In Palm OS Cobalt the PIM applications are ARM-native applications, and those applications now use Schema databases to hold application data. Although the "classic" PIM application databases are no longer present, PACE does what it can to "do the right thing" when it detects that a 68K application is attempting to access a PIM application database.
NOTE: The PIM database access solution described here depends entirely on the presence of the ARM-native PIM applications. As well, those applications must correctly support the
sysAppLaunchCmdImportRecord
, sysAppLaunchCmdExportRecord
and sysAppLaunchCmdDeleteRecord
launch commands. PACE further assumes that the database names, database schema names, and field IDs haven't changed (additional fields may be present, however, and the field order can be changed).
When an application tries to access a 68K PIM application database—either to open or to find it—PACE creates the 68K database, opens it, initializes its application info block (using category names from the corresponding native PIM app) and creates a cache of all records in the corresponding ARM-native PIM application database. Each cache entry contains the following information:
- the unique ID of the native record
- handle to the 68K record
- index of the 68K record
- category that the record belongs to
- attribute flags (dirty and deleted)
Each entry is initialized with the unique ID and category information. All other fields are cleared.
When the application then tries to read a record (for example, by calling DmQueryRecord()
or DmGetRecord()
), PACE sends a sysAppLaunchCmdExportRecord
request to the native application. In response, the native application returns the record in vcard format. PACE converts the vcard information into a 68K PIM application record and stores that record into the 68K PIM application database that was created when the database was opened. The index and record handle of this record are stored in the cache; any further requests for the record will return the record handle from the cache.
If the application creates a new record, PACE creates a record in the 68K PIM application database, adds an entry to the cache, and initializes the cache entry's unique ID to NULL
.
When the application writes to the new record, PACE marks the record in the cache as "dirty" so that it will be written back to the ARM-native PIM application database when the database is flushed. At that time, PACE converts the 68K record to its vcard representation and then sends a sysAppLaunchCmdImportRecord
request to the native application. Records are flushed:
- when a database is closed
- whenever another record is created
- before a unique ID is returned to an application (in response to a call to
DmGetRecordInfo()
).
When an application deletes a PIM database record, PACE marks the record in the cache as "deleted" and sends a sysAppLaunchCmdDeleteRecord
request to the native application.
Once the 68K application closes the PIM application database, PACE flushes any dirty records that have yet to be written, frees up memory allocated for the cache, and closes and deletes the 68K PIM application database.
The two functions DmFindDatabase()
and DmGetNextDatabaseByTypeCreator()
have the side effect of leaving the 68K PIM application database around. To clean up these stray databases, PACE deletes any existing 68K PIM application databases whenever a 68K application exits. Note that if you call DmOpenDatabase()
after locating a database with either of these two functions, and later call DmCloseDatabase()
, the database will be deleted when the close function is called.
Although DmFindDatabase()
leaves the 68K PIM application database around, other Data Manager calls may cause PACE to delete it. Because of this, if you are going to open a PIM application database by calling DmFindDatabase()
followed by DmOpenDatabase()
(as opposed to the more common method of using DmOpenDatabaseByTypeCreator()
), avoid making other Data Manager calls on the PIM application database between the call to DmFindDatabase()
and DmOpenDatabase()
.
Limitations
The PIM application database access solution provided by PACE has a number of limitations. For one, not all database access functions are supported. Here is a list of the known limitations:
- It can be slow. The ARM-native PIM applications are sub-launched for each PIM database read, write, or delete.
- Category changes are not reflected back to the native PIM application. Category information should be treated as read-only.
- All three "varieties" of record delete—
DmDeleteRecord()
,DmRemoveRecord()
andDmArchiveRecord()
—become requests for the native PIM application to delete the record. - Some things in the application info blocks are "hard-coded." For example, the ToDo sort order is always priority/due date and the Address Book labels are hard-coded to English text labels.
- The
totalBytes
anddataBytes
sizes returned fromDmDatabaseSize()
come from the 68K database and thus are usually wrong. They would only be correct if every record has been read in from the ARM-native PIM application database. - Some database record access functions are not supported, including
DmRemoveSecretRecords()
,DmMoveCategory()
andDmDeleteCategory()
. - There are some limitations with private records. Private records will be masked or hidden when a 68K PIM application is run, but changing the "maskedness" or "hiddenness" has no effect while running the 68K PIM application.
- Because records are not immediately written to the ARM-native PIM application databases, some data may be lost while running a 68K PIM application replacement if the system is reset while the application is running.
Summary of PIM Database Access APIs
Table 1.2 lists those functions for which PACE checks to see if a PIM application database is being accessed. If so, PACE acts as described in the second column.
Table 1.2 Functions that PACE monitors for PIM database access