Amiga MagicWB icons
Amiga Icon File Format
An unofficial guide to decoding classic Amiga icon images

1. Introduction

Icons in AmigaOS and its derivatives (MorphOS, AROS), are basically the same thing as on other operating systems – a small images identifying files, directories, disks and so on. Except of image data, Amiga icons contain some additional informations. File icons can contain a path to an application used to open the project file when it is doubleclicked (the default tool). They can also contain so-called tooltypes, which are just strings used as program parameters. Dawer (folder) and disk icons contain position, size and viewmode of a window opened on the desktop after clicking the icon. All icons can store their position in parent drawer (or desktop) window.

I've decided to write this unofficial specification, after I've found none on the Internet. While Amiga icons are not very popular, as AmigaOS itself is rather a niche, hobby OS, someone may find this article useful. Note that there are a few kinds of Amiga icons. This article describes an old, bitplane based format. Later NewIcons and PNG icons (as used in AmigaOS 4, MorphOS and AROS) are not described here.

2. Real and default icons

Icons in AmigaOS are separate files, with the same name as the 'main' file, and '.info' extension at the end. Note that if a file has an extension by itself (for example 'archive.lha'), the '.info' extension does not replace file extension, but is appended at the end, so an icon for 'archive.lha' has the name ''. It may look strange for a Windows user, but comes from the fact, that Amiga system does not use extensions for file type recognition at all. An executable file without an '.exe' is perfectly OK for example. To say more, executable files on Amiga have no extension at all usually.

When a file has no icon associated, it is invisible in Workbench window until "Show all files" viewmode is selected. Then a default icon for the file is used. Older AmigaOS versions have stored default icons in "ENVARC:sys/", where xxxx is 'drawer', 'project', 'tool' or 'disk'. Some extensions to this system have been developed, which allowed different icons for different file types. What is important here, default icons have the same file format as real ones. One can easily create a real icon from a default one, using system tools, or just by copying the icon and changing its name.

3. Amiga icon structure

The icon file is composed directly of some system structures. It has an advantage of fast icon loading and displaying, the file is just loaded to memory, structures addresses are extracted and may be passed directly to Intuition, the main Amiga UI library. On the other hand many fields of these system structures are unused or redundant, making the icon file bigger. Some data in these structures are referenced via pointers in memory, in an icon file, the data are stored after structures in a defined order.

The selected state of an Amiga icon is not generated programatically, but is specified in the icon itself. Often the selected state is a second, separate image, sometimes it is specified as palette entries swap.

3.1. Format overview.

The icon file starts from a DiskObject structure, which embeds Gadget structure. Then there may be a DrawerData structure, followed by one or two Image structures. After them raster image data for Image(s) follows. Then there is a default tool string and tooltypes strings. DrawerData contains a NewWindow structure. Here is a block diagram of an Amiga icon:

DiskObject DrawerData Image 1 raster data
for Image 1
Image 2 raster data
for Image 2
default tool tooltypes

Fig. 1. A block diagram of Amiga icon file structure (gray elements are optional).

NOTE: All multi-byte fields of an Amiga icon are big-endian. x86 programmers have to swap bytes.

3.2. DiskObject structure

0000uint16do_MagicA file identifier. All icons have 0xE310 here.
0002uint16do_VersionIcon version. The current version is 1.
0004uint32do_Gadget.NextGadgetUnused. Contains 0 usually.
0008int16do_Gadget.LeftEdgeHorizontal position of the icon left edge relative to its parent window left edge. This field is only used when an icon is loaded into memory.
0010int16do_Gadget.TopEdgeVertical position of the icon top edge relative to its parent window top edge. This field is only used when an icon is loaded into memory.
0012uint16do_Gadget.WidthIcon width in pixels.
0014uint16do_Gadget.HeightIcon height in pixels.
0016uint16do_Gadget.FlagsGadget flags. Used only by Intuition, when the icon is loaded into memory. Usually set to 5.
0018uint16do_Gadget.ActivationGadget activation flags. The usual value is 3 here (both 'immediate' and 'relverify' activation methods set).
0020uint16do_Gadget.GadgetTypeGadget type. The usual value is 1 here (means boolean gadget).
0022uint32do_Gadget.GadgetRenderIn memory a pointer to the first Image, used for not selected state. In file it should be any non-zero value. Zero here should not happen.
0026uint32do_Gadget.SelectRenderIn memory a pointer to the second Image, used for selected state. In file non-zero value means that the icon has the second Image and raster data.
0030uint32do_Gadget.GadgetTextUnused. Usually 0.
0034uint32do_Gadget.MutualExcludeUnused. Usually 0.
0038uint32do_Gadget.SpecialInfoUnused. Usually 0.
0042uint16do_Gadget.GadgetIDUnused. Usually 0.
0044uint32do_Gadget.UserDataUsed for icon revision. 0 for OS 1.x icons. 1 for OS 2.x/3.x icons.
0048uint8do_TypeA type of icon:
  • 1 – disk or volume.
  • 2 – drawer (folder).
  • 3 – tool (executable).
  • 4 – project (data file).
  • 5 – trashcan.
  • 6 – device.
  • 7 – Kickstart ROM image.
  • 8 – an appicon (placed on the desktop by application).
