Home  |  software  |  Musings  |  Pictorial  |  Academics  |  Links


Standards For OS X Themes On Intel Architecture

Intended Audience

Developers creating applications that read and write Mac OS X theme data, specifically, the data stored in the files titled "Extras.rsrc" and "Extras2.rsrc".

The Problem

With the release of Intel-based Macintosh computers, Mac developers need to concern themselves with the possibility that the endianness of data may not match the endianness of the processor that is manipulating that data. Mac OS X themes present such a scenario — until now, the theme data has always been created on a big-endian machine and stored in big-endian format.

But now the situation has changed; it's possible to generate or read theme data on little-endian architectures. The question immediately presents itself – how do you store the data, in big-endian or in little-endian format? Apple solved this in the lazy, but smart, manner. They just duplicated the data. If the machine is running in big-endian mode (PPC chips, or applications running in Rosetta), the big-endian file is used (Extras.rsrc). If the machine is running in little-endian mode (native applications on an Intel processor), the little-endian file is used (Extras2.rsrc).

The problem for us is that our software also reads and writes this data! If we open some arbitrary file named "ThemeStuff.rsrc", how do we know whether it's big-endian or not? We don't, and that's not very nice. So let's try to make it nicer.

It's Anarchy!

To digress for a moment, the reason that this proposal is necessary is that if multiple software vendors release software that reads and writes theme data, one vendor has no good way of knowing the endianness of another vendor's output. Even closer to home, the software vendor doesn't even know how to read it's own data! Here's an example:

  • SuperSoftwareCompany has a program named ThemeBuilder.
  • Joe, running on a PowerPC Macintosh, uses ThemeBuilder to generate an Extras.rsrc file. He names it "MyTheme.rsrc".
  • Joe shares his generated file with Sally. Sally is using an Intel Macintosh.
  • Sally opens Joe's "MyTheme.rsrc" file using her Intel-native version of ThemeBuilder.
  • The Intel version of ThemeBuilder reads the file, but has no way of knowing that its internal representation of all of the data is flipped. ThemeBuilder probably crashes, leading to unhappy Joe, Sally, and also leading to bankruptcy for SuperSoftwareCompany.
  • The world ends.
The Proposal

If a consistent set of rules is in place to determine whether a given file contains big or little endian data, things become a non-issue. The proposal is to use a combination of heuristics and methodology to absolutely determine whether any individual resource is in big- or little-endian format. It's all pretty simple.

Let's do it in plain English first. If it's not a rsrc file, it's big-endian. If the filename is "Extras2.rsrc", assume that it's little-endian. If the file is tagged with a special resource, determine the endianness from the tag. Otherwise, it's big-endian.

At this point, this is still just a proposal, and I'd love comments if you've got a better way, or think this is silly, or whatever.

Let's Get Algorithmic, Baby!
  • If the filename extension is NOT "rsrc":
    all resource data within the file is stored in big-endian format. Always. No exceptions, ever.
  • If the filename extension IS "rsrc":
    • If the filename is "Extras2.rsrc":
      all resource data within the file is stored in little-endian format.
    • If the file contains a resource of type 'Endn' with ID 128:
      all resource data within the file is stored in the format specified by the resource (see below).
    • If the file does not contain a resource of type 'Endn' with ID 128:
      all resource data within the file is stored in big-endian format.
The 'Endn' Resource

The resource is pretty basic. The most important point is that the 'Endn' resource data is always big-endian, regardless of the format of the remainder of the rsrc file. Here's what's in the resource:

	// version: 		always set to zero
	// isLittleEndian:	if zero, all data in file is big-endian.
	//			otherwise, all data is little-endian
	typedef struct {
		UInt32		version;
		UInt32		isLittleEndian;
	} ThemeEndianness;

Note that this specification does not state that isLittleEndian is boolean. Any non-zero value indicates little-endian data.

Sample Code!

Last, but not least, here's some sample code to handle it all for you. You may use this code in your project with no limitations whatsoever.


© 2005 — All Rights Reserved Site credits >