0049uint8paddingJust padding byte.
0050uint32do_DefaultToolIn memory a pointer to a default tool path string. In file should be interpreted as boolean field indicating default tool presence.
0054uint32do_ToolTypesIn memory a pointer to a table containing pointers to tooltype strings. In file should be interptered as boolean field indicating tooltypes table presence.
0058int32do_CurrentXVirtual horizontal position of the icon in the drawer window.
0062int32do_CurrentYVirtual vertical position of the icon in the drawer window.
0066uint32do_DrawerDataIn memory a pointer to DrawerData structure. In file should be interpreted as a boolean field indicating DrawerData presence.
0074uint32do_StackSizeTask stack size for an application. (in case of project file, this size is for default tool application).
Total size: 78 bytes.

3.3. DrawerData structure

The structure starts from a NewWindow structure. Note that DrawerData may be just skipped when only icon image is to be decoded. I've put the information here just for completness.

0000int16dd_NewWindow.LeftEdgeDrawer window left edge relative to the Workbench screen.
0002int16dd_NewWindow.TopEdgeDrawer window top edge relative to the Workbench screen.
0004int16dd_NewWindow.WidthDrawer window width.
0006int16dd_NewWindow.HeightDrawer window height.
0008uint8dd_NewWindow.DetailPenNumber of graphics pen used to render window details.
0009uint8dd_NewWindow.BlockPenNumber of graphics pen used to render window frame background.
0010uint32dd_NewWindow.IDCMPFlagsKinds of IDCMP (GUI -> application) events requested.
0014uint32dd_NewWindow.FlagsVarious window flags (borders, system gadgets etc.).
0018uint32dd_NewWindow.FirstGadgetIn memory a pointer to the first window gadget in a linked list. Unused in an icon file.
0022uint32dd_NewWindow.CheckMarkIn memory a pointer to checkmark imagery for the window. Unused in an icon file.
0026uint32dd_NewWindow.TitleIn memory a pointer to the window title string. Unused in an icon file.
0030uint32dd_NewWindow.ScreenIn memory a pointer to system Screen a window is to be opened on. Unused in an icon file.
0034uint32dd_NewWindow.BitMapIn memory points to a system BitMap for the window. Unused in an icon file.
0038int16dd_NewWindow.MinWidthMinimum width for the window.
0040int16dd_NewWindow.MinHeightMinimum height for the window.
0042uint16dd_NewWindow.MaxWidthMaximum width for the window.
0044uint16dd_NewWindow.MaxHeightMaximum height for the window.
0046uint16dd_NewWindow.TypeWindow type (public/custom screen).
0048int32dd_CurrentXHorizontal position of originating icon.
0052int32dd_CurrentYVertical position of originating icon.
Total size: 56 bytes.

3.4. Image structure

0000int16LeftEdgeImage left edge position relative to the icon left edge. Image clipping should be done for negative values.
0002int16TopEdgeImage top edge position relative to the icon top edge. Image clipping should be done for negative values.
0004uint16WidthImage width in pixels. May be less than icon width (stored in DiskObject.Gadget), missing columns use color 0. If it is bigger than icon width I recommend to clip the image.
0006uint16HeightImage height in pixels. May be less than icon height (stored in DiskObject.Gadget), missing rows use color 0. If it is bigger than icon height I recommend to clip the image.
0008uint16DepthNumber of image bitplanes (see chapter 3.5.).
0010uint32ImageDataIn memory it is a pointer to bitplanes, in file it should be treated as a boolean value (if not zero, bitplane data are stored as shown on fig. 1.).
0014uint8PlanePickA bitfield controlling which image bitplane is copied to which screen bitplane. Used only by classic Amiga graphics chipset. Meaningless in a file, as it is interpreted in Amiga chipset context displaying particular screen.
0015uint8PlaneOnOffA bitfield controlling screen bitplanes not fed with icon data. They may be either filled by zeros or by ones. Used only by classic Amiga graphics chipset. Meaningless in a file, as it is interpreted in Amiga chipset context displaying particular screen.
0016uint32NextImageUnused. Usually 0.
Total size: 20 bytes.

3.5. Image data and palette

Icon image data are stored as bitplanes. While a bit cumbersome for nowadays display devices, this format is a native one for Amiga graphics chipsets. Then image data, once loaded into graphics ("chip") memory, can be directly blitted to a screen. On bitplanes, every pixel occupies one bit, regardless of number of palette colors. Palette size is determined by a number of bitplanes, for N bitplanes there are 2N colors available. To determine a pixel color, one has to gather this pixel bits from all bitplanes (bitplane 0, which comes first in the data, is the most significant one) as shown on fig. 2, form a number and use it as an index to the palette table.

Bitplaned image data

Fig. 2. Bitplaned image data.

Amiga icon bitplanes are not interleaved, complete planes are stored one after one. Pixel scanning order is usual left-to-right, top-to-bottom. Plane rows are padded to 16-bit words, there is no vertical padding.

In spite of image data are palette-based, there is no palette stored in the icon, just some standard palette is assumed. Unfortunately there are a few "standard" palettes used:

  1. Standard AmigaOS 1.x palette, 4 colors.
          color 0, R=0, G=85, B=170 (0x0055AA)
          color 1, R=255, G=255, B=255 (0xFFFFFF)
          color 2, R=0, G=0, B=0 (0x000000)
          color 3, R=255, G=136, B=0 (0xFF8800)
  2. Standard AmigaOS 2.x palette, 4 colors.
          color 0, R=149, G=149, B=149 (0x959595)
          color 1, R=0, G=0, B=0 (0x000000)
          color 2, R=255, G=255, B=255 (0xFFFFFF)
          color 3, R=59, G=103, B=162 (0x3B67A2)
  3. MagicWB palette, 8 colors. It extends AmigaOS 2.x palette with 4 additional colors.
          color 4, R=123, G=123, B=123 (0x7B7B7B)
          color 5, R=175, G=175, B=175 (0xAFAFAF)
          color 6, R=170, G=144, B=124 (0xAA907C)
          color 7, R=255, G=169, B=151 (0xFFA997)

There were some other palettes proposed, usually extending MagicWB with more colors, but they have not gained popularity. NewIcons format solved the problem finally, storing a palette inside an icon. Which palette one should use converting the icon image to RGB color space? If we limit possibilities to palettes shown above, icon revision allows to choose between OS 1.x and OS 2.x palette. Then if revision is 1 and number of bitplanes is 3, the icon is MagicWB one.

4. Decoding icon images

Usually you will be only interested in extracting images from an icon, and convert them to the RGB color space (unless you are writing an Amiga Workbench replacement...). Here is a short guide how to do it:

  1. Take into account, that most of information in the icon is unused. All fields in DiskObject and Image structures really needed to decode imagery are marked gray in the above tables. White entries may be ignored. If you are on x86 or other little-endian platform, do not forget about byte-swapping.
  2. Start from loading a fixed size DiskObject structure. Verify do_Magic and do_Version. Then check for presence of DrawerData. Non zero do_DrawerData is the primary indicator, do_Type of 1, 2 or 5 is the secondary one. Check for presence of the first image (do_Gadget.GadgetRender). The second image primary indicator is do_Gadget.SelectRender, the secondary one is that gadget highlight bits are set to 2 (do_Gadget.Flags & 0x0003 == 0x0002).
  3. If DrawerData is present, skip it.
  4. Read the first Image structure. Extract offsets, width, height and number of bitplanes. Calculate bitplane width in bytes taking horizontal padding into account. It may be calculated as ((Width + 15) >> 4) << 1.
  5. Check for ImageData. If it is 0, it may mean that the image is empty, or the file is damaged. If not, load bitplanes to memory.
  6. If you've detected the second Image, repeat 4. and 5. Be prepared for different offsets and dimensions (may happen often) or different bitplanes number (very unlikely, but who knows).
  7. Select the palette for every image, based on icon revision and number of bitplanes. Convert bitplanes to a RGB pixelmap, using selected palette. Note that padding bits should be ignored even if non-zero.
  8. Create an empty rectangle of icon size (do_Gadget.Width × do_Gadget_Height). Fill it with palette color 0. Then impose the normal or selected image on it using Image LeftEdge and TopEdge as offsets. Perform clipping if neccesary